summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@helsinki.at>2016-04-02 05:33:00 (GMT)
committerChristian Pointner <equinox@helsinki.at>2016-04-02 05:33:00 (GMT)
commit89075959bf7ff1832cc38414a1ae392a49536294 (patch)
tree0e2c7f5f58d39c9b3eaf9899d3527e2b119a0d2b
parent27eaf84de6c5900c739f73725bd07270d43d49b7 (diff)
added simple HTTP upload handler
-rw-r--r--html/upload-form.html25
-rw-r--r--src/rhimportd/ctrlWeb.go3
-rw-r--r--src/rhimportd/uploadWeb.go127
3 files changed, 154 insertions, 1 deletions
diff --git a/html/upload-form.html b/html/upload-form.html
new file mode 100644
index 0000000..1718b1b
--- /dev/null
+++ b/html/upload-form.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <title>rhimportd File Upload</title>
+ </head>
+ <body>
+ <div class="container">
+ <h1>rhimportd File Upload</h1>
+ <form class="form-upload" method="post" enctype="multipart/form-data">
+ <fieldset>
+ <label for="LOGIN_NAME">Username:</label>
+ <input type="text" name="LOGIN_NAME">
+ </br>
+ <label for="LOGIN_NAME">Password:</label>
+ <input type="password" name="PASSWORD">
+ </br>
+ <label for="FILENAME">File:</label>
+ <input type="file" name="FILENAME">
+ </br>
+ <input type="submit" name="submit" value="Submit">
+ </fieldset>
+ </form>
+ </div>
+ </body>
+</html>
diff --git a/src/rhimportd/ctrlWeb.go b/src/rhimportd/ctrlWeb.go
index 40075d0..70d8733 100644
--- a/src/rhimportd/ctrlWeb.go
+++ b/src/rhimportd/ctrlWeb.go
@@ -45,10 +45,11 @@ func (self webHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
func StartControlWeb(addr string, conf *rhimport.Config, db *rddb.DBChan, sessions *rhimport.SessionStoreChan) {
- http.Handle("/public/simple", webHandler{conf, db, sessions, false, webSimpleHandler})
// http.Handle("/trusted/simple", webHandler{conf, db, sessions, true, webSimpleHandler})
+ http.Handle("/public/simple", webHandler{conf, db, sessions, false, webSimpleHandler})
http.Handle("/public/socket", webHandler{conf, db, sessions, false, webSocketHandler})
+ http.Handle("/public/upload", webHandler{conf, db, sessions, false, webUploadHandler})
rhl.Println("web-ctrl: listening on", addr)
server := &http.Server{Addr: addr, ReadTimeout: 60 * time.Second, WriteTimeout: 60 * time.Second}
diff --git a/src/rhimportd/uploadWeb.go b/src/rhimportd/uploadWeb.go
new file mode 100644
index 0000000..02d918c
--- /dev/null
+++ b/src/rhimportd/uploadWeb.go
@@ -0,0 +1,127 @@
+//
+// rhimportd
+//
+// The Radio Helsinki Rivendell Import Daemon
+//
+//
+// Copyright (C) 2015-2016 Christian Pointner <equinox@helsinki.at>
+//
+// This file is part of rhimportd.
+//
+// rhimportd is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// any later version.
+//
+// rhimportd is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with rhimportd. If not, see <http://www.gnu.org/licenses/>.
+//
+
+package main
+
+import (
+ "code.helsinki.at/rhrd-go/rddb"
+ "code.helsinki.at/rhrd-go/rhimport"
+ "encoding/json"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "os"
+ "strings"
+)
+
+type webUploadResponseData struct {
+ ResponseCode int `json:"RESPONSE_CODE"`
+ ErrorString string `json:"ERROR_STRING"`
+ SourceFile string `json:"SOURCE_FILE"`
+}
+
+func webUploadErrorResponse(w http.ResponseWriter, code int, errStr string) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(code)
+ encoder := json.NewEncoder(w)
+ respdata := webUploadResponseData{code, errStr, ""}
+ encoder.Encode(respdata)
+}
+
+func webUploadResponse(w http.ResponseWriter, file string) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ encoder := json.NewEncoder(w)
+ respdata := webUploadResponseData{http.StatusOK, "success", file}
+ encoder.Encode(respdata)
+}
+
+func webUploadHandler(conf *rhimport.Config, db *rddb.DBChan, sessions *rhimport.SessionStoreChan, trusted bool, w http.ResponseWriter, r *http.Request) {
+ if r.Method == "GET" {
+ http.ServeFile(w, r, "./html/upload-form.html")
+ return
+ }
+
+ if r.Method != "POST" {
+ rhl.Printf("WebUploadHandler: got invalid request method")
+ webUploadErrorResponse(w, http.StatusMethodNotAllowed, "only POST and GET method are allowed")
+ return
+ }
+
+ if err := r.ParseMultipartForm(2 << 30); err != nil { // TODO: howto limit max file size???
+ rhl.Printf("WebUploadHandler: error while parsing multi-part-form: %v", err)
+ webUploadErrorResponse(w, http.StatusBadRequest, err.Error())
+ return
+ }
+
+ username := r.FormValue("LOGIN_NAME")
+ password := r.FormValue("PASSWORD")
+ if username == "" {
+ webUploadErrorResponse(w, http.StatusBadRequest, "missing field LOGIN_NAME")
+ return
+ }
+ if password == "" {
+ webUploadErrorResponse(w, http.StatusBadRequest, "missing field LOGIN_NAME")
+ return
+ }
+
+ if authenticated, err := db.CheckPassword(username, password); err != nil {
+ rhl.Printf("WebUploadHandler: error checking username/password: %v", err)
+ webUploadErrorResponse(w, http.StatusUnauthorized, err.Error())
+ return
+ } else if !authenticated {
+ rhl.Printf("WebUploadHandler: invalid username/password")
+ webUploadErrorResponse(w, http.StatusUnauthorized, "invalid username/password")
+ return
+ }
+
+ src, hdr, err := r.FormFile("FILENAME")
+ if err != nil {
+ rhdl.Printf("WebUploadHandler: error looking for upload file in form: %s", err)
+ webUploadErrorResponse(w, http.StatusBadRequest, err.Error())
+ return
+ }
+ defer src.Close()
+
+ rhl.Printf("WebUploadHandler: got request from user '%s', filename='%s'", username, hdr.Filename)
+
+ dstpath, err := ioutil.TempDir(conf.TempDir, "rhimportd-")
+ if err != nil {
+ rhl.Printf("WebUploadHandler: error creating temporary directory: %v", err)
+ webUploadErrorResponse(w, http.StatusInternalServerError, err.Error())
+ return
+ }
+
+ dstfile := dstpath + "/" + hdr.Filename
+ dst, err := os.OpenFile(dstfile, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600)
+ if err != nil {
+ rhl.Printf("WebUploadHandler: Unable to create file '%s': %v", dstfile, err)
+ webUploadErrorResponse(w, http.StatusInternalServerError, err.Error())
+ return
+ }
+ defer dst.Close()
+
+ io.Copy(dst, src)
+ webUploadResponse(w, "tmp://"+strings.TrimPrefix(dstfile, conf.TempDir))
+}