(c) BigSpeed Computing Inc. - Secure private networking
//Visual C++ .NET example of secure file sharing server
//To keep this VB.NET example simple, we are going to implement
//only the main file operations and one predefined user account


// CbsFileSrvDlg.cpp : implementation file
//

#include "stdafx.h"
#include "bsFileSrv.h"
#include "bsFileSrvDlg.h"
#include "dlgSettings.h"
#include ".\bsfilesrvdlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif



//Globals
const CString MyUsername = "test";
const CString MyPassword = "test";


// CbsFileSrvDlg dialog



CbsFileSrvDlg::CbsFileSrvDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CbsFileSrvDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CbsFileSrvDlg::DoDataExchange(CDataExchange* pDX)
{
  CDialog::DoDataExchange(pDX);
  DDX_Control(pDX, IDC_lvClients, c_lvClients);
  DDX_Control(pDX, IDC_btnStart, c_btnStart);
  DDX_Control(pDX, IDC_btnStop, c_btnStop);
  DDX_Control(pDX, IDC_BTNREMOVE, c_btnRemove);
  DDX_Control(pDX, IDC_stLog, c_stLog);
  DDX_Control(pDX, IDC_STATUS1, c_Status1);
  DDX_Control(pDX, IDC_STATUS2, c_Status2);
  DDX_Control(pDX, IDC_BSFILESRVX1, FileSrv);
}

BEGIN_MESSAGE_MAP(CbsFileSrvDlg, CDialog)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
  ON_BN_CLICKED(IDC_btnExit, OnBnClickedbtnexit)
  ON_BN_CLICKED(IDC_btnMyIP, OnBnClickedbtnmyip)
  ON_BN_CLICKED(IDC_btnSettings, OnBnClickedbtnsettings)
  ON_BN_CLICKED(IDC_btnClear, OnBnClickedbtnclear)
  ON_BN_CLICKED(IDC_BTNREMOVE, OnBnClickedBtnremove)
  ON_BN_CLICKED(IDC_btnStart, OnBnClickedbtnstart)
  ON_BN_CLICKED(IDC_btnStop, OnBnClickedbtnstop)
END_MESSAGE_MAP()


// CbsFileSrvDlg message handlers

BOOL CbsFileSrvDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	//extra initialization

	dlgSettings.v_edPort = "2222";  //set the default port

	c_lvClients.InsertColumn(0, "User", LVCFMT_LEFT, 120); 
	c_lvClients.InsertColumn(1, "IP Address", LVCFMT_LEFT, 120); 
	c_lvClients.InsertColumn(2, "Port", LVCFMT_LEFT, 100); 
	c_lvClients.InsertColumn(3, "Time", LVCFMT_LEFT, 150); 
	c_lvClients.InsertColumn(4, "Status", LVCFMT_LEFT, 150); 

	c_lvClients.ModifyStyle(NULL, LVS_REPORT, 0);
	c_lvClients.SetExtendedStyle(LVS_EX_FULLROWSELECT);


  SetProperties();
  UpdateStatus();  
  
	return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CbsFileSrvDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CbsFileSrvDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}



BEGIN_EVENTSINK_MAP(CbsFileSrvDlg, CDialog)
  ON_EVENT(CbsFileSrvDlg, IDC_BSFILESRVX1, 201, OnClientDisconnectedBsfilesrvx1, VTS_I4)
  ON_EVENT(CbsFileSrvDlg, IDC_BSFILESRVX1, 202, OnDownloadDoneBsfilesrvx1, VTS_I4 VTS_I4)
  ON_EVENT(CbsFileSrvDlg, IDC_BSFILESRVX1, 203, OnKeyChangedBsfilesrvx1, VTS_I4)
  ON_EVENT(CbsFileSrvDlg, IDC_BSFILESRVX1, 205, OnNeedCreateFolderBsfilesrvx1, VTS_I4 VTS_BSTR VTS_PBOOL VTS_PBSTR)
  ON_EVENT(CbsFileSrvDlg, IDC_BSFILESRVX1, 206, OnNeedDeleteFileBsfilesrvx1, VTS_I4 VTS_BSTR VTS_PBOOL VTS_PBSTR)
  ON_EVENT(CbsFileSrvDlg, IDC_BSFILESRVX1, 207, OnNeedDeleteFolderBsfilesrvx1, VTS_I4 VTS_BSTR VTS_PBOOL VTS_PBSTR)
  ON_EVENT(CbsFileSrvDlg, IDC_BSFILESRVX1, 208, OnNeedDownloadBsfilesrvx1, VTS_I4 VTS_BSTR VTS_PBOOL VTS_PBSTR)
  ON_EVENT(CbsFileSrvDlg, IDC_BSFILESRVX1, 213, OnNeedPasswordBsfilesrvx1, VTS_I4 VTS_BSTR VTS_PBOOL VTS_PBSTR)
  ON_EVENT(CbsFileSrvDlg, IDC_BSFILESRVX1, 214, OnNeedRenameFileBsfilesrvx1, VTS_I4 VTS_BSTR VTS_PBOOL VTS_PBSTR)
  ON_EVENT(CbsFileSrvDlg, IDC_BSFILESRVX1, 215, OnNeedRenameFolderBsfilesrvx1, VTS_I4 VTS_BSTR VTS_PBOOL VTS_PBSTR)
  ON_EVENT(CbsFileSrvDlg, IDC_BSFILESRVX1, 218, OnNeedUploadBsfilesrvx1, VTS_I4 VTS_BSTR VTS_PBOOL VTS_PBSTR)
  ON_EVENT(CbsFileSrvDlg, IDC_BSFILESRVX1, 220, OnNewClientBsfilesrvx1, VTS_I4)
  ON_EVENT(CbsFileSrvDlg, IDC_BSFILESRVX1, 222, OnSigninBsfilesrvx1, VTS_I4 VTS_I4)
  ON_EVENT(CbsFileSrvDlg, IDC_BSFILESRVX1, 226, OnUploadDoneBsfilesrvx1, VTS_I4 VTS_I4)
  ON_EVENT(CbsFileSrvDlg, IDC_BSFILESRVX1, 211, OnNeedListFolderBsfilesrvx1, VTS_I4 VTS_BSTR VTS_PBOOL VTS_PBSTR)
