'  
'   Rebex Sample Code License
' 
'   Copyright 2026, 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.
' 


Imports System
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms
Imports Rebex.Net
Imports Rebex
Imports Rebex.IO



'/ <summary>
'/ Summary description for Form1.
'/ </summary>

Public Class FileListEvents
    Inherits System.Windows.Forms.Form
    Private lblServerDirectory As System.Windows.Forms.Label
    Private WithEvents listServer As System.Windows.Forms.ListView
    Private chName As System.Windows.Forms.ColumnHeader
    Private chSize As System.Windows.Forms.ColumnHeader
    Private chDate As System.Windows.Forms.ColumnHeader
    Private WithEvents btnConnect As System.Windows.Forms.Button
    Private WithEvents btnRefresh As System.Windows.Forms.Button
    Private statusStrip As System.Windows.Forms.StatusStrip
    Private statusLabel As System.Windows.Forms.ToolStripStatusLabel
    '/ <summary>
    '/ Required designer variable.
    '/ </summary>
    Private components As System.ComponentModel.Container = Nothing

    ' ftp object
    Private _ftp As Ftp

    Private _itemCounter As Integer


    Public Sub New()
        Application.EnableVisualStyles()
        CheckForIllegalCrossThreadCalls = True
        '
        ' Required for Windows Form Designer support
        '
        InitializeComponent()

        '
        ' TODO: Add any constructor code after InitializeComponent call
        '
        _itemCounter = 0
        btnRefresh.Enabled = False
    End Sub 'New


    '/ <summary>
    '/ Clean up any resources being used.
    '/ </summary>
    Protected Overloads Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub 'Dispose

#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 Sub InitializeComponent()
        Me.lblServerDirectory = New System.Windows.Forms.Label
        Me.listServer = New System.Windows.Forms.ListView
        Me.chName = New System.Windows.Forms.ColumnHeader
        Me.chSize = New System.Windows.Forms.ColumnHeader
        Me.chDate = New System.Windows.Forms.ColumnHeader
        Me.btnConnect = New System.Windows.Forms.Button
        Me.btnRefresh = New System.Windows.Forms.Button
        Me.statusStrip = New System.Windows.Forms.StatusStrip
        Me.statusLabel = New System.Windows.Forms.ToolStripStatusLabel
        Me.statusStrip.SuspendLayout()
        Me.SuspendLayout()
        ' 
        ' lblServerDirectory
        ' 
        Me.lblServerDirectory.Anchor = CType(System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left Or System.Windows.Forms.AnchorStyles.Right, System.Windows.Forms.AnchorStyles)
        Me.lblServerDirectory.BackColor = System.Drawing.SystemColors.InactiveCaption
        Me.lblServerDirectory.FlatStyle = System.Windows.Forms.FlatStyle.Popup
        Me.lblServerDirectory.Font = New System.Drawing.Font("Microsoft Sans Serif", 8.25, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, System.Byte))
        Me.lblServerDirectory.ForeColor = System.Drawing.SystemColors.InactiveCaptionText
        Me.lblServerDirectory.Location = New System.Drawing.Point(8, 8)
        Me.lblServerDirectory.Name = "lblServerDirectory"
        Me.lblServerDirectory.Size = New System.Drawing.Size(336, 16)
        Me.lblServerDirectory.TabIndex = 2
        Me.lblServerDirectory.Text = "/root"
        Me.lblServerDirectory.TextAlign = System.Drawing.ContentAlignment.MiddleLeft
        ' 
        ' listServer
        ' 
        Me.listServer.Anchor = CType(System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left Or System.Windows.Forms.AnchorStyles.Right, System.Windows.Forms.AnchorStyles)
        Me.listServer.Columns.AddRange(New System.Windows.Forms.ColumnHeader() {Me.chName, Me.chSize, Me.chDate})
        Me.listServer.FullRowSelect = True
        Me.listServer.Location = New System.Drawing.Point(8, 24)
        Me.listServer.MultiSelect = False
        Me.listServer.Name = "listServer"
        Me.listServer.Size = New System.Drawing.Size(336, 328)
        Me.listServer.TabIndex = 3
        Me.listServer.View = System.Windows.Forms.View.Details
        ' 
        ' name
        ' 
        Me.chName.Text = "Name"
        Me.chName.Width = 150
        ' 
        ' size
        ' 
        Me.chSize.Text = "Size"
        Me.chSize.TextAlign = System.Windows.Forms.HorizontalAlignment.Right
        ' 
        ' date
        ' 
        Me.chDate.Text = "Date"
        Me.chDate.Width = 120
        ' 
        ' btnConnect
        ' 
        Me.btnConnect.Anchor = CType(System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right, System.Windows.Forms.AnchorStyles)
        Me.btnConnect.FlatStyle = System.Windows.Forms.FlatStyle.System
        Me.btnConnect.Location = New System.Drawing.Point(272, 360)
        Me.btnConnect.Name = "btnConnect"
        Me.btnConnect.TabIndex = 4
        Me.btnConnect.Text = "&Connect..."
        ' 
        ' btnRefresh
        ' 
        Me.btnRefresh.Anchor = CType(System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left, System.Windows.Forms.AnchorStyles)
        Me.btnRefresh.FlatStyle = System.Windows.Forms.FlatStyle.System
        Me.btnRefresh.Location = New System.Drawing.Point(8, 360)
        Me.btnRefresh.Name = "btnRefresh"
        Me.btnRefresh.TabIndex = 5
        Me.btnRefresh.Text = "&Refresh"
        ' 
        ' statusStrip
        ' 
        Me.statusStrip.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.statusLabel})
        Me.statusStrip.Location = New System.Drawing.Point(0, 392)
        Me.statusStrip.Name = "statusStrip"
        Me.statusStrip.Size = New System.Drawing.Size(352, 22)
        Me.statusStrip.TabIndex = 6
        '
        'statusLabel
        '
        Me.statusLabel.Name = "statusLabel"
        Me.statusLabel.Size = New System.Drawing.Size(90, 21)
        ' 
        ' FileListEvents
        ' 
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(352, 414)
        Me.Controls.Add(statusStrip)
        Me.Controls.Add(btnRefresh)
        Me.Controls.Add(btnConnect)
        Me.Controls.Add(listServer)
        Me.Controls.Add(lblServerDirectory)
        Me.Name = "FileListEvents"
        Me.Text = "FileListEvents"
        Me.statusStrip.ResumeLayout(False)
        Me.statusStrip.PerformLayout()
        Me.ResumeLayout(False)
        Me.PerformLayout()

    End Sub 'InitializeComponent 
