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);
}