diff options
| author | Mitch Riedstra <mitch@riedstra.us> | 2021-01-08 22:25:55 -0500 |
|---|---|---|
| committer | Mitch Riedstra <mitch@riedstra.us> | 2021-01-08 22:25:55 -0500 |
| commit | 11c0e0ca37ce58d74f3cd5831265b9912f6bc8ea (patch) | |
| tree | 358be5b2e8b3f6c0a0ffcfc8fce4fc9432bd14c5 /cmd | |
| parent | f26c564dcadf71e7c4c8fe99555fb7d038216140 (diff) | |
| download | steam-export-11c0e0ca37ce58d74f3cd5831265b9912f6bc8ea.tar.gz steam-export-11c0e0ca37ce58d74f3cd5831265b9912f6bc8ea.tar.xz | |
Make the application a bit more user friendly
Make a split between being accessed over loopback and remotely.
Attempt to show the IP of the server on the internal page to make
it easy to hand out.
Remove the ability to change any of the runtime configuration
or quit the program unless you're local.
Diffstat (limited to 'cmd')
| -rw-r--r-- | cmd/web/delete.go | 4 | ||||
| -rw-r--r-- | cmd/web/index.go | 58 | ||||
| -rw-r--r-- | cmd/web/install.go | 5 | ||||
| -rw-r--r-- | cmd/web/main.go | 72 | ||||
| -rw-r--r-- | cmd/web/serve-self.go | 27 |
5 files changed, 159 insertions, 7 deletions
diff --git a/cmd/web/delete.go b/cmd/web/delete.go index 5bf747e..8edd6c6 100644 --- a/cmd/web/delete.go +++ b/cmd/web/delete.go @@ -6,6 +6,10 @@ import ( ) func gameDelete(w http.ResponseWriter, r *http.Request) { + if unauthorizedIfNotLocal(w, r) { + return + } + err := r.ParseForm() if err != nil { Logger.Printf("Installer: While parsing form: %s", err) diff --git a/cmd/web/index.go b/cmd/web/index.go index a4a91c2..87f9e25 100644 --- a/cmd/web/index.go +++ b/cmd/web/index.go @@ -20,11 +20,14 @@ var ( <body> <nav> <a href="/">Home</a> + {{ if .Local }} <div style="display: block; float: right;"> <a href="/quit">Shutdown Server / Quit</a> </div> + {{ end }} </nav> +{{ if .Local }} <h2>Library: {{.Lib.Folder}}</h2> {{ if .Info.Running }} @@ -39,6 +42,42 @@ Error {{.Info.Error}} Downloading from: {{.Info.Url}} {{ end }} </pre></code> +<h3>About</h3> +<p> +The steam exporter is designed to let you export your steam games, either to +another local hard drive or another computer on the network. +</p> +<p> +It also allows you to import games from across the network as well if you +provide an HTTP url from which to download the game file as exported +from this application. +</p> +<p> +<a href="/steam-export-web.exe"> + You can download this application from this UI as well here. +</a> +</p> + +<p> +You can give people this link to view the library remotely and download +games from your computer: +<br /><br /> +<a href="http://{{.HostIP}}:{{.Port}}/">http://{{.HostIP}}:{{.Port}}/</a> +</p> +{{ else }} +<h2>Remote Steam library access</h2> + +<a href="/steam-export-web.exe"> + If you need this program to install the games click here. +</a> + +<p> +Right click and copy the link address to paste into your local machine +if you do not wish to store the archive or have enough space for it on +your drive. +</p> +{{ end }} + <p> Installed games: @@ -54,6 +93,7 @@ an external hard drive {{ end }} </ul> +{{ if .Local }} Delete a game: ( Type out exact name, case sensitive ) <form action="/delete" method="POST"> @@ -80,7 +120,7 @@ Change library path <input type="text" name="path" /> <input type="submit" value="Update"> </form> - +{{ end }} <h3>Version information</h3> <pre><code>{{.Version}}</pre></code> @@ -97,10 +137,20 @@ func index(w http.ResponseWriter, r *http.Request) { err := Templ.ExecuteTemplate(w, "index", struct { - Lib *steam.Library - Info *statusInfo + Lib *steam.Library + Info *statusInfo + Local bool + HostIP string + Port string Version string - }{Lib, status.s, Version}) + }{ + Lib, + status.s, + isLocal(r.RemoteAddr), + getHostIP(), + getPort(), + Version, + }) if err != nil { Logger.Printf("While Rendering template: %s", err) } diff --git a/cmd/web/install.go b/cmd/web/install.go index aae4191..63faaf6 100644 --- a/cmd/web/install.go +++ b/cmd/web/install.go @@ -83,6 +83,11 @@ func installer(urls <-chan string) { } func gameInstaller(w http.ResponseWriter, r *http.Request) { + if unauthorizedIfNotLocal(w, r) { + return + } + + err := r.ParseForm() if err != nil { Logger.Printf("Installer: While parsing form: %s", err) diff --git a/cmd/web/main.go b/cmd/web/main.go index ec0704d..0f76670 100644 --- a/cmd/web/main.go +++ b/cmd/web/main.go @@ -5,8 +5,10 @@ import ( "fmt" "log" "math/rand" + "net" "net/http" "os" + "strings" "sync" "time" @@ -16,8 +18,8 @@ import ( var ( Version = "Development" - Logger = log.New(os.Stderr, "", log.LstdFlags) - Listen = ":8899" + Logger = log.New(os.Stderr, "", log.LstdFlags) + Listen = ":8899" libMu = &sync.RWMutex{} Lib *steam.Library @@ -38,6 +40,10 @@ func reloadLib() { } func setLibHandler(w http.ResponseWriter, r *http.Request) { + if unauthorizedIfNotLocal(w, r) { + return + } + err := r.ParseForm() if err != nil { Logger.Printf("Setlib: While parsing form: %s", err) @@ -51,16 +57,75 @@ func setLibHandler(w http.ResponseWriter, r *http.Request) { } func quitHandler(w http.ResponseWriter, r *http.Request) { + if unauthorizedIfNotLocal(w, r) { + return + } + Logger.Println("Quit was called, exiting") w.Header().Add("Content-type", "text/plain") w.Write([]byte("Shutting down...")) go func() { - time.Sleep(time.Second*2) + time.Sleep(time.Second * 2) os.Exit(0) }() return } +func unauthorizedIfNotLocal(w http.ResponseWriter, r *http.Request) bool { + if !isLocal(r.RemoteAddr) { + http.Error(w, "Unauthorized", http.StatusUnauthorized) + Logger.Printf("Unauthorized request from: %s for %s", + r.RemoteAddr, r.RequestURI) + return true + } + return false +} + +func isLocal(addr string) bool { + _, localNet, _ := net.ParseCIDR("127.0.0.1/8") + return localNet.Contains(net.ParseIP(strings.Split(addr, ":")[0])) +} + +// getHostIP attempts to guess the IP address of the current machine and +// returns that. Simply bails at the first non loopback IP returning that. +// not ideal but it should work well enough most of the time +func getHostIP() string { + iFaces, err := net.Interfaces() + if err != nil { + return "127.0.0.1" + } + + for _, iFace := range iFaces { + addrs, err := iFace.Addrs() + if err != nil { + return "127.0.0.1" + } + + for _, a := range addrs { + n, ok := a.(*net.IPNet) + if !ok { + continue + } + + if n.IP.To4() != nil && !n.IP.IsLoopback() { + return n.IP.String() + } + } + } + + return "127.0.0.1" +} + +func getPort() string { + s := strings.Split(Listen, ":") + + if len(s) != 2 { + return Listen + } + + return s[1] +} + func main() { fl := flag.NewFlagSet("steam-export", flag.ExitOnError) debug := fl.Bool("d", false, "Print line numbers in log") @@ -86,6 +151,7 @@ func main() { r.HandleFunc("/setLib", setLibHandler) r.HandleFunc("/delete", gameDelete) r.HandleFunc("/install", gameInstaller) + r.HandleFunc("/steam-export-web.exe", serveSelf) r.HandleFunc("/download/{game}", gameDownloader) r.HandleFunc("/style.css", cssHandler) r.HandleFunc("/", index) diff --git a/cmd/web/serve-self.go b/cmd/web/serve-self.go new file mode 100644 index 0000000..103fbf1 --- /dev/null +++ b/cmd/web/serve-self.go @@ -0,0 +1,27 @@ +package main + +import ( + "io" + "os" + "net/http" +) + +func serveSelf(w http.ResponseWriter, r *http.Request) { + s, err := os.Executable() + if err != nil { + Logger.Println("While trying to get my executable path: ", err) + http.Error(w, "Internal server error", http.StatusInternalServerError) + return + } + + fh, err := os.Open(s) + if err != nil { + Logger.Println("While opening my own executable for reading: ", err) + http.Error(w, "Internal server error", http.StatusInternalServerError) + return + } + + _, err = io.Copy(w, fh) + fh.Close() + return +} |
