//  
//   Rebex Sample Code License
// 
//   Copyright 2025, REBEX CR s.r.o.
//   All rights reserved.
//   https://www.rebex.net/
// 
//   Permission to use, copy, modify, and/or distribute this software for any
//   purpose with or without fee is hereby granted.
// 
//   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
//   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
//   OTHER DEALINGS IN THE SOFTWARE.
// 

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Resources;
using System.IO;
using System.Text;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

using Rebex.IO;
using Rebex.Net;
using Rebex.Security.Certificates;
using System.Net;

namespace Rebex.Samples
{
    /// <summary>
    /// very simple FTP and/or SFTP client
    /// </summary>
    public class MainForm : System.Windows.Forms.Form
    {

        private System.ComponentModel.Container components = null;
        private System.Windows.Forms.RichTextBox tbLog;
        private System.Windows.Forms.ListView listServer;
        private System.Windows.Forms.ColumnHeader name;
        private System.Windows.Forms.ColumnHeader size;
        private System.Windows.Forms.Label lblServer;
        private System.Windows.Forms.ListView listLocal;
        private System.Windows.Forms.Label lblLocal;
        private System.Windows.Forms.Label lblServerDirectory;
        private System.Windows.Forms.ColumnHeader columnHeader1;
        private System.Windows.Forms.ColumnHeader columnHeader2;
        private System.Windows.Forms.Label lblLocalDirectory;
        private System.Windows.Forms.ColumnHeader date;
        private System.Windows.Forms.ColumnHeader columnHeader3;
        private System.Windows.Forms.Button btnStop;
        private System.Windows.Forms.Button btnDelete;
        private System.Windows.Forms.Button btnUpload;
        private System.Windows.Forms.Button btnDownload;
        private System.Windows.Forms.RadioButton rbBin;
        private System.Windows.Forms.RadioButton rbAsc;
        private System.Windows.Forms.Button btnRefresh;
        private System.Windows.Forms.Button btnMakeDir;
        private System.Windows.Forms.ComboBox cbDrives;
        private System.Windows.Forms.Button btnConnect;
        private System.Windows.Forms.GroupBox gbControl;
        private System.Windows.Forms.GroupBox gbTransfer;
        private System.Windows.Forms.PictureBox headerLeft;
        private System.Windows.Forms.Panel headerMiddle;
        private System.Windows.Forms.PictureBox headerRight;
        private System.Windows.Forms.TrackBar trackBar;
        private System.Windows.Forms.Label lblSpeed;
        private System.Windows.Forms.Button btnErrorWarning;
        private System.Windows.Forms.PictureBox pbSecure;

        private FileTransferClient _client;			// FTP or SFTP session
        private readonly ConnectionFormData _connectionData;	// connection fields gathered from the connection form
        private ListView listActive;                // active list (server x local)
        private int _serverDirs;                    // number of dirs on server side
        private int _localDirs;                     // number of dirs on local side
        private int _selectedDrive = -1;            // selected drive (A:, C:, ...) in combo
        private string _localPath;                  // local path
        private bool _isWorking;                    // determines whether any operation is running
        private DateTime _transferTime;             // transfer launch-time
        private ProblemDetectedForm _problemForm;   // informs the user about problems while transferring data

        // constants
        private const string SYMLINK = "--->";      // symlink tag
        private const string URL = "https://www.rebex.net/file-transfer-pack/";
        private StatusStrip mainStatusStrip;
        private ToolStripProgressBar pbTransfer;
        private ToolStripStatusLabel lblProgress;
        private SplitContainer mainSplitContainer; // url
        private TableLayoutPanel tableLayout;
        private Panel panelRight;
        private Panel panelLeft;
        private Panel panelMiddle;
        private string _exception = "";			  // last occurred exception

        public void WriteToLog(Exception x)
        {
            if (x is AggregateException)
            {
                foreach (Exception inner in ((AggregateException)x).InnerExceptions)
                {
                    WriteToLog(inner);
                }
                return;
            }

            ShowErrorWarning(x.ToString());

            // FtpExceptions and SftpExceptions are automatically logged by component logger.
            // No need to display them again.
            // We don't wont duplicate entries for such exceptions.
            if (x is FtpException || x is SftpException)
                return;

            WriteToLog("* " + x.ToString(), RichTextBoxLogWriter.COLORERROR);
        }

        public void ShowErrorWarning(string message)
        {
            _exception = message;
            btnErrorWarning.Visible = true;
        }

        public void WriteToLog(string message, Color color)
        {
            tbLog.Focus();
            tbLog.SelectionColor = color;
            tbLog.AppendText(message + "\r\n");
        }

        
        /// <summary>
        /// format datetime to readable form in the panels
        /// </summary>
        /// <param name="dt">datetime</param>
        /// <returns>formatted string</returns>
        private static string FormatFileTime(DateTime dt)
        {
            return dt.ToString("yyyy-MM-dd HH:mm");
        }

        /// <summary>
        /// handles the displaying traversing event
        /// </summary>
        void Traversing(object sender, TraversingEventArgs e)
        {
            if (e.Action == TransferAction.Listing)
                return;

            string strBatchInfo = string.Format("({0} file{1} traversed)    ",
                e.FilesTotal, (e.FilesTotal > 1 ? "s" : null));

            switch (e.TraversingState)
            {
                case TraversingState.DirectoryRetrieved:
                    strBatchInfo += "Directory retrieved.";
                    break;
                case TraversingState.DirectoryRetrieving:
                    strBatchInfo += "Retrieving directory...";
                    break;
                case TraversingState.HierarchyRetrieved:
                    strBatchInfo += string.Format("Hierarchy retrieved ({0} byte{1} in {2} file{3}).",
                        e.BytesTotal, (e.BytesTotal > 1 ? "s" : null),
                        e.FilesTotal, (e.FilesTotal > 1 ? "s" : null));
                    break;
                case TraversingState.HierarchyRetrieving:
                    strBatchInfo += "Retrieving hierarchy...";
                    break;
            }

            lblProgress.Text = strBatchInfo;
        }

        /// <summary>
        /// handles the transfer progress changed event
        /// </summary>
        void TransferProgressChanged(object sender, TransferProgressChangedEventArgs e)
        {
            string strBatchInfo = string.Format("({0} / {1} file{2} processed)    ",
                e.FilesProcessed, e.FilesTotal, (e.FilesProcessed > 1 ? "s" : null));

            SetProgressValue(Convert.ToInt32(e.ProgressPercentage));

            switch (e.TransferState)
            {
                case TransferProgressState.DataBlockProcessed:
                    strBatchInfo += e.BytesTransferred + " bytes";
                    break;
                case TransferProgressState.DirectoryProcessing:
                    strBatchInfo += "Processing directory...";
                    break;
                case TransferProgressState.FileTransferring:
                    strBatchInfo += "Transferring file...";
                    break;
                case TransferProgressState.FileTransferred:
                    strBatchInfo += "File transferred.";
                    break;
                case TransferProgressState.TransferCompleted:
                    strBatchInfo += "Transfer completed.";
                    ShowTransferStatus(e.BytesTransferred, e.FilesTransferred);
                    break;
            }

            lblProgress.Text = strBatchInfo;
        }

        private void SetProgressValue(int value)
        {
            // workaround for progress bar smoothing
            if (value == 100)
            {
                pbTransfer.Maximum = 101;
                pbTransfer.Value = 101;
                pbTransfer.Maximum = 100;
                System.Threading.Thread.Sleep(200);
            }
            else
            {
                pbTransfer.Value = value;
            }
        }

        /// <summary>
        /// handles the delete progress changed event
        /// </summary>
        private void DeleteProgressChanged(object sender, DeleteProgressChangedEventArgs e)
        {
            string strDeleteInfo = string.Format("({0} / {1} file{2} deleted)    ",
                e.FilesProcessed, e.FilesTotal, (e.FilesProcessed > 1 ? "s" : null));

            switch (e.DeleteState)
            {
                case DeleteProgressState.DeleteCompleted:
                    strDeleteInfo += "Delete completed.";
                    break;
                case DeleteProgressState.DirectoryDeleted:
                    strDeleteInfo += "Directory deleted.";
                    break;
                case DeleteProgressState.DirectoryProcessing:
                    strDeleteInfo += "Processing directory...";
                    break;
                case DeleteProgressState.FileDeleted:
                    strDeleteInfo += "File deleted.";
                    break;
                case DeleteProgressState.FileDeleting:
                    strDeleteInfo += "Deleting file...";
                    break;
            }

            lblProgress.Text = strDeleteInfo;
        }

