| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 | package ftpservimport (	"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 Managerfunc 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}
 |