// FileZilla Server - a Windows ftp server // Copyright (C) 2002-2004 - Tim Kosse // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // MainFrm.cpp : Implementierung der Klasse CMainFrame // #include "stdafx.h" #include "FileZilla server.h" #include "misc/led.h" #include "MainFrm.h" #include "../iputils.h" #include "../platform.h" #include "statusview.h" #include "usersdlg.h" #include "GroupsDlg.h" #include "options.h" #include "usersview.h" #include "userslistctrl.h" #include "misc/systemtray.h" #include "offlineaskdlg.h" #include "../version.h" #include "AdminSocket.h" #include "OptionsDlg.h" #include "ConnectDialog.h" #include "mainfrm.h" #include "../defs.h" #include "OutputFormat.h" #if defined(_DEBUG) && !defined(MMGR) #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CMainFrame IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd) BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) //{{AFX_MSG_MAP(CMainFrame) ON_WM_CREATE() ON_WM_SETFOCUS() ON_WM_SIZE() ON_WM_CLOSE() ON_COMMAND(ID_EDIT_SETTINGS, OnEditSettings) ON_COMMAND(ID_ACTIVE, OnActive) ON_UPDATE_COMMAND_UI(ID_ACTIVE, OnUpdateActive) ON_WM_SYSCOMMAND() ON_COMMAND(ID_TRAY_EXIT, OnTrayExit) ON_COMMAND(ID_TRAY_RESTORE, OnTrayRestore) ON_COMMAND(ID_LOCK, OnLock) ON_UPDATE_COMMAND_UI(ID_LOCK, OnUpdateLock) ON_WM_TIMER() ON_COMMAND(ID_USERS, OnMenuEditUsers) ON_COMMAND(ID_GROUPS, OnMenuEditGroups) ON_COMMAND(ID_FILE_CONNECT, OnFileConnect) ON_COMMAND(ID_FILE_DISCONNECT, OnFileDisconnect) ON_UPDATE_COMMAND_UI(ID_FILE_DISCONNECT, OnUpdateFileDisconnect) ON_UPDATE_COMMAND_UI(ID_EDIT_SETTINGS, OnUpdateEditSettings) ON_UPDATE_COMMAND_UI(ID_MENU_EDIT_USERS, OnUpdateMenuEditUsers) ON_UPDATE_COMMAND_UI(ID_MENU_EDIT_GROUPS, OnUpdateMenuEditGroups) ON_UPDATE_COMMAND_UI(ID_USERS, OnUpdateUsers) ON_UPDATE_COMMAND_UI(ID_GROUPS, OnUpdateGroups) ON_COMMAND(ID_MENU_EDIT_USERS, OnMenuEditUsers) ON_COMMAND(ID_MENU_EDIT_GROUPS, OnMenuEditGroups) ON_COMMAND(ID_USERLISTTOOLBAR_DISPLAYLOGICAL, OnDisplayLogicalNames) ON_COMMAND(ID_USERLISTTOOLBAR_DISPLAYPHYSICAL, OnDisplayPhysicalNames) ON_UPDATE_COMMAND_UI(ID_USERLISTTOOLBAR_DISPLAYLOGICAL, OnUpdateDisplayLogicalNames) ON_UPDATE_COMMAND_UI(ID_USERLISTTOOLBAR_DISPLAYPHYSICAL, OnUpdateDisplayPhysicalNames) ON_COMMAND(ID_USERLISTTOOLBAR_SORT, OnDisplaySortMenu) ON_NOTIFY(TBN_DROPDOWN, AFX_IDW_TOOLBAR, OnToolbarDropDown) ON_COMMAND(ID_DISPLAY_SORTBYUSERID, OnDisplaySortByUserid) ON_COMMAND(ID_DISPLAY_SORTBYACCOUNT, OnDisplaySortByAccount) ON_COMMAND(ID_DISPLAY_SORTBYIP, OnDisplaySortByIP) ON_UPDATE_COMMAND_UI(ID_DISPLAY_SORTBYUSERID, OnUpdateDisplaySortByUserid) ON_UPDATE_COMMAND_UI(ID_DISPLAY_SORTBYACCOUNT, OnUpdateDisplaySortByAccount) ON_UPDATE_COMMAND_UI(ID_DISPLAY_SORTBYIP, OnUpdateDisplaySortByIP) ON_WM_DESTROY() //}}AFX_MSG_MAP ON_WM_ERASEBKGND() END_MESSAGE_MAP() static UINT indicators[] = { ID_SEPARATOR, // Statusleistenanzeige ID_INDICATOR_RECVCOUNT, ID_INDICATOR_RECVRATE, ID_INDICATOR_SENDCOUNT, ID_INDICATOR_SENDRATE, ID_INDICATOR_RECVLED, ID_INDICATOR_SENDLED, ID_SEPARATOR }; ///////////////////////////////////////////////////////////////////////////// // CMainFrame Konstruktion/Zerstörung CMainFrame::CMainFrame(COptions *pOptions) { ASSERT(pOptions); s_winClassName = 0; nTrayNotificationMsg_ = RegisterWindowMessage(_T("FileZilla Server Tray Notification Message")); m_bQuit = FALSE; m_nSendCount = 0; m_nRecvCount = 0; m_lastchecktime = GetTickCount(); m_lastreaddiff = 0; m_lastwritediff = 0; m_nOldRecvCount = 0; m_nOldSendCount = 0; m_pOptions = pOptions; m_pAdminSocket = NULL; m_nServerState = 0; m_nEdit = 0; m_pOptionsDlg = 0; m_pUsersDlg = 0; m_pGroupsDlg = 0; m_nReconnectTimerID = 0; m_nReconnectCount = 0; } CMainFrame::~CMainFrame() { delete m_pOptions; m_pOptions = 0; CloseAdminSocket(false); delete [] s_winClassName; //Does seem to crash } int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; SetupTrayIcon(); if (!m_wndReBar.Create(this)) return -1; if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { TRACE0("Could not create Toolbar 1\n"); return -1; // Fehler bei Erstellung } if (!m_wndUserListToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_ALIGN_LEFT | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndUserListToolBar.LoadToolBar(IDR_USERLISTTOOLBAR)) { TRACE0("Could not create Toolbar 2\n"); return -1; // Fehler bei Erstellung } m_wndUserListToolBar.GetToolBarCtrl().SetExtendedStyle(TBSTYLE_EX_DRAWDDARROWS); DWORD dwStyle = m_wndUserListToolBar.GetButtonStyle(m_wndUserListToolBar.CommandToIndex(ID_USERLISTTOOLBAR_SORT)); dwStyle |= TBSTYLE_DROPDOWN; m_wndUserListToolBar.SetButtonStyle(m_wndUserListToolBar.CommandToIndex(ID_USERLISTTOOLBAR_SORT), dwStyle); m_wndReBar.AddBar(&m_wndToolBar); m_wndReBar.AddBar(&m_wndUserListToolBar); m_wndReBar.GetReBarCtrl().MinimizeBand(0); if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) { TRACE0("Statusleiste konnte nicht erstellt werden\n"); return -1; // Fehler bei Erstellung } // The last statusbar pane is a fake one, it has zero width. m_wndStatusBar.SetPaneInfo(7, 0, SBPS_NOBORDERS, 0); CRect rect; m_wndStatusBar.GetItemRect(m_wndStatusBar.CommandToIndex(ID_INDICATOR_RECVLED), rect); //Create the first LED control m_RecvLed.Create(_T(""), WS_VISIBLE|WS_CHILD, rect, &m_wndStatusBar, m_wndStatusBar.CommandToIndex(ID_INDICATOR_RECVLED)); m_RecvLed.SetLed( CLed::LED_COLOR_GREEN, CLed::LED_OFF, CLed::LED_ROUND); //Create the second LED control m_SendLed.Create(_T(""), WS_VISIBLE|WS_CHILD, rect, &m_wndStatusBar, m_wndStatusBar.CommandToIndex(ID_INDICATOR_SENDLED)); m_SendLed.SetLed( CLed::LED_COLOR_RED, CLed::LED_OFF, CLed::LED_ROUND); m_wndStatusBar.GetItemRect(m_wndStatusBar.CommandToIndex(ID_INDICATOR_SENDLED), &rect); m_wndStatusBar.SetPaneInfo(m_wndStatusBar.CommandToIndex(ID_INDICATOR_RECVLED),ID_INDICATOR_RECVLED,SBPS_NOBORDERS,6); m_wndStatusBar.SetPaneInfo(m_wndStatusBar.CommandToIndex(ID_INDICATOR_SENDLED),ID_INDICATOR_SENDLED,SBPS_NOBORDERS,6); ShowStatus(GetVersionString(), 0); ShowStatus(_T("Copyright 2001-2011 by Tim Kosse (tim.kosse@filezilla-project.org)"), 0); m_nTimerID = SetTimer(7777, 10000, 0); m_nRateTimerID = SetTimer(7778, 1000, 0); SetStatusbarText(m_wndStatusBar.CommandToIndex(ID_INDICATOR_SENDCOUNT), _T("0 bytes sent")); SetStatusbarText(m_wndStatusBar.CommandToIndex(ID_INDICATOR_RECVCOUNT), _T("0 bytes received")); SetStatusbarText(m_wndStatusBar.CommandToIndex(ID_INDICATOR_RECVRATE), _T("0 B/s")); SetStatusbarText(m_wndStatusBar.CommandToIndex(ID_INDICATOR_SENDRATE), _T("0 B/s")); CConnectDialog dlg(m_pOptions); if (!m_pOptions->GetOptionVal(IOPTION_ALWAYS) && dlg.DoModal() != IDOK) return 0; m_pAdminSocket = new CAdminSocket(this); ShowStatus("Connecting to server...", 0); DoConnect(); return 0; } ////////////////// // Helper function to register a new window class based on an already // existing window class, but with a different name and icon. // Returns new name if successful; otherwise NULL. // static bool RegisterSimilarClass(LPCTSTR lpszNewClassName, LPCTSTR lpszOldClassName, UINT nIDResource) { // Get class info for old class. // HINSTANCE hInst = AfxGetInstanceHandle(); WNDCLASS wc; if (!::GetClassInfo(hInst, lpszOldClassName, &wc)) { TRACE("Can't find window class %s\n", lpszOldClassName); return false; } // Register new class with same info, but different name and icon. // wc.lpszClassName = lpszNewClassName; wc.hIcon = ::LoadIcon(hInst, MAKEINTRESOURCE(nIDResource)); if (!AfxRegisterClass(&wc)) { TRACE("Unable to register window class%s\n", lpszNewClassName); return false; } return true; } BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { if( !CFrameWnd::PreCreateWindow(cs) ) return FALSE; // ZU ERLEDIGEN: Ändern Sie hier die Fensterklasse oder das Erscheinungsbild, indem Sie // CREATESTRUCT cs modifizieren. cs.lpszClass = AfxRegisterWndClass(0); cs.dwExStyle &= ~WS_EX_CLIENTEDGE; //Change the window class name if (!s_winClassName) { s_winClassName = new TCHAR[_tcslen(_T("FileZilla Server Main Window")) + 1]; _tcscpy(s_winClassName, _T("FileZilla Server Main Window")); RegisterSimilarClass(s_winClassName, cs.lpszClass, IDR_MAINFRAME); } cs.lpszClass = s_winClassName; return TRUE; } ///////////////////////////////////////////////////////////////////////////// // CMainFrame Nachrichten-Handler void CMainFrame::OnSetFocus(CWnd* pOldWnd) { // Fokus an das Ansichtfenster weitergeben } BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) { // andernfalls die Standardbehandlung durchführen return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); } BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) { CRect rect; GetClientRect(rect); // Unterteiltes Fenster erstellen if (!m_wndSplitter.CreateStatic(this, 2, 1)) return FALSE; if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CStatusView), CSize(1, rect.Height() - 150), pContext)) { m_wndSplitter.DestroyWindow(); return FALSE; } m_pStatusPane = (CStatusView*)m_wndSplitter.GetPane(0, 0); if (!m_wndSplitter.CreateView(1, 0, RUNTIME_CLASS(CUsersView), CSize(1, 150), pContext)) { m_wndSplitter.DestroyWindow(); return FALSE; } m_pUsersPane = (CUsersView*) m_wndSplitter.GetPane(1, 0); // Filename display option. GetUsersPane()->m_pListCtrl->SetDisplayPhysicalNames(m_pOptions->GetOptionVal(IOPTION_FILENAMEDISPLAY) != 0); // Set layout options. int sortInfo = (int)m_pOptions->GetOptionVal(IOPTION_USERSORTING); GetUsersPane()->m_pListCtrl->SetSortColumn(sortInfo & 0x0F, sortInfo >> 4); return CFrameWnd::OnCreateClient(lpcs, pContext); } CStatusView* CMainFrame::GetStatusPane() { return m_pStatusPane; } CUsersView* CMainFrame::GetUsersPane() { return m_pUsersPane; } void CMainFrame::OnSize(UINT nType, int cx, int cy) { if (m_wndStatusBar.GetSafeHwnd()) { if (nType!=SIZE_MAXIMIZED) m_wndStatusBar.SetPaneInfo(m_wndStatusBar.CommandToIndex(ID_INDICATOR_SENDLED),ID_INDICATOR_SENDLED,SBPS_NOBORDERS,0); else m_wndStatusBar.SetPaneInfo(m_wndStatusBar.CommandToIndex(ID_INDICATOR_SENDLED),ID_INDICATOR_SENDLED,SBPS_NOBORDERS,10); } if (m_wndSplitter.GetSafeHwnd()) { //Hide the queue if visible m_wndSplitter.HideRow(1, 0); } //Now only the main splitter gets resized CFrameWnd::OnSize(nType, cx, cy); if (m_wndSplitter.GetSafeHwnd()) { //Restore the queue m_wndSplitter.ShowRow(1); } if (m_wndStatusBar.GetSafeHwnd()) { RECT rc; m_wndStatusBar.GetItemRect(m_wndStatusBar.CommandToIndex(ID_INDICATOR_RECVLED), &rc); // Reposition the first LED correctly! m_RecvLed.SetWindowPos(&wndTop, rc.left, rc.top+1, rc.right - rc.left, rc.bottom - rc.top, 0); m_wndStatusBar.GetItemRect(m_wndStatusBar.CommandToIndex(ID_INDICATOR_SENDLED), &rc); // Reposition the second LED correctly! m_SendLed.SetWindowPos(&wndTop, rc.left, rc.top+1, rc.right - rc.left, rc.bottom - rc.top, 0); } } void CMainFrame::OnClose() { CFrameWnd::OnClose(); } void CMainFrame::OnEditSettings() { if (m_nEdit) { MessageBeep(MB_OK); return; } m_nEdit |= 0x04; SendCommand(5, 0, 0); ShowStatus(_T("Retrieving settings, please wait..."), 0); } void CMainFrame::OnActive() { if (m_nServerState & STATE_ONLINE && !(m_nServerState & STATE_MASK_GOOFFLINE)) { if (!GetUsersPane()->m_pListCtrl->GetItemCount()) { if (AfxMessageBox(_T("Do you really want to take the server offline?"), MB_YESNO | MB_ICONQUESTION) != IDYES) return; int nServerState = m_nServerState | STATE_GOOFFLINE_NOW; unsigned char buffer[2]; buffer[0] = nServerState / 256; buffer[1] = nServerState % 256; SendCommand(2, buffer, 2); ShowStatus(_T("Server is going offline..."), 0); return; } else { COfflineAskDlg dlg; if (dlg.DoModal() != IDOK) return; if (dlg.m_nRadio == 2) { int nServerState = m_nServerState | STATE_GOOFFLINE_WAITTRANSFER; unsigned char buffer[2]; buffer[0] = nServerState / 256; buffer[1] = nServerState % 256; SendCommand(2, buffer, 2); ShowStatus(_T("Server is going offline..."), 0); return; } if (dlg.m_nRadio == 1) { int nServerState = m_nServerState | STATE_GOOFFLINE_LOGOUT; unsigned char buffer[2]; buffer[0] = nServerState / 256; buffer[1] = nServerState % 256; SendCommand(2, buffer, 2); ShowStatus(_T("Server is going offline..."), 0); return; } else { int nServerState = m_nServerState | STATE_GOOFFLINE_NOW; unsigned char buffer[2]; buffer[0] = nServerState / 256; buffer[1] = nServerState % 256; SendCommand(2, buffer, 2); ShowStatus(_T("Server is going offline..."), 0); return; } } } else { int nServerState = 1 + (m_nServerState & STATE_LOCKED); unsigned char buffer[2]; buffer[0] = nServerState / 256; buffer[1] = nServerState % 256; SendCommand(2, buffer, 2); } } void CMainFrame::OnUpdateActive(CCmdUI* pCmdUI) { pCmdUI->Enable(m_pAdminSocket && m_pAdminSocket->IsConnected()); pCmdUI->SetCheck(m_nServerState & STATE_ONLINE && !(m_nServerState & STATE_MASK_GOOFFLINE)); } void CMainFrame::OnSysCommand(UINT nID, LPARAM lParam) { CFrameWnd::OnSysCommand(nID, lParam); if (nID == SC_MINIMIZE) ShowWindow(SW_HIDE); else if (nID == SC_RESTORE) ShowWindow(SW_SHOW); } //// SetupTrayIcon ///////////////////////////////////////////////////// // If we're minimized, create an icon in the systray. Otherwise, remove // the icon, if one is present. void CMainFrame::SetupTrayIcon() { m_TrayIcon.Create(0, nTrayNotificationMsg_, _T("FileZilla Server"), 0, IDR_SYSTRAY_MENU); m_TrayIcon.SetIcon(IDI_UNKNOWN); } //// SetupTaskBarButton //////////////////////////////////////////////// // Show or hide the taskbar button for this app, depending on whether // we're minimized right now or not. void CMainFrame::OnTrayExit() { if (!m_bQuit) OnClose(); } void CMainFrame::OnTrayRestore() { ShowWindow(SW_RESTORE); ShowWindow(SW_SHOW); } void CMainFrame::SetIcon() { if (!m_pAdminSocket || !m_pAdminSocket->IsConnected()) { m_TrayIcon.StopAnimation(); m_TrayIcon.SetIcon(IDI_UNKNOWN); } else if (!(m_nServerState & STATE_ONLINE) || m_nServerState & STATE_MASK_GOOFFLINE) { if (!GetUsersPane()->m_pListCtrl->GetItemCount()) { m_TrayIcon.StopAnimation(); m_TrayIcon.SetIcon(IDI_RED); } else { m_TrayIcon.SetIconList(IDI_GREEN, IDI_RED); m_TrayIcon.Animate(500); } } else if (m_nServerState & STATE_LOCKED) { if (GetUsersPane()->m_pListCtrl->GetItemCount()) { m_TrayIcon.SetIconList(IDI_GREEN, IDI_YELLOW); m_TrayIcon.Animate(300); } else { m_TrayIcon.SetIconList(IDI_YELLOW, IDI_RED); m_TrayIcon.Animate(500); } } else { m_TrayIcon.StopAnimation(); m_TrayIcon.SetIcon(GetUsersPane()->m_pListCtrl->GetItemCount()?IDI_GREEN:IDI_YELLOW); } } void CMainFrame::OnLock() { if (!(m_nServerState & STATE_ONLINE) || m_nServerState & STATE_MASK_GOOFFLINE) return; if (m_nServerState & STATE_LOCKED) { int nServerState = m_nServerState & ~STATE_LOCKED; unsigned char buffer[2]; buffer[0] = nServerState / 256; buffer[1] = nServerState % 256; SendCommand(2, buffer, 2); } else { if (AfxMessageBox(_T("Do you really want to lock the server? No new connenctions will be accepted while locked."), MB_YESNO|MB_ICONQUESTION)!=IDYES) return; int nServerState = m_nServerState | STATE_LOCKED; unsigned char buffer[2]; buffer[0] = nServerState / 256; buffer[1] = nServerState % 256; SendCommand(2, buffer, 2); ShowStatus("Server locked", 0); } } void CMainFrame::OnUpdateLock(CCmdUI* pCmdUI) { pCmdUI->Enable(m_pAdminSocket && m_pAdminSocket->IsConnected() && m_nServerState & STATE_ONLINE && !(m_nServerState & STATE_MASK_GOOFFLINE)); pCmdUI->SetCheck((m_nServerState & STATE_LOCKED) ? 1 : 0); } CString FormatSpeed(__int64 diff, const int span) { diff = (__int64)((double)diff * 1000 / span); CString str = _T(""); CString digit; int shift = 0; while (diff >= 10000) { diff /= 10; shift++; } while (diff) { digit = (TCHAR)('0' + static_cast(diff % 10)); str = digit + str; diff /= 10; } if (str == _T("")) str = _T("0"); if (shift % 3) str = str.Left((shift % 3) + 1) + "," + str.Right(str.GetLength() - (shift % 3) - 1); shift += 2; shift /= 3; if (!shift) str += _T(" B/s"); else if (shift == 1) str += _T(" KB/s"); else if (shift == 2) str += _T(" MB/s"); else if (shift == 3) str += _T(" GB/s"); else if (shift == 4) str += _T(" TB/s"); else str = _T("n/a"); //If this happens, you really have a fast connection return str; } void CMainFrame::OnTimer(UINT_PTR nIDEvent) { if (!nIDEvent) return; else if (nIDEvent == m_nTimerID) { SendCommand(8); m_TrayIcon.RefreshIcon(); } else if (nIDEvent == m_nRateTimerID) { const int span = GetTickCount() - m_lastchecktime; m_lastchecktime=GetTickCount(); __int64 diff = m_nSendCount - m_nOldSendCount; m_nOldSendCount = m_nSendCount; if (m_lastwritediff && diff) { __int64 tmp = diff; diff = (diff + m_lastwritediff) / 2; m_lastwritediff = tmp; } else m_lastwritediff = diff; CString writeSpeed = FormatSpeed(diff, span); SetStatusbarText(m_wndStatusBar.CommandToIndex(ID_INDICATOR_SENDRATE), writeSpeed); diff = m_nRecvCount - m_nOldRecvCount; m_nOldRecvCount = m_nRecvCount; if (m_lastreaddiff && diff) { __int64 tmp = diff; diff = (diff + m_lastreaddiff) / 2; m_lastreaddiff = tmp; } else m_lastreaddiff = diff; CString readSpeed = FormatSpeed(diff, span); SetStatusbarText(m_wndStatusBar.CommandToIndex(ID_INDICATOR_RECVRATE), readSpeed); } else if (nIDEvent == m_nReconnectTimerID) { KillTimer(m_nReconnectTimerID); m_nReconnectTimerID = 0; if (m_pAdminSocket) return; m_pAdminSocket = new CAdminSocket(this); ShowStatus("Reconnecting to server...", 0); DoConnect(); } CFrameWnd::OnTimer(nIDEvent); } void CMainFrame::SetStatusbarText(int nIndex,CString str) { m_wndStatusBar.GetStatusBarCtrl().SetText(str,nIndex,0); HFONT hFont = (HFONT)m_wndStatusBar.SendMessage(WM_GETFONT); if (str=="") { str.LoadString(m_wndStatusBar.GetItemID(nIndex)); } CClientDC dcScreen(NULL); HGDIOBJ hOldFont = NULL; if (hFont != NULL) hOldFont = dcScreen.SelectObject(hFont); int cx=dcScreen.GetTextExtent(str).cx; int cxold; unsigned int nID,nStyle; m_wndStatusBar.GetPaneInfo(nIndex,nID,nStyle,cxold); if (cx!=cxold) { if (cxShowStatus(status, nType); } void CMainFrame::ShowStatusRaw(const char *status, int nType) { #ifdef _UNICODE CString msg(ConvFromNetwork(status)); #else CString msg(ConvToLocal(ConvFromNetwork(status))); #endif ShowStatus(msg, nType); } void CMainFrame::ParseReply(int nReplyID, unsigned char *pData, int nDataLength) { switch(nReplyID) { case 0: { ShowStatus(_T("Logged on"), 0); SendCommand(2); unsigned char buffer = USERCONTROL_GETLIST; SendCommand(3, &buffer, 1); } break; case 1: { char *pBuffer = new char[nDataLength]; memcpy(pBuffer, pData+1, nDataLength-1); pBuffer[nDataLength-1] = 0; ShowStatusRaw(pBuffer, *pData); delete [] pBuffer; } break; case 2: m_nServerState = *pData*256 + pData[1]; SetIcon(); break; case 3: { if (nDataLength<2) { ShowStatus(_T("Protocol error: Unexpected data length"), 1); return; } else if (!GetUsersPane()->m_pListCtrl->ParseUserControlCommand(pData, nDataLength)) ShowStatus(_T("Protocol error: Invalid data"), 1); } break; case 5: if (nDataLength == 1) { if (*pData == 0) ShowStatus(_T("Done sending settings."), 0); else if (*pData == 1) ShowStatus(_T("Could not change settings"), 1); break; } ShowStatus(_T("Done retrieving settings"), 0); if (nDataLength<2) ShowStatus(_T("Protocol error: Unexpected data length"), 1); else { if ((m_nEdit & 0x1C) == 0x04) { m_pOptionsDlg = new COptionsDlg(m_pOptions, m_pAdminSocket->IsLocal()); m_nEdit |= 0x08; if (!m_pOptionsDlg->Init(pData, nDataLength)) { ShowStatus(_T("Protocol error: Invalid data"), 1); delete m_pOptionsDlg; m_pOptionsDlg = 0; m_nEdit = 0; } else if (!PostMessage(WM_APP)) { ShowStatus(_T("Can't send window message"), 1); delete m_pOptionsDlg; m_pOptionsDlg = 0; m_nEdit = 0; } } } break; case 6: if (nDataLength == 1) { if (*pData == 0) ShowStatus(_T("Done sending account settings."), 0); else if (*pData == 1) ShowStatus(_T("Could not change account settings"), 1); break; } ShowStatus(_T("Done retrieving account settings"), 0); if (nDataLength<2) ShowStatus(_T("Protocol error: Unexpected data length"), 1); else { if ((m_nEdit & 0x19) == 0x01) { m_pUsersDlg = new CUsersDlg(this, m_pAdminSocket->IsLocal()); m_nEdit |= 0x08; if (!m_pUsersDlg->Init(pData, nDataLength)) { ShowStatus(_T("Protocol error: Invalid data"), 1); delete m_pUsersDlg; m_pUsersDlg = 0; m_nEdit = 0; break; } else if (!PostMessage(WM_APP)) { ShowStatus(_T("Can't send window message"), 1); delete m_pUsersDlg; m_pUsersDlg = 0; m_nEdit = 0; } } if ((m_nEdit & 0x1A) == 0x02) { m_pGroupsDlg = new CGroupsDlg(this, m_pAdminSocket->IsLocal()); m_nEdit |= 0x08; if (!m_pGroupsDlg->Init(pData, nDataLength)) { ShowStatus(_T("Protocol error: Invalid data"), 1); delete m_pGroupsDlg; m_pGroupsDlg = 0; m_nEdit = 0; break; } else if (!PostMessage(WM_APP)) { ShowStatus(_T("Can't send window message"), 1); delete m_pGroupsDlg; m_pGroupsDlg = 0; m_nEdit = 0; } } } break; case 8: break; default: { CString str; str.Format(_T("Protocol error: Unexpected reply id (%d)."), nReplyID); ShowStatus(str, 1); break; } } } void CMainFrame::ParseStatus(int nStatusID, unsigned char *pData, int nDataLength) { switch(nStatusID) { case 1: { char *pBuffer = new char[nDataLength]; memcpy(pBuffer, pData+1, nDataLength-1); pBuffer[nDataLength-1] = 0; ShowStatusRaw(pBuffer, *pData); delete [] pBuffer; } break; case 2: m_nServerState = *pData*256 + pData[1]; SetIcon(); break; case 3: { if (nDataLength<2) { ShowStatus(_T("Protocol error: Unexpected data length"), 1); return; } else if (!GetUsersPane()->m_pListCtrl->ParseUserControlCommand(pData, nDataLength)) ShowStatus(_T("Protocol error: Invalid data"), 1); } break; case 4: { if (nDataLength < 10) { ShowStatus(_T("Protocol error: Unexpected data length"), 1); return; } CString msg; char *buffer = new char[nDataLength - 9 + 1]; unsigned char *p = pData + 9; char *q = buffer; int pos = 0; while ((pos + 9) < nDataLength) { if (*p == '-') { *q = 0; msg = ConvFromNetwork(buffer); q = buffer; DWORD timeHigh = GET32(pData + 1); DWORD timeLow = GET32(pData + 5); FILETIME fFileTime; fFileTime.dwHighDateTime = timeHigh; fFileTime.dwLowDateTime = timeLow; SYSTEMTIME sFileTime; FileTimeToSystemTime(&fFileTime, &sFileTime); TCHAR datetime[200]; int res = GetDateFormat( LOCALE_USER_DEFAULT, // locale for which date is to be formatted DATE_SHORTDATE, // flags specifying function options &sFileTime, // date to be formatted 0, // date format string datetime, // buffer for storing formatted string 200 // size of buffer ); if (res) { msg += datetime; msg += ' '; } res = GetTimeFormat( LOCALE_USER_DEFAULT, // locale for which date is to be formatted TIME_FORCE24HOURFORMAT, // flags specifying function options &sFileTime, // date to be formatted 0, // date format string datetime, // buffer for storing formatted string 200 // size of buffer ); if (res) { msg += datetime; msg += ' '; } if ((nDataLength - pos - 9) > 0) { memcpy(q, p, nDataLength - pos - 9); q += nDataLength - pos - 9; } break; } else *(q++) = *(p++); pos++; } *q = 0; if (q != buffer) msg += ConvFromNetwork(buffer); if (msg != _T("")) ShowStatus(msg, *pData); delete [] buffer; } break; case 7: if (nDataLength != 5) ShowStatus(_T("Protocol error: Invalid data"), 1); else { int nType = *pData; int size = (int)GET32(pData + 1); if (!nType) { m_nRecvCount += size; m_RecvLed.Ping(100); CString str; str.Format(_T("%s bytes received"), makeUserFriendlyString(m_nRecvCount).GetString()); SetStatusbarText(m_wndStatusBar.CommandToIndex(ID_INDICATOR_RECVCOUNT), str); } else { m_nSendCount += size; m_SendLed.Ping(100); CString str; str.Format(_T("%s bytes sent"), makeUserFriendlyString(m_nSendCount).GetString()); SetStatusbarText(m_wndStatusBar.CommandToIndex(ID_INDICATOR_SENDCOUNT), str); } } break; default: { CString str; str.Format(_T("Protocol error: Unexpected status id (%d)."), nStatusID); ShowStatus(str, 1); } break; } } BOOL CMainFrame::SendCommand(int nType) { if (!m_pAdminSocket) return FALSE; if (!m_pAdminSocket->SendCommand(nType)) { CloseAdminSocket(); ShowStatus("Error: Connection to server lost...", 1); return FALSE; } return TRUE; } BOOL CMainFrame::SendCommand(int nType, void *pData, int nDataLength) { if (!m_pAdminSocket) return FALSE; if (!m_pAdminSocket->SendCommand(nType, pData, nDataLength)) { CloseAdminSocket(); ShowStatus("Error: Connection to server lost...", 1); return FALSE; } return TRUE; } void CMainFrame::CloseAdminSocket(bool shouldReconnect /*=true*/) { if (m_pAdminSocket) { m_pAdminSocket->DoClose(); delete m_pAdminSocket; m_pAdminSocket = NULL; SetIcon(); CString title; title.LoadString(IDR_MAINFRAME); SetWindowText(title + _T(" (disconnected)")); } m_nEdit = 0; if (!shouldReconnect) { if (m_nReconnectTimerID) { KillTimer(m_nReconnectTimerID); m_nReconnectTimerID = 0; } } else { if (!m_nReconnectTimerID) { m_nReconnectCount++; if (m_nReconnectCount < 15) { ShowStatus("Trying to reconnect in 5 seconds", 0); m_nReconnectTimerID = SetTimer(7779, 5000, 0); } else m_nReconnectCount = 0; } } } void CMainFrame::OnFileConnect() { if (m_nReconnectTimerID) { KillTimer(m_nReconnectTimerID); m_nReconnectTimerID = 0; } if (m_pAdminSocket) if (AfxMessageBox(_T("Do you really want to close the current connection?"), MB_ICONQUESTION|MB_YESNO) != IDYES) return; CConnectDialog dlg(m_pOptions); if (dlg.DoModal() == IDOK) { CloseAdminSocket(false); m_pAdminSocket = new CAdminSocket(this); ShowStatus("Connecting to server...", 0); DoConnect(); } } void CMainFrame::OnFileDisconnect() { CloseAdminSocket(false); } void CMainFrame::OnUpdateFileDisconnect(CCmdUI* pCmdUI) { pCmdUI->Enable(m_pAdminSocket?TRUE:FALSE); } void CMainFrame::OnUpdateEditSettings(CCmdUI* pCmdUI) { pCmdUI->Enable(m_pAdminSocket && m_pAdminSocket->IsConnected()); } void CMainFrame::OnUpdateMenuEditUsers(CCmdUI* pCmdUI) { pCmdUI->Enable(m_pAdminSocket && m_pAdminSocket->IsConnected()); } void CMainFrame::OnUpdateMenuEditGroups(CCmdUI* pCmdUI) { pCmdUI->Enable(m_pAdminSocket && m_pAdminSocket->IsConnected()); } void CMainFrame::OnUpdateUsers(CCmdUI* pCmdUI) { pCmdUI->Enable(m_pAdminSocket && m_pAdminSocket->IsConnected()); } void CMainFrame::OnUpdateGroups(CCmdUI* pCmdUI) { pCmdUI->Enable(m_pAdminSocket && m_pAdminSocket->IsConnected()); } // this function gets called whenever the user decides to quit the app // (by pressing the 'x' for example void CMainFrame::OnDestroy() { m_pOptions->SetOption(IOPTION_USERSORTING, GetUsersPane()->m_pListCtrl->GetSortColumn() + (GetUsersPane()->m_pListCtrl->GetSortDirection() << 4)); CloseAdminSocket(false); CFrameWnd::OnDestroy(); } BOOL CMainFrame::OnEraseBkgnd(CDC* pDC) { return TRUE; } LRESULT CMainFrame::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam) { if (message == WM_APP) { if ((m_nEdit & 0x1C) == 0x0C) { m_nEdit |= 0x10; if (m_pOptionsDlg->Show()) { char *pBuffer; DWORD dwBufferLength; if (m_pOptionsDlg->GetAsCommand(&pBuffer, &dwBufferLength)) { SendCommand(5, pBuffer, dwBufferLength); ShowStatus(_T("Sending settings, please wait..."), 0); delete [] pBuffer; } else ShowStatus(_T("Could not serialize settings, too much data."), 1); } delete m_pOptionsDlg; m_pOptionsDlg = 0; m_nEdit = 0; } else if ((m_nEdit & 0x19) == 0x09) { m_nEdit |= 0x10; if (m_pUsersDlg->DoModal() == IDOK) { char *pBuffer; DWORD dwBufferLength; if (m_pUsersDlg->GetAsCommand(&pBuffer, &dwBufferLength)) { SendCommand(6, pBuffer, dwBufferLength); ShowStatus(_T("Sending account settings, please wait..."), 0); delete [] pBuffer; } } delete m_pUsersDlg; m_pUsersDlg = 0; m_nEdit = 0; } else if ((m_nEdit & 0x1A) == 0x0A) { m_nEdit |= 0x10; if (m_pGroupsDlg->DoModal() == IDOK) { char *pBuffer; DWORD dwBufferLength; if (m_pGroupsDlg->GetAsCommand(&pBuffer, &dwBufferLength)) { SendCommand(6, pBuffer, dwBufferLength); ShowStatus(_T("Sending account settings, please wait..."), 0); delete [] pBuffer; } } delete m_pGroupsDlg; m_pGroupsDlg = 0; m_nEdit = 0; } } else if (message == WM_APP + 1) OnAdminInterfaceClosed(); return CFrameWnd::DefWindowProc(message, wParam, lParam); } void CMainFrame::OnAdminInterfaceConnected() { m_nReconnectCount = 0; CString title; title.LoadString(IDR_MAINFRAME); CString ip; UINT port; if (m_pAdminSocket->GetPeerName(ip, port)) { if (ip.Find(':') != -1) ip = GetIPV6ShortForm(ip); SetWindowText(title + _T(" (") + ip + _T(")")); } } void CMainFrame::OnAdminInterfaceClosed() { if (m_pAdminSocket && m_pAdminSocket->IsClosed()) { CloseAdminSocket(); } } void CMainFrame::OnDisplayLogicalNames() { GetUsersPane()->m_pListCtrl->SetDisplayPhysicalNames(false); m_pOptions->SetOption(IOPTION_FILENAMEDISPLAY, 0); } void CMainFrame::OnDisplayPhysicalNames() { GetUsersPane()->m_pListCtrl->SetDisplayPhysicalNames(true); m_pOptions->SetOption(IOPTION_FILENAMEDISPLAY, 1); } void CMainFrame::OnUpdateDisplayLogicalNames(CCmdUI* pCmdUI) { pCmdUI->SetRadio(!GetUsersPane()->m_pListCtrl->GetDisplayPhysicalNames()); } void CMainFrame::OnUpdateDisplayPhysicalNames(CCmdUI* pCmdUI) { pCmdUI->SetRadio(GetUsersPane()->m_pListCtrl->GetDisplayPhysicalNames()); } void CMainFrame::OnDisplaySortMenu() { // load and display popup menu CMenu menu; menu.LoadMenu(IDR_SORTMENU); CMenu* pPopup = menu.GetSubMenu(0); ASSERT(pPopup); CRect rc; m_wndUserListToolBar.GetItemRect(m_wndUserListToolBar.CommandToIndex(ID_USERLISTTOOLBAR_SORT), &rc); m_wndUserListToolBar.ClientToScreen(&rc); pPopup->TrackPopupMenu( TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL, rc.left, rc.bottom, this, &rc); } void CMainFrame::OnToolbarDropDown(NMHDR* pnmh, LRESULT* plRes) { NMTOOLBAR* pnmtb = (NMTOOLBAR*)pnmh; if (pnmtb->iItem == ID_USERLISTTOOLBAR_SORT) OnDisplaySortMenu(); } void CMainFrame::OnDisplaySortByUserid() { GetUsersPane()->m_pListCtrl->SetSortColumn(0); } void CMainFrame::OnDisplaySortByAccount() { GetUsersPane()->m_pListCtrl->SetSortColumn(1); } void CMainFrame::OnDisplaySortByIP() { GetUsersPane()->m_pListCtrl->SetSortColumn(2); } void CMainFrame::OnUpdateDisplaySortByUserid(CCmdUI* pCmdUI) { pCmdUI->SetRadio(GetUsersPane()->m_pListCtrl->GetSortColumn() == 0); } void CMainFrame::OnUpdateDisplaySortByAccount(CCmdUI* pCmdUI) { pCmdUI->SetRadio(GetUsersPane()->m_pListCtrl->GetSortColumn() == 1); } void CMainFrame::OnUpdateDisplaySortByIP(CCmdUI* pCmdUI) { pCmdUI->SetRadio(GetUsersPane()->m_pListCtrl->GetSortColumn() == 3); } void CMainFrame::DoConnect() { int family; if (!GetIPV6LongForm(m_pOptions->GetOption(IOPTION_LASTSERVERADDRESS)).IsEmpty()) family = AF_INET6; else family = AF_INET; m_pAdminSocket->Create(0, SOCK_STREAM, FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE, 0, family); m_pAdminSocket->m_Password = m_pOptions->GetOption(IOPTION_LASTSERVERPASS); if (!m_pAdminSocket->Connect(m_pOptions->GetOption(IOPTION_LASTSERVERADDRESS), (UINT)m_pOptions->GetOptionVal(IOPTION_LASTSERVERPORT)) && WSAGetLastError() != WSAEWOULDBLOCK) { ShowStatus(_T("Error, could not connect to server"), 1); CloseAdminSocket(); } }