diff --git a/handlers.go b/handlers.go index 08ce727..0da8ad5 100644 --- a/handlers.go +++ b/handlers.go @@ -18,6 +18,12 @@ import ( bolt "go.etcd.io/bbolt" ) +const ( + // formParseMaxMemory value is based on the default value that is used in + // Request.ParseMultipartForm. + formParseMaxMemory = 32 << 20 // 32 MB +) + type viewPaste uint const ( @@ -223,25 +229,37 @@ func (rl *rushlink) viewActionSuccess(w http.ResponseWriter, r *http.Request, p } func (rl *rushlink) newPasteHandler(w http.ResponseWriter, r *http.Request) { - file, fileHeader, err := r.FormFile("file") - if err == nil { - rl.newFileUploadPasteHandler(w, r, file, *fileHeader) - return - } else if err == http.ErrMissingFile { - // Fallthrough - } else { + if err := r.ParseMultipartForm(formParseMaxMemory); err != nil { msg := fmt.Sprintf("could not parse form: %v\n", err) rl.renderError(w, r, http.StatusBadRequest, msg) return } - shorten := r.FormValue("shorten") - if shorten != "" { - rl.newRedirectPasteHandler(w, r, shorten) + fileHeaders, fileHeadersPrs := r.MultipartForm.File["file"] + shortens, shortensPrs := r.MultipartForm.Value["shorten"] + + if !shortensPrs && !fileHeadersPrs { + rl.renderError(w, r, http.StatusBadRequest, "no 'file' and no 'shorten' fields given in form\n") + return + } + if shortensPrs && fileHeadersPrs { + rl.renderError(w, r, http.StatusBadRequest, "both 'file' and 'shorten' fields provided in form\n") + return + } + if shortensPrs { + rl.newRedirectPasteHandler(w, r, shortens[0]) + return + } + if fileHeadersPrs { + fileHeader := fileHeaders[0] + file, err := fileHeader.Open() + if err != nil { + rl.renderInternalServerError(w, r, err) + return + } + rl.newFileUploadPasteHandler(w, r, file, *fileHeader) return } - - rl.renderError(w, r, http.StatusBadRequest, "no 'file' and no 'shorten' fields given in form\n") } func (rl *rushlink) newFileUploadPasteHandler(w http.ResponseWriter, r *http.Request, file multipart.File, header multipart.FileHeader) { diff --git a/handlers_test.go b/handlers_test.go index 529c2b2..c0e2381 100644 --- a/handlers_test.go +++ b/handlers_test.go @@ -159,3 +159,26 @@ func TestIssue60(t *testing.T) { srv.ServeHTTP(rr, req) checkStatusCode(t, rr, http.StatusNotFound) } + +func TestIssue56(t *testing.T) { + srv, _ := createTemporaryRouter(t) + + // Make a POST request with both a 'file' *and* a 'shorten' part. + var body bytes.Buffer + form := multipart.NewWriter(&body) + if _, err := form.CreateFormFile("file", "empty.txt"); err != nil { + t.Fatal(err) + } + if _, err := form.CreateFormField("shorten"); err != nil { + t.Fatal(err) + } + form.Close() + req, err := http.NewRequest("POST", "/", bytes.NewReader(body.Bytes())) + if err != nil { + t.Fatal(err) + } + req.Header.Add("Content-Type", form.FormDataContentType()) + rr := httptest.NewRecorder() + srv.ServeHTTP(rr, req) + checkStatusCode(t, rr, http.StatusBadRequest) +}