Initial commit master
authorvolpol <volpol@packet-gain.de>
Sun, 10 Jun 2018 14:09:03 +0000 (16:09 +0200)
committervolpol <volpol@packet-gain.de>
Sun, 10 Jun 2018 14:09:03 +0000 (16:09 +0200)
golfex.go [new file with mode: 0644]

diff --git a/golfex.go b/golfex.go
new file mode 100644 (file)
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<br>\n", mh.Filename);
+                                       //fmt.Fprintf(w, "File size: %v bytes<br>\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))
+}