package web import ( "errors" "fmt" "mime/multipart" "net/http" "path" "strings" ) // parseUpload parses a multipart form with a file in the "file" field. On // failure it returns an HTTP status and a message for the page. // // Files bigger than 1 MB are spooled to temporary files rather than kept in // memory; net/http removes them when the handler returns. func (s *Server) parseUpload(w http.ResponseWriter, r *http.Request) (multipart.File, *multipart.FileHeader, int, string) { // Allow some slack over the file size limit for the multipart framing and form fields. r.Body = http.MaxBytesReader(w, r.Body, s.cfg.MaxUploadBytes+64<<10) if err := r.ParseMultipartForm(1 << 20); err != nil { var tooBig *http.MaxBytesError if errors.As(err, &tooBig) { return nil, nil, http.StatusRequestEntityTooLarge, "file too large; the maximum upload is " + s.maxUpload() } return nil, nil, http.StatusBadRequest, "bad upload: " + err.Error() } file, hdr, err := r.FormFile("file") if err != nil { return nil, nil, http.StatusBadRequest, "choose a pcap file" } return file, hdr, 0, "" } func (s *Server) maxUpload() string { return fmt.Sprintf("%d MB", s.cfg.MaxUploadBytes/1e6) } // uploadStem returns the sanitized name of an uploaded file without its extension. func uploadStem(hdr *multipart.FileHeader) string { name := safeName(hdr.Filename, "capture.pcap") return strings.TrimSuffix(name, path.Ext(name)) }