| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 | package mainimport (	"encoding/json"	"errors"	"log"	"net/http"	"strconv"	prout "imuslab.com/arozos/mod/prouter"	ftp "imuslab.com/arozos/mod/storage/ftp")/*	FTP Server related handlers*/var (	ftpServer *ftp.Handler)//Handle init of the FTP server endpointsfunc FTPServerInit() {	//Register FTP Server Setting page	registerSetting(settingModule{		Name:         "FTP Server",		Desc:         "File Transfer Protocol Server",		IconPath:     "SystemAO/disk/smart/img/small_icon.png",		Group:        "Network",		StartDir:     "SystemAO/disk/ftp.html",		RequireAdmin: true,	})	//Register FTP Endpoints	adminRouter := prout.NewModuleRouter(prout.RouterOption{		ModuleName:  "System Setting",		AdminOnly:   true,		UserHandler: userHandler,		DeniedHandler: func(w http.ResponseWriter, r *http.Request) {			errorHandlePermissionDenied(w, r)		},	})	//Create database related tables	sysdb.NewTable("ftp")	defaultEnable := false	if sysdb.KeyExists("ftp", "default") {		sysdb.Read("ftp", "default", &defaultEnable)	} else {		sysdb.Write("ftp", "default", false)	}	//Enable this service	if defaultEnable {		storageFTPServerStart()	}	adminRouter.HandleFunc("/system/storage/ftp/start", storageHandleFTPServerStart)	adminRouter.HandleFunc("/system/storage/ftp/stop", storageHandleFTPServerStop)	adminRouter.HandleFunc("/system/storage/ftp/upnp", storageHandleFTPuPnP)	adminRouter.HandleFunc("/system/storage/ftp/status", storageHandleFTPServerStatus)	adminRouter.HandleFunc("/system/storage/ftp/updateGroups", storageHandleFTPAccessUpdate)	adminRouter.HandleFunc("/system/storage/ftp/setPort", storageHandleFTPSetPort)	adminRouter.HandleFunc("/system/storage/ftp/passivemode", storageHandleFTPPassiveModeSettings)}/*	Handle the settings for passive mode related files	Example set commands	set=ip&ip=123.456.789.1	set=mode&passive=true*/func storageHandleFTPPassiveModeSettings(w http.ResponseWriter, r *http.Request) {	set, err := mv(r, "set", true)	if err != nil {		sendErrorResponse(w, "Invalid set type")		return	}	if set == "ip" {		//Updat the public up addr		ip, err := mv(r, "ip", true)		if err != nil {			sendErrorResponse(w, "Invalid ip given")			return		}		sysdb.Write("ftp", "publicip", ip)	} else if set == "mode" {		//Update the passive mode setting		passive, err := mv(r, "passive", true)		if err != nil {			sendErrorResponse(w, "Invalid passive option (true/false)")			return		}		log.Println("Updatng FTP Server PassiveMode to", passive)		if passive == "true" {			sysdb.Write("ftp", "passive", true)		} else {			sysdb.Write("ftp", "passive", false)		}	} else {		sendErrorResponse(w, "Unknown setting filed")		return	}	//Restart the FTP server if it is running now	if ftpServer != nil && ftpServer.ServerRunning {		storageFTPServerStart()	}}//Start the FTP Server by requestfunc storageHandleFTPServerStart(w http.ResponseWriter, r *http.Request) {	err := storageFTPServerStart()	if err != nil {		sendErrorResponse(w, err.Error())	}	//Remember the FTP server status	sysdb.Write("ftp", "default", true)	sendOK(w)}//Stop the FTP server by requestfunc storageHandleFTPServerStop(w http.ResponseWriter, r *http.Request) {	if ftpServer != nil {		ftpServer.Close()	}	sysdb.Write("ftp", "default", false)	log.Println("FTP Server Stopped")	sendOK(w)}//Update UPnP setting on FTP serverfunc storageHandleFTPuPnP(w http.ResponseWriter, r *http.Request) {	enable, _ := mv(r, "enable", false)	if enable == "true" {		log.Println("Enabling UPnP on FTP Server Port")		sysdb.Write("ftp", "upnp", true)	} else {		log.Println("Disabling UPnP on FTP Server Port")		sysdb.Write("ftp", "upnp", false)	}	//Restart FTP Server if server is running	if ftpServer != nil && ftpServer.ServerRunning {		storageFTPServerStart()	}	sendOK(w)}//Update access permission on FTP serverfunc storageHandleFTPAccessUpdate(w http.ResponseWriter, r *http.Request) {	//Get groups paramter from post req	groupString, err := mv(r, "groups", true)	if err != nil {		sendErrorResponse(w, "groups not defined")		return	}	//Prase it	groups := []string{}	err = json.Unmarshal([]byte(groupString), &groups)	if err != nil {		sendErrorResponse(w, "Unable to parse groups")		return	}	log.Println("Updating FTP Access group to: ", groups)	//Set the accessable group	ftp.UpdateAccessableGroups(sysdb, groups)	sendOK(w)}func storageHandleFTPSetPort(w http.ResponseWriter, r *http.Request) {	port, err := mv(r, "port", true)	if err != nil {		sendErrorResponse(w, "Port not defined")		return	}	//Try parse the port into int	portInt, err := strconv.Atoi(port)	if err != nil {		sendErrorResponse(w, "Invalid port number")		return	}	//Update the database port configuration	sysdb.Write("ftp", "port", portInt)	//Restart the FTP server	storageFTPServerStart()	sendOK(w)}func storageHandleFTPServerStatus(w http.ResponseWriter, r *http.Request) {	type ServerStatus struct {		Enabled        bool		Port           int		AllowUPNP      bool		UPNPEnabled    bool		FTPUpnpEnabled bool		PublicAddr     string		PassiveMode    bool		UserGroups     []string	}	enabled := false	if ftpServer != nil && ftpServer.ServerRunning {		enabled = true	}	serverPort := 21	if sysdb.KeyExists("ftp", "port") {		sysdb.Read("ftp", "port", &serverPort)	}	enableUPnP := false	if sysdb.KeyExists("ftp", "upnp") {		sysdb.Read("ftp", "upnp", &enableUPnP)	}	userGroups := []string{}	if sysdb.KeyExists("ftp", "groups") {		sysdb.Read("ftp", "groups", &userGroups)	}	ftpUpnp := false	if ftpServer != nil && ftpServer.UPNPEnabled {		ftpUpnp = true	}	publicAddr := ""	if UPNP != nil && UPNP.ExternalIP != "" && ftpUpnp == true {		publicAddr = UPNP.ExternalIP	} else {		manualPublicIpEntry := ""		if sysdb.KeyExists("ftp", "publicip") {			sysdb.Read("ftp", "publicip", &manualPublicIpEntry)		}		publicAddr = manualPublicIpEntry	}	forcePassiveMode := false	if ftpUpnp == true {		forcePassiveMode = true	} else {		if sysdb.KeyExists("ftp", "passive") {			sysdb.Read("ftp", "passive", &forcePassiveMode)		}		if forcePassiveMode {			//Read the ip setting from database			manualPublicIpEntry := ""			if sysdb.KeyExists("ftp", "publicip") {				sysdb.Read("ftp", "publicip", &manualPublicIpEntry)			}			publicAddr = manualPublicIpEntry		}	}	jsonString, _ := json.Marshal(ServerStatus{		Enabled:        enabled,		Port:           serverPort,		AllowUPNP:      *allow_upnp,		UPNPEnabled:    enableUPnP,		FTPUpnpEnabled: ftpUpnp,		PublicAddr:     publicAddr,		UserGroups:     userGroups,		PassiveMode:    forcePassiveMode,	})	sendJSONResponse(w, string(jsonString))}func storageFTPServerStart() error {	if ftpServer != nil {		//If the previous ftp server is not closed, close it and open a new one		if ftpServer.UPNPEnabled && UPNP != nil {			UPNP.ClosePort(ftpServer.Port)		}		ftpServer.Close()	}	//Load new server config from database	serverPort := int(21)	if sysdb.KeyExists("ftp", "port") {		sysdb.Read("ftp", "port", &serverPort)	}	enableUPnP := false	if sysdb.KeyExists("ftp", "upnp") {		sysdb.Read("ftp", "upnp", &enableUPnP)	}	forcePassiveMode := false	sysdb.Read("ftp", "passive", &forcePassiveMode)	//Create a new FTP Handler	passiveModeIP := ""	if *allow_upnp && enableUPnP {		//Using External IP address from the UPnP router reply		externalIP := UPNP.ExternalIP		if externalIP != "" {			passiveModeIP = externalIP		}	} else if forcePassiveMode {		//Not allowing upnp but still use passive mode (aka manual port forward)		externalIP := ""		if sysdb.KeyExists("ftp", "publicip") {			sysdb.Read("ftp", "publicip", &externalIP)		}		passiveModeIP = externalIP	}	h, err := ftp.NewFTPHandler(userHandler, *host_name, serverPort, *tmp_directory, passiveModeIP)	if err != nil {		return err	}	h.Start()	ftpServer = h	if *allow_upnp {		if enableUPnP {			if UPNP == nil {				return errors.New("UPnP did not started correctly on this host. Ignore this option")			} else {				//Forward the port				err := UPNP.ForwardPort(ftpServer.Port, *host_name+" FTP Server")				if err != nil {					log.Println("Failed to start FTP Server UPnP: ", err)					ftpServer.UPNPEnabled = false					return err				} else {					//Forward other data ports					UPNP.ForwardPort(ftpServer.Port+1, *host_name+" FTP Data 1")					UPNP.ForwardPort(ftpServer.Port+2, *host_name+" FTP Data 2")					ftpServer.UPNPEnabled = true				}				return nil			}		} else {			//UPNP disabled			if UPNP == nil {				return errors.New("UPnP did not started correctly on this host. Ignore this option")			} else {				UPNP.ClosePort(ftpServer.Port)				UPNP.ClosePort(ftpServer.Port + 1)				UPNP.ClosePort(ftpServer.Port + 2)				ftpServer.UPNPEnabled = false			}		}	}	return nil}
 |