END_EVENTSINK_MAP()




// *** General ***



//Insert a leading slash
CString PreSlash(CString aPath)
{
  if (aPath.Left(1) == "\\")
    return aPath;
  else
    return "\\" + aPath;
}






// *** Working ***


CString CbsFileSrvDlg::GetAppDir(void)
{
  CString R;
  
  R = theApp.m_pszHelpFilePath;
  R = R.Left(R.ReverseFind('\\'));
 
  return R;
}


CString CbsFileSrvDlg::GetUsername(int aHandle)
{
  CString R;
  
  R = FileSrv.GetUsername(aHandle);
  if (R == "")
    R = "Default";
  return "User " + R;
}





//Update the status text
void CbsFileSrvDlg::UpdateStatus(void)
{
  CString St, IP, Port;


  if (FileSrv.get_Running())
  {
    c_Status1.SetWindowText("Started");
    c_btnStart.EnableWindow(false);
    c_btnStop.EnableWindow(true);
  }
  else
  {
    c_Status1.SetWindowText("Stopped");
    c_btnStart.EnableWindow(true);
    c_btnStop.EnableWindow(false);
  }
  
  if (c_lvClients.GetSelectedCount() == 0)
    c_Status2.SetWindowText("No active connection");
  else
  {
    St.Format("%d connection(s)", c_lvClients.GetItemCount());
    c_Status2.SetWindowText(St);
  }
  c_btnRemove.EnableWindow(c_lvClients.GetSelectedCount() > 0);
}






//Set the component properties
void CbsFileSrvDlg::SetProperties(void)
{
  FileSrv.put_ListeningPort(dlgSettings.v_edPort);
  FileSrv.put_CryptoKey(dlgSettings.v_edKey);
  FileSrv.put_UseCompression(dlgSettings.v_chkCompress);
}





//Add an error message to the log
void CbsFileSrvDlg::LogMsg(CString aMsg)
{
  CString Log;
  CTime Tm;
  
  Tm = CTime::GetCurrentTime();
  c_stLog.GetWindowText(Log);
  if (Log > "") 
    Log = Log + "\r\n";

  Log = Log + "[" + Tm.Format("%H:%M:%S") + "]: ";
  Log = Log + aMsg;
  c_stLog.SetWindowText(Log);
}



int CbsFileSrvDlg::IndexFromHandle(int aHandle)
{
  int i;
  LVITEM lvi;
  
  for (i=c_lvClients.GetItemCount()-1; i>= 0; i--)
  {
    lvi.mask = LVIF_PARAM;
    lvi.iItem = i;
    lvi.iSubItem = 0;
    c_lvClients.GetItem(&lvi);
//    if (lvi.iImage == aHandle)
    if (int(lvi.lParam) == aHandle)
      return i;
  }  
  return -1;
}


int CbsFileSrvDlg::GetSelectedIndex(void)
{
  POSITION pos = c_lvClients.GetFirstSelectedItemPosition();
  if (pos == NULL) 
    return -1;
  else
    return c_lvClients.GetNextSelectedItem(pos);
}


// *** Event handlers ***




//Terminate the application
void CbsFileSrvDlg::OnBnClickedbtnexit()
{
  OnCancel();
}



