www.pudn.com > 完整的FTP客户端ftpwanderersrc.zip > MainFrm.cpp


/****************************************************************/ 
/*																*/ 
/*  MainFrm.cpp													*/ 
/*																*/ 
/*  Implementation of the CMainFrame class.						*/ 
/*	This file is part of the FTP Wanderer application.			*/ 
/*																*/ 
/*  Programmed by Pablo van der Meer							*/ 
/*  Copyright Pablo Software Solutions 2002						*/ 
/*	http://www.pablovandermeer.nl								*/ 
/*																*/ 
/*  Last updated: 08 july 2002									*/ 
/*																*/ 
/****************************************************************/ 
 
 
#include "stdafx.h" 
#include "ftpwanderer.h" 
 
#include "MainFrm.h" 
#include "FtpTreeView.h" 
#include "TraceView.h" 
#include "FtpListView.h" 
#include "ConnectDlg.h" 
#include "GeneralPage.h" 
#include "GoToFolderDlg.h" 
#include "OptionsSheet.h" 
#include "ReplaceFileDlg.h" 
#include "ReplaceFolderDlg.h" 
#include "WaitMessageDlg.h" 
#include "WizardPages.h" 
#include "afxpriv.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
 
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd) 
 
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) 
	ON_COMMAND_EX(ID_VIEW_QUICKCONNECT, OnBarCheck) 
	ON_UPDATE_COMMAND_UI(ID_VIEW_QUICKCONNECT, OnUpdateControlBarMenu) 
	//{{AFX_MSG_MAP(CMainFrame) 
	ON_WM_CREATE() 
	ON_COMMAND(ID_FILE_RENAME, OnFileRename) 
	ON_COMMAND(ID_FILE_DELETE, OnFileDelete) 
	ON_COMMAND(ID_FILE_EXPLORE, OnFileExplore) 
	ON_COMMAND(ID_VIEW_UPONELEVEL, OnViewUponelevel) 
	ON_COMMAND(ID_FILE_CONNECT, OnFileConnect) 
	ON_UPDATE_COMMAND_UI(ID_FILE_DISCONNECT, OnUpdateFileDisconnect) 
	ON_COMMAND(ID_FILE_DISCONNECT, OnFileDisconnect) 
	ON_COMMAND(ID_FILE_CANCEL, OnFileCancel) 
	ON_COMMAND(ID_FILE_DOWNLOAD, OnFileDownload) 
	ON_COMMAND(ID_FILE_DOWNLOADTO, OnFileDownloadto) 
	ON_UPDATE_COMMAND_UI(ID_FILE_DELETE, OnUpdateActions) 
	ON_COMMAND(ID_FILE_PROPERTIES, OnFileProperties) 
	ON_UPDATE_COMMAND_UI(ID_FILE_CANCEL, OnUpdateFileCancel) 
	ON_COMMAND(ID_VIEW_REFRESH, OnViewRefresh) 
	ON_COMMAND(ID_VIEW_GOTO, OnViewGoTo) 
	ON_COMMAND(ID_FILE_NEWFOLDER, OnFileNewfolder) 
	ON_COMMAND(ID_VIEW_BYNAME, OnViewByname) 
	ON_COMMAND(ID_VIEW_BYSIZE, OnViewBysize) 
	ON_COMMAND(ID_VIEW_BYTYPE, OnViewBytype) 
	ON_COMMAND(ID_VIEW_BYDATE, OnViewBydate) 
	ON_COMMAND(ID_FILE_UPLOAD, OnFileUpload) 
	ON_COMMAND(ID_TOOLS_OPTIONS, OnToolsOptions) 
	ON_COMMAND(ID_TOOLS_ASCII, OnToolsAscii) 
	ON_UPDATE_COMMAND_UI(ID_TOOLS_ASCII, OnUpdateToolsAscii) 
	ON_COMMAND(ID_TOOLS_BINARY, OnToolsBinary) 
	ON_UPDATE_COMMAND_UI(ID_TOOLS_BINARY, OnUpdateToolsBinary) 
	ON_WM_CLOSE() 
	ON_COMMAND(ID_VIEW_TRACE, OnViewTrace) 
	ON_UPDATE_COMMAND_UI(ID_VIEW_TRACE, OnUpdateViewTrace) 
	ON_UPDATE_COMMAND_UI(ID_FILE_CONNECT, OnUpdateFileConnect) 
	ON_COMMAND(ID_VIEW_TRANSFERMANAGER, OnViewTransfermanager) 
	ON_UPDATE_COMMAND_UI(ID_VIEW_TRANSFERMANAGER, OnUpdateViewTransfermanager) 
	ON_WM_DESTROY() 
	ON_COMMAND(ID_EDIT_SELECT_ALL, OnEditSelectAll) 
	ON_COMMAND(ID_EDIT_INVERTSELECTION, OnEditInvertselection) 
	ON_COMMAND(ID_FILE_CONNECTIONWIZARD, OnFileConnectionwizard) 
	ON_UPDATE_COMMAND_UI(ID_FILE_RENAME, OnUpdateActions) 
	ON_UPDATE_COMMAND_UI(ID_FILE_DOWNLOAD, OnUpdateActions) 
	ON_UPDATE_COMMAND_UI(ID_FILE_UPLOAD, OnUpdateFileDisconnect) 
	ON_UPDATE_COMMAND_UI(ID_FILE_DOWNLOADTO, OnUpdateActions) 
	ON_UPDATE_COMMAND_UI(ID_FILE_PROPERTIES, OnUpdateActions) 
	ON_UPDATE_COMMAND_UI(ID_FILE_NEWFOLDER, OnUpdateFileDisconnect) 
	ON_UPDATE_COMMAND_UI(ID_FILE_EXPLORE, OnUpdateFileDisconnect) 
	ON_UPDATE_COMMAND_UI(ID_VIEW_REFRESH, OnUpdateFileDisconnect) 
	ON_UPDATE_COMMAND_UI(ID_VIEW_UPONELEVEL, OnUpdateFileDisconnect) 
	ON_UPDATE_COMMAND_UI(ID_VIEW_GOTO, OnUpdateFileDisconnect) 
	ON_UPDATE_COMMAND_UI(ID_VIEW_REFRESH, OnUpdateFileDisconnect) 
	ON_UPDATE_COMMAND_UI(ID_EDIT_INVERTSELECTION, OnUpdateFileDisconnect) 
	ON_UPDATE_COMMAND_UI(ID_EDIT_SELECT_ALL, OnUpdateFileDisconnect) 
	ON_BN_CLICKED(IDC_QUICKCONNECT, OnQuickconnect) 
	//}}AFX_MSG_MAP 
	ON_UPDATE_COMMAND_UI_RANGE(AFX_ID_VIEW_MINIMUM, AFX_ID_VIEW_MAXIMUM, OnUpdateViewStyles) 
	ON_COMMAND_RANGE(AFX_ID_VIEW_MINIMUM, AFX_ID_VIEW_MAXIMUM, OnViewStyle) 
	ON_MESSAGE(WM_FTP_STATUS, OnFtpStatus) 
	ON_MESSAGE(WM_DOWNLOAD_FINISHED, OnDownloadFinished) 
	ON_MESSAGE(WM_UPLOAD_FINISHED, OnUploadFinished) 
END_MESSAGE_MAP() 
 
static UINT indicators[] = 
{ 
	ID_SEPARATOR,           // status line indicator 
	ID_INDICATOR_CAPS, 
	ID_INDICATOR_NUM, 
	ID_INDICATOR_SCRL, 
}; 
 
 
CMainFrame::CMainFrame() 
{ 
	m_pFtpConnection = NULL; 
	m_pInternetSession = NULL; 
	m_strCurrentDirectory = ""; 
	m_hCurrentTreeItem = NULL; 
	m_bBusy = FALSE; 
	m_bNewFolderMode = FALSE; 
	m_bMultipleLevels = FALSE; 
	m_bInitialized = FALSE; 
} 
 