        /// <summary>
        /// handles the batch transfer problem detected event
        /// </summary>
        private void ProblemDetected(object sender, ProblemDetectedEventArgs e)
        {
            _problemForm.ShowModal(this, e);
        }

        /// <summary>
        /// make local list + drives combo box
        /// </summary>
        public void MakeLocalList()
        {
            int dirs = 0;
            int files = 0;
            long size = 0;

            // make a logical drives list [first run only]

            if (cbDrives.Items.Count <= 0)
            {
                string[] drives = Directory.GetLogicalDrives();
                string lowerDrive = @"c:\";

                // find "lower" acceptable drive

                for (int c = drives.Length - 1; c >= 0; c--)
                {
                    if (drives[c].ToLower().CompareTo(@"c:\") >= 0) lowerDrive = drives[c].ToLower();
                }

                // feed the drives' list and select one

                for (int c = 0; c < drives.Length; c++)
                {
                    string drive = drives[c];

                    cbDrives.Items.Add(drive);

                    if (_selectedDrive == -1 && drive.ToLower().CompareTo(lowerDrive) == 0)
                    {
                        cbDrives.SelectedIndex = c;
                        _selectedDrive = c;
                    }
                }

                if (cbDrives.SelectedIndex <= 0) cbDrives.SelectedIndex = 0;
            }

            // create the list
            listLocal.Items.Clear();

            // directory up
            if (_localPath != null && _localPath.Length > 3)
            {
                listLocal.Items.Add(new ListViewItem("..", 0));
                dirs++;
            }
            else
            {
                _localPath = cbDrives.SelectedItem.ToString();
            }

            DirectoryInfo directory = new DirectoryInfo(_localPath);
            DirectoryInfo[] list = directory.GetDirectories();

            for (int c = 0; c < list.Length; c++)
            {
                string[] row = new string[3];
                row[0] = list[c].Name;
                row[1] = "";

                // time [on read-only devices LWT is not available for dirs?]

                try
                {
                    row[2] = FormatFileTime(list[c].LastWriteTime);
                }
                catch
                {
                    row[2] = "";
                }

                listLocal.Items.Add(new ListViewItem(row, 1 + c));
                dirs++;
            }

            _localDirs = dirs;

            // files

            FileInfo[] list2 = directory.GetFiles();

            for (int c = 0; c < list2.Length; c++)
            {
                string[] row = new string[3];
                row[0] = list2[c].Name;
                row[1] = list2[c].Length.ToString();
                row[2] = FormatFileTime(list2[c].LastWriteTime);

                listLocal.Items.Add(new ListViewItem(row, 1 + dirs + files));
                size += list2[c].Length;
                files++;
            }

            // stats

            lblLocal.Text = dirs + " folder" + (dirs > 1 ? "s" : "") + ", " +
                files + " file" + (files > 1 ? "s" : "") + ", " +
                size / 1024 + " K";

            // working directory

            lblLocalDirectory.Text = directory.FullName;
            _localPath = directory.FullName;
        }

        /// <summary>
        /// make remote list
        /// </summary>
        public async void MakeRemoteList()
        {
            int dirs = 0;
            int files = 0;
            long size = 0;

            listServer.Items.Clear();

            // not connected?

            if (_client == null)
            {
                lblServerDirectory.Text = "";
                lblServer.Text = "";
                _serverDirs = 0;
                return;
            }

            //// secure transfers
            //if (cbST.Enabled && !_cccMode)
            //	_client.SecureTransfers = cbST.Checked;

            // make the list
            FileSystemItemCollection list = null;
            try
            {
                _isWorking = true;
                btnStop.Visible = true;

                list = await _client.GetListAsync();
        
                list.Sort();
            }
            catch (Exception ex)
            {
                WriteToLog(ex);
                listServer.Items.Add(new ListViewItem("..", 0));
                return;
            }
            finally
            {
                btnStop.Visible = false;
                _isWorking = false;
            }

            // directories

            listServer.Items.Add(new ListViewItem("..", 0));
            dirs++;

            for (int c = 0; c < list.Count; c++)
            {
                string[] row = new string[3];
                row[0] = list[c].Name;
                row[1] = null;
                row[2] = list[c].LastWriteTime.HasValue ? FormatFileTime(list[c].LastWriteTime.Value) : null;

                if (list[c].IsLink)
                {
                    row[1] = SYMLINK;
                }
                else if (list[c].IsFile)
                {
                    row[1] = list[c].Length.ToString();
                    size += list[c].Length;
                    files++;
                }
                else if (list[c].IsDirectory)
                {
                    dirs++;
                }

                ListViewItem lvi = new ListViewItem(row);
                lvi.Tag = list[c];
                listServer.Items.Add(lvi);

            }

            listServer.ListViewItemSorter = new ListViewColumnSorter();
            listServer.Sort();

            // stats
            lblServer.Text = dirs + " folder" + (dirs > 1 ? "s" : "") + ", " +
                files + " file" + (files > 1 ? "s" : "") + ", " +
                size / 1024 + " K";

            // working directory
            lblServerDirectory.Text = _client.GetCurrentDirectory();

            _serverDirs = dirs;
        }

        /// <summary>
        /// constructor
        /// </summary>
        public MainForm()
        {
            Application.EnableVisualStyles();
            CheckForIllegalCrossThreadCalls = true;
            InitializeComponent();

            rbBin.Checked = true;
            trackBar.Enabled = false;
            btnErrorWarning.Visible = false;
            lblServer.Text = "";
            listLocal.Focus();
            btnConnect.Select();

            _connectionData = new ConnectionFormData(FileTransferComponent.FileTransfer);
            _connectionData.LoadConfig();

            MakeLocalList();
            _problemForm = new ProblemDetectedForm();

            WriteToLog("Welcome to Rebex File Transfer sample app!", Color.DarkGreen);
        }

        /// <summary>
        /// clean up any resources being used
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
            this.listServer = new System.Windows.Forms.ListView();
            this.name = new System.Windows.Forms.ColumnHeader();
            this.size = new System.Windows.Forms.ColumnHeader();
            this.date = new System.Windows.Forms.ColumnHeader();
            this.listLocal = new System.Windows.Forms.ListView();
            this.columnHeader1 = new System.Windows.Forms.ColumnHeader();
            this.columnHeader2 = new System.Windows.Forms.ColumnHeader();
            this.columnHeader3 = new System.Windows.Forms.ColumnHeader();
            this.tbLog = new System.Windows.Forms.RichTextBox();
            this.lblServer = new System.Windows.Forms.Label();
            this.lblServerDirectory = new System.Windows.Forms.Label();
            this.lblLocal = new System.Windows.Forms.Label();
            this.lblLocalDirectory = new System.Windows.Forms.Label();
            this.btnStop = new System.Windows.Forms.Button();
            this.btnDelete = new System.Windows.Forms.Button();
            this.btnUpload = new System.Windows.Forms.Button();
            this.btnDownload = new System.Windows.Forms.Button();
            this.rbBin = new System.Windows.Forms.RadioButton();
            this.rbAsc = new System.Windows.Forms.RadioButton();
            this.btnRefresh = new System.Windows.Forms.Button();
            this.btnMakeDir = new System.Windows.Forms.Button();
            this.cbDrives = new System.Windows.Forms.ComboBox();
            this.btnConnect = new System.Windows.Forms.Button();
            this.gbControl = new System.Windows.Forms.GroupBox();
            this.gbTransfer = new System.Windows.Forms.GroupBox();
            this.pbSecure = new System.Windows.Forms.PictureBox();
            this.headerLeft = new System.Windows.Forms.PictureBox();
            this.headerRight = new System.Windows.Forms.PictureBox();
            this.btnErrorWarning = new System.Windows.Forms.Button();
            this.trackBar = new System.Windows.Forms.TrackBar();
            this.lblSpeed = new System.Windows.Forms.Label();
            this.headerMiddle = new System.Windows.Forms.Panel();
            this.mainStatusStrip = new System.Windows.Forms.StatusStrip();
            this.pbTransfer = new System.Windows.Forms.ToolStripProgressBar();
            this.lblProgress = new System.Windows.Forms.ToolStripStatusLabel();
            this.mainSplitContainer = new System.Windows.Forms.SplitContainer();
            this.tableLayout = new System.Windows.Forms.TableLayoutPanel();
            this.panelRight = new System.Windows.Forms.Panel();
            this.panelLeft = new System.Windows.Forms.Panel();
            this.panelMiddle = new System.Windows.Forms.Panel();
            this.gbControl.SuspendLayout();
            this.gbTransfer.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.pbSecure)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.headerLeft)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.headerRight)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.trackBar)).BeginInit();
            this.headerMiddle.SuspendLayout();
            this.mainStatusStrip.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.mainSplitContainer)).BeginInit();
            this.mainSplitContainer.Panel1.SuspendLayout();
            this.mainSplitContainer.Panel2.SuspendLayout();
            this.mainSplitContainer.SuspendLayout();
            this.tableLayout.SuspendLayout();
            this.panelRight.SuspendLayout();
            this.panelLeft.SuspendLayout();
            this.panelMiddle.SuspendLayout();
            this.SuspendLayout();
            // 
            // listServer
            // 
            this.listServer.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
            | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.listServer.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
            this.name,
            this.size,
            this.date});
            this.listServer.FullRowSelect = true;
            this.listServer.HideSelection = false;
            this.listServer.Location = new System.Drawing.Point(0, 20);
            this.listServer.MultiSelect = false;
            this.listServer.Name = "listServer";
            this.listServer.Size = new System.Drawing.Size(314, 380);
            this.listServer.TabIndex = 2;
            this.listServer.UseCompatibleStateImageBehavior = false;
            this.listServer.View = System.Windows.Forms.View.Details;
            this.listServer.DoubleClick += new System.EventHandler(this.listServer_DoubleClick);
            this.listServer.Enter += new System.EventHandler(this.listServer_Enter);
            this.listServer.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.listServer_KeyPress);
            // 
            // name
            // 
            this.name.Name = "name";
            this.name.Text = "Name";
            this.name.Width = 120;
            // 
            // size
            // 
            this.size.Name = "size";
            this.size.Text = "Size";
            this.size.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
            // 
            // date
            // 
            this.date.Name = "date";
            this.date.Text = "Date";
            this.date.Width = 120;
            // 
            // listLocal
            // 
            this.listLocal.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
            | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.listLocal.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
            this.columnHeader1,
            this.columnHeader2,
            this.columnHeader3});
            this.listLocal.FullRowSelect = true;
            this.listLocal.HideSelection = false;
            this.listLocal.Location = new System.Drawing.Point(0, 20);
            this.listLocal.MultiSelect = false;
            this.listLocal.Name = "listLocal";
            this.listLocal.Size = new System.Drawing.Size(314, 429);
            this.listLocal.TabIndex = 25;
            this.listLocal.UseCompatibleStateImageBehavior = false;
            this.listLocal.View = System.Windows.Forms.View.Details;
            this.listLocal.DoubleClick += new System.EventHandler(this.listLocal_DoubleClick);
            this.listLocal.Enter += new System.EventHandler(this.listLocal_Enter);
            this.listLocal.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.listLocal_KeyPress);
            // 
            // columnHeader1
            // 
            this.columnHeader1.Name = "columnHeader1";
            this.columnHeader1.Text = "Name";
            this.columnHeader1.Width = 120;
            // 
            // columnHeader2
            // 
            this.columnHeader2.Name = "columnHeader2";
            this.columnHeader2.Text = "Size";
            this.columnHeader2.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
            // 
            // columnHeader3
            // 
            this.columnHeader3.Name = "columnHeader3";
            this.columnHeader3.Text = "Date";
            this.columnHeader3.Width = 120;
            // 
            // tbLog
            // 
            this.tbLog.AccessibleRole = System.Windows.Forms.AccessibleRole.None;
            this.tbLog.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
            | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.tbLog.BackColor = System.Drawing.SystemColors.Control;
            this.tbLog.Cursor = System.Windows.Forms.Cursors.IBeam;
            this.tbLog.Font = new System.Drawing.Font("Lucida Console", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
            this.tbLog.Location = new System.Drawing.Point(0, 0);
            this.tbLog.MaxLength = 1000000;
            this.tbLog.Name = "tbLog";
            this.tbLog.ReadOnly = true;
            this.tbLog.Size = new System.Drawing.Size(755, 110);
            this.tbLog.TabIndex = 8;
            this.tbLog.Text = "";
            this.tbLog.WordWrap = false;
            // 
            // lblServer
            // 
            this.lblServer.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.lblServer.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
            this.lblServer.Location = new System.Drawing.Point(4, 407);
            this.lblServer.Name = "lblServer";
            this.lblServer.Size = new System.Drawing.Size(187, 25);
            this.lblServer.TabIndex = 9;
            this.lblServer.Text = "12345";
            // 
            // lblServerDirectory
            // 
            this.lblServerDirectory.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.lblServerDirectory.BackColor = System.Drawing.SystemColors.InactiveCaption;
            this.lblServerDirectory.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
            this.lblServerDirectory.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point);
            this.lblServerDirectory.ForeColor = System.Drawing.SystemColors.InactiveCaptionText;
            this.lblServerDirectory.Location = new System.Drawing.Point(0, 0);
            this.lblServerDirectory.Name = "lblServerDirectory";
            this.lblServerDirectory.Size = new System.Drawing.Size(314, 20);
            this.lblServerDirectory.TabIndex = 1;
            this.lblServerDirectory.Text = "/root";
            this.lblServerDirectory.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
            this.lblServerDirectory.Click += new System.EventHandler(this.listServer_Enter);
            // 
            // lblLocal
            // 
            this.lblLocal.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.lblLocal.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
            this.lblLocal.Location = new System.Drawing.Point(4, 454);
            this.lblLocal.Name = "lblLocal";
            this.lblLocal.Size = new System.Drawing.Size(310, 16);
            this.lblLocal.TabIndex = 12;
            this.lblLocal.Text = "12345";
            // 
            // lblLocalDirectory
            // 
            this.lblLocalDirectory.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.lblLocalDirectory.BackColor = System.Drawing.SystemColors.InactiveCaption;
            this.lblLocalDirectory.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
            this.lblLocalDirectory.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point);
            this.lblLocalDirectory.ForeColor = System.Drawing.SystemColors.InactiveCaptionText;
            this.lblLocalDirectory.Location = new System.Drawing.Point(0, 0);
            this.lblLocalDirectory.Name = "lblLocalDirectory";
            this.lblLocalDirectory.Size = new System.Drawing.Size(314, 20);
            this.lblLocalDirectory.TabIndex = 23;
            this.lblLocalDirectory.Text = "/root";
            this.lblLocalDirectory.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
            this.lblLocalDirectory.Click += new System.EventHandler(this.listLocal_Enter);
            // 
            // btnStop
            // 
            this.btnStop.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.btnStop.Location = new System.Drawing.Point(19, 272);
            this.btnStop.Name = "btnStop";
            this.btnStop.Size = new System.Drawing.Size(90, 28);
            this.btnStop.TabIndex = 17;
            this.btnStop.Text = "Abort";
            this.btnStop.Visible = false;
            this.btnStop.Click += new System.EventHandler(this.btnStop_Click);
            // 
            // btnDelete
            // 
            this.btnDelete.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.btnDelete.Location = new System.Drawing.Point(19, 154);
            this.btnDelete.Name = "btnDelete";
            this.btnDelete.Size = new System.Drawing.Size(90, 28);
            this.btnDelete.TabIndex = 11;
            this.btnDelete.Text = "Delete";
            this.btnDelete.Click += new System.EventHandler(this.btnDelete_Click);
            // 
            // btnUpload
            // 
            this.btnUpload.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.btnUpload.Location = new System.Drawing.Point(19, 239);
            this.btnUpload.Name = "btnUpload";
            this.btnUpload.Size = new System.Drawing.Size(90, 28);
            this.btnUpload.TabIndex = 15;
            this.btnUpload.Text = "< Upload";
            this.btnUpload.Click += new System.EventHandler(this.btnUpload_Click);
            // 
            // btnDownload
            // 
            this.btnDownload.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.btnDownload.Location = new System.Drawing.Point(19, 206);
            this.btnDownload.Name = "btnDownload";
            this.btnDownload.Size = new System.Drawing.Size(90, 28);
            this.btnDownload.TabIndex = 13;
            this.btnDownload.Text = "Download >";
            this.btnDownload.Click += new System.EventHandler(this.btnDownload_Click);
            // 
            // rbBin
            // 
            this.rbBin.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.rbBin.Location = new System.Drawing.Point(19, 20);
            this.rbBin.Name = "rbBin";
            this.rbBin.Size = new System.Drawing.Size(78, 24);
            this.rbBin.TabIndex = 19;
            this.rbBin.Text = "Binary";
            // 
            // rbAsc
            // 
            this.rbAsc.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.rbAsc.Location = new System.Drawing.Point(19, 46);
            this.rbAsc.Name = "rbAsc";
            this.rbAsc.Size = new System.Drawing.Size(82, 24);
            this.rbAsc.TabIndex = 21;
            this.rbAsc.Text = "ASCII";
            // 
            // btnRefresh
            // 
            this.btnRefresh.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.btnRefresh.Location = new System.Drawing.Point(19, 87);
            this.btnRefresh.Name = "btnRefresh";
            this.btnRefresh.Size = new System.Drawing.Size(90, 29);
            this.btnRefresh.TabIndex = 5;
            this.btnRefresh.Text = "Refresh";
            this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click);
            // 
            // btnMakeDir
            // 
            this.btnMakeDir.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.btnMakeDir.Location = new System.Drawing.Point(19, 121);
            this.btnMakeDir.Name = "btnMakeDir";
            this.btnMakeDir.Size = new System.Drawing.Size(90, 28);
            this.btnMakeDir.TabIndex = 7;
            this.btnMakeDir.Text = "Create folder";
            this.btnMakeDir.Click += new System.EventHandler(this.btnMakeDir_Click);
            // 
            // cbDrives
            // 
            this.cbDrives.ItemHeight = 15;
            this.cbDrives.Location = new System.Drawing.Point(20, 49);
            this.cbDrives.Name = "cbDrives";
            this.cbDrives.Size = new System.Drawing.Size(88, 23);
            this.cbDrives.TabIndex = 4;
            this.cbDrives.SelectedIndexChanged += new System.EventHandler(this.cbDrives_SelectedIndexChanged);
            // 
            // btnConnect
            // 
            this.btnConnect.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.btnConnect.Location = new System.Drawing.Point(19, 20);
            this.btnConnect.Name = "btnConnect";
            this.btnConnect.Size = new System.Drawing.Size(90, 28);
            this.btnConnect.TabIndex = 3;
            this.btnConnect.Text = "Connect...";
            this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);
            // 
            // gbControl
            // 
            this.gbControl.Anchor = System.Windows.Forms.AnchorStyles.Top;
            this.gbControl.Controls.Add(this.btnStop);
            this.gbControl.Controls.Add(this.btnDelete);
            this.gbControl.Controls.Add(this.btnUpload);
            this.gbControl.Controls.Add(this.btnDownload);
            this.gbControl.Controls.Add(this.btnRefresh);
            this.gbControl.Controls.Add(this.btnMakeDir);
            this.gbControl.Controls.Add(this.cbDrives);
            this.gbControl.Controls.Add(this.btnConnect);
            this.gbControl.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.gbControl.Location = new System.Drawing.Point(5, 4);
            this.gbControl.Name = "gbControl";
            this.gbControl.Size = new System.Drawing.Size(127, 323);
            this.gbControl.TabIndex = 25;
            this.gbControl.TabStop = false;
            this.gbControl.Text = "Controls";
            // 
            // gbTransfer
            // 
            this.gbTransfer.Anchor = System.Windows.Forms.AnchorStyles.Top;
            this.gbTransfer.Controls.Add(this.rbBin);
            this.gbTransfer.Controls.Add(this.rbAsc);
            this.gbTransfer.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.gbTransfer.Location = new System.Drawing.Point(5, 333);
            this.gbTransfer.Name = "gbTransfer";
            this.gbTransfer.Size = new System.Drawing.Size(127, 137);
            this.gbTransfer.TabIndex = 29;
            this.gbTransfer.TabStop = false;
            this.gbTransfer.Text = "Transfer";
            // 
            // pbSecure
            // 
            this.pbSecure.Image = ((System.Drawing.Image)(resources.GetObject("pbSecure.Image")));
            this.pbSecure.Location = new System.Drawing.Point(45, 12);
            this.pbSecure.Name = "pbSecure";
            this.pbSecure.Size = new System.Drawing.Size(38, 39);
            this.pbSecure.TabIndex = 29;
            this.pbSecure.TabStop = false;
            this.pbSecure.Visible = false;
            // 
            // headerLeft
            // 
            this.headerLeft.BackColor = System.Drawing.Color.White;
            this.headerLeft.Image = ((System.Drawing.Image)(resources.GetObject("headerLeft.Image")));
            this.headerLeft.Location = new System.Drawing.Point(0, 0);
            this.headerLeft.Margin = new System.Windows.Forms.Padding(0);
            this.headerLeft.Name = "headerLeft";
            this.headerLeft.Size = new System.Drawing.Size(470, 59);
            this.headerLeft.TabIndex = 26;
            this.headerLeft.TabStop = false;
            // 
            // headerRight
            // 
            this.headerRight.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.headerRight.BackColor = System.Drawing.Color.White;
            this.headerRight.Cursor = System.Windows.Forms.Cursors.Hand;
            this.headerRight.Image = ((System.Drawing.Image)(resources.GetObject("headerRight.Image")));
            this.headerRight.Location = new System.Drawing.Point(634, 0);
            this.headerRight.Margin = new System.Windows.Forms.Padding(0);
            this.headerRight.Name = "headerRight";
            this.headerRight.Size = new System.Drawing.Size(150, 59);
            this.headerRight.TabIndex = 28;
            this.headerRight.TabStop = false;
            this.headerRight.Click += new System.EventHandler(this.headerRight_Click);
            // 
            // btnErrorWarning
            // 
            this.btnErrorWarning.Dock = System.Windows.Forms.DockStyle.Right;
            this.btnErrorWarning.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
            this.btnErrorWarning.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point);
            this.btnErrorWarning.Location = new System.Drawing.Point(759, 0);
            this.btnErrorWarning.Name = "btnErrorWarning";
            this.btnErrorWarning.Size = new System.Drawing.Size(25, 110);
            this.btnErrorWarning.TabIndex = 29;
            this.btnErrorWarning.Text = "!";
            this.btnErrorWarning.Click += new System.EventHandler(this.btnErrorWarning_Click);
            // 
            // trackBar
            // 
            this.trackBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.trackBar.LargeChange = 10;
            this.trackBar.Location = new System.Drawing.Point(4, 434);
            this.trackBar.Maximum = 100;
            this.trackBar.Minimum = 1;
            this.trackBar.Name = "trackBar";
            this.trackBar.Size = new System.Drawing.Size(307, 45);
            this.trackBar.SmallChange = 5;
            this.trackBar.TabIndex = 30;
            this.trackBar.TickFrequency = 5;
            this.trackBar.Value = 100;
            this.trackBar.Scroll += new System.EventHandler(this.trackBar_Scroll);
            // 
            // lblSpeed
            // 
            this.lblSpeed.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
            this.lblSpeed.Location = new System.Drawing.Point(197, 407);
            this.lblSpeed.Name = "lblSpeed";
            this.lblSpeed.Size = new System.Drawing.Size(114, 25);
            this.lblSpeed.TabIndex = 0;
            this.lblSpeed.Text = "Speed: Unlimited";
            this.lblSpeed.TextAlign = System.Drawing.ContentAlignment.TopRight;
            // 
            // headerMiddle
            // 
            this.headerMiddle.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.headerMiddle.BackColor = System.Drawing.Color.White;
            this.headerMiddle.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("headerMiddle.BackgroundImage")));
            this.headerMiddle.Controls.Add(this.pbSecure);
            this.headerMiddle.Location = new System.Drawing.Point(470, 0);
            this.headerMiddle.Name = "headerMiddle";
            this.headerMiddle.Size = new System.Drawing.Size(164, 59);
            this.headerMiddle.TabIndex = 27;
            // 
            // mainStatusStrip
            // 
            this.mainStatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.pbTransfer,
            this.lblProgress});
            this.mainStatusStrip.Location = new System.Drawing.Point(0, 656);
            this.mainStatusStrip.Name = "mainStatusStrip";
            this.mainStatusStrip.Size = new System.Drawing.Size(784, 25);
            this.mainStatusStrip.TabIndex = 31;
            this.mainStatusStrip.Text = "statusStrip";
            // 
            // pbTransfer
            // 
            this.pbTransfer.Name = "pbTransfer";
            this.pbTransfer.Size = new System.Drawing.Size(192, 19);
            // 
            // lblProgress
            // 
            this.lblProgress.Name = "lblProgress";
            this.lblProgress.Size = new System.Drawing.Size(60, 20);
            this.lblProgress.Text = "Welcome!";
            // 
            // mainSplitContainer
            // 
            this.mainSplitContainer.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
            | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.mainSplitContainer.Location = new System.Drawing.Point(0, 59);
            this.mainSplitContainer.Name = "mainSplitContainer";
            this.mainSplitContainer.Orientation = System.Windows.Forms.Orientation.Horizontal;
            // 
            // mainSplitContainer.Panel1
            // 
            this.mainSplitContainer.Panel1.Controls.Add(this.tableLayout);
            this.mainSplitContainer.Panel1MinSize = 320;
            // 
            // mainSplitContainer.Panel2
            // 
            this.mainSplitContainer.Panel2.Controls.Add(this.tbLog);
            this.mainSplitContainer.Panel2.Controls.Add(this.btnErrorWarning);
            this.mainSplitContainer.Panel2MinSize = 30;
            this.mainSplitContainer.Size = new System.Drawing.Size(784, 597);
            this.mainSplitContainer.SplitterDistance = 483;
            this.mainSplitContainer.TabIndex = 32;
            // 
            // tableLayout
            // 
            this.tableLayout.ColumnCount = 3;
            this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
            this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 144F));
            this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
            this.tableLayout.Controls.Add(this.panelRight, 2, 0);
            this.tableLayout.Controls.Add(this.panelLeft, 0, 0);
            this.tableLayout.Controls.Add(this.panelMiddle, 1, 0);
            this.tableLayout.Dock = System.Windows.Forms.DockStyle.Fill;
            this.tableLayout.Location = new System.Drawing.Point(0, 0);
            this.tableLayout.Name = "tableLayout";
            this.tableLayout.RowCount = 1;
            this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
            this.tableLayout.Size = new System.Drawing.Size(784, 483);
            this.tableLayout.TabIndex = 31;
            // 
            // panelRight
            // 
            this.panelRight.Controls.Add(this.lblLocalDirectory);
            this.panelRight.Controls.Add(this.lblLocal);
            this.panelRight.Controls.Add(this.listLocal);
            this.panelRight.Dock = System.Windows.Forms.DockStyle.Fill;
            this.panelRight.Location = new System.Drawing.Point(467, 3);
            this.panelRight.Name = "panelRight";
            this.panelRight.Size = new System.Drawing.Size(314, 477);
            this.panelRight.TabIndex = 2;
            // 
            // panelLeft
            // 
            this.panelLeft.Controls.Add(this.lblServerDirectory);
            this.panelLeft.Controls.Add(this.trackBar);
            this.panelLeft.Controls.Add(this.listServer);
            this.panelLeft.Controls.Add(this.lblServer);
            this.panelLeft.Controls.Add(this.lblSpeed);
            this.panelLeft.Dock = System.Windows.Forms.DockStyle.Fill;
            this.panelLeft.Location = new System.Drawing.Point(3, 3);
            this.panelLeft.Name = "panelLeft";
            this.panelLeft.Size = new System.Drawing.Size(314, 477);
            this.panelLeft.TabIndex = 1;
            // 
            // panelMiddle
            // 
            this.panelMiddle.Controls.Add(this.gbControl);
            this.panelMiddle.Controls.Add(this.gbTransfer);
            this.panelMiddle.Dock = System.Windows.Forms.DockStyle.Fill;
            this.panelMiddle.Location = new System.Drawing.Point(323, 3);
            this.panelMiddle.Name = "panelMiddle";
            this.panelMiddle.Size = new System.Drawing.Size(138, 477);
            this.panelMiddle.TabIndex = 0;
            // 
            // MainForm
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(6, 16);
            this.ClientSize = new System.Drawing.Size(784, 681);
            this.Controls.Add(this.mainSplitContainer);
            this.Controls.Add(this.headerLeft);
            this.Controls.Add(this.headerMiddle);
            this.Controls.Add(this.mainStatusStrip);
            this.Controls.Add(this.headerRight);
            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
            this.KeyPreview = true;
            this.MinimumSize = new System.Drawing.Size(690, 720);
            this.Name = "MainForm";
            this.Text = "Simple WinForm File Transfer Client";
            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_Closing);
            this.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.MainForm_KeyPress);
            this.gbControl.ResumeLayout(false);
            this.gbTransfer.ResumeLayout(false);
            ((System.ComponentModel.ISupportInitialize)(this.pbSecure)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.headerLeft)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.headerRight)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.trackBar)).EndInit();
            this.headerMiddle.ResumeLayout(false);
            this.mainStatusStrip.ResumeLayout(false);
            this.mainStatusStrip.PerformLayout();
            this.mainSplitContainer.Panel1.ResumeLayout(false);
            this.mainSplitContainer.Panel2.ResumeLayout(false);
            ((System.ComponentModel.ISupportInitialize)(this.mainSplitContainer)).EndInit();
            this.mainSplitContainer.ResumeLayout(false);
            this.tableLayout.ResumeLayout(false);
            this.panelRight.ResumeLayout(false);
            this.panelLeft.ResumeLayout(false);
            this.panelLeft.PerformLayout();
            this.panelMiddle.ResumeLayout(false);
            this.ResumeLayout(false);
            this.PerformLayout();

        }
        #endregion

        /// <summary>
        /// win form client starts here
        /// </summary>
        [STAThread]
        static void Main()
        {
            // set the trial license key
            Rebex.Licensing.Key = Rebex.Samples.TrialKey.Key;


            Application.Run(new MainForm());
        }

        /// <summary>
        /// connect/disconnect remote server
        /// </summary>
        private async void btnConnect_Click(object sender, System.EventArgs e)
        {
            if (_client != null)
            {
                if (_isWorking)
                    return;

                // disconnect

                trackBar.Enabled = false;
                _client.Disconnect();
                _client.Dispose();
                _client = null;
                lblProgress.Text = "Disconnected";
                btnConnect.Text = "Connect...";
                MakeRemoteList(); // clearing
                return;
            }

            // connection dialog

            ConnectionForm connectionDialog = new ConnectionForm(_connectionData);

            DialogResult result = connectionDialog.ShowDialog();

            _connectionData.SaveConfig();

            if (result != DialogResult.OK)
                return;

            // create client object
            _client = new FileTransferClient();

            // assign the logger
            _client.LogWriter = new RichTextBoxLogWriter(tbLog, tbLog.MaxLength, _connectionData.LogLevel);

            // set event handlers
            _client.Traversing += new EventHandler<TraversingEventArgs>(Traversing);
            _client.TransferProgressChanged += new EventHandler<TransferProgressChangedEventArgs>(TransferProgressChanged);
            _client.DeleteProgressChanged += new EventHandler<DeleteProgressChangedEventArgs>(DeleteProgressChanged);
            _client.ProblemDetected += new EventHandler<ProblemDetectedEventArgs>(ProblemDetected);

            try
            {
                _client.FtpPassiveMode = _connectionData.PassiveMode;

                // proxy
                if (_connectionData.ProxyType != FileTransferProxyType.None)
                {
                    NetworkCredential credential = null;
                    if (!string.IsNullOrEmpty(_connectionData.ProxyUser))
                        credential = new System.Net.NetworkCredential(_connectionData.ProxyUser, _connectionData.ProxyPassword);

                    _client.Proxy = (_connectionData.FileTransferMode == FileTransferMode.Sftp ? new Proxy() : new FtpProxy());
                    _client.Proxy.AuthenticationMethod = ProxyAuthentication.Basic;
                    _client.Proxy.ProxyType = (ProxyType)_connectionData.ProxyType;
                    _client.Proxy.Host = _connectionData.ProxyHost;
                    _client.Proxy.Port = _connectionData.ProxyPort;
                    _client.Proxy.Credentials = credential;
                }

                // setup SSL server certificate verifier
                if (_connectionData.FileTransferMode == FileTransferMode.FtpSslExplicit || _connectionData.FileTransferMode == FileTransferMode.FtpSslImplicit)
                {
                    _client.ValidatingCertificate += client_ValidatingCertificate;
                }

                if (_connectionData.FileTransferMode == FileTransferMode.Sftp)
                {
                    _client.FingerprintCheck += client_FingerprintCheck;
                }

                // set preferred SSH host key algorithm 
                if (_connectionData.FileTransferMode == FileTransferMode.Sftp && _connectionData.ServerKeyVerifyingMode == KeyVerifyingMode.LocalyStoredFingerprint)
                    _client.Settings.SshParameters.PreferredHostKeyAlgorithm = _connectionData.ServerKeyAlgorithm;

                if (_connectionData.AllowWeakSuites)
                {
                    _client.Settings.SshParameters.EncryptionAlgorithms = SshEncryptionAlgorithm.Any;
                    _client.Settings.SshParameters.HostKeyAlgorithms = SshHostKeyAlgorithm.Any;
                    _client.Settings.SshParameters.KeyExchangeAlgorithms = SshKeyExchangeAlgorithm.Any;
                    _client.Settings.SshParameters.MacAlgorithms = SshMacAlgorithm.Any;
                    _client.Settings.SshParameters.MinimumDiffieHellmanKeySize = 512;
                    _client.Settings.SshParameters.MinimumRsaKeySize = 512;
                }

                if (_connectionData.ClientCertificate != null)
                    _client.Settings.SslClientCertificateRequestHandler = CertificateRequestHandler.CreateRequestHandler(_connectionData.ClientCertificate);

                

                _client.Settings.SslAllowedSuites = _connectionData.AllowedSuite;
                _client.Settings.SslAllowedVersions = _connectionData.TlsProtocol;

                // connect
                btnStop.Visible = true;
                _isWorking = true;

                try
                {
                    await _client.ConnectAsync(_connectionData.ServerHost, _connectionData.ServerPort, _connectionData.FileTransferMode);
                }
                finally
                {
                    btnStop.Visible = false;
                    _isWorking = false;
                }

                // login
                if (!_client.IsAuthenticated)
                {
                    btnStop.Visible = true;
                    _isWorking = true;

                    try
                    {
                        if (_connectionData.UseGssApi && _connectionData.FileTransferMode == FileTransferMode.Sftp)
                        {
                            SshGssApiCredentials credentials;
                            if (string.IsNullOrEmpty(_connectionData.ServerUser))
                                credentials = new SshGssApiCredentials();	// single sign-on
                            else
                                credentials = new SshGssApiCredentials(_connectionData.ServerUser, _connectionData.ServerPassword, _connectionData.ServerDomain);

                            await _client.LoginAsync(credentials);
                        }
                        else
                        {
                            if (_connectionData.PrivateKey != null)
                            {
                                await _client.LoginAsync(_connectionData.ServerUser, _connectionData.ServerPassword, _connectionData.PrivateKey);
                            }
                            else if (_connectionData.ClientCertificate != null && _connectionData.FileTransferMode == FileTransferMode.Sftp)
                            {
                                SshPrivateKey key = null;
                                if (_connectionData.ClientCertificate != null)
                                    key = new SshPrivateKey(_connectionData.ClientCertificate.LeafCertificate);

                                await _client.LoginAsync(_connectionData.ServerUser, _connectionData.ServerPassword, key);
                            }
                            else
                            {
                                await _client.LoginAsync(_connectionData.ServerUser, _connectionData.ServerPassword);
                            }
                        }
                    }
                    finally
                    {
                        btnStop.Visible = false;
                        _isWorking = false;
                    }
                }

                // CCC
                if (_connectionData.ClearCommandChannel 
                    && (_connectionData.FileTransferMode == FileTransferMode.FtpSslExplicit || _connectionData.FileTransferMode == FileTransferMode.FtpSslImplicit))
                    _client.Settings.ClearCommandChannel();

                trackBar.Enabled = true;
                btnErrorWarning.Visible = false;
                btnConnect.Text = "Disconnect";
                lblProgress.Text = "Connected";
                MakeRemoteList();
            }
            catch (Exception ex)
            {
                WriteToLog(ex);
                if (_client != null)
                {
                    _client.Dispose();
                    _client = null;
                    lblProgress.Text = "Disconnected";
                }
            }
            finally
            {
                btnStop.Visible = false;
                _isWorking = false;
            }
        }

        /// <summary>
        /// Event handler for FileTransferClient.FingerprintCheck. Validates SFTP server keys (using a fingerprint).
        /// </summary>
        private void client_FingerprintCheck(object sender, SshFingerprintEventArgs e)
        {
            switch (_connectionData.ServerKeyVerifyingMode)
            {
                case KeyVerifyingMode.AcceptAnyKey:
                    e.Accept = true;
                    break;

                case KeyVerifyingMode.LocalyStoredFingerprint:
                    string fingerprint = e.Fingerprint.ToString(_connectionData.ServerKeyHashAlgorithm);
                    if (fingerprint == _connectionData.ServerKeyFingerprint)
                    {
                        e.Accept = true;
                        break;
                    }

                    ResolveDialogMode resolveMode;
                    string resolveMessage;

                    if (!string.IsNullOrEmpty(_connectionData.ServerKeyFingerprint))
                    {
                        resolveMode = ResolveDialogMode.EntryDiffer;
                        resolveMessage = "Stored fingerprint does not match the server key fingerprint.";
                    }
                    else
                    {
                        resolveMode = ResolveDialogMode.EntryNotFound;
                        resolveMessage = "Server key is not known yet.";
                    }

                    // ask user for an action, if the stored fingerprint does not match
                    ResolveInvalidKeyDialog dlg = new ResolveInvalidKeyDialog(
                        resolveMode,
                        resolveMessage,
                        _connectionData.ServerKeyHashAlgorithm,
                        _connectionData.ServerKeyAlgorithm,
                        _connectionData.ServerKeyFingerprint,
                        e.ServerKey.KeyAlgorithm,
                        fingerprint);

                    // a) user has not specified any solution
                    if (dlg.ShowDialog() != DialogResult.OK)
                    {
                        e.Accept = false;
                        break;
                    }

                    // b) user has specified a solution, that changes the current mode
                    KeyVerifyingMode mode = dlg.GetChoosenMode();
                    switch (mode)
                    {
                        case KeyVerifyingMode.AcceptAnyKey:
                            e.Accept = true;
                            break;
                        case KeyVerifyingMode.LocalyStoredFingerprint:
                            _connectionData.ServerKeyFingerprint = fingerprint;
                            _connectionData.SaveConfig(); // save the changed mode
                            e.Accept = true;
                            break;
                        case KeyVerifyingMode.RejectKey:
                            e.Accept = false;
                            break;
                        default:
                            throw new InvalidOperationException(string.Format("Unsupported enum value '{0}'", mode));
                    }					
                    break;
                default:
                    throw new InvalidOperationException(string.Format("Unsupported KeyVerifyingMode '{0}'.", _connectionData.ServerKeyVerifyingMode));
            }
        }

        /// <summary>
        /// Event handler for FileTransferClient.ValidatingCertificate. Validates FTP server certificates.
        /// </summary>
        private void client_ValidatingCertificate(object sender, SslCertificateValidationEventArgs e)
        {
            while (true)
            {
                TlsCertificateAcceptance rejectReason = TlsCertificateAcceptance.Other;
                ResolveDialogMode resolveMode = 0;
                string resolveMessage = null;
                bool showAddIssuerCaToTrustedCaStore = false;

                switch (_connectionData.ServerCertificateVerifyingMode)
                {
                    case CertificateVerifyingMode.AcceptAnyCertificate:
                        // do nothing
                        e.Accept();
                        return;

                    case CertificateVerifyingMode.LocalyStoredThumbprint:
                        if (_connectionData.ServerCertificateThumbprint == e.Certificate.Thumbprint)
                        {
                            e.Accept();
                            return;
                        }

                        if (!string.IsNullOrEmpty(_connectionData.ServerCertificateThumbprint))
                        {
                            resolveMode = ResolveDialogMode.EntryDiffer;
                            resolveMessage = "Certificate thumbprint does not match the stored thumbprint.";
                        }
                        else
                        {
                            resolveMode = ResolveDialogMode.EntryNotFound;
                            resolveMessage = "Server certificate is not known yet.";
                        }
                        break;

                    case CertificateVerifyingMode.UseWindowsInfrastructure:
                        // validate using Windows infrastructure
                        ValidationResult res = e.CertificateChain.Validate(e.ServerName, ValidationOptions.None);

                        if (res.Valid)
                        {
                            e.Accept();
                            return;
                        }

                        resolveMode = ResolveDialogMode.EntryDiffer;

                        if (e.CertificateChain.RootCertificate != null && ((res.Status & ValidationStatus.RootNotTrusted) != 0))
                            showAddIssuerCaToTrustedCaStore = true;

                        resolveMessage = GetValidationResultDescription(res);

                        rejectReason = GetRejectReason(res);
                        break;

                    default:
                        throw new InvalidOperationException(string.Format("Unsupported VerifyingMode '{0}'.", _connectionData.ServerCertificateVerifyingMode));
                }

                // ask user for an action, if the certificate is invalid
                ResolveInvalidCertficiateDialog dlg = new ResolveInvalidCertficiateDialog(
                    resolveMode,
                    resolveMessage,
                    e.CertificateChain,
                    _connectionData.ServerCertificateThumbprint);

                dlg.EnableAddCertificateToCA(showAddIssuerCaToTrustedCaStore);

                if (dlg.ShowDialog() != DialogResult.OK)
                {
                    e.Reject(rejectReason);
                    return;
                }

                // change current mode according to selected options
                CertificateVerifyingMode choosenMode = dlg.GetChoosenMode();
                switch (choosenMode)
                {
                    case CertificateVerifyingMode.AcceptAnyCertificate:
                        e.Accept();
                        return;
                    case CertificateVerifyingMode.LocalyStoredThumbprint:
                        // store the new thumbprint
                        _connectionData.ServerCertificateVerifyingMode = choosenMode;
                        _connectionData.ServerCertificateThumbprint = e.Certificate.Thumbprint;
                        _connectionData.SaveConfig();
                        break;
                    case CertificateVerifyingMode.UseWindowsInfrastructure:
                        _connectionData.ServerCertificateVerifyingMode = choosenMode;
                        _connectionData.SaveConfig();
                        break;
                    case CertificateVerifyingMode.RejectCertificate:
                        e.Reject(TlsCertificateAcceptance.Other); 
                        return;
                }
            }
        }

        /// <summary>
        /// Converts certificate validation result to rejection reason.
        /// </summary>
        /// <param name="result">Certificate validation result.</param>
        /// <returns>Reject reason.</returns>
        private TlsCertificateAcceptance GetRejectReason(ValidationResult result)
        {
            if ((result.Status & ValidationStatus.TimeNotValid) != 0)
                return TlsCertificateAcceptance.Expired;
            if ((result.Status & ValidationStatus.Revoked) != 0)
                return TlsCertificateAcceptance.Revoked;
            if ((result.Status & (ValidationStatus.RootNotTrusted | ValidationStatus.IncompleteChain)) != 0)
                return TlsCertificateAcceptance.UnknownAuthority;
            if ((result.Status & (ValidationStatus.Malformed | ValidationStatus.UnknownError)) != 0)
                return TlsCertificateAcceptance.Other;
            return TlsCertificateAcceptance.Bad;
        }

        /// <summary>
        /// Constructs a human-readable string describing the certificate validation result.
        /// </summary>
        /// <param name="result">Certificate validation result.</param>
        /// <returns>Validation result description.</returns>
        private static string GetValidationResultDescription(ValidationResult result)
        {
            StringBuilder sb = new StringBuilder();
            ValidationStatus status = result.Status;
            ValidationStatus[] values = (ValidationStatus[])Enum.GetValues(typeof(ValidationStatus));

            for (int i = 0; i < values.Length; i++)
            {
                if ((status & values[i]) == 0)
                    continue;

                status ^= values[i];
                string problem;

                switch (values[i])
                {
                    case ValidationStatus.TimeNotValid:
                        problem = "Server certificate has expired or is not valid yet.";
                        break;
                    case ValidationStatus.Revoked:
                        problem = "Server certificate has been revoked.";
                        break;
                    case ValidationStatus.RootNotTrusted:
                        problem = "Server certificate was issued by an untrusted authority.";						
                        break;
                    case ValidationStatus.IncompleteChain:
                        problem = "Server certificate does not chain up to a trusted root authority.";
                        break;
                    case ValidationStatus.Malformed:
                        problem = "Server certificate is malformed.";
                        break;
                    case ValidationStatus.CnNotMatch:
                        problem = "Server hostname does not match the certificate.";
                        break;
                    case ValidationStatus.UnknownError:
                        problem = string.Format("Error {0:x} encountered while validating server's certificate.", result.NativeErrorCode);
                        break;
                    default:
                        problem = values[i].ToString();
                        break;
                }

                sb.AppendFormat("{0}\r\n", problem);
            }
            return sb.ToString();
        }

        /// <summary>
        /// disconnect on exit
        /// </summary>
        private void MainForm_Closing(object sender, FormClosingEventArgs e)
        {
            if (_client != null)
                _client.Dispose();
        }

        /// <summary>
        /// CWD or GET file command on server side
        /// </summary>
        private void ListServerClick()
        {
            try
            {
                if (listServer.Items.Count < 1)
                    return;

                if (listServer.SelectedItems.Count < 1)
                    listServer.Items[0].Selected = true;

                listServer.Focus();

                // client state test

                if (_isWorking)
                    return;

                int index = listServer.SelectedIndices[0];
                ListViewItem item = listServer.SelectedItems[0];

                if (index >= _serverDirs)
                {
                    // GET file

                    DownloadFiles(item.Text, _localPath);
                }
                else
                {
                    // CWD

                    string directory;
                    if (index == 0)
                        directory = "..";
                    else
                        directory = item.Text;

                    _client.ChangeDirectory(directory);

                    MakeRemoteList();
                }
            }
            catch (Exception ex)
            {
                WriteToLog(ex);
            }
        }

        private void listServer_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
        {
            if (e.KeyChar == '\r')
            {
                ListServerClick();
                listServer.Focus();
            }
        }

        private void listServer_DoubleClick(object sender, System.EventArgs e)
        {
            ListServerClick();
            listServer.Focus();
        }

        /// <summary>
        /// change drive letter
        /// </summary>
        private void cbDrives_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            try
            {
                _localPath = cbDrives.SelectedItem.ToString();
                MakeLocalList();
            }
            catch (Exception ex)
            {
                WriteToLog(ex);
                listLocal.Items.Clear();
                lblLocalDirectory.Text = lblLocal.Text = null;
            }
        }

        /// <summary>
        /// LCD or PUT command on local side
        /// </summary>
        private void ListLocalClick()
        {
            try
            {
                if (listLocal.Items.Count < 1)
                    return;

                if (listLocal.SelectedItems.Count < 1)
                    listLocal.Items[0].Selected = true;

                listLocal.Focus();

                int index = listLocal.SelectedIndices[0];
                ListViewItem item = listLocal.SelectedItems[0];

                if (index >= _localDirs)
                {
                    // upload file

                    UploadFiles(item.Text, _localPath);
                }
                else
                {
                    // local change directory

                    _localPath = Path.Combine(_localPath, item.Text);
                    MakeLocalList();
                }
            }
            catch (Exception ex)
            {
                WriteToLog(ex);
            }
        }

        private void listLocal_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
        {
            if (e.KeyChar == '\r')
            {
                ListLocalClick();
                if (listLocal.Items.Count > 0)
                {
                    listLocal.Focus();
                }
            }
        }

        private void listLocal_DoubleClick(object sender, System.EventArgs e)
        {
            ListLocalClick();
            listLocal.Focus();
        }

        /// <summary>
        /// make dir
        /// </summary>
        private void btnMakeDir_Click(object sender, System.EventArgs e)
        {
            try
            {
                MakeDir dir = new MakeDir();

                // REMOTE: MKDIR

                if (listActive == listServer)
                {
                    if (_isWorking)
                        return;

                    dir.ShowDialog();
                    if (dir.Directory != null)
                    {
                        _client.CreateDirectory(dir.Directory);
                        MakeRemoteList();
                    }
                }
                else
                {
                    // LOCAL: MKDIR

                    dir.ShowDialog();

                    if (dir.Directory != null)
                    {
                        Directory.CreateDirectory(Path.Combine(_localPath, dir.Directory));
                        MakeLocalList();
                    }
                }
            }
            catch (Exception ex)
            {
                WriteToLog(ex);
            }
        }

        /// <summary>
        /// refresh listing
        /// </summary>
        private void btnRefresh_Click(object sender, System.EventArgs e)
        {
            try
            {
                if (listActive == listServer)
                {
                    if (_isWorking)
                        return;

                    MakeRemoteList();
                }
                else
                {
                    MakeLocalList();
                }
            }
            catch (Exception ex)
            {
                WriteToLog(ex);
            }
        }

        private void PrepareTransfer()
        {
            // set asc/bin transfers
            if (rbBin.Checked)
                _client.TransferType = TransferType.Binary;
            else
                _client.TransferType = TransferType.Ascii;

            // transfer
            _isWorking = true;
            btnStop.Visible = true;
            _problemForm.Initialize();
            _transferTime = DateTime.Now;
        }

        /// <summary>
        /// download file or directory tree
        /// </summary>
        /// <param name="fileName">remote file name</param>
        /// <param name="localPath">local path</param>
        private async void DownloadFiles(string fileName, string localPath)
        {
            // client state test
            if (_isWorking)
                return;

            PrepareTransfer();

            try
            {
                await _client.DownloadAsync(fileName, localPath, TraversalMode.Recursive, TransferMethod.Copy, ActionOnExistingFiles.ThrowException);
            }
            catch (Exception ex)
            {
                WriteToLog(ex);
            }
            finally
            {
                MakeLocalList();
                TransferCompleted();
            }
        }

        /// <summary>
        /// upload file or directory tree
        /// </summary>
        /// <param name="fileName">local file name</param>
        /// <param name="localPath">local path</param>
        private async void UploadFiles(string fileName, string localPath)
        {
            // client state test
            if (_client == null)
            {
                WriteToLog("Not connected!", Color.DarkOrange);
                return;
            }
            if (_isWorking)
                return;

            localPath = Path.Combine(localPath, fileName);

            PrepareTransfer();

            try
            {
                await _client.UploadAsync(localPath, ".", TraversalMode.Recursive, TransferMethod.Copy, ActionOnExistingFiles.ThrowException);
            }
            catch (Exception ex)
            {
                WriteToLog(ex);
            }
            finally
            {
                MakeRemoteList();
                TransferCompleted();
            }


        }

        private void TransferCompleted()
        {
            btnStop.Visible = false;
            _isWorking = false;
            SetProgressValue(0);
        }

        /// <summary>
        /// show transfer status: files, bytes, time, speed
        /// </summary>
        private void ShowTransferStatus(long bytesTransferred, int filesTransferred)
        {
            // unknown bytes transferred
            if (bytesTransferred == 0)
                return;

            // files and bytes transferred
            string outstring = string.Format("{0} file{1} ({2} byte{3}) transferred in",
                filesTransferred, (filesTransferred > 1 ? "s" : null),
                bytesTransferred, (bytesTransferred > 1 ? "s" : null));

            // time spent
            TimeSpan ts = DateTime.Now - _transferTime;

            // speed
            if (ts.TotalSeconds > 1)
            {
                outstring += (ts.Days > 0 ? " " + ts.Days + " day" + (ts.Days > 1 ? "s" : null) : null);
                outstring += (ts.Hours > 0 ? " " + ts.Hours + " hour" + (ts.Hours > 1 ? "s" : null) : null);
                outstring += (ts.Minutes > 0 ? " " + ts.Minutes + " min" + (ts.Minutes > 1 ? "s" : null) : null);
                outstring += (ts.Seconds > 0 ? " " + ts.Seconds + " sec" + (ts.Seconds > 1 ? "s" : null) : null);
            }
            else
            {
                outstring += " " + ts.TotalSeconds + " sec";
            }

            double speed = bytesTransferred / ts.TotalSeconds;
            if (speed < 1)
                outstring += string.Format(" at {0:F3} B/s", speed);
            else if (speed < 1024)
                outstring += string.Format(" at {0:F0} B/s", speed);
            else
                outstring += string.Format(" at {0:F0} KB/s", speed / 1024);


            WriteToLog("> " + outstring, RichTextBoxLogWriter.COLORCOMMAND);
        }

        /// <summary>
        /// handle download button click
        /// </summary>
        private void btnDownload_Click(object sender, System.EventArgs e)
        {
            try
            {
                if (listActive != listServer)
                    return;

                if (_isWorking)
                    return;

                if (listServer.SelectedItems.Count > 0)
                    DownloadFiles(listServer.SelectedItems[0].Text, _localPath);
            }
            catch (Exception ex)
            {
                WriteToLog(ex);
            }
        }

        /// <summary>
        /// handle upload button click
        /// </summary>
        private void btnUpload_Click(object sender, System.EventArgs e)
        {
            try
            {
                if (listActive == listServer)
                    return;

                if (_isWorking)
                    return;

                if (listLocal.SelectedItems.Count > 0)
                    UploadFiles(listLocal.SelectedItems[0].Text, _localPath);
            }
            catch (Exception ex)
            {
                WriteToLog(ex);
            }
        }

        /// <summary>
        /// handle delete button click
        /// </summary>
        private void btnDelete_Click(object sender, System.EventArgs e)
        {
            try
            {
                if (listActive == listServer)
                {
                    if (_isWorking)
                        return;

                    if (listServer.SelectedItems.Count > 0)
                    {
                        int index = listServer.SelectedIndices[0];
                        ListViewItem item = listServer.SelectedItems[0];

                        if (index >= _serverDirs)
                        {
                            DeleteDialog dialog = new DeleteDialog(DeleteDialog.DialogPrompt.DeleteFile);
                            dialog.Path = item.Text;
                            dialog.ShowDialog();

                            if (dialog.OK)
                            {
                                _client.DeleteFile(item.Text);
                                MakeRemoteList();
                            }
                        }
                        else
                        {
                            DeleteDialog dialog = new DeleteDialog(DeleteDialog.DialogPrompt.DeleteDirectory);
                            dialog.Path = item.Text;
                            dialog.ShowDialog();

                            if (dialog.OK)
                            {
                                _client.Delete(item.Text, TraversalMode.Recursive);
                                MakeRemoteList();
                            }
                        }
                    }
                }
                else
                {
                    if (listLocal.SelectedItems.Count > 0)
                    {
                        int index = listLocal.SelectedIndices[0];
                        ListViewItem item = listLocal.SelectedItems[0];
                        string path = Path.Combine(_localPath, item.Text);

                        if (index >= _localDirs)
                        {
                            DeleteDialog dialog = new DeleteDialog(DeleteDialog.DialogPrompt.DeleteFile);
                            dialog.Path = item.Text;
                            dialog.ShowDialog();

                            if (dialog.OK)
                            {
                                File.Delete(path);
                                MakeLocalList();
                            }
                        }
                        else
                        {
                            DeleteDialog dialog = new DeleteDialog(DeleteDialog.DialogPrompt.DeleteDirectory);
                            dialog.Path = item.Text;
                            dialog.ShowDialog();

                            if (dialog.OK)
                            {
                                Directory.Delete(path, false);
                                MakeLocalList();
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                WriteToLog(ex);
            }
        }

        /// <summary>
        /// activate panel on focus event
        /// </summary>
        private void listServer_Enter(object sender, System.EventArgs e)
        {
            listActive = listServer;
            lblServerDirectory.BackColor = SystemColors.ActiveCaption;
            lblServerDirectory.ForeColor = SystemColors.ActiveCaptionText;
            lblLocalDirectory.BackColor = SystemColors.InactiveCaption;
            lblLocalDirectory.ForeColor = SystemColors.InactiveCaptionText;
        }

        /// <summary>
        /// activate panel on focus event
        /// </summary>
        private void listLocal_Enter(object sender, System.EventArgs e)
        {
            listActive = listLocal;
            lblServerDirectory.BackColor = SystemColors.InactiveCaption;
            lblServerDirectory.ForeColor = SystemColors.InactiveCaptionText;
            lblLocalDirectory.BackColor = SystemColors.ActiveCaption;
            lblLocalDirectory.ForeColor = SystemColors.ActiveCaptionText;
        }

        /// <summary>
        /// stop transfer when something is being transferred
        /// </summary>
        private void btnStop_Click(object sender, System.EventArgs e)
        {
            _client.Abort();
        }

        /// <summary>
        /// go to the url
        /// </summary>
        private void headerRight_Click(object sender, System.EventArgs e)
        {
            var info = new ProcessStartInfo(URL);
            info.UseShellExecute = true;
            info.Verb = "open";
            Process.Start(info);
        }

        /// <summary>
        /// space bar for changing panels server <-> local
        /// </summary>
        private void MainForm_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
        {
            if (e.KeyChar == Convert.ToChar(Keys.Space))
            {
                if (listActive == listLocal)
                    listServer.Focus();
                else
                    listLocal.Focus();
            }
        }

        private void btnErrorWarning_Click(object sender, System.EventArgs e)
        {
            MessageBox.Show(_exception, "Last occured error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        private void trackBar_Scroll(object sender, EventArgs e)
        {
            if (trackBar.Value == 100)
            {
                lblSpeed.Text = "Speed: Unlimited";
                _client.MaxDownloadSpeed = 0;
                _client.MaxUploadSpeed = 0;
            }
            else
            {
                lblSpeed.Text = string.Format("Speed: {0} kB/s", trackBar.Value);
                _client.MaxDownloadSpeed = trackBar.Value;
                _client.MaxUploadSpeed = trackBar.Value;
            }
        } 
    }

    #region ListViewColumnSorter

    public class ListViewColumnSorter : MultiComparer, IComparer
    {
        public ListViewColumnSorter()
            : base(new FileSystemItemComparer(FileSystemItemComparerType.FileType, SortingOrder.Ascending), new FileSystemItemComparer(FileSystemItemComparerType.Name))
        {
        }

        int IComparer.Compare(object x, object y)
        {
            ListViewItem listViewX = (ListViewItem)x;
            ListViewItem listViewY = (ListViewItem)y;

            FileSystemItem itemX = (FileSystemItem)listViewX.Tag;
            FileSystemItem itemY = (FileSystemItem)listViewY.Tag;

            if (itemX == null)
            {
                if (itemY == null)
                    return 0;

                return -1;
            }
            else if (itemY == null)
            {
                return 1;
            }

            return base.Compare(itemX, itemY);
        }
    }

    #endregion
}
