From: volpol Date: Sun, 10 Jun 2018 14:09:03 +0000 (+0200) Subject: Initial commit X-Git-Url: https://git.packet-gain.de/?a=commitdiff_plain;h=refs%2Fheads%2Fmaster;p=golfex.git Initial commit --- 2df905012282aa07d0b8a90d0ed49908020158a8 diff --git a/golfex.go b/golfex.go new file mode 100644 index 0000000..4b4b6a3 --- /dev/null +++ b/golfex.go @@ -0,0 +1,125 @@ +package main + +import ( + "database/sql" + "flag" + "fmt" + _ "github.com/mattn/go-sqlite3" + "io" + "log" + "net/http" + "net/url" + "os" + "path/filepath" + "strings" +) + +const ( + DefaultFormFileKey = "fileToUpload" + DefaultUploadPath = "/tmp" + DefaultUploadPrefix = "/upload" + DefaultRootIndex = "index.html" +) + +var FormFileKey = flag.String("k", DefaultFormFileKey, "FormFileKey") +var UploadPath = flag.String("u", DefaultUploadPath, "UploadPath") +var UploadPrefix = flag.String("p", DefaultUploadPrefix, "UploadPrefix") +var RootIndex = flag.String("i", DefaultRootIndex, "RootIndex") +var Help = flag.Bool("h", false, "Show usage") + +func urlEscape(s string) string { + url := url.URL{Path: s} + return url.String() +} + +func getFromDB(name string) (string, error) { + content := "" + db, err := sql.Open("sqlite3", "golfex.sqlite") + if err == nil { + defer db.Close() + var stmt *sql.Stmt + stmt, err = db.Prepare("SELECT content FROM docroot WHERE name = ?") + if nil == err { + defer stmt.Close() + err = stmt.QueryRow(name).Scan(&content) + } + } + return content, err +} + +func rootHF(w http.ResponseWriter, r *http.Request) { + log.Print(r.RemoteAddr, " ", r.Method, " ", r.URL.String()) + if http.MethodGet == r.Method { + //http module does plenty of cleaning on r.URL.Path + //so this should be "safe" + docName := strings.TrimLeft(r.URL.String(), "/") + if "" == docName { + docName = *RootIndex + } + //check if this is upload file request + if strings.HasPrefix(r.URL.String(), *UploadPrefix) { + upath := filepath.Join(*UploadPath, strings.Replace(r.URL.String(), *UploadPrefix, "", 1)) + log.Print("Serving ", upath) + //only here because we want to do dir listing + //otherwise docName = upath should've done it + http.ServeFile(w, r, upath) + return + } + log.Print("Final docName: ", docName) + //see if there is a local file and serve it + fio, err := os.Stat(docName) + if (nil == err) && (fio.Mode().IsRegular()) { + log.Print("Serving local file") + http.ServeFile(w, r, docName) + return + } + log.Print("Serving from DB") + var content string + content, err = getFromDB(docName) + if err == nil { + w.Header().Add("Content-Length", fmt.Sprintf("%d", len(content))) + w.WriteHeader(http.StatusOK) + io.WriteString(w, content) + } else { + log.Print("DB lookup failed: ", err) + http.Error(w, "404 Not Found", http.StatusNotFound) + } + } else { + if http.MethodPost == r.Method { + ufile, mh, err := r.FormFile(*FormFileKey) + if nil == err { + defer ufile.Close() + of_dump, of_err := os.OpenFile(filepath.Join(*UploadPath, mh.Filename), os.O_CREATE|os.O_WRONLY, 0644) + if nil == of_err { + defer of_dump.Close() + io.Copy(of_dump, ufile) + log.Printf("Saved %v bytes to %v\n", mh.Size, mh.Filename) + w.WriteHeader(http.StatusOK) + io.WriteString(w, "Success!") + //fmt.Fprintf(w, "File name: %s
\n", mh.Filename); + //fmt.Fprintf(w, "File size: %v bytes
\n", mh.Size); + } else { + err = of_err + } + } + if nil != err { + w.WriteHeader(http.StatusInternalServerError) + fmt.Fprintf(w, "Error: %v", strings.Replace(err.Error(), *UploadPath, *UploadPrefix, -1)) + log.Print(err) + } + } + } +} + +func main() { + flag.Parse() + if *Help { + fmt.Printf("Usage: \n") + flag.PrintDefaults() + return + } + fmt.Printf("Current settings: \n") + flag.VisitAll(func(f *flag.Flag) { fmt.Printf("%v: %v\n", f.Usage, f.Value) }) + http.HandleFunc("/", rootHF) + log.Fatal(http.ListenAndServe(":8000", nil)) +}