package main import ( "encoding/json" "fmt" "net/http" "net/url" "os" "strings" "sync" "time" ) type statusInfo struct { Running bool Error error Url string Transferred int64 Size int64 Start *time.Time } var ( status = struct { m *sync.RWMutex s *statusInfo }{ m: &sync.RWMutex{}, s: &statusInfo{Running: false}, } getPath = make(chan string) ) func statsHandler(w http.ResponseWriter, r *http.Request) { status.m.RLock() defer status.m.RUnlock() enc := json.NewEncoder(w) err := enc.Encode(status.s) if err != nil { Logger.Println("While encoding status: ", err) } return } func installHttp(u string) error { Logger.Println("Installer: loading from url") resp, err := http.Get(u) if err != nil { return fmt.Errorf("Installer: getting %w", err) } err = Lib.Extract(resp.Body) if err != nil { return fmt.Errorf("Installer: extracting %w", err) } resp.Body.Close() return nil } func installPath(p string) error { Logger.Println("Installer: loading from filesystem") fh, err := os.Open(p) if err != nil { return fmt.Errorf("Installer: opening %w", err) } err = Lib.Extract(fh) if err != nil { return fmt.Errorf("Installer: opening %w", err) } fh.Close() return nil } // installer handles installing games either from a local path or a // remote URL func installer(urls <-chan string) { var err error for u := range urls { status.m.Lock() Logger.Printf("Installer: running for URI: %s", u) status.s.Running = true status.s.Url = u status.m.Unlock() if strings.HasPrefix(u, "http") { err = installHttp(u) } else { err = installPath(u) } status.m.Lock() status.s.Running = false status.s.Error = err Logger.Printf("Installer: Completed request %s Errors: %s", u, err) status.m.Unlock() reloadLib() } } 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) http.Error(w, fmt.Sprintf("Invalid form: %s", err), 400) return } uri := r.Form.Get("uri") if strings.HasPrefix(uri, "http") { _, err := url.Parse(uri) if err != nil { Logger.Printf("Installer: While parsing url: %s", err) http.Error(w, fmt.Sprintf("Invalid url: %s", err), 400) return } } else { fi, err := os.Stat(uri) if err != nil { Logger.Printf("Installer: While parsing url: %s", err) http.Error(w, fmt.Sprintf("Invalid uri/path: %s", err), 400) return } if !fi.Mode().IsRegular() { Logger.Printf("Installer: While parsing url: %s", err) http.Error(w, fmt.Sprintf("Invalid uri/path: %s", err), 400) return } } Logger.Printf("Installer: Sending request for: %s to channel", uri) getPath <- uri http.Redirect(w, r, "/", 302) }