//Show my IP address
void CbsFileSrvDlg::OnBnClickedbtnmyip()
{
  MessageBox(FileSrv.get_LocalIP(), "My IP Address", MB_OK);
}



//Modify the settings
void CbsFileSrvDlg::OnBnClickedbtnsettings()
{
  if (dlgSettings.DoModal() != IDOK) return;

  SetProperties(); 
  UpdateStatus();
}


//Clear the log
void CbsFileSrvDlg::OnBnClickedbtnclear()
{
  c_stLog.SetWindowText("");
}


//Remove a client connection
void CbsFileSrvDlg::OnBnClickedBtnremove()
{
  int si;
  LVITEM lvi;
  
  si = GetSelectedIndex();
  if (si < 0) return;
  lvi.mask =  LVIF_TEXT | LVIF_IMAGE;
  lvi.iItem = si;
  lvi.iSubItem = 0;
  if (!c_lvClients.GetItem(&lvi)) return;
  FileSrv.RemoveClient(int(lvi.iImage));
  c_lvClients.DeleteItem(si);
  UpdateStatus();
}


//Start the server
void CbsFileSrvDlg::OnBnClickedbtnstart()
{
  if (FileSrv.Start())
    LogMsg("Server started");
  else
    MessageBox("Cannot start the server!", "Error", MB_OK);
  UpdateStatus();
}



//Stop the server
void CbsFileSrvDlg::OnBnClickedbtnstop()
{
  int i;
  LVITEM lvi;
  
  FileSrv.Stop();
  
  for (i=c_lvClients.GetItemCount()-1; i>= 0; i--)
  {
    lvi.mask =  LVIF_TEXT | LVIF_IMAGE;
    lvi.iItem = i;
    lvi.iSubItem = 0;
    if (c_lvClients.GetItem(&lvi))
      FileSrv.RemoveClient(int(lvi.iImage));
    c_lvClients.DeleteItem(i);
  }  
  
  UpdateStatus();
  LogMsg("Server stopped");
}






// *** FileSrv events ***




//A new connection is available
void CbsFileSrvDlg::OnNewClientBsfilesrvx1(long aHandle)
{
  LVITEM lvi;
  CString Addr, Port, Tm;

  Addr = FileSrv.GetClientAddress(aHandle);
  Port = FileSrv.GetClientPort(aHandle);
  
  int i = c_lvClients.GetItemCount();

  lvi.mask =  LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  lvi.iItem = i;
  lvi.iSubItem = 0;
  lvi.lParam = aHandle;
  lvi.pszText = "Not signed in";
  c_lvClients.InsertItem(&lvi);

  c_lvClients.SetItemText(i, 1, Addr);
  c_lvClients.SetItemText(i, 2, Port);
  CTime tm = time(NULL);
  Tm = tm.Format("%m/%d/%Y %H:%M:%S");
  c_lvClients.SetItemText(i, 3, Tm);
  c_lvClients.SetItemText(i, 4, "Connected");
 
  UpdateStatus();
  LogMsg("New connection from " + Addr + ":" + Port);
}



//A connection is broken
void CbsFileSrvDlg::OnClientDisconnectedBsfilesrvx1(long aHandle)
{
  int i;
  LVITEM lvi;
  CString Name, Addr, Port;
  
  i = IndexFromHandle(aHandle);
  if (i < 0) return;
  
  lvi.mask =  LVIF_TEXT;
  lvi.iItem = i;
  lvi.iSubItem = 0;
  c_lvClients.GetItem(&lvi);

  Name = c_lvClients.GetItemText(i, 0);
  Addr = c_lvClients.GetItemText(i, 1);
  Name = c_lvClients.GetItemText(i, 2);

  LogMsg("Disconnected " + Name + " " + Addr + ":" + Port);
  FileSrv.RemoveClient(int(lvi.iImage));
  c_lvClients.DeleteItem(i);
  UpdateStatus();
}



//The key matching is changed
void CbsFileSrvDlg::OnKeyChangedBsfilesrvx1(long aHandle)
{
  int i;
  LVITEM li;
  CString Name, Addr, Port;
  
  i = IndexFromHandle(aHandle);
  if (i < 0) return;
  if (!c_lvClients.GetItem(&li)) return;

  Name = c_lvClients.GetItemText(i, 0);
  Addr = c_lvClients.GetItemText(i, 1);
  Name = c_lvClients.GetItemText(i, 2);

  LogMsg("Key is changed for " + Name + " " + Addr + ":" + Port);
  if (FileSrv.WrongKey(aHandle))
    c_lvClients.SetItemText(i, 4, "Wrong key");
  else
    c_lvClients.SetItemText(i, 4, "Connected");
  
  UpdateStatus();
}