#End Region


    '/ <summary>
    '/ The main entry point for the application.
    '/ </summary>
    <STAThread()> _
    Shared Sub Main()
            ' set the trial license key
            Rebex.Licensing.Key = Rebex.Samples.TrialKey.Key


        Application.Run(New FileListEvents)
    End Sub 'Main


    Private Sub btnConnect_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnConnect.Click
        If Not (_ftp Is Nothing) Then
            btnRefresh.Enabled = False
            _ftp.Disconnect()
            _ftp = Nothing
            MakeFtpList()
            btnConnect.Text = "Connect..."
            Return
        End If

        Dim con As New Connection
        If con.ShowDialog() = DialogResult.OK Then
            Try
                statusLabel.Text = "Connecting..."

                _ftp = New Ftp

                AddHandler _ftp.ListItemReceived, AddressOf Ftp_ListItemReceived

                ' Connect to the server.
                _ftp.Connect(con.Hostname, con.Port)

                ' If TLS/SSL was checked, try to secure the connection.
                If con.Secure Then
                    _ftp.Settings.SslAcceptAllCertificates = con.AcceptAll
                    _ftp.Secure()
                End If
                ' Log in.
                _ftp.Login(con.Username, con.Password)

                btnConnect.Text = "Disconnect"

                MakeFtpList()

                btnRefresh.Enabled = True
            Catch x As Exception
                If Not (_ftp Is Nothing) Then
                    _ftp.Disconnect()
                    _ftp = Nothing
                End If

                MessageBox.Show(x.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End Try
        End If
    End Sub 'btnConnect_Click


    Private Sub Ftp_ListItemReceived(ByVal sender As Object, ByVal e As FtpListItemReceivedEventArgs)
        ' We just recieved a list item from server. Let's play with it a little bit :)

        Dim pars() As String
        ' Detects if the item represents directory or file.
        ' (We do this, because we want to display different information
        ' for files and different information for directories.)
        If e.Item.IsDirectory Then
            pars = New String() {e.Item.Name, "", e.Item.LastWriteTime.ToString()}
        Else
            pars = New String() {e.Item.Name, e.Item.Length.ToString(), e.Item.LastWriteTime.ToString()}
        End If

        ' Create a ListViewItem from gathered info.
        Dim lvi As New ListViewItem(pars)
        lvi.Tag = e.Item

        ' Add ListViewItem to our ListView (which represents the remote file system for us).
        listServer.Items.Add(lvi)

        ' It's not guaranteed that the server has to return the list of files/dirs in a sorted form,
        ' so to avoid confusing the user we will sort out our ListView each time the list item
        ' arrives to keep it nicely sorted and tidy ;)
        listServer.ListViewItemSorter = New ListViewColumnSorter
        listServer.Sort()

        ' Make sure that our changes to the ListView are visible to the user.
        listServer.Update()

        ' Update our counter of items (=dirs/files) in our list.
        _itemCounter += 1
        statusLabel.Text = String.Format("Loaded {0} item(s).", _itemCounter)
    End Sub 'Ftp_ListItemReceived


    Private Sub MakeFtpList()
        listServer.Items.Clear()

        ' Not connected?
        If _ftp Is Nothing Then
            lblServerDirectory.Text = "/root"
            Return
        End If

        listServer.Items.Add("..")

        lblServerDirectory.Text = _ftp.GetCurrentDirectory()
        _ftp.GetList()
    End Sub 'MakeFtpList


    Private Sub listServer_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles listServer.DoubleClick
        Try
            ' Not connected?
            If _ftp Is Nothing Then
                Return
            End If
            If listServer.Items.Count < 1 Then
                Return
            End If
            If listServer.SelectedItems.Count < 1 Then
                listServer.Items(0).Selected = True
            End If
            Dim item As ListViewItem = listServer.SelectedItems(0)

            ' Is the selected item a directory?
            If item.SubItems.Count > 1 Then
                If item.SubItems(1).Text <> "" Then
                    Return
                End If
            End If
            _ftp.ChangeDirectory(item.Text)

            _itemCounter = 0
            statusLabel.Text = "No items."
            MakeFtpList()
        Catch x As FtpException
            If x.Status = FtpExceptionStatus.Timeout OrElse x.Status = FtpExceptionStatus.ConnectFailure OrElse x.Status = FtpExceptionStatus.ConnectionClosed Then
                btnConnect_Click(sender, e)
            End If
            MessageBox.Show(x.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub 'listServer_DoubleClick


    Private Sub FileListEvents_Closing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
        If Not (_ftp Is Nothing) Then
            _ftp.Dispose()
        End If
    End Sub 'FileListEvents_Closing

    Private Sub btnRefresh_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnRefresh.Click
        Try
            _itemCounter = 0
            statusLabel.Text = "Refreshing..."
            MakeFtpList()
        Catch x As FtpException
            If x.Status = FtpExceptionStatus.Timeout Then
                btnConnect_Click(sender, e)
            End If
            MessageBox.Show(x.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub 'btnRefresh_Click
End Class 'FileListEvents


Public Class ListViewColumnSorter
    Inherits MultiComparer
    Implements IComparer

    Public Sub New()
        MyBase.New(New FileSystemItemComparer(FileSystemItemComparerType.FileType, SortingOrder.Ascending), New FileSystemItemComparer(FileSystemItemComparerType.Name))
    End Sub

    Private Overloads Function Compare(x As Object, y As Object) As Integer Implements IComparer.Compare
        Dim listViewX As ListViewItem = DirectCast(x, ListViewItem)
        Dim listViewY As ListViewItem = DirectCast(y, ListViewItem)

        Dim itemX As FtpItem = DirectCast(listViewX.Tag, FtpItem)
        Dim itemY As FtpItem = DirectCast(listViewY.Tag, FtpItem)

        If itemX Is Nothing Then
            If itemY Is Nothing Then
                Return 0
            End If

            Return -1
        ElseIf itemY Is Nothing Then
            Return 1
        End If

        Return MyBase.Compare(itemX, itemY)

    End Function 'Compare
End Class 'ListViewColumnSorter
