B4J Question Ftp server - how to manage multi-user system ?

amorosik

Expert
Licensed User
Example of ftp server is perfectly clear
But to accept a connection the ftp server must already be started
And to start it I must provide both a BaseDir and a user directory (the third parameter) on AddUser command
But how to allow the connection from different clients, each of which must 'see' their own directory on the ftp server?
 

DonManfred

Expert
Licensed User
Longtime User
And to start it I must provide both a BaseDir and a user directory (the third parameter) on AddUser command
AddUser only have two parameters. What third parameter are you talking about?

Anyway the library is a b4xlib = zip-File
Feel free to extract the classes and edit them to you wish.
 
Upvote 0

amorosik

Expert
Licensed User
AddUser only have two parameters. What third parameter are you talking about?

Anyway the library is a b4xlib = zip-File
Feel free to extract the classes and edit them to you wish.

AddUser (of FTPServer class) has tree parameter, the last is the DefaultDir

1715094976832.png
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
AddUser (of FTPServer class) has tree parameter, the last is the DefaultDir
then you are using another version than the lib available at the link you posted in #1

This is the FTPServer class from the link you provided

AddUser only have TWO parameters
B4X:
Sub Class_Globals
    Type FTPUser (Name As String, Password As String)
    Private clients As List
    Public const EOL As String = Chr(13) & Chr(10)
    Public ssocket As ServerSocket
    Public port As Int
    Private dataPorts As Map
    Public Users As Map
    Public BaseDir As String
    Private mCallback As Object
    Private mEventName As String
    Private stopped As Boolean = True
    Public ForcedServerIp As String
End Sub

Public Sub Initialize (Callback As Object, EventName As String)
    clients.Initialize
    Users.Initialize
    mCallback = Callback
    mEventName = EventName
End Sub

'Sets the control part and the data ports range
Public Sub SetPorts(ControlPort As Int, DataPortBegin As Int, DataPortEnd As Int)
    dataPorts.Initialize
    For i = DataPortBegin To DataPortEnd
        dataPorts.Put(i, False)
    Next
    port = ControlPort
End Sub

Public Sub getRunning As Boolean
    Return stopped = False
End Sub

Public Sub Start
    ssocket.Initialize(port, "ssocket")
    ssocket.Listen
    stopped = False
End Sub

Public Sub AddUser (Name As String, Password As String)
    Dim u As FTPUser
    u.Initialize
    u.Name = Name
    u.Password = Password
    Users.Put(u.Name, u)
End Sub

Public Sub Stop
    If stopped Then Return
    stopped = True
    ssocket.Close
    For Each Client As FTPClient In clients
        Client.CloseConnection
    Next
End Sub

Public Sub ClientClosed (client As FTPClient)
    If stopped Then Return
    If client.mDataPort > 0 Then dataPorts.Put(client.mDataPort, False)
    Dim i As Int = clients.IndexOf(client)
    If i > -1 Then
        clients.RemoveAt(i)
        CallSub(mCallback, mEventName & "_StateChanged")
    End If
End Sub

Public Sub getNumberOfClients As Int
    Return clients.Size
End Sub

Private Sub ssocket_NewConnection (Successful As Boolean, NewSocket As Socket)
    If Successful Then
        Dim Client As FTPClient
        Dim dp As Int = GetDataPort
        Client.Initialize(Me, NewSocket, dp)
        clients.Add(Client)
        If dp > 0 Then dataPorts.Put(dp, True)
        CallSub(mCallback, mEventName & "_StateChanged")
    End If
    If stopped = False Then ssocket.Listen
End Sub


Private Sub GetDataPort As Int
    For Each i As Int In dataPorts.Keys
        If dataPorts.Get(i) = False Then
            Return i
        End If
    Next
    Return -1
End Sub
 
Upvote 0

amorosik

Expert
Licensed User
O
then you are using another version than the lib available at the link you posted in #1

This is the FTPServer class from the link you provided

AddUser only have TWO parameters
B4X:
Sub Class_Globals
    Type FTPUser (Name As String, Password As String)
    Private clients As List
    Public const EOL As String = Chr(13) & Chr(10)
    Public ssocket As ServerSocket
    Public port As Int
    Private dataPorts As Map
    Public Users As Map
    Public BaseDir As String
    Private mCallback As Object
    Private mEventName As String
    Private stopped As Boolean = True
    Public ForcedServerIp As String
End Sub

Public Sub Initialize (Callback As Object, EventName As String)
    clients.Initialize
    Users.Initialize
    mCallback = Callback
    mEventName = EventName
End Sub

'Sets the control part and the data ports range
Public Sub SetPorts(ControlPort As Int, DataPortBegin As Int, DataPortEnd As Int)
    dataPorts.Initialize
    For i = DataPortBegin To DataPortEnd
        dataPorts.Put(i, False)
    Next
    port = ControlPort
End Sub