CMainFrame::~CMainFrame() 
{ 
	// clean up any objects that are still lying around 
	if (m_pFtpConnection != NULL) 
	{ 
		m_pFtpConnection->Close(); 
		delete m_pFtpConnection; 
	} 
	if (m_pInternetSession != NULL) 
	{ 
		m_pInternetSession->Close(); 
		delete m_pInternetSession; 
	} 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnCreate											*/ 
/* Description   : Called when window needs to be created.			*/ 
/*																	*/ 
/********************************************************************/ 
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{ 
	if (CFrameWnd::OnCreate(lpCreateStruct) == -1) 
		return -1; 
	 
	if (!CreateHotToolBar()) 
		return -1; 
 
	if (!m_wndStatusBar.Create(this) || 
		!m_wndStatusBar.SetIndicators(indicators, 
		  sizeof(indicators)/sizeof(UINT))) 
	{ 
		TRACE0("Failed to create status bar\n"); 
		return -1;      // fail to create 
	} 
 
	// TODO: Remove this if you don't want tool tips 
	m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY); 
 
	m_dwTransferType = AfxGetApp()->GetProfileInt("Settings", "TransferType", FTP_TRANSFER_TYPE_BINARY); 
	m_bShowTransferManager = AfxGetApp()->GetProfileInt("Settings", "ShowTransferManager", 0); 
 
	m_pTransferManager = new CTransferManagerDlg; 
	m_pTransferManager->Create(m_bShowTransferManager); 
	m_pTransferManager->m_nMaximumTransfers = AfxGetApp()->GetProfileInt("Settings", "TransferMax", 10); 
	m_pTransferManager->m_nConnectionTimeout = AfxGetApp()->GetProfileInt("Settings", "ConnectionTimeout", 30); 
	m_pTransferManager->m_bRemoveFailed = AfxGetApp()->GetProfileInt("Settings", "RemoveFailed", 0); 
	TRACE1("Max transfers: %d\n", m_pTransferManager->m_nMaximumTransfers); 
 
	EnableDocking(CBRS_ALIGN_ANY); 
 
	// Initialize dialog bar m_wndQuickConnect
	if (!m_wndQuickConnect.Create(this, IDD_QUICKCONNECT,
		CBRS_TOP | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_HIDE_INPLACE,
		ID_VIEW_QUICKCONNECT))
	{
		TRACE0("Failed to create dialog bar m_wndQuickConnect\n");
		return -1;		// fail to create
	}
 
	m_wndQuickConnect.SetWindowText("Quick Connect");
	m_wndQuickConnect.EnableDocking(CBRS_ALIGN_TOP | CBRS_ALIGN_BOTTOM);
	DockControlBar(&m_wndQuickConnect);
 
	ShowControlBar(&m_wndQuickConnect, FALSE, FALSE); 
 
	LoadBarState("QuickConnectState");
	return 0; 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnCreateClient									*/ 
/* Description   : Create some splitter windows.					*/ 
/*																	*/ 
/********************************************************************/ 
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext) 
{ 
	// create splitter window 
	if (!m_wndSplitter.CreateStatic(this, 2, 1)) 
		return FALSE; 
 
    // add the second splitter pane - a message view in raw 1 
	if (!m_wndSplitter.CreateView(1, 0, RUNTIME_CLASS(CTraceView), CSize(0, 0), pContext)) 
		return FALSE; 
 
    // split the first splitter pane 
	if (!m_wndSplitter2.CreateStatic(&m_wndSplitter, 1, 2, WS_CHILD|WS_VISIBLE|WS_BORDER, m_wndSplitter.IdFromRowCol(0, 0))) 
    { 
		return FALSE;  
	}; 
 
	// add default view to the first pane 
    if (!m_wndSplitter2.CreateView(0, 0, RUNTIME_CLASS(CFtpTreeView), CSize(100, 100), pContext)) 
    { 
		return FALSE; 
	}; 
     
	// add list view to the second pane 
    if (!m_wndSplitter2.CreateView(0, 1, RUNTIME_CLASS(CFtpListView), CSize(100, 100), pContext)) 
    { 
		return FALSE; 
	}; 
 
	// remember CTraceView pointer 
	CWnd* pWnd = m_wndSplitter.GetPane(1, 0); 
	m_pTraceView = DYNAMIC_DOWNCAST(CTraceView, pWnd); 
 
	CRect rc; 
	GetClientRect(&rc); 
 
	m_wndSplitter.SetRowInfo(0, rc.Height()*3/4, 50); 
	m_wndSplitter.SetRowInfo(1, rc.Height()/4, 50); 
 
    m_wndSplitter2.SetColumnInfo(0, 200, 10); 
    m_wndSplitter2.SetActivePane(0, 0); 
 
	m_bInitialized = TRUE; 
 
	// Initialize Tree Control here 
//	PopulateTree(); 
 
	m_bShowTrace = AfxGetApp()->GetProfileInt("Settings", "ShowTrace", 1); 
	if (!m_bShowTrace) 
		m_wndSplitter.HideRow(1); 
 
	// show connect dialog 
	if (AfxGetApp()->GetProfileInt("Settings", "ShowConnectionDlg", 1)) 
		PostMessage(WM_COMMAND, ID_FILE_CONNECT); 
 
	// save view style 
	int nViewStyle = AfxGetApp()->GetProfileInt("Settings", "ViewStyle", ID_VIEW_LARGEICON); 
	OnViewStyle(nViewStyle); 
 
	return TRUE; 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CMainFrame diagnostics 
 
#ifdef _DEBUG 
void CMainFrame::AssertValid() const 
{ 
	CFrameWnd::AssertValid(); 
} 
 
void CMainFrame::Dump(CDumpContext& dc) const 
{ 
	CFrameWnd::Dump(dc); 
} 
 
#endif //_DEBUG 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : GetFtpListView									*/ 
/* Description   : Get pointer to the listview.						*/ 
/*																	*/ 
/********************************************************************/ 
CFtpListView* CMainFrame::GetFtpListView() 
{ 
	CWnd* pWnd = m_wndSplitter2.GetPane(0, 1); 
	CFtpListView* pView = DYNAMIC_DOWNCAST(CFtpListView, pWnd); 
	return pView; 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : GetFtpTreeView									*/ 
/* Description   : Get pointer to the treeview.						*/ 
/*																	*/ 
/********************************************************************/ 
CFtpTreeView* CMainFrame::GetFtpTreeView() 
{ 
	CWnd* pWnd = m_wndSplitter2.GetPane(0, 0); 
	CFtpTreeView* pView = DYNAMIC_DOWNCAST(CFtpTreeView, pWnd); 
	return pView; 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnUpdateViewStyles								*/ 
/* Description   : Update toolbar/menu status for view styles.		*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnUpdateViewStyles(CCmdUI* pCmdUI) 
{ 
	CFtpListView* pView = GetFtpListView();  
 
	// if the right-hand pane hasn't been created or isn't a view, 
	// disable commands in our range 
 
	if (pView == NULL) 
		pCmdUI->Enable(FALSE); 
	else 
	{ 
		DWORD dwStyle = pView->GetStyle() & LVS_TYPEMASK; 
 
		// if the command is ID_VIEW_LINEUP, only enable command 
		// when we're in LVS_ICON or LVS_SMALLICON mode 
 
		if (pCmdUI->m_nID == ID_VIEW_LINEUP) 
		{ 
			if (dwStyle == LVS_ICON || dwStyle == LVS_SMALLICON) 
				pCmdUI->Enable(); 
			else 
				pCmdUI->Enable(FALSE); 
		} 
		else 
		{ 
			// otherwise, use dots to reflect the style of the view 
			pCmdUI->Enable(); 
			BOOL bChecked = FALSE; 
 
			switch (pCmdUI->m_nID) 
			{ 
			case ID_VIEW_DETAILS: 
				bChecked = (dwStyle == LVS_REPORT); 
				break; 
 
			case ID_VIEW_SMALLICON: 
				bChecked = (dwStyle == LVS_SMALLICON); 
				break; 
 
			case ID_VIEW_LARGEICON: 
				bChecked = (dwStyle == LVS_ICON); 
				break; 
 
			case ID_VIEW_LIST: 
				bChecked = (dwStyle == LVS_LIST); 
				break; 
 
			default: 
				bChecked = FALSE; 
				break; 
			} 
 
			pCmdUI->SetRadio(bChecked ? 1 : 0); 
		} 
	} 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnViewStyle										*/ 
/* Description   : Change view style.								*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnViewStyle(UINT nCommandID) 
{ 
	// TODO: customize or extend this code to handle choices on the 
	// View menu. 
	CFtpListView* pView = GetFtpListView(); 
 
	// if the right-hand pane has been created and is a CFtpListView, 
	// process the menu commands... 
	if (pView != NULL) 
	{ 
		DWORD dwStyle = -1; 
 
		switch (nCommandID) 
		{ 
		case ID_VIEW_LINEUP: 
			{ 
				// ask the list control to snap to grid 
				CListCtrl& refListCtrl = pView->GetListCtrl(); 
				refListCtrl.Arrange(LVA_SNAPTOGRID); 
			} 
			break; 
 
		// other commands change the style on the list control 
		case ID_VIEW_DETAILS: 
			dwStyle = LVS_REPORT; 
			break; 
 
		case ID_VIEW_SMALLICON: 
			dwStyle = LVS_SMALLICON; 
			break; 
 
		case ID_VIEW_LARGEICON: 
			dwStyle = LVS_ICON; 
			break; 
 
		case ID_VIEW_LIST: 
			dwStyle = LVS_LIST; 
			break; 
		} 
 
		// change the style; window will repaint automatically 
		if (dwStyle != -1) 
			pView->ModifyStyle(LVS_TYPEMASK, dwStyle); 
	} 
	// save change to registry 
	AfxGetApp()->WriteProfileInt("Settings", "ViewStyle", nCommandID);	 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnFileConnect									*/ 
/* Description   : Connect to FTP server							*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnFileConnect()  
{ 
	Connect(); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnUpdateFileConnect								*/ 
/* Description   : Enable/disable Connect command					*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnUpdateFileConnect(CCmdUI* pCmdUI)  
{ 
	pCmdUI->Enable(!m_bBusy);	 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnFileDisconnect									*/ 
/* Description   : Disconnect from FTP Server						*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnFileDisconnect()  
{ 
	// clean up any objects that are still lying around 
	if (m_pFtpConnection != NULL) 
	{ 
		GetTraceView()->AddTraceLine(0, "[%d] Closing FTP session...", AfxGetThread()->m_nThreadID); 
		DoEvents(); 
		m_pFtpConnection->Close(); 
		delete m_pFtpConnection; 
 
		m_pFtpConnection = NULL; 
		GetTraceView()->AddTraceLine(1, "[%d] FTP session closed.", AfxGetThread()->m_nThreadID); 
	} 
 
	if (m_pInternetSession != NULL) 
	{ 
		GetTraceView()->AddTraceLine(0, "[%d] Closing Internet Session...", AfxGetThread()->m_nThreadID); 
		DoEvents(); 
		m_pInternetSession->Close(); 
		delete m_pInternetSession; 
		 
		m_pInternetSession = NULL; 
		GetTraceView()->AddTraceLine(1, "[%d] Internet session closed.", AfxGetThread()->m_nThreadID); 
	} 
 
	CDocument* pDocument = GetActiveDocument(); 
	if (pDocument != NULL) 
		pDocument->SetTitle("Not Connected"); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnUpdateFileDisconnect							*/ 
/* Description   : Enable/disable Disconnect command				*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnUpdateFileDisconnect(CCmdUI* pCmdUI)  
{ 
	pCmdUI->Enable(m_pFtpConnection	!= NULL  && !m_bBusy); 
	GetFtpListView()->GetListCtrl().EnableWindow(m_pFtpConnection != NULL); 
	GetFtpTreeView()->GetTreeCtrl().EnableWindow(m_pFtpConnection != NULL); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnFileCancel										*/ 
/* Description   : 													*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnFileCancel()  
{ 
	m_bBusy = FALSE; 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnUpdateFileCancel								*/ 
/* Description   : Enable/disable Cancel command					*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnUpdateFileCancel(CCmdUI* pCmdUI)  
{ 
	pCmdUI->Enable(m_bBusy || m_bMultipleLevels); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : Connect											*/ 
/* Description   : Connect to FTP site.								*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::Connect(LPCTSTR lpszSiteName, LPCTSTR lpszUserName, LPCTSTR lpszPassword) 
{ 
	CConnectDlg dlg; 
 
	// clear name! 
	m_FtpSite.m_strName.Empty(); 
 
	// if no sitename is specified, show connect dialog 
	if (lpszSiteName == NULL) 
	{ 
		if (dlg.DoModal() != IDOK) 
		{ 
			return; 
		} 
		m_FtpSite.m_bUsePASVMode = dlg.m_bUsePASVMode; 
		m_FtpSite.m_nRetries = dlg.m_nRetries; 
		m_FtpSite.m_nPort = dlg.m_nPort; 
		m_FtpSite.m_nRetryDelay = dlg.m_nRetryDelay; 
		m_FtpSite.m_strAddress = dlg.m_strAddress; 
		m_FtpSite.m_strDescription = dlg.m_strDescription; 
		m_FtpSite.m_strLocalPath = dlg.m_strLocalPath; 
		m_FtpSite.m_strLogin = dlg.m_strLogin; 
		m_FtpSite.m_strName = dlg.m_strName; 
		m_FtpSite.m_strPassword = dlg.m_strPassword; 
		m_FtpSite.m_strRemotePath = dlg.m_strRemotePath; 
	} 
	else 
	{ 
		// read site names 
		dlg.Serialize(FALSE); 
 
		// find specified name 
		for (int i=0; i < dlg.m_SitesArray.GetSize(); i++) 
		{ 
			if (dlg.m_SitesArray[i].m_strName.CompareNoCase(lpszSiteName) == 0) 
			{ 
				// copy site data 
				m_FtpSite = dlg.m_SitesArray[i]; 
				break; 
			} 
		} 
	} 
 
	// quick connect ? 
	if (m_FtpSite.m_strName.IsEmpty()) 
	{ 
		m_FtpSite.m_bUsePASVMode = AfxGetApp()->GetProfileInt("Settings", "DefaultUsePASVMode", 0); 
		m_FtpSite.m_nRetries = AfxGetApp()->GetProfileInt("Settings", "DefaultRetries", 3); 
		m_FtpSite.m_nPort = 21; 
		m_FtpSite.m_nRetryDelay = AfxGetApp()->GetProfileInt("Settings", "DefaultRetryDelay", 10); 
		m_FtpSite.m_strAddress = lpszSiteName; 
		m_FtpSite.m_strDescription = ""; 
		m_FtpSite.m_strLocalPath = AfxGetApp()->GetProfileString("Settings", "DefaultLocalPath", ""); 
		m_FtpSite.m_strLogin = lpszUserName; 
		m_FtpSite.m_strName = ""; 
		m_FtpSite.m_strPassword = lpszPassword; 
		m_FtpSite.m_strRemotePath = ""; 
	} 
 
	// fix paths the ways we like it... 
	m_FtpSite.m_strLocalPath.TrimRight("\\"); 
 
	if (!m_FtpSite.m_strRemotePath.IsEmpty()) 
	{ 
		m_FtpSite.m_strRemotePath.Replace("\\", "/"); 
		m_FtpSite.m_strRemotePath.TrimLeft('/'); 
		m_FtpSite.m_strAddress += "/"; 
		m_FtpSite.m_strAddress += m_FtpSite.m_strRemotePath; 
	} 
 
	CString strObject; 
	INTERNET_PORT nPort; 
	DWORD dwServiceType; 
 
	// if there's already a connection open, close it first 
	if (m_pFtpConnection != NULL) 
	{ 
		GetTraceView()->AddTraceLine(0, "[%d] Closing existing FTP session...", AfxGetThread()->m_nThreadID); 
		m_pFtpConnection->Close(); 
 
		delete m_pFtpConnection; 
		m_pFtpConnection = NULL; 
	} 
 
	if (m_pInternetSession != NULL) 
	{ 
		GetTraceView()->AddTraceLine(0, "[%d] Closing existing Internet Session...", AfxGetThread()->m_nThreadID); 
 
		m_pInternetSession->Close(); 
		delete m_pInternetSession; 
		 
		m_pInternetSession = NULL; 
	} 
 
	GetTraceView()->AddTraceLine(0, "[%d] Opening Internet Session...", AfxGetThread()->m_nThreadID); 
 
	CString str; 
	if (!str.LoadString(AFX_IDS_APP_TITLE)) 
		str = _T("AppUnknown"); 
 
	m_pInternetSession = new CMyInternetSession(str, 1, PRE_CONFIG_INTERNET_ACCESS); 
 
	// Alert the user if the internet session could 
	// not be started and close app 
	if (!m_pInternetSession) 
	{ 
		GetTraceView()->AddTraceLine(3, "[%d] Cannot open an Internet Session. Please check your internet configuration.", AfxGetThread()->m_nThreadID); 
		return; 
	} 
 
	m_pInternetSession->m_pMainWnd = m_hWnd; 
	m_pInternetSession->EnableStatusCallback(); 
 
	GetTraceView()->AddTraceLine(0, "[%d] Checking URL...", AfxGetThread()->m_nThreadID); 
 
	// check to see if this is a reasonable URL -- 
	// ie "ftp://servername/dirs" or just "servername/dirs" 
 
	if (!AfxParseURL(m_FtpSite.m_strAddress, dwServiceType, m_strServerName, strObject, nPort)) 
	{ 
		// try adding the "ftp://" protocol 
		CString strFtpURL = _T("ftp://"); 
		strFtpURL += m_FtpSite.m_strAddress; 
 
		if (!AfxParseURL(strFtpURL, dwServiceType, m_strServerName, strObject, nPort)) 
		{ 
			GetTraceView()->AddTraceLine(3, "[%d] Please enter a valid FTP URL.", AfxGetThread()->m_nThreadID); 
	 
			AfxMessageBox(IDS_INVALID_URL, MB_OK); 
			PopulateTree(); 
			return; 
		} 
	} 
	GetTraceView()->AddTraceLine(1, "[%d] URL was successfully parsed.", AfxGetThread()->m_nThreadID); 
 
	CWaitCursor cursor; // this will automatically display a wait cursor 
 
	// Now open a FTP connection to the server 
	if ((dwServiceType == INTERNET_SERVICE_FTP) && !m_strServerName.IsEmpty()) 
	{ 
		int nRetries = m_FtpSite.m_nRetries; 
		while(nRetries > 0) 
		{ 
			nRetries--; 
			try 
			{ 
				GetTraceView()->AddTraceLine(0, "[%d] Connecting to: %s (Attempt %d of %d)", AfxGetThread()->m_nThreadID, m_strServerName, m_FtpSite.m_nRetries - nRetries, m_FtpSite.m_nRetries); 
				 
				int nTimeout = AfxGetApp()->GetProfileInt("Settings", "ConnectionTimeout", 30); 
				m_pInternetSession->SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, nTimeout * 1000); 
				m_pInternetSession->SetOption(INTERNET_OPTION_RECEIVE_TIMEOUT, nTimeout * 1000); 
				m_pInternetSession->SetOption(INTERNET_OPTION_SEND_TIMEOUT, nTimeout * 1000); 
				m_pFtpConnection = m_pInternetSession->GetFtpConnection(m_strServerName, m_FtpSite.m_strLogin, m_FtpSite.m_strPassword, m_FtpSite.m_nPort, m_FtpSite.m_bUsePASVMode); 
				nRetries = 0; 
			} 
			catch (CInternetException* pEx) 
			{ 
				DWORD dwLength = 255, dwError; 
				 
				CString strLastResponce; 
				InternetGetLastResponseInfo(&dwError, strLastResponce.GetBuffer(dwLength), &dwLength); 
				strLastResponce.ReleaseBuffer(); 
				strLastResponce.Remove('\n'); 
				strLastResponce.Remove('\r'); 
 
				if (!strLastResponce.IsEmpty()) 
					GetTraceView()->AddTraceLine(3, "[%d] %s", AfxGetThread()->m_nThreadID, strLastResponce); 
 
				// catch errors from WinINet 
				dwLength = 255; 
				CString strInfo; 
				if (pEx->GetErrorMessage(strInfo.GetBuffer(dwLength), dwLength)) 
				{ 
					strInfo.ReleaseBuffer(); 
					strInfo.Remove('\n'); 
					strInfo.Remove('\r'); 
					GetTraceView()->AddTraceLine(3, "[%d] %s", AfxGetThread()->m_nThreadID, strInfo); 
 
					// show wait dialog 
					if (nRetries > 0) 
					{ 
						CWaitMessageDlg dlg; 
						dlg.m_nRetryDelay = m_FtpSite.m_nRetryDelay; 
						dlg.m_strMessage = strInfo; 
						if (dlg.DoModal() != IDOK) 
						{ 
							// canceled by user 
							nRetries = 0; 
						} 
					} 
					else 
					{ 
						if (!strLastResponce.IsEmpty()) 
						{ 
							strLastResponce += "\r\n"; 
						} 
						 
						strLastResponce += strInfo; 
						AfxMessageBox(strLastResponce, MB_OK); 
					} 
				} 
				else 
				{ 
					GetTraceView()->AddTraceLine(3, "[%d] An exception occurred when attempting to create an FTP connection. Please check your internet configuration and make sure your environment is set up with WININET.DLL in the path.", AfxGetThread()->m_nThreadID); 
					nRetries = 0; 
					AfxMessageBox(IDS_EXCEPTION, MB_OK); 
				} 
				pEx->Delete(); 
 
				m_pFtpConnection = NULL; 
			} 
		} 
	} 
	else 
	{ 
		GetTraceView()->AddTraceLine(3, "[%d] Please enter a valid FTP URL.", AfxGetThread()->m_nThreadID); 
		AfxMessageBox(IDS_INVALID_URL, MB_OK); 
	} 
 
	// PopulateTree() will display an error if the FTP connection 
	// could not be made, otherwise, it grabs the root listing 
	// and expands any folder indicated by the site name 
 
	if (m_pFtpConnection != NULL) 
	{ 
		GetTraceView()->AddTraceLine(1, "[%d] Successfully connected to: %s.", AfxGetThread()->m_nThreadID, m_strServerName); 
 
		PopulateTree(strObject); 
		 
		if (!m_FtpSite.m_strName.IsEmpty()) 
			AfxGetApp()->AddToRecentFileList(m_FtpSite.m_strName); 
	} 
	else 
	{ 
		GetTraceView()->AddTraceLine(3, "[%d] FTP connection could not be made.", AfxGetThread()->m_nThreadID); 
		PopulateTree(); 
	}	 
 
	// get document title 
	CDocument* pDocument = GetActiveDocument(); 
	if (pDocument != NULL) 
	{ 
		if (!m_FtpSite.m_strName.IsEmpty()) 
			pDocument->SetTitle(m_FtpSite.m_strName); 
		else 
			pDocument->SetTitle(m_FtpSite.m_strAddress); 
	} 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : PopulateTree										*/ 
/* Description   : Populate tree with contents of strDir			*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::PopulateTree(const CString& strDir, BOOL bDoNotReset) 
{ 
	TRACE1("Populate Tree: %s\n", strDir); 
	CWaitCursor cursor; // this will automatically display a wait cursor 
 
	if (!bDoNotReset) 
	{ 
		// Make sure tree and list are empty before (re)populating it 
		GetFtpTreeView()->GetTreeCtrl().DeleteAllItems(); 
		GetFtpListView()->GetListCtrl().DeleteAllItems(); 
	} 
	 
	if (!m_pFtpConnection) 
	{ 
	} 
	else 
	{ 
		CString cstr = _T("/"); // look at the root directory first 
 
		if (!bDoNotReset) 
		{ 
			// insert the the root into the tree struct 
			TV_INSERTSTRUCT tvstruct; 
			int nIcon = GetIconIndex("Desktop", TRUE); 
			tvstruct.hParent = NULL; 
			tvstruct.hInsertAfter = TVI_LAST; 
			tvstruct.item.iImage = nIcon; 
			tvstruct.item.iSelectedImage = nIcon; 
			tvstruct.item.pszText = _T("/"); 
			tvstruct.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT; 
			GetFtpTreeView()->GetTreeCtrl().InsertItem(&tvstruct); 
		} 
 
		m_bMultipleLevels = bDoNotReset; 
 
		GetFtpTreeView()->GetTreeCtrl().SelectItem(GetFtpTreeView()->GetTreeCtrl().GetRootItem()); 
		GetFtpTreeView()->GetTreeCtrl().Expand(GetFtpTreeView()->GetTreeCtrl().GetRootItem(), TVE_EXPAND); 
 
		// if the root has no real children, make sure TVS_LINESATROOT is not set 
		if (!GetFtpTreeView()->GetTreeCtrl().ItemHasChildren(GetFtpTreeView()->GetTreeCtrl().GetRootItem())) 
		{ 
			GetFtpTreeView()->GetTreeCtrl().ModifyStyle(TVS_LINESATROOT, 0); 
			return; 
		} 
 
		// otherwise, there are children, so set TVS_LINESATROOT 
		GetFtpTreeView()->GetTreeCtrl().ModifyStyle(0, TVS_LINESATROOT); 
 
		if (!strDir) 
			return; 
 
		// expand as far as was indicated in strDir 
		int nIndex; 
		CString strTemp; 
		CString strSrc = strDir; 
		 
		HTREEITEM hTI = GetFtpTreeView()->GetTreeCtrl().GetRootItem(); 
		while (!strSrc.IsEmpty()) 
		{ 
			nIndex = strSrc.Find(_T("/")); 
			if (nIndex < 0) 
			{ 
				// last part of path 
				cstr = strSrc; 
				strSrc.Empty(); 
				m_bMultipleLevels = FALSE; 
			} 
			else  
			if (nIndex > 0) 
			{  
				// the "/" trailing the directory name is not included 
				cstr = strSrc.Left(nIndex); 
				strTemp = strSrc.Right(strSrc.GetLength() - (nIndex+1)); 
				strSrc = strTemp; 
			} 
 
			if(!cstr.IsEmpty() && (nIndex != 0)) 
			{ 
				// cstr now has the name of a file or dir -- look for a child that matches it 
				hTI = GetFtpTreeView()->GetTreeCtrl().GetChildItem(hTI); 
				while ((hTI != NULL) && (cstr.CompareNoCase(GetFtpTreeView()->GetTreeCtrl().GetItemText(hTI)) != 0)) 
				{ 
					hTI = GetFtpTreeView()->GetTreeCtrl().GetNextItem(hTI, TVGN_NEXT); 
				} 
 
				// if you find it, expand the node or select the file 
				if ((hTI != NULL) && (cstr.CompareNoCase(GetFtpTreeView()->GetTreeCtrl().GetItemText(hTI)) == 0)) 
				{ 
					GetFtpTreeView()->GetTreeCtrl().SelectItem(hTI); 
					GetFtpTreeView()->GetTreeCtrl().Expand(hTI, TVE_EXPAND); 
				} 
				// if it wasn't found, you've gone as far as you can, so quit... 
				else  
				{	 
					strSrc.Empty(); 
				} 
			} 
			else // nIndex == 0 
			{ 
				strTemp = strSrc.Right(strSrc.GetLength() - 1); 
				strSrc = strTemp; 
			} 
		} // end expand 
		m_bMultipleLevels = FALSE; 
	} 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : ExploreDirectory									*/ 
/* Description   : Explore specified directory, fill tree and list.	*/ 
/*																	*/ 
/********************************************************************/ 
BOOL CMainFrame::ExploreDirectory(const CString& strDir, HTREEITEM hParent, BOOL bRefresh) 
{ 
	// show wait cursor 
	CWaitCursor cursor;  
 
	if (!IsStillConnected()) 
		return FALSE; 
 
	if (strDir.IsEmpty()) 
		return FALSE; 
 
	// activate animation 
	GetFtpListView()->ActivateAnimation(TRUE); 
 
	// delete complete tree ? 
	if (bRefresh) 
	{ 
		// remove any children of this directory 
		HTREEITEM hItem = GetFtpTreeView()->GetTreeCtrl().GetChildItem(hParent); 
		HTREEITEM hTemp; 
 
		while (hItem != NULL) 
		{ 
			hTemp = GetFtpTreeView()->GetTreeCtrl().GetNextSiblingItem(hItem); 
			GetFtpTreeView()->GetTreeCtrl().DeleteItem(hItem); 
			hItem = hTemp; 
		} 
	} 
 
	// is it already expanded ? 
	BOOL bHasChilderen = GetFtpTreeView()->GetTreeCtrl().ItemHasChildren(hParent); 
 
	// prepare to find all the files in the specified directory 
	if (hParent != GetFtpTreeView()->GetTreeCtrl().GetRootItem()) 
	{ 
		m_strCurrentDirectory = strDir; 
	} 
	else 
	{ 
		m_strCurrentDirectory = "/"; 
	} 
	 
	DoEvents(); 
 
	if (!m_pFtpConnection->SetCurrentDirectory(m_strCurrentDirectory)) 
	{ 
		GetTraceView()->AddTraceLine(3, "[%d] %s", AfxGetThread()->m_nThreadID, GetLastResponceInfo("FTP Folder Error", "An error occurred opening the folder: " + m_strCurrentDirectory)); 
		GetTraceView()->AddTraceLine(3, "[%d] An error occurred opening the folder: \"%s\".", AfxGetThread()->m_nThreadID, m_strCurrentDirectory); 
//		GetFtpListView()->ActivateAnimation(FALSE); 
//		m_bBusy = FALSE; 
		return FALSE; 
	} 
 
	// empty listview 
	GetFtpListView()->GetListCtrl().DeleteAllItems(); 
 
	GetTraceView()->AddTraceLine(2, "[%d] Receiving listing of \"%s\"...", AfxGetThread()->m_nThreadID, m_strCurrentDirectory); 
 
	// we're busy ! 
	m_bBusy = TRUE; 
	m_wndToolBar.OnUpdateCmdUI(this, FALSE); 
	DoEvents(); 
 
 	CFtpFileFind ftpFind(m_pFtpConnection); 
 
	BOOL bContinue = ftpFind.FindFile("");//strSearchDir); 
 
	if (!bContinue) 
	{ 
		DWORD dwError = GetLastError(); 
 
		// the directory is empty; just close up and return. 
		ftpFind.Close(); 
		GetFtpListView()->ActivateAnimation(FALSE); 
		m_bBusy = FALSE; 
		 
		if (dwError == ERROR_INTERNET_TIMEOUT) 
		{ 
			if (!m_FtpSite.m_bUsePASVMode) 
				GetTraceView()->AddTraceLine(3, "[%d] The request has timed out, try connecting using PASV mode.", AfxGetThread()->m_nThreadID); 
			else 
				GetTraceView()->AddTraceLine(3, "[%d] The request has timed out.", AfxGetThread()->m_nThreadID); 
		} 
		else 
		{ 
			GetTraceView()->AddTraceLine(1, "[%d] \"%s\" is empty.", AfxGetThread()->m_nThreadID, m_strCurrentDirectory); 
		} 
		return TRUE; 
	} 
 
	TV_INSERTSTRUCT tvstruct; 
	CString strFileName; 
	int nCount = 0; 
 
	// set up and insert a tvstruct for each item in the directory 
	while (bContinue)  
	{ 
		// FindNextFile muxt be called before info can be gleaned from ftpFind 
		bContinue = ftpFind.FindNextFile(); 
 
		if (ftpFind.IsDots()) 
			continue; 
 
		strFileName = ftpFind.GetFileName(); 
		 
		// is selected item a directory ? 
		if (ftpFind.IsDirectory()) 
		{ 
			// get folder icon index  
			int nIndex = GetIconIndex(strFileName, TRUE); 
			tvstruct.item.iImage = nIndex; 
			 
			// get selected folder icon index  
			nIndex = GetIconIndex(strFileName, TRUE, TRUE); 
			tvstruct.item.iSelectedImage = nIndex; 
 
			tvstruct.hParent = hParent; 
			tvstruct.hInsertAfter = TVI_LAST; 
			tvstruct.item.pszText = (LPTSTR)(LPCTSTR)strFileName;    
			tvstruct.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT; 
 
			// insert item in treeview 
			if (!bHasChilderen) 
				GetFtpTreeView()->GetTreeCtrl().InsertItem(&tvstruct); 
 
			// insert item to listview 
			GetFtpListView()->AddItem(nCount++, &ftpFind); 
		} 
		else 
		{ 
			// insert item to listview 
			GetFtpListView()->AddItem(nCount++, &ftpFind); 
		} 
		DoEvents(); 
		if (!m_bBusy) 
			bContinue = FALSE; 
	} 
 
	ftpFind.Close(); 
	 
	m_bBusy = FALSE; 
 
	// update toolbar status 
	m_wndToolBar.OnUpdateCmdUI(this, FALSE); 
 
	// when processing 'goto' do not turn off animation (we're not ready yet) 
	if (!m_bMultipleLevels) 
	{ 
		// sort column 
		GetFtpListView()->Sort(); 
		// stop animation 
		GetFtpListView()->ActivateAnimation(FALSE); 
 
		GetFtpListView()->GetListCtrl().SetFocus(); 
		GetFtpListView()->GetListCtrl().SetItemState(0, LVNI_SELECTED, LVNI_SELECTED); 
	} 
	GetTraceView()->AddTraceLine(1, "[%d] Listing of \"%s\" succesfully received.", AfxGetThread()->m_nThreadID, m_strCurrentDirectory); 
	return TRUE; 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnSelchanged										*/ 
/* Description   : Selected folder has changed, show contents.		*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult)  
{ 
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; 
	 
	if (pNMTreeView->hdr.code == TVN_SELCHANGED) 
	{ 
		HTREEITEM hPrevious = m_hCurrentTreeItem; 
		HTREEITEM hIT = pNMTreeView->itemNew.hItem; 
 
		m_hCurrentTreeItem = pNMTreeView->itemNew.hItem; 
 
		CString str, strPath; 
 
		// build up the path to htreeitem 
		strPath = GetFtpTreeView()->GetTreeCtrl().GetItemText(hIT); 
 
		if (strPath.IsEmpty()) 
		{ 
			DoEvents(); 
			strPath = GetFtpTreeView()->GetTreeCtrl().GetItemText(hIT); 
		} 
		 
		while (hIT != GetFtpTreeView()->GetTreeCtrl().GetRootItem()) 
		{ 
			hIT = GetFtpTreeView()->GetTreeCtrl().GetParentItem(hIT); 
			 
			if (hIT == NULL) 
				break; 
 
			if (hIT == GetFtpTreeView()->GetTreeCtrl().GetRootItem()) 
				str.Format(_T("/%s"), (LPCTSTR)strPath); 
			else 
				str.Format(_T("%s/%s"), (LPCTSTR)GetFtpTreeView()->GetTreeCtrl().GetItemText(hIT), (LPCTSTR)strPath); 
 
			strPath = str; 
			TRACE1("OnSelchanged: %s\n", strPath);	 
		} 
 
		// use that dir to call ExploreDir 
		if (!ExploreDirectory(strPath, pNMTreeView->itemNew.hItem)) 
		{ 
			// failed to explore directory, select previous item 
			m_hCurrentTreeItem = hPrevious; 
			GetFtpTreeView()->GetTreeCtrl().SelectItem(m_hCurrentTreeItem); 
		} 
	} 
 
	*pResult = 0; 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnFtpStatus										*/ 
/* Description   : Add trace line									*/ 
/*																	*/ 
/********************************************************************/ 
LRESULT CMainFrame::OnFtpStatus(WPARAM wParam, LPARAM lParam) 
{ 
	LPCSTR prtline; 
	prtline = (LPCSTR)lParam; 
     
	CString string; 
    string.Format("%s", prtline); 
 
	GetTraceView()->AddTraceLine(0, string); 
	return 0L; 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnDblclk											*/ 
/* Description   : Double clicked on a item, let's explore it.		*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult)  
{ 
	OnFileExplore(); 
	*pResult = 0; 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : ChangeDirectory									*/ 
/* Description   : Change to specified directory, this will			*/ 
/*				   automatically call OnSelchanged()				*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::ChangeDirectory(LPCTSTR lpszDirectory)  
{ 
	GetTraceView()->AddTraceLine(2, "[%d] Changing Folder: \"%s\"", AfxGetThread()->m_nThreadID, lpszDirectory); 
 
	m_hCurrentTreeItem = GetFtpTreeView()->GetTreeCtrl().GetSelectedItem(); 
	GetFtpTreeView()->GetTreeCtrl().Expand(m_hCurrentTreeItem, TVE_EXPAND); 
	HTREEITEM hItem = GetFtpTreeView()->FindItem(CString(lpszDirectory), m_hCurrentTreeItem); 
	GetFtpTreeView()->GetTreeCtrl().SelectItem(hItem); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : DownloadFile										*/ 
/* Description   : Download a file									*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::DownloadFile(LPCTSTR lpszFileName, DWORD dwFileLength, LPCTSTR lpszDestination)  
{ 
	GetTraceView()->AddTraceLine(2, "[%d] Downloading File: \"%s\"", AfxGetThread()->m_nThreadID, lpszFileName); 
 
	// add download to queue 
	m_pTransferManager->QueueDownload(m_strServerName, 
									  m_FtpSite.m_strLogin, 
									  m_FtpSite.m_strPassword, 
									  lpszFileName, 
									  lpszDestination, 
									  m_strCurrentDirectory, 
									  dwFileLength,  
									  m_dwTransferType, 
									  m_FtpSite.m_nRetries, 
									  m_FtpSite.m_nRetryDelay, 
									  m_FtpSite.m_nPort, 
									  m_FtpSite.m_bUsePASVMode); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : DownloadDirectory								*/ 
/* Description   : Download a complete directory incl. sub dirs		*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::DownloadDirectory(LPCTSTR lpszDirectory, LPCTSTR lpszDestination)  
{ 
	GetTraceView()->AddTraceLine(2, "[%d] Downloading Folder: \"%s\"", AfxGetThread()->m_nThreadID, lpszDirectory); 
 
	CString strDestination; 
	CString strDirectory = lpszDirectory; 
	CString strDirectory2 = lpszDirectory; 
	 
	strDirectory2.TrimLeft('/'); 
 
	int nPos = strDirectory.ReverseFind('/'); 
	if (nPos != -1) 
	{ 
		strDirectory = strDirectory.Mid(nPos+1); 
	} 
 
	// enumerate directory structure and add everything to queue  
	CStringArray strFileNames; 
	CString strFileName, strSize, strPath; 
	RecursiveFileList(strDirectory /*lpszDirectory*/, strFileNames); 
 
	m_pTransferManager->m_bBuildingQueue = TRUE; 
	// queue all found files 
	for (int i = 0; i < strFileNames.GetSize(); i++) 
	{ 
		AfxExtractSubString(strFileName, strFileNames.GetAt(i), 0, '|'); 
		AfxExtractSubString(strPath,	 strFileNames.GetAt(i), 1, '|'); 
		AfxExtractSubString(strSize,	 strFileNames.GetAt(i), 2, '|'); 
 
		// fix path 
		strDestination = strPath; 
		strDestination.TrimLeft('/'); 
		strDestination.TrimLeft(strDirectory2); 
		strDestination.Replace("/", "\\"); 
		strDestination = lpszDestination + strDestination; 
 
		// add download to queue 
		m_pTransferManager->QueueDownload(m_strServerName, 
									  m_FtpSite.m_strLogin, 
									  m_FtpSite.m_strPassword, 
									  strFileName, 
									  strDestination + "\\" + strFileName, 
									  strPath, 
									  atol(strSize),  
									  m_dwTransferType, 
  									  m_FtpSite.m_nRetries, 
									  m_FtpSite.m_nRetryDelay, 
									  m_FtpSite.m_nPort, 
									  m_FtpSite.m_bUsePASVMode); 
 
	} 
	m_pTransferManager->m_bBuildingQueue = FALSE; 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : RecursiveFileList								*/ 
/* Description   : Recursively walk through directory to be able to	*/ 
/*				   download complete directory structure.			*/ 
/*																	*/ 
/********************************************************************/ 
BOOL CMainFrame::RecursiveFileList(LPCTSTR lpszPath, CStringArray &strFileNameArray) 
{ 
	CFtpFileFind ftpFind(m_pFtpConnection); 
	CStringArray strDirectoryArray; 
 
	CString strPrevDirectory; 
 
	// remember current directory 
	if (!m_pFtpConnection->GetCurrentDirectory(strPrevDirectory)) 
	{ 
		return FALSE; 
	} 
	 
	// go to requested directory 
	if (!m_pFtpConnection->SetCurrentDirectory(lpszPath)) 
	{ 
		return FALSE; 
	} 
 
	// add directory (without filename), so we can create the directory structure later 
	CString strPath = strPrevDirectory; 
	strPath.TrimLeft('/'); 
 
	CString strFileName; 
	strFileName.Format("|%s|0", strPath + "/" + lpszPath); 
	strFileNameArray.Add(strFileName); 
 
	GetTraceView()->AddTraceLine(2, "[%d] Receiving listing of \"%s\"...", AfxGetThread()->m_nThreadID, strPath + "/" + lpszPath); 
	 
	BOOL bContinue = ftpFind.FindFile("");//"*"); 
	if (!bContinue) 
	{ 
		// the directory is empty; just close up and return. 
		ftpFind.Close(); 
 
		// go back to parent directory 
		m_pFtpConnection->SetCurrentDirectory(!strPrevDirectory.IsEmpty() ? strPrevDirectory : "/"); 
 
		GetTraceView()->AddTraceLine(1, "[%d] \"%s\" is empty.", AfxGetThread()->m_nThreadID, strPath + "/" + lpszPath); 
		return TRUE; 
	} 
 
	// add all files in lpszPath 
	while (bContinue) 
	{ 
		bContinue = ftpFind.FindNextFile(); 
 
		if (ftpFind.IsDots()) 
			continue; 
		 
		// is selected item a directory ? 
		if (ftpFind.IsDirectory()) 
		{ 
			strDirectoryArray.Add(ftpFind.GetFileName()); 
		} 
		else 
		{ 
			strFileName.Format("%s|%s|%u", ftpFind.GetFileName(), strPrevDirectory + "/" + lpszPath, ftpFind.GetLength()); 
			strFileNameArray.Add(strFileName); 
		} 
	} 
	ftpFind.Close(); 
 
	// get contains of directories 
	for (int i = 0; i < strDirectoryArray.GetSize(); i++) 
	{ 
		if (!RecursiveFileList(/*CString(lpszPath) + "/" + */strDirectoryArray.GetAt(i), strFileNameArray)) 
		{ 
			m_pFtpConnection->SetCurrentDirectory(!strPrevDirectory.IsEmpty() ? strPrevDirectory : "/"); 
			GetTraceView()->AddTraceLine(3, "[%d] Failed to receive listing of \"%s\".", AfxGetThread()->m_nThreadID, strPath + "/" + lpszPath); 
			return FALSE; 
		} 
	} 
 
	// go back to parent directory 
	m_pFtpConnection->SetCurrentDirectory(!strPrevDirectory.IsEmpty() ? strPrevDirectory : "/"); 
	 
	GetTraceView()->AddTraceLine(1, "[%d] Listing of \"%s\" successfully received.", AfxGetThread()->m_nThreadID, strPath + "/" + lpszPath); 
	return TRUE; 
} 
 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : RecursiveEmptyDirectory							*/ 
/* Description   : Recursively walk through directory and delete	*/ 
/*				   everything.										*/ 
/*																	*/ 
/********************************************************************/ 
BOOL CMainFrame::RecursiveEmptyDirectory(LPCTSTR lpszPath) 
{ 
	CFtpFileFind ftpFind(m_pFtpConnection); 
	CStringArray strDirectoryArray; 
	CString strPrevDirectory; 
 
	// remember current directory 
	if (!m_pFtpConnection->GetCurrentDirectory(strPrevDirectory)) 
	{ 
		return FALSE; 
	} 
 
	// go to requested directory 
	if (!m_pFtpConnection->SetCurrentDirectory(lpszPath)) 
	{ 
		return FALSE; 
	} 
 
	// list all files 
	BOOL bContinue = ftpFind.FindFile("");//"*"); 
	while (bContinue) 
	{ 
		bContinue = ftpFind.FindNextFile(); 
 
		if (ftpFind.IsDots()) 
			continue; 
 
		// is selected item a directory ? 
		if (ftpFind.IsDirectory()) 
		{ 
			strDirectoryArray.Add(ftpFind.GetFileName()); 
		} 
		else 
		{ 
			GetTraceView()->AddTraceLine(2, "[%d] Deleting file \"%s\"", AfxGetThread()->m_nThreadID, ftpFind.GetFileName()); 
			if (m_pFtpConnection->Remove(ftpFind.GetFileName())) 
			{ 
				GetTraceView()->AddTraceLine(1, "[%d] \"%s\" successfully deleted", AfxGetThread()->m_nThreadID, ftpFind.GetFileName()); 
			} 
			else 
			{ 
				GetTraceView()->AddTraceLine(3, "[%d] %s", AfxGetThread()->m_nThreadID, GetLastResponceInfo("FTP Delete Error", "An error occurred deleting the file or folder: " + ftpFind.GetFileName())); 
				GetTraceView()->AddTraceLine(3, "[%d] An error occurred deleting the file or folder: \"%s\"", AfxGetThread()->m_nThreadID, ftpFind.GetFileName()); 
				ftpFind.Close(); 
				return FALSE; 
			} 
		} 
	} 
	ftpFind.Close(); 
 
	// get contents of directories 
	for (int i = 0; i < strDirectoryArray.GetSize(); i++) 
	{ 
		if (!RecursiveEmptyDirectory(strDirectoryArray.GetAt(i))) 
			return FALSE; 
	} 
 
	// go back to parent directory 
	if (!m_pFtpConnection->SetCurrentDirectory(strPrevDirectory)) 
	{ 
		return FALSE; 
	} 
 
	GetTraceView()->AddTraceLine(2, "[%d] Deleting Folder \"%s\"", AfxGetThread()->m_nThreadID, lpszPath); 
 
	// remove empty directory  
	if (m_pFtpConnection->RemoveDirectory(lpszPath)) 
	{ 
		GetTraceView()->AddTraceLine(1, "[%d] \"%s\" successfully deleted", AfxGetThread()->m_nThreadID, lpszPath); 
	} 
	else 
	{ 
		GetTraceView()->AddTraceLine(3, "[%d] %s", AfxGetThread()->m_nThreadID, GetLastResponceInfo("FTP Delete Error", "An error occurred deleting the file or folder: " + CString(lpszPath))); 
		GetTraceView()->AddTraceLine(3, "[%d] An error occurred deleting the file or folder: \"%s\"", AfxGetThread()->m_nThreadID, lpszPath); 
		return FALSE; 
	} 
	return TRUE; 
} 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : UploadFile										*/ 
/* Description   : Upload a file									*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::UploadFile(LPCTSTR lpszFileName, LPCTSTR lpszDestination)  
{ 
	GetTraceView()->AddTraceLine(2, "[%d] Uploading: \"%s\"", AfxGetThread()->m_nThreadID, lpszFileName); 
 
	m_pTransferManager->QueueUpload(m_strServerName, 
									m_FtpSite.m_strLogin, 
									m_FtpSite.m_strPassword, 
									lpszFileName, 
									lpszDestination, 
									m_strCurrentDirectory, 
									m_dwTransferType, 
									m_FtpSite.m_nRetries, 
									m_FtpSite.m_nRetryDelay, 
									m_FtpSite.m_nPort, 
									m_FtpSite.m_bUsePASVMode); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : IsStillConnected									*/ 
/* Description   : Are we still connected to the server?			*/ 
/*																	*/ 
/********************************************************************/ 
BOOL CMainFrame::IsStillConnected() 
{ 
	if (!m_pFtpConnection) 
		return FALSE; 
 
	CString strDirName; 
	if (m_pFtpConnection->GetCurrentDirectory(strDirName)) 
	{ 
		GetTraceView()->AddTraceLine(0, "[%d] FTP status: Connected.", AfxGetThread()->m_nThreadID); 
		return TRUE; 
	} 
 
	// close connection 
	m_pFtpConnection->Close(); 
	delete m_pFtpConnection; 
	m_pFtpConnection = NULL; 
 
	GetTraceView()->AddTraceLine(0, "[%d] FTP status: Connection has been closed.", AfxGetThread()->m_nThreadID); 
	return FALSE; 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnDownloadFinished								*/ 
/* Description   : Download has finished							*/ 
/*																	*/ 
/********************************************************************/ 
LRESULT CMainFrame::OnDownloadFinished(WPARAM wParam, LPARAM lParam) 
{ 
	GetTraceView()->AddTraceLine((int)wParam, (LPCTSTR)lParam); 
	return 0; 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnUploadFinished									*/ 
/* Description   : Upload has finished								*/ 
/*																	*/ 
/********************************************************************/ 
LRESULT CMainFrame::OnUploadFinished(WPARAM wParam, LPARAM lParam) 
{ 
	GetTraceView()->AddTraceLine((int)wParam, (LPCTSTR)lParam); 
	return 0; 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnFileRename										*/ 
/* Description   : Rename item										*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnFileRename()  
{ 
	// get selected item 
	int nIndex = GetFtpListView()->GetListCtrl().GetNextItem(-1, LVNI_ALL | LVNI_SELECTED);  
	if (nIndex != -1) 
	{ 
		m_strOldName = GetFtpListView()->GetListCtrl().GetItemText(nIndex, 0); 
 
		// Make sure the focus is set to the list view control. 
		GetFtpListView()->GetListCtrl().SetFocus(); 
		GetFtpListView()->GetListCtrl().EditLabel(nIndex); 
	} 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnEndlabeledit									*/ 
/* Description   : Finished editing file or directory name.			*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult)  
{ 
	LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR; 
	 
	if ((pDispInfo->item.pszText) && (m_pFtpConnection)) 
	{ 
		if (m_bNewFolderMode) 
		{ 
			GetTraceView()->AddTraceLine(2, "[%d] Creating New Folder \"%s\"", AfxGetThread()->m_nThreadID, pDispInfo->item.pszText); 
			if (m_pFtpConnection->CreateDirectory(pDispInfo->item.pszText)) 
			{ 
				GetFtpListView()->SetFileName(pDispInfo->item.iItem, pDispInfo->item.pszText); 
 
				m_hCurrentTreeItem = GetFtpTreeView()->GetTreeCtrl().GetSelectedItem(); 
				int nIcon = GetIconIndex("Desktop", TRUE); 
				HTREEITEM hItem = GetFtpTreeView()->GetTreeCtrl().InsertItem(pDispInfo->item.pszText, nIcon, nIcon, m_hCurrentTreeItem); 
				GetTraceView()->AddTraceLine(1, "[%d] \"%s\" folder successfully created", AfxGetThread()->m_nThreadID, pDispInfo->item.pszText); 
			} 
			else 
			{ 
				GetFtpListView()->GetListCtrl().DeleteItem(pDispInfo->item.iItem); 
				GetTraceView()->AddTraceLine(3, "[%d] %s", AfxGetThread()->m_nThreadID, GetLastResponceInfo("FTP Folder Error", "An error occurred creating a new folder: " + CString(pDispInfo->item.pszText))); 
				GetTraceView()->AddTraceLine(3, "[%d] An error occurred creating a new folder:: \"%s\"", AfxGetThread()->m_nThreadID, pDispInfo->item.pszText); 
			} 
		} 
		else 
		{ 
			GetTraceView()->AddTraceLine(2, "[%d] Renaming \"%s\" to \"%s\"", AfxGetThread()->m_nThreadID, m_strOldName, pDispInfo->item.pszText); 
			if (m_pFtpConnection->Rename(m_strOldName, pDispInfo->item.pszText)) 
			{ 
				GetFtpListView()->SetFileName(pDispInfo->item.iItem, pDispInfo->item.pszText); 
 
				m_hCurrentTreeItem = GetFtpTreeView()->GetTreeCtrl().GetSelectedItem(); 
	//			GetFtpTreeView()->GetTreeCtrl().Expand(m_hCurrentTreeItem, TVE_EXPAND); 
				HTREEITEM hItem = GetFtpTreeView()->FindItem(m_strOldName, m_hCurrentTreeItem); 
				GetFtpTreeView()->GetTreeCtrl().SetItemText(hItem, pDispInfo->item.pszText); 
				GetTraceView()->AddTraceLine(1, "[%d] \"%s\" successfully renamed", AfxGetThread()->m_nThreadID, m_strOldName); 
			} 
			else 
			{ 
				GetTraceView()->AddTraceLine(3, "[%d] %s", AfxGetThread()->m_nThreadID, GetLastResponceInfo("FTP Rename Error", "An error occurred renaming the file or folder: " + m_strOldName)); 
				GetTraceView()->AddTraceLine(3, "[%d] An error occurred renaming the file or folder: \"%s\"", AfxGetThread()->m_nThreadID, m_strOldName); 
			} 
		} 
	} 
	else 
	{ 
		if (m_bNewFolderMode) 
		{ 
			m_bNewFolderMode = FALSE; 
			// delete empty item 
			GetFtpListView()->GetListCtrl().DeleteItem(pDispInfo->item.iItem); 
		} 
	} 
//	*pResult = TRUE; 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnFileDelete										*/ 
/* Description   :													*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnFileDelete()  
{ 
	int nIndex = GetFtpListView()->GetListCtrl().GetNextItem(-1, LVNI_ALL | LVNI_SELECTED); 
	if (nIndex == -1) 
		return; 
 
	if (AfxGetApp()->GetProfileInt("Settings", "DeleteConfirmation", 1)) 
	{ 
		CString str; 
		int nCount = GetFtpListView()->GetListCtrl().GetSelectedCount(); 
		if (nCount == 1) 
		{ 
			// is selected item a directory ? 
			if (GetFtpListView()->IsDirectory(nIndex)) 
			{ 
				str = "Are you sure you want to remove the folder '"  
						+ GetFtpListView()->GetListCtrl().GetItemText(nIndex, 0)  
						+ "' and all its contents?"; 
				if (MessageBox(str, "Confirm Folder Delete" , MB_YESNO | MB_ICONQUESTION) == IDNO) 
					return; 
			} 
			else 
			{ 
				str = "Are you sure you want to delete '"  
						+ GetFtpListView()->GetListCtrl().GetItemText(nIndex, 0)  
						+ "'?"; 
				if (MessageBox(str, "Confirm File Delete" , MB_YESNO | MB_ICONQUESTION) == IDNO) 
					return; 
			} 
		} 
		else 
		{ 
			str.Format("Are you sure you want to delete these %d items?", nCount); 
			if (MessageBox(str, "Confirm Multiple File Delete", MB_YESNO | MB_ICONQUESTION) == IDNO) 
				return; 
		} 
	} 
	 
	// delete items 
	while (nIndex != -1) 
	{ 
		CString strName = GetFtpListView()->GetListCtrl().GetItemText(nIndex, 0); 
 
		// is selected item a directory ? 
		if (GetFtpListView()->IsDirectory(nIndex)) 
		{ 
			// delete folder and all of its contents 
			if (RecursiveEmptyDirectory(strName)) 
			{ 
				// delete folder from listview 
				GetFtpListView()->GetListCtrl().DeleteItem(nIndex); 
 
				// delete folder from tree too 
				m_hCurrentTreeItem = GetFtpTreeView()->GetTreeCtrl().GetSelectedItem(); 
				GetFtpTreeView()->GetTreeCtrl().Expand(m_hCurrentTreeItem, TVE_EXPAND); 
				HTREEITEM hItem = GetFtpTreeView()->FindItem(strName, m_hCurrentTreeItem); 
				GetFtpTreeView()->GetTreeCtrl().DeleteItem(hItem); 
 
				nIndex--; 
			} 
		} 
		else 
		{ 
			GetTraceView()->AddTraceLine(2, "[%d] Deleting file \"%s\"", AfxGetThread()->m_nThreadID, strName); 
			// delete file 
			if (m_pFtpConnection->Remove(strName)) 
			{ 
				// delete file from listview 
				GetFtpListView()->GetListCtrl().DeleteItem(nIndex); 
				GetTraceView()->AddTraceLine(1, "[%d] \"%s\" successfully deleted", AfxGetThread()->m_nThreadID, strName); 
				nIndex--; 
			} 
			else 
			{ 
				GetTraceView()->AddTraceLine(3, "[%d] %s", AfxGetThread()->m_nThreadID, GetLastResponceInfo("FTP Delete Error", "An error occurred deleting the file or folder: " + strName)); 
				GetTraceView()->AddTraceLine(3, "[%d] An error occurred deleting the file or folder: \"%s\"", AfxGetThread()->m_nThreadID, strName); 
			} 
		} 
		nIndex = GetFtpListView()->GetListCtrl().GetNextItem(nIndex, LVNI_ALL | LVNI_SELECTED); 
	}	 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnFileExplore									*/ 
/* Description   : Explore directory.								*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnFileExplore()  
{ 
	// get selected item 
	int nIndex = GetFtpListView()->GetListCtrl().GetNextItem(-1, LVNI_ALL | LVNI_SELECTED);  
	if (nIndex != -1) 
	{ 
		CString strFile = GetFtpListView()->GetListCtrl().GetItemText(nIndex, 0); 
 
		// is selected item a directory ? 
		if (GetFtpListView()->IsDirectory(nIndex)) 
		{ 
			ChangeDirectory(strFile); 
		} 
		else 
		{ 
			OnFileDownload(); 
		} 
	} 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnViewUponelevel									*/ 
/* Description   :													*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnViewUponelevel()  
{ 
	m_hCurrentTreeItem = GetFtpTreeView()->GetTreeCtrl().GetSelectedItem();		 
	HTREEITEM hParent = GetFtpTreeView()->GetTreeCtrl().GetParentItem(m_hCurrentTreeItem); 
	if (hParent != NULL) 
		GetFtpTreeView()->GetTreeCtrl().SelectItem(hParent); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : GetLastResponceInfo								*/ 
/* Description   : Get last responce from server.					*/ 
/*																	*/ 
/********************************************************************/ 
CString CMainFrame::GetLastResponceInfo(LPCTSTR lpszCaption, LPCTSTR lpszExtraInfo) 
{ 
	DWORD dwLength = 255, dwError; 
	CString strInfo; 
	InternetGetLastResponseInfo(&dwError, strInfo.GetBuffer(dwLength), &dwLength); 
	strInfo.ReleaseBuffer(); 
	strInfo.Remove('\n'); 
	strInfo.Remove('\r'); 
	 
	BOOL bShowMessageBox = AfxGetApp()->GetProfileInt("Settings", "ShowMessageBox", 1); 
 
	if (!m_bShowTrace || bShowMessageBox) 
	{ 
		CString strText; 
		if (lpszExtraInfo != NULL) 
		{ 
			strText = lpszExtraInfo; 
			strText += "\r\n\r\nDetails:\r\n"; 
		} 
		strText += strInfo; 
		MessageBox(strText, lpszCaption, MB_OK | MB_ICONSTOP); 
 
	} 
	return strInfo; 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnFileDownload									*/ 
/* Description   : Download selected file or directory				*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnFileDownload()  
{ 
	DoFileDownload(FALSE); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnFileDownloadto									*/ 
/* Description   : Download selected file or directory to specific	*/ 
/*				   path.											*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnFileDownloadto()  
{ 
	DoFileDownload(TRUE); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : DoFileDownload									*/ 
/* Description   : Download selected file or directory to specific	*/ 
/*				   path.											*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::DoFileDownload(BOOL bShowFileDialog) 
{ 
	// get selected items 
	int nIndex = GetFtpListView()->GetListCtrl().GetNextItem(-1, LVNI_ALL | LVNI_SELECTED);  
	int nCount = GetFtpListView()->GetListCtrl().GetSelectedCount(); 
	 
	BOOL bYesToAll = FALSE; 
 
	// download items 
	while (nIndex != -1) 
	{ 
		// get filename 
		CString strFile = GetFtpListView()->GetListCtrl().GetItemText(nIndex, 0); 
 
		CString strLocalName; 
		if (bShowFileDialog) 
		{ 
			CFileDialog dlg(FALSE, strFile, strFile, OFN_NOVALIDATE | OFN_HIDEREADONLY, "All Files (*.*)|*.*||", this); 
		 
			dlg.m_ofn.lpstrTitle = "Download to"; 
			 
			if (dlg.DoModal() == IDOK) 
			{ 
				strLocalName = dlg.GetPathName(); 
			} 
			else 
			{ 
				// canceled 
				return; 
			} 
		} 
		else 
		{ 
			strLocalName = m_FtpSite.m_strLocalPath + "\\" + strFile; 
		} 
 
		int nResult = IDYES; 
		// A quick'n'easy way to see if a file or directory exists. 
		DWORD dwAttributes = GetFileAttributes(strLocalName); 
		if ((dwAttributes != 0xFFFFFFFF) && !bYesToAll) 
		{ 
			// is selected item a directory ? 
			if (GetFtpListView()->IsDirectory(nIndex)) 
			{ 
				CReplaceFolderDlg dlg; 
			 
				dlg.m_nFileCount = nCount; 
				dlg.m_strFileName = strFile; 
				// show confirm dialog 
				nResult = dlg.DoModal(); 
			} 
			else 
			{ 
				CReplaceFileDlg dlg; 
			 
				dlg.m_nFileCount = nCount; 
				dlg.m_strFileName = strFile; 
 
				WIN32_FILE_ATTRIBUTE_DATA fad; 
				// get local file attributes 
				if (GetFileAttributesEx(strLocalName, GetFileExInfoStandard, &fad)) 
				{ 
					CTime localLastWrite(fad.ftLastWriteTime); 
					dlg.m_strPropertiesOld.Format("%s\r\nmodified: %s", GetFtpListView()->FormatSize(fad.nFileSizeLow), localLastWrite.Format("%#c")); 
				} 
				 
				// get remote file attributes 
				CFtpListView::ITEMINFO* pItem = (CFtpListView::ITEMINFO*)GetFtpListView()->GetListCtrl().GetItemData(nIndex); 
				CTime remoteLastWrite(pItem->ftLastWriteTime); 
				dlg.m_strPropertiesNew.Format("%s\r\nmodified: %s", GetFtpListView()->FormatSize(pItem->nFileSize), remoteLastWrite.Format("%#c")); 
				 
				// show confirm dialog 
				nResult = dlg.DoModal(); 
			} 
			// check result code 
			if (nResult == IDYES) 
			{ 
			} 
			else 
			if (nResult == IDYESTOALL) 
			{ 
				bYesToAll = TRUE; 
			} 
			else 
			if (nResult == IDNO) 
			{ 
				nIndex = GetFtpListView()->GetListCtrl().GetNextItem(nIndex, LVNI_ALL | LVNI_SELECTED); 
				continue; 
			} 
			else 
			{ 
				// quit download 
				return; 
			} 
		} 
		// is selected item a directory ? 
		if (GetFtpListView()->IsDirectory(nIndex)) 
		{ 
			CString strCurrentDirectory = m_strCurrentDirectory; 
			strCurrentDirectory.TrimRight('/'); 
			DownloadDirectory(strCurrentDirectory + "/" + strFile, strLocalName); 
		} 
		else 
		{ 
			DWORD dwSize = GetFtpListView()->GetFileSize(nIndex); 
 
			CString strCurrentDirectory = m_strCurrentDirectory; 
			strCurrentDirectory.TrimRight('/'); 
 
			DownloadFile(strCurrentDirectory + "/" + strFile, dwSize, strLocalName); 
		} 
		nIndex = GetFtpListView()->GetListCtrl().GetNextItem(nIndex, LVNI_ALL | LVNI_SELECTED); 
	}	 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnUpdateActions									*/ 
/* Description   : 													*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnUpdateActions(CCmdUI* pCmdUI)  
{ 
	int nIndex = GetFtpListView()->GetListCtrl().GetNextItem(-1, LVNI_ALL | LVNI_SELECTED);  
	pCmdUI->Enable(m_pFtpConnection	!= NULL && nIndex != -1); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnFileProperties									*/ 
/* Description   : Show properties of file/directory				*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnFileProperties()  
{ 
	// get selected item 
	int nIndex = GetFtpListView()->GetListCtrl().GetNextItem(-1, LVNI_ALL | LVNI_SELECTED);  
	if (nIndex != -1) 
	{ 
		CPropertySheet sheet("Properties", this); 
		CGeneralPage page; 
	 
		page.m_bIsDirectory = GetFtpListView()->IsDirectory(nIndex); 
		page.m_strFileName = GetFtpListView()->GetListCtrl().GetItemText(nIndex, 0); 
		page.m_strSize.Format("%s (%s bytes)",	GetFtpListView()->GetListCtrl().GetItemText(nIndex, 1),  
												FormatWithCommas(GetFtpListView()->GetFileSize(nIndex))); 
		page.m_strType = GetFtpListView()->GetListCtrl().GetItemText(nIndex, 2); 
		page.m_strDate = GetFtpListView()->GetListCtrl().GetItemText(nIndex, 3); 
		page.m_strLocation = m_strCurrentDirectory; 
		page.m_strLocation.TrimRight("/"); 
		page.m_strLocation += "/" + GetFtpListView()->GetListCtrl().GetItemText(nIndex, 0); 
		sheet.AddPage(&page); 
		sheet.DoModal(); 
	} 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnViewRefresh									*/ 
/* Description   : Refreshes the contents of the current page.		*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnViewRefresh()  
{ 
	ExploreDirectory(m_strCurrentDirectory, m_hCurrentTreeItem, TRUE); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnViewGoTo										*/ 
/* Description   : Go to specific folder							*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnViewGoTo()  
{ 
	CGoToFolderDlg dlg; 
	 
	if (dlg.DoModal() == IDOK) 
	{ 
		if (dlg.m_strFolder.IsEmpty()) 
			return; 
 
		// make unix style 
		dlg.m_strFolder.Replace('\\', '/'); 
		if (dlg.m_strFolder.Left(1) == '/') 
		{ 
			// it's rooted 
		} 
		else 
		{ 
			// append current dir 
			dlg.m_strFolder = m_strCurrentDirectory + "/" + dlg.m_strFolder; 
		} 
		 
		GetTraceView()->AddTraceLine(2, "[%d] Changing folder: \"%s\"", AfxGetThread()->m_nThreadID, dlg.m_strFolder); 
		// does directory exist ? 
		if (m_pFtpConnection->SetCurrentDirectory(dlg.m_strFolder)) 
		{ 
			PopulateTree(dlg.m_strFolder, TRUE); 
		} 
		else 
		{ 
			GetTraceView()->AddTraceLine(3, "[%d] %s", AfxGetThread()->m_nThreadID, GetLastResponceInfo("FTP Folder Error", "An error occurred opening the folder: " + dlg.m_strFolder)); 
			GetTraceView()->AddTraceLine(3, "[%d] An error occurred opening the folder: \"%s\"", AfxGetThread()->m_nThreadID, dlg.m_strFolder); 
		} 
	} 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnFileNewfolder									*/ 
/* Description   : Create new folder on FTP server					*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnFileNewfolder()  
{ 
	// create empty item (we set the text later, just in case the users doesn't change the text) 
	int nIndex = GetFtpListView()->AddNewFolder(0, "redloF weN"); 
	if (nIndex != -1) 
	{ 
		GetFtpListView()->GetListCtrl().EnsureVisible(nIndex, FALSE); 
		// Make sure the focus is set to the list view control. 
		GetFtpListView()->GetListCtrl().SetFocus(); 
		m_bNewFolderMode = TRUE; 
		GetFtpListView()->GetListCtrl().EditLabel(nIndex); 
		CEdit *pEdit = GetFtpListView()->GetListCtrl().GetEditControl(); 
		// set the initial folder name 
		if (pEdit) 
		{ 
			pEdit->SetWindowText("New Folder"); 
			pEdit->SetSel(0, -1, TRUE); 
		} 
	} 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnViewByname										*/ 
/* Description   : Sort fileview by name.							*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnViewByname()  
{ 
	GetFtpListView()->Sort(0);		 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnViewBysize										*/ 
/* Description   : Sort fileview by size.							*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnViewBysize()  
{ 
	GetFtpListView()->Sort(1);		 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnViewBytype										*/ 
/* Description   : Sort fileview by type.							*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnViewBytype()  
{ 
	GetFtpListView()->Sort(2); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnViewBydate										*/ 
/* Description   : Sort fileview by date.							*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnViewBydate()  
{ 
	GetFtpListView()->Sort(3); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnUpdateFrameTitle								*/ 
/* Description   : Override to change window caption.				*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnUpdateFrameTitle(BOOL bAddToTitle) 
{ 
	CFrameWnd::OnUpdateFrameTitle(bAddToTitle); 
 
	if (m_pFtpConnection) 
	{ 
		AfxSetWindowText(m_hWnd, m_FtpSite.m_strName + " - " + AfxGetAppName()); 
	} 
	else 
	{ 
		AfxSetWindowText(m_hWnd, "Not Connected - " + CString(AfxGetAppName())); 
	} 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnFileUpload										*/ 
/* Description   : Upload file(s).									*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnFileUpload()  
{ 
	char szFilters[] = "All Files (*.*)|*.*||"; 
	 
	CFileDialog dlg(FALSE, "*", "*.*" , OFN_NOVALIDATE| OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT, szFilters, this); 
	 
	dlg.m_ofn.lpstrTitle = "Upload"; 
	 
	if (dlg.DoModal() == IDOK) 
	{ 
		POSITION pos = dlg.GetStartPosition(); 
		while (pos != NULL) 
		{ 
			CString strPath = dlg.GetNextPathName(pos); 
			if (strPath.Find(":\\\\") == 1 && strPath.GetLength() > 4) 
			{ 
				// this means we have an invalid path that looks like this: 
				// C:\\foo.bmp 
				// We need to cut out the extra slash 
				CString temp; 
				temp = strPath.Left(3); 
				temp += strPath.Mid(4); 
				strPath = temp; 
			} 
			int nPos = strPath.ReverseFind('\\'); 
			UploadFile(strPath, strPath.Mid(nPos+1)); 
		} 
	}		 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnToolsOptions									*/ 
/* Description   : Bring up the options dialog.						*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnToolsOptions()  
{ 
	COptionsSheet propSheet("FTP Wanderer Settings"); 
	propSheet.InitPages(); 
	if (propSheet.DoModal() == IDOK) 
	{ 
		m_pTransferManager->m_nMaximumTransfers = AfxGetApp()->GetProfileInt("Settings", "TransferMax", 10); 
		m_pTransferManager->m_nConnectionTimeout = AfxGetApp()->GetProfileInt("Settings", "ConnectionTimeout", 30); 
		m_pTransferManager->m_bRemoveFailed = AfxGetApp()->GetProfileInt("Settings", "RemoveFailed", 0); 
		TRACE1("Max transfers: %d\n", m_pTransferManager->m_nMaximumTransfers); 
	} 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnToolsAscii										*/ 
/* Description   : Set transfermode to ASCII.						*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnToolsAscii()  
{ 
	m_dwTransferType = FTP_TRANSFER_TYPE_ASCII; 
	AfxGetApp()->WriteProfileInt("Settings", "TransferType", m_dwTransferType);	 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnUpdateToolsAscii								*/ 
/* Description   : Update menu state.								*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnUpdateToolsAscii(CCmdUI* pCmdUI)  
{ 
	pCmdUI->SetCheck(m_dwTransferType == FTP_TRANSFER_TYPE_ASCII); 
} 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnToolsBinary									*/ 
/* Description   : Set transfermode to Binary.						*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnToolsBinary()  
{ 
	m_dwTransferType = FTP_TRANSFER_TYPE_BINARY; 
	AfxGetApp()->WriteProfileInt("Settings", "TransferType", m_dwTransferType); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnUpdateToolsBinary								*/ 
/* Description   : Update menu state.								*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnUpdateToolsBinary(CCmdUI* pCmdUI)  
{ 
	pCmdUI->SetCheck(m_dwTransferType == FTP_TRANSFER_TYPE_BINARY); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnViewTrace										*/ 
/* Description   : Show or hide the trace window.					*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnViewTrace()  
{ 
	m_bShowTrace = !m_bShowTrace; 
	if (m_bShowTrace) 
		m_wndSplitter.ShowRow(); 
	else 
	{ 
		// first set active pane (or it will crash...) 
		m_wndSplitter.SetActivePane(1, 0); 
		m_wndSplitter.HideRow(1); 
	} 
	AfxGetApp()->WriteProfileInt("Settings", "ShowTrace", m_bShowTrace); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnUpdateViewTrace								*/ 
/* Description   : Update menu state.								*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnUpdateViewTrace(CCmdUI* pCmdUI)  
{ 
	pCmdUI->SetCheck(m_bShowTrace);	 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : CreateHotToolBar									*/ 
/* Description   : Create the main toolbar.							*/ 
/*																	*/ 
/********************************************************************/ 
BOOL CMainFrame::CreateHotToolBar() 
{ 
    if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP 
		| CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC /*| CBRS_GRIPPER*/) || 
		!m_wndToolBar.LoadToolBar(IDR_TOOLBAR1)) 
	{ 
		TRACE0("Failed to create toolbar\n"); 
		return FALSE;      // fail to create 
	} 
 
	// Set the text for each button 
	CToolBarCtrl& bar = m_wndToolBar.GetToolBarCtrl(); 
 
	int	nIndex = 0; 
	TBBUTTON tb; 
 
    for (nIndex = m_wndToolBar.GetToolBarCtrl().GetButtonCount() - 1; nIndex >= 0; nIndex--) 
	{ 
		ZeroMemory(&tb, sizeof(TBBUTTON)); 
		m_wndToolBar.GetToolBarCtrl().GetButton(nIndex, &tb); 
 
		// Do we have a separator? 
		if ((tb.fsStyle & TBSTYLE_SEP) ==  TBSTYLE_SEP) 
			continue; 
 
		// Have we got a valid command id? 
		if (tb.idCommand == 0) 
			continue; 
 
		// Get the resource string if there is one. 
		CString strText; 
		LPCTSTR lpszButtonText = NULL; 
		CString	strButtonText(_T("")); 
		_TCHAR	seps[] = _T("\n"); 
 
		strText.LoadString(tb.idCommand); 
 
		if (!strText.IsEmpty()) 
		{ 
			lpszButtonText = _tcstok((LPTSTR)(LPCTSTR)strText, seps); 
 
			while(lpszButtonText) 
			{ 
				strButtonText = lpszButtonText; 
				lpszButtonText = _tcstok(NULL, seps); 
			} 
		} 
 
		if (!strButtonText.IsEmpty()) 
			m_wndToolBar.SetButtonText(nIndex, strButtonText); 
	} 
 
	// Resize the buttons so that the text will fit. 
	CRect rc(0, 0, 0, 0); 
	CSize sizeMax(0, 0); 
 
	for (nIndex = m_wndToolBar.GetToolBarCtrl().GetButtonCount() - 1; nIndex >= 0; nIndex--) 
	{ 
		m_wndToolBar.GetToolBarCtrl().GetItemRect(nIndex, rc); 
 
		rc.NormalizeRect(); 
		sizeMax.cx = __max(rc.Size().cx, sizeMax.cx); 
		sizeMax.cy = __max(rc.Size().cy, sizeMax.cy); 
	} 
	m_wndToolBar.SetSizes(sizeMax, CSize(20,20)); 
 
    // Set up hot bar image lists. 
    CImageList	imageList; 
	CBitmap		bitmap; 
 
    // Create and set the normal toolbar image list. 
	bitmap.LoadBitmap(IDB_TOOLBAR_COLD); 
	imageList.Create(26, 20, ILC_COLORDDB|ILC_MASK, 15, 1); 
	imageList.Add(&bitmap, RGB(255,0,255)); 
	m_wndToolBar.SendMessage(TB_SETIMAGELIST, 0, (LPARAM)imageList.m_hImageList); 
	imageList.Detach(); 
	bitmap.Detach(); 
     
    // Create and set the hot toolbar image list. 
	bitmap.LoadBitmap(IDB_TOOLBAR_HOT); 
	imageList.Create(26, 20, ILC_COLORDDB|ILC_MASK, 15, 1); 
	imageList.Add(&bitmap, RGB(255,0,255)); 
	m_wndToolBar.SendMessage(TB_SETHOTIMAGELIST, 0, (LPARAM)imageList.m_hImageList); 
	imageList.Detach(); 
	bitmap.Detach(); 
 
	m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY); 
    return TRUE; 
} 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnClose											*/ 
/* Description   : Save window position.							*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnClose()  
{ 
	if (AfxGetApp()->GetProfileInt("Settings", "SavePosition", 1)) 
	{ 
		// Save main window position 
		WINDOWPLACEMENT wp; 
		GetWindowPlacement(&wp); 
		AfxGetApp()->WriteProfileInt("Settings", "FrameStatus", wp.showCmd); 
		AfxGetApp()->WriteProfileInt("Settings", "FrameTop",    wp.rcNormalPosition.top); 
		AfxGetApp()->WriteProfileInt("Settings", "FrameLeft",   wp.rcNormalPosition.left); 
		AfxGetApp()->WriteProfileInt("Settings", "FrameBottom", wp.rcNormalPosition.bottom); 
		AfxGetApp()->WriteProfileInt("Settings", "FrameRight",  wp.rcNormalPosition.right); 
	}	 
	SaveBarState("QuickConnectState"); 
	CFrameWnd::OnClose(); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : PreCreateWindow									*/ 
/* Description   : Restore old window position.						*/ 
/*																	*/ 
/********************************************************************/ 
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)  
{ 
	int s, t, b, r, l; 
 
	if (AfxGetApp()->GetProfileInt("Settings", "SavePosition", 1)) 
	{ 
		// only restore if there is a previously saved position 
		if ( -1 != (s = AfxGetApp()->GetProfileInt("Settings", "FrameStatus",   -1)) && 
			 -1 != (t = AfxGetApp()->GetProfileInt("Settings", "FrameTop",      -1)) && 
			 -1 != (l = AfxGetApp()->GetProfileInt("Settings", "FrameLeft",     -1)) && 
			 -1 != (b = AfxGetApp()->GetProfileInt("Settings", "FrameBottom",   -1)) && 
			 -1 != (r = AfxGetApp()->GetProfileInt("Settings", "FrameRight",    -1)) 
		   )  
		{ 
			// restore the window's status 
			AfxGetApp()->m_nCmdShow = s; 
 
			// restore the window's width and height 
			cs.cx = r - l; 
			cs.cy = b - t; 
 
			// the following correction is needed when the taskbar is 
			// at the left or top and it is not "auto-hidden" 
			RECT workArea; 
			SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0); 
			l += workArea.left; 
			t += workArea.top; 
 
			// make sure the window is not completely out of sight 
			int max_x = GetSystemMetrics(SM_CXSCREEN) - 
							GetSystemMetrics(SM_CXICON); 
			int max_y = GetSystemMetrics(SM_CYSCREEN) - 
							GetSystemMetrics(SM_CYICON); 
			cs.x = min(l, max_x); 
			cs.y = min(t, max_y); 
		} 
	} 
	return CFrameWnd::PreCreateWindow(cs); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnViewTransfermanager							*/ 
/* Description   : Show or hide the transfer manager.				*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnViewTransfermanager()  
{ 
	m_bShowTransferManager = !m_pTransferManager->IsWindowVisible(); 
	if (m_bShowTransferManager) 
		m_pTransferManager->ShowWindow(SW_SHOW); 
	else 
		m_pTransferManager->ShowWindow(SW_HIDE); 
	AfxGetApp()->WriteProfileInt("Settings", "ShowTransferManager", m_bShowTransferManager); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnUpdateViewTransfermanager						*/ 
/* Description   : Update menu state.								*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnUpdateViewTransfermanager(CCmdUI* pCmdUI)  
{ 
	pCmdUI->SetCheck(m_pTransferManager->IsWindowVisible());	 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnDestroy										*/ 
/* Description   : Called when CMainFrame is being destroyed.		*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnDestroy()  
{ 
	CFrameWnd::OnDestroy(); 
 
	// destroy transfer manager 
	m_pTransferManager->DestroyWindow(); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : AddNewFile										*/ 
/* Description   : Called when file is succesfully uploaded.		*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::AddNewFile(LPCTSTR lpszFileName, DWORD dwFileLength, LPCTSTR lpszCurrentDirectory) 
{ 
	// still in same directory ? 
	if (m_strCurrentDirectory.Compare(lpszCurrentDirectory) == 0) 
	{ 
		GetFtpListView()->AddNewFile(GetFtpListView()->GetListCtrl().GetItemCount(), lpszFileName, dwFileLength); 
	} 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : AddNewFolder										*/ 
/* Description   : Called when file is succesfully created.			*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::AddNewFolder(LPCTSTR lpszFileName, LPCTSTR lpszCurrentDirectory) 
{ 
	// still in same directory ? 
	if (m_strCurrentDirectory.Compare(lpszCurrentDirectory) == 0) 
	{ 
		GetFtpListView()->AddNewFolder(GetFtpListView()->GetListCtrl().GetItemCount(), lpszFileName); 
		m_hCurrentTreeItem = GetFtpTreeView()->GetTreeCtrl().GetSelectedItem(); 
		int nIcon = GetIconIndex("Desktop", TRUE); 
		HTREEITEM hItem = GetFtpTreeView()->GetTreeCtrl().InsertItem(lpszFileName, nIcon, nIcon, m_hCurrentTreeItem); 
	} 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnEditSelectAll									*/ 
/* Description   : Select all items in the list						*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnEditSelectAll()  
{ 
	for (int i = 0; i < GetFtpListView()->GetListCtrl().GetItemCount(); i++) 
	{ 
		GetFtpListView()->GetListCtrl().SetItemState(i, LVIS_SELECTED | LVIS_FOCUSED , LVIS_SELECTED | LVIS_FOCUSED); 
	} 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnEditInvertselection							*/ 
/* Description   : Invert selection									*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnEditInvertselection()  
{ 
	for (int i = 0; i < GetFtpListView()->GetListCtrl().GetItemCount(); i++) 
	{ 
		if (GetFtpListView()->GetListCtrl().GetItemState(i, LVNI_SELECTED)) 
			GetFtpListView()->GetListCtrl().SetItemState(i, ~LVIS_SELECTED, LVIS_SELECTED); 
		else 
			GetFtpListView()->GetListCtrl().SetItemState(i, LVIS_SELECTED, LVIS_SELECTED); 
	} 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnNotify											*/ 
/* Description   : Handle notifications								*/ 
/*																	*/ 
/********************************************************************/ 
BOOL CMainFrame::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)  
{ 
	LPNMHDR pNMHDR = (LPNMHDR)lParam; 
 
	if (!m_bInitialized) 
		return CFrameWnd::OnNotify(wParam, lParam, pResult); 
 
	// process notification from list control 
	if (pNMHDR->hwndFrom == GetFtpListView()->m_hWnd) 
    { 
		LPNMLISTVIEW pListView = (LPNMLISTVIEW)lParam; 
 
		switch (pListView->hdr.code) 
		{ 
			case NM_DBLCLK: 
       			OnFileExplore(); 
        	    break; 
			case LVN_ENDLABELEDIT: 
				OnEndlabeledit(pNMHDR, pResult); 
				break; 
		} 
	} 
 
    // process notification from tree control 
	if (pNMHDR->hwndFrom == GetFtpTreeView()->m_hWnd) 
    { 
		LPNMTREEVIEW pTreeView = (LPNMTREEVIEW)lParam; 
 
		switch (pTreeView->hdr.code) 
		{ 
			case TVN_SELCHANGED: 
       			OnSelchanged(pNMHDR, pResult); 
        	    break; 
		} 
	} 
 
	return CFrameWnd::OnNotify(wParam, lParam, pResult); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnFileConnectionwizard							*/ 
/* Description   : Activate Connection wizard						*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnFileConnectionwizard()  
{ 
	CBitmap bmpHeader, bmpWatermark; 
 
	VERIFY(bmpHeader.LoadBitmap(IDB_BANNER)); 
	VERIFY(bmpWatermark.LoadBitmap(IDB_WATERMARK)); 
	 
	// show windows 2000-like wizard 
	CWizardSheet wizSheet("Connection Wizard", this, 0, bmpWatermark, NULL, bmpHeader); 
	wizSheet.m_psh.hInstance = ::GetModuleHandle(NULL); 
	if (wizSheet.DoModal() == ID_WIZFINISH) 
	{ 
		CConnectDlg dlg; 
 
		CFtpSite ftpSite; 
 
		ftpSite.m_bUsePASVMode = AfxGetApp()->GetProfileInt("Settings", "DefaultUsePASVMode", 0); 
		ftpSite.m_nPort = 21; 
		ftpSite.m_nRetries = AfxGetApp()->GetProfileInt("Settings", "DefaultRetries", 3); 
		ftpSite.m_nRetryDelay = AfxGetApp()->GetProfileInt("Settings", "DefaultRetryDelay", 10); 
		ftpSite.m_strAddress = wizSheet.m_Page2.m_strHostAddress; 
		ftpSite.m_strDescription = ""; 
		ftpSite.m_strLocalPath = wizSheet.m_Page4.m_strLocalFolder; 
		ftpSite.m_strLogin = wizSheet.m_Page3.m_strUserName; 
		ftpSite.m_strPassword = wizSheet.m_Page3.m_strPassword; 
		ftpSite.m_strName = wizSheet.m_Page1.m_strProfileName; 
		ftpSite.m_strRemotePath = ""; 
		 
		dlg.AddSite(ftpSite); 
 
		// connect to the site 
		if (wizSheet.m_PageFinish.m_bConnectNow) 
		{ 
			Connect(wizSheet.m_Page1.m_strProfileName); 
		} 
	} 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnQuickconnect									*/ 
/* Description   : Handle Quick Connect command						*/ 
/*																	*/ 
/********************************************************************/ 
void CMainFrame::OnQuickconnect()  
{ 
	CString strHost, strUserName, strPassword; 
	 
	m_wndQuickConnect.GetDlgItemText(IDC_HOST, strHost); 
 
	// remove spaces 
	strHost.TrimLeft(); 
	strHost.TrimRight(); 
 
	// do not accept empty host name 
	if (strHost.IsEmpty()) 
		return; 
 
	m_wndQuickConnect.GetDlgItemText(IDC_USERNAME, strUserName); 
	m_wndQuickConnect.GetDlgItemText(IDC_PASSWORD, strPassword); 
	 
	// clear list if SHIFT+OK is pressed 
	if (GetKeyState(VK_SHIFT) < 0) 
	{ 
		m_wndQuickConnect.m_cmbHost.ResetMRU(); 
 
		m_wndQuickConnect.SetDlgItemText(IDC_USERNAME, ""); 
		m_wndQuickConnect.SetDlgItemText(IDC_PASSWORD, ""); 
		return; 
	} 
	else 
	{ 
 
		m_wndQuickConnect.m_cmbHost.AddStringEx(strHost + "|" + strUserName + "," + strPassword); 
	} 
	// make connection with default settings 
	Connect(strHost, strUserName, strPassword); 
}