package main import ( "html/template" "net/http" "sync" "github.com/gin-contrib/multitemplate" "github.com/gin-gonic/gin" ) var mu sync.Mutex var indexPage = template.Must(template.New("index.html").Parse(` <html> <head> <title>System Configuration</title> <style type="text/css"> div { margin-left: 20px; } </style> </head> <body> <h1>{{.Device}} Configuration</h1> <div> <p>System Version: {{.falinux_version}}</p> </div> <hr> <h1>Updating System</h1> <div> <form action="/system" method="post" enctype="multipart/form-data"> <input type="file" name="image" /> <input type="submit" value="Update" /> </form> </div> <h1>Updating Application</h1> <div> <form action="/application" method="post" enctype="multipart/form-data"> <input type="file" name="image" /> <input type="submit" value="Update" /> </form> </div> <h1>Restore System Image</h1> <div> <form action="/restore"> <input type="submit" value="Restore" /> </form> </div> </body> </html> `)) var networkPage = template.Must(template.New("network.html").Parse(` <html> <head> <title>Network Configuration</title> <style type="text/css"> div { margin-left: 20px; } </style> </head> <body> <form action="/network" method="post"> <h1>Setting Network</h1> <div> <p> <label for="ethaddr">Ethernet Address</label><br /> <input type="text" id="ethaddr" name="ethaddr" value="{{.ethaddr}}" required /> </p> <p> <label for="ipaddr">IP Address</label><br /> <input type="text" id="ipaddr" name="ipaddr" value="{{.ipaddr}}" required /> </p> <p> <label for="netmask">Netmask</label><br /> <input type="text" id="netmask" name="netmask" value="{{.netmask}}" required /> </p> <p> <label for="gateway">Gateway</label><br /> <input type="text" id="gateway" name="gateway" value="{{.gateway}}" required /> </p> </div> <label for="submit"><h1>Click to Apply</h1></label> <div> <p><input id="submit" type="submit" value="Set" /></p> </div> </form> </body> </html> `)) var networkPageDual = template.Must(template.New("network.html").Parse(` <html> <head> <title>Network Configuration</title> <style type="text/css"> div { margin-left: 20px; } </style> </head> <body> <form action="/network" method="post"> <h1>Setting Network</h1> <div> <p> <label for="ethaddr">Ethernet Address</label><br /> <input type="text" id="ethaddr" name="ethaddr" value="{{.ethaddr}}" required /> </p> <p> <label for="ipaddr">IP Address</label><br /> <input type="text" id="ipaddr" name="ipaddr" value="{{.ipaddr}}" required /> </p> <p> <label for="netmask">Netmask</label><br /> <input type="text" id="netmask" name="netmask" value="{{.netmask}}" required /> </p> <p> <label for="gateway">Gateway</label><br /> <input type="text" id="gateway" name="gateway" value="{{.gateway}}" required /> </p> </div> <h1>Setting Network 2</h1> <div> <p> <label for="ethaddr2">Ethernet Address</label><br /> <input type="text" id="ethaddr2" name="ethaddr2" value="{{.ethaddr2}}" required /> </p> <p> <label for="ipaddr2">IP Address</label><br /> <input type="text" id="ipaddr2" name="ipaddr2" value="{{.ipaddr2}}" required /> </p> <p> <label for="netmask2">Netmask</label><br /> <input type="text" id="netmask2" name="netmask2" value="{{.netmask2}}" required /> </p> <p> <label for="gateway2">Gateway</label><br /> <input type="text" id="gateway2" name="gateway2" value="{{.gateway2}}" required /> </p> </div> <label for="submit"><h1>Click to Apply</h1></label> <div> <p><input id="submit" type="submit" value="Set" /></p> </div> </form> </body> </html> `)) var rebootPage = template.Must(template.New("reboot.html").Parse(` <html> <head> <title>OK</title> </head> <body> <p>{{.Message}}</p> <form action="/reboot/"> <input type="submit" value="Reboot" /> </form> </body> </html> `)) func runHttp() { gin.SetMode(gin.ReleaseMode) g := gin.Default() r := multitemplate.NewRenderer() r.Add("index.html", indexPage) r.Add("reboot.html", rebootPage) if hasDualNetwork { r.Add("network.html", networkPageDual) } else { r.Add("network.html", networkPage) } g.HTMLRender = r g.GET("/", renderIndex) g.GET("/network", renderNetwork) g.POST("/network", handleNetwork) g.POST("/system", handleSystem) g.POST("/application", handleApplication) g.GET("/reboot", handleReboot) g.GET("/restore", handleRestore) g.Run(":8988") } func handleNetwork(c *gin.Context) { mu.Lock() defer mu.Unlock() keyList := []string{"ethaddr", "ipaddr", "netmask", "gateway"} if hasDualNetwork { keyList = append(keyList, "ethaddr2", "ipaddr2", "netmask2", "gateway2") } env := map[string]string{} for _, key := range keyList { env[key] = c.PostForm(key) } if err := setNetwork(env); err != nil { c.String(http.StatusBadRequest, "network: setNetwork: %s", err.Error()) return } c.HTML(http.StatusOK, "reboot.html", gin.H{"Message": "Network is configured."}) } func handleSystem(c *gin.Context) { mu.Lock() defer mu.Unlock() if err := saveFormFile(c, "image", "/tmp/system.zip"); err != nil { c.String(http.StatusBadRequest, "system: saveFormFile: %s", err.Error()) return } if err := updateSystem(); err != nil { c.String(http.StatusBadRequest, "system: updateSystem: %s", err.Error()) return } c.HTML(http.StatusOK, "reboot.html", gin.H{"Message": "System is updated."}) } func handleApplication(c *gin.Context) { mu.Lock() defer mu.Unlock() if err := saveFormFile(c, "image", "/tmp/application.zip"); err != nil { c.String(http.StatusBadRequest, "application: saveFormFile: %s", err.Error()) return } if err := updateApp(); err != nil { c.String(http.StatusBadRequest, "application: updateApplication: %s", err.Error()) return } c.HTML(http.StatusOK, "reboot.html", gin.H{"Message": "Application is updated."}) } func handleReboot(c *gin.Context) { reboot() c.String(http.StatusOK, "OK") } func handleRestore(c *gin.Context) { mu.Lock() defer mu.Unlock() restore() c.HTML(http.StatusOK, "reboot.html", gin.H{"Message": "Restoration is done."}) } func renderIndex(c *gin.Context) { env, _ := getEnv(1) env["Device"] = deviceName c.HTML(http.StatusOK, "index.html", env) } func renderNetwork(c *gin.Context) { env, _ := getEnv(0) c.HTML(http.StatusOK, "network.html", env) } func saveFormFile(c *gin.Context, name string, dst string) error { file, err := c.FormFile(name) if err != nil { return err } return c.SaveUploadedFile(file, dst) }