From 89075959bf7ff1832cc38414a1ae392a49536294 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Sat, 2 Apr 2016 07:33:00 +0200 Subject: added simple HTTP upload handler 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 @@ + + + + rhimportd File Upload + + +
+

rhimportd File Upload

+
+
+ + +
+ + +
+ + +
+ +
+
+
+ + 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 +// +// 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 . +// + +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)) +} -- cgit v0.10.2