//A request for a password
void CbsFileSrvDlg::OnNeedPasswordBsfilesrvx1(long aHandle, LPCTSTR aUsername, BOOL* aOkay, BSTR* aPassword)
{
  if (aUsername = MyUsername)
  {
    //this is our user
    *aOkay = true;
    *aPassword = MyPassword.AllocSysString(); 

  }
  else
  {
    //Unknown user
    *aOkay = false;
  }
}



//An user is signed-in
void CbsFileSrvDlg::OnSigninBsfilesrvx1(long aHandle, long aCode)
{
  int i;
  CString Name, S;
  
  i = IndexFromHandle(aHandle);
  if (i < 0) return;

  Name = GetUsername(aHandle);
  c_lvClients.SetItemText(i, 0, Name);
  
  S = Name + " " + FileSrv.GetClientAddress(aHandle) + ":" + FileSrv.GetClientPort(aHandle);
  if (aCode == 0)
    S = S + " signed in successfully";
  else
    S = S + " failed sign-in";
  LogMsg(S);
}





//A request to list the folder contents
void CbsFileSrvDlg::OnNeedListFolderBsfilesrvx1(long aHandle, LPCTSTR aPath, BOOL* aOkay, BSTR* aRoot)
{
  CString Dir = GetAppDir();
  *aOkay = true;
  *aRoot = Dir.AllocSysString(); 
  LogMsg(GetUsername(aHandle) + ": list folder " + PreSlash(aPath));
}



//A request to create a folder
void CbsFileSrvDlg::OnNeedCreateFolderBsfilesrvx1(long aHandle, LPCTSTR aPath, BOOL* aOkay, BSTR* aRoot)
{
  CString Dir = GetAppDir();
  *aOkay = true;
  *aRoot = Dir.AllocSysString(); 
  LogMsg(GetUsername(aHandle) + ": create folder " + PreSlash(aPath));
}



//A request to rename a file
void CbsFileSrvDlg::OnNeedRenameFileBsfilesrvx1(long aHandle, LPCTSTR aPath, BOOL* aOkay, BSTR* aRoot)
{
  CString Dir = GetAppDir();
  *aOkay = true;
  *aRoot = Dir.AllocSysString(); 
  LogMsg(GetUsername(aHandle) + ": rename file " + PreSlash(aPath));
}


//A request to rename a folder
void CbsFileSrvDlg::OnNeedRenameFolderBsfilesrvx1(long aHandle, LPCTSTR aPath, BOOL* aOkay, BSTR* aRoot)
{
  CString Dir = GetAppDir();
  *aOkay = true;
  *aRoot = Dir.AllocSysString(); 
  LogMsg(GetUsername(aHandle) + ": rename folder " + PreSlash(aPath));
}


//A request to delete a file
void CbsFileSrvDlg::OnNeedDeleteFileBsfilesrvx1(long aHandle, LPCTSTR aPath, BOOL* aOkay, BSTR* aRoot)
{
  CString Dir = GetAppDir();
  *aOkay = true;
  *aRoot = Dir.AllocSysString(); 
  LogMsg(GetUsername(aHandle) + ": delete file " + PreSlash(aPath));
}


//A request to delete a folder
void CbsFileSrvDlg::OnNeedDeleteFolderBsfilesrvx1(long aHandle, LPCTSTR aPath, BOOL* aOkay, BSTR* aRoot)
{
  CString Dir = GetAppDir();
  *aOkay = true;
  *aRoot = Dir.AllocSysString(); 
  LogMsg(GetUsername(aHandle) + ": delete folder " + PreSlash(aPath));
}


//A request to download
void CbsFileSrvDlg::OnNeedDownloadBsfilesrvx1(long aHandle, LPCTSTR aPath, BOOL* aOkay, BSTR* aRoot)
{
  CString Dir = GetAppDir();
  *aOkay = true;
  *aRoot = Dir.AllocSysString(); 
  LogMsg(GetUsername(aHandle) + ": starting download " + PreSlash(aPath));
}


//The download operation is completed
void CbsFileSrvDlg::OnDownloadDoneBsfilesrvx1(long aHandle, long aCode)
{
  LogMsg(GetUsername(aHandle) + ": finishing download");
}


//A request to upload
void CbsFileSrvDlg::OnNeedUploadBsfilesrvx1(long aHandle, LPCTSTR aPath, BOOL* aOkay, BSTR* aRoot)
{
  CString Dir = GetAppDir();
  *aOkay = true;
  *aRoot = Dir.AllocSysString(); 
  LogMsg(GetUsername(aHandle) + ": starting upload " + PreSlash(aPath));
}


//The upload operation is completed
void CbsFileSrvDlg::OnUploadDoneBsfilesrvx1(long aHandle, long aCode)
{
  LogMsg(GetUsername(aHandle) + ": finishing upload");
}


(c) BigSpeed Computing Inc. - Secure private networking