Public Sub getRunning As Boolean
    Return stopped = False
End Sub

Public Sub Start
    ssocket.Initialize(port, "ssocket")
    ssocket.Listen
    stopped = False
End Sub

Public Sub AddUser (Name As String, Password As String)
    Dim u As FTPUser
    u.Initialize
    u.Name = Name
    u.Password = Password
    Users.Put(u.Name, u)
End Sub

Public Sub Stop
    If stopped Then Return
    stopped = True
    ssocket.Close
    For Each Client As FTPClient In clients
        Client.CloseConnection
    Next
End Sub

Public Sub ClientClosed (client As FTPClient)
    If stopped Then Return
    If client.mDataPort > 0 Then dataPorts.Put(client.mDataPort, False)
    Dim i As Int = clients.IndexOf(client)
    If i > -1 Then
        clients.RemoveAt(i)
        CallSub(mCallback, mEventName & "_StateChanged")
    End If
End Sub

Public Sub getNumberOfClients As Int
    Return clients.Size
End Sub

Private Sub ssocket_NewConnection (Successful As Boolean, NewSocket As Socket)
    If Successful Then
        Dim Client As FTPClient
        Dim dp As Int = GetDataPort
        Client.Initialize(Me, NewSocket, dp)
        clients.Add(Client)
        If dp > 0 Then dataPorts.Put(dp, True)
        CallSub(mCallback, mEventName & "_StateChanged")
    End If
    If stopped = False Then ssocket.Listen
End Sub


Private Sub GetDataPort As Int
    For Each i As Int In dataPorts.Keys
        If dataPorts.Get(i) = False Then
            Return i
        End If
    Next
    Return -1
End Sub

Ok, my mistake
The project I'm working on is not like the example I indicated which uses the FTPServer.b4xlib library
But it is derived from another example, probably previous, where the FTPServer code is enclosed in a code module
And also includes the third parameter
My FTPServer code is:

FTPServer code:
#Event: StateChanged
#Event: Llog
Sub Class_Globals
    Type FTPUser (Name As String, Password As String, DefaultDir As String)
    Private clients As List
    Public const EOL As String = Chr(13) & Chr(10)
    Public ssocket As ServerSocket
    Public port As Int
    Private dataPorts As Map
    Public Users As Map
    Public BaseDir As String
    Private mCallback As Object
    Private mEventName As String
    Private stopped As Boolean = True
    Public ForcedServerIp As String
End Sub

Public Sub Initialize (Callback As Object, EventName As String)
    clients.Initialize
    Users.Initialize
    mCallback = Callback
    mEventName = EventName
End Sub

'Sets the control part and the data ports range
Public Sub SetPorts(ControlPort As Int, DataPortBegin As Int, DataPortEnd As Int)
    dataPorts.Initialize
    For i = DataPortBegin To DataPortEnd
        dataPorts.Put(i, False)
    Next
    port = ControlPort
End Sub

Public Sub getRunning As Boolean
    Return stopped = False
End Sub

Public Sub Start
    ssocket.Initialize(port, "ssocket")
    ssocket.Listen
    stopped = False
End Sub

Public Sub AddUser (Name As String, Password As String,DefaultDir As String)
    Dim u As FTPUser
    u.Initialize
    u.Name = Name
    u.Password = Password
    u.DefaultDir = DefaultDir
    Users.Put(u.Name, u)
End Sub

Public Sub Stop
    If stopped Then Return
    stopped = True
    ssocket.Close
    For Each Client As FTPClient In clients
        Client.CloseConnection
    Next
End Sub

Public Sub ClientClosed (client As FTPClient)
    If stopped Then Return
    If client.mDataPort > 0 Then dataPorts.Put(client.mDataPort, False)
    Dim i As Int = clients.IndexOf(client)
    If i > -1 Then
        clients.RemoveAt(i)
        CallSub(mCallback, mEventName & "_StateChanged")
    End If
End Sub

Public Sub getNumberOfClients As Int
    Return clients.Size
End Sub

Private Sub ssocket_NewConnection (Successful As Boolean, NewSocket As Socket)
    If Successful Then
        Dim Client As FTPClient
        Dim dp As Int = GetDataPort
        Client.Initialize(Me, NewSocket, dp)
        clients.Add(Client)
        If dp > 0 Then dataPorts.Put(dp, True)
        CallSub(mCallback, mEventName & "_StateChanged")
        End If
    If stopped = False Then ssocket.Listen
End Sub


Private Sub GetDataPort As Int
    For Each i As Int In dataPorts.Keys
        If dataPorts.Get(i) = False Then
            Return i
        End If
    Next
    Return -1
End Sub

'Call a event Llog(param_string)
Public Sub Llog(stringa As String)
'    Log(stringa)
    If SubExists(mCallback,mEventName & "_Llog") Then
        CallSub2(mCallback,mEventName & "_Llog",stringa)
    End If
End Sub
 
Upvote 0
Top