123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- package ftpserv
- import (
- "errors"
- "imuslab.com/arozos/mod/database"
- "imuslab.com/arozos/mod/fileservers"
- "imuslab.com/arozos/mod/info/logger"
- upnp "imuslab.com/arozos/mod/network/upnp"
- "imuslab.com/arozos/mod/storage/ftp"
- user "imuslab.com/arozos/mod/user"
- )
- type ServerStatus struct {
- Enabled bool
- Port int
- AllowUpnp bool
- UPNPEnabled bool
- FTPUPNPEnabled bool
- PublicAddr string
- PassiveMode bool
- UserGroups []string
- }
- type ManagerOption struct {
- Hostname string
- TmpFolder string
- Logger *logger.Logger
- UserManager *user.UserHandler
- FtpServer *ftp.Handler
- Sysdb *database.Database
- Upnp *upnp.UPnPClient
- AllowUpnp bool
- }
- type Manager struct {
- option ManagerOption
- }
- //Create a new FTP Manager
- func NewFTPManager(option *ManagerOption) *Manager {
- //Create database related tables
- option.Sysdb.NewTable("ftp")
- defaultEnable := false
- if option.Sysdb.KeyExists("ftp", "default") {
- option.Sysdb.Read("ftp", "default", &defaultEnable)
- } else {
- option.Sysdb.Write("ftp", "default", false)
- }
- //Create the Manager object
- manager := Manager{
- option: *option,
- }
- //Enable this service
- if defaultEnable {
- manager.StartFtpServer()
- }
- return &manager
- }
- func (m *Manager) StartFtpServer() error {
- if m.option.FtpServer != nil {
- //If the previous ftp server is not closed, close it and open a new one
- if m.option.FtpServer.UPNPEnabled && m.option.Upnp != nil {
- m.option.Upnp.ClosePort(m.option.FtpServer.Port)
- }
- m.option.FtpServer.Close()
- }
- //Load new server config from database
- serverPort := int(21)
- if m.option.Sysdb.KeyExists("ftp", "port") {
- m.option.Sysdb.Read("ftp", "port", &serverPort)
- }
- enableUpnp := false
- if m.option.Sysdb.KeyExists("ftp", "Upnp") {
- m.option.Sysdb.Read("ftp", "Upnp", &enableUpnp)
- }
- forcePassiveMode := false
- m.option.Sysdb.Read("ftp", "passive", &forcePassiveMode)
- //Create a new FTP Handler
- passiveModeIP := ""
- if m.option.AllowUpnp && enableUpnp {
- //Using External IP address from the Upnp router reply
- externalIP := m.option.Upnp.ExternalIP
- if externalIP != "" {
- passiveModeIP = externalIP
- }
- } else if forcePassiveMode {
- //Not allowing Upnp but still use passive mode (aka manual port forward)
- externalIP := ""
- if m.option.Sysdb.KeyExists("ftp", "publicip") {
- m.option.Sysdb.Read("ftp", "publicip", &externalIP)
- }
- passiveModeIP = externalIP
- }
- h, err := ftp.NewFTPHandler(m.option.UserManager, m.option.Hostname, serverPort, m.option.TmpFolder, passiveModeIP)
- if err != nil {
- return err
- }
- h.Start()
- m.option.FtpServer = h
- if m.option.AllowUpnp {
- if enableUpnp {
- if m.option.Upnp == nil {
- return errors.New("Upnp did not started correctly on this host. Ignore this option")
- } else {
- //Forward the port
- err := m.option.Upnp.ForwardPort(m.option.FtpServer.Port, m.option.Hostname+" FTP Server")
- if err != nil {
- m.option.Logger.PrintAndLog("FTP", "Failed to start FTP Server Upnp ", err)
- m.option.FtpServer.UPNPEnabled = false
- return err
- } else {
- //Forward other data ports
- m.option.Upnp.ForwardPort(m.option.FtpServer.Port+1, m.option.Hostname+" FTP Data 1")
- m.option.Upnp.ForwardPort(m.option.FtpServer.Port+2, m.option.Hostname+" FTP Data 2")
- m.option.FtpServer.UPNPEnabled = true
- }
- return nil
- }
- } else {
- //Upnp disabled
- if m.option.Upnp == nil {
- return errors.New("Upnp did not started correctly on this host. Ignore this option")
- } else {
- m.option.Upnp.ClosePort(m.option.FtpServer.Port)
- m.option.Upnp.ClosePort(m.option.FtpServer.Port + 1)
- m.option.Upnp.ClosePort(m.option.FtpServer.Port + 2)
- m.option.FtpServer.UPNPEnabled = false
- }
- }
- }
- //Remember the FTP server status
- m.option.Sysdb.Write("ftp", "default", true)
- return nil
- }
- func (m *Manager) StopFtpServer() {
- if m.option.FtpServer != nil {
- m.option.FtpServer.Close()
- }
- m.option.Sysdb.Write("ftp", "default", false)
- m.option.Logger.PrintAndLog("FTP", "FTP Server Stopped", nil)
- }
- func (m *Manager) GetFtpServerStatus() (*ServerStatus, error) {
- enabled := false
- if m.option.FtpServer != nil && m.option.FtpServer.ServerRunning {
- enabled = true
- }
- serverPort := 21
- if m.option.Sysdb.KeyExists("ftp", "port") {
- m.option.Sysdb.Read("ftp", "port", &serverPort)
- }
- enableUpnp := false
- if m.option.Sysdb.KeyExists("ftp", "Upnp") {
- m.option.Sysdb.Read("ftp", "Upnp", &enableUpnp)
- }
- userGroups := []string{}
- if m.option.Sysdb.KeyExists("ftp", "groups") {
- m.option.Sysdb.Read("ftp", "groups", &userGroups)
- }
- ftpUpnp := false
- if m.option.FtpServer != nil && m.option.FtpServer.UPNPEnabled {
- ftpUpnp = true
- }
- publicAddr := ""
- if m.option.Upnp != nil && m.option.Upnp.ExternalIP != "" && ftpUpnp == true {
- publicAddr = m.option.Upnp.ExternalIP
- } else {
- manualPublicIpEntry := ""
- if m.option.Sysdb.KeyExists("ftp", "publicip") {
- m.option.Sysdb.Read("ftp", "publicip", &manualPublicIpEntry)
- }
- publicAddr = manualPublicIpEntry
- }
- forcePassiveMode := false
- if ftpUpnp == true {
- forcePassiveMode = true
- } else {
- if m.option.Sysdb.KeyExists("ftp", "passive") {
- m.option.Sysdb.Read("ftp", "passive", &forcePassiveMode)
- }
- if forcePassiveMode {
- //Read the ip setting from database
- manualPublicIpEntry := ""
- if m.option.Sysdb.KeyExists("ftp", "publicip") {
- m.option.Sysdb.Read("ftp", "publicip", &manualPublicIpEntry)
- }
- publicAddr = manualPublicIpEntry
- }
- }
- currnetStatus := ServerStatus{
- Enabled: enabled,
- Port: serverPort,
- AllowUpnp: m.option.AllowUpnp,
- UPNPEnabled: enableUpnp,
- FTPUPNPEnabled: ftpUpnp,
- PublicAddr: publicAddr,
- UserGroups: userGroups,
- PassiveMode: forcePassiveMode,
- }
- return &currnetStatus, nil
- }
- func (m *Manager) IsFtpServerEnabled() bool {
- return m.option.FtpServer != nil && m.option.FtpServer.ServerRunning
- }
- func (m *Manager) FTPServerToggle(enabled bool) error {
- if m.option.FtpServer != nil && m.option.FtpServer.ServerRunning {
- //Enabled
- if !enabled {
- //Shut it down
- m.StopFtpServer()
- }
- } else if enabled {
- //Startup FTP Server
- return m.StartFtpServer()
- }
- return nil
- }
- func (m *Manager) FTPGetEndpoints(userinfo *user.User) []*fileservers.Endpoint {
- ftpEndpoints := []*fileservers.Endpoint{}
- port := 21
- if m.option.FtpServer != nil {
- port = m.option.FtpServer.Port
- }
- ftpEndpoints = append(ftpEndpoints, &fileservers.Endpoint{
- ProtocolName: "ftp://",
- Port: port,
- Subpath: "",
- })
- return ftpEndpoints
- }
|