fileupload: serve select MIME types as inline

This commit is contained in:
Simon Ser 2024-01-25 14:23:28 +01:00
parent 741fd040bb
commit c1fc2f1e61

View file

@ -17,6 +17,27 @@ import (
const maxSize = 50 * 1024 * 1024 // 50 MiB const maxSize = 50 * 1024 * 1024 // 50 MiB
// inlineMIMETypes contains MIME types which are allowed to be displayed inline
// by the Web browser. This has security implications: we don't want the
// browser to execute any kind of script. For instance, SVG images are
// intentionally omitted.
var inlineMIMETypes = map[string]bool{
"audio/aac": true,
"audio/mp4": true,
"audio/mpeg": true,
"audio/ogg": true,
"audio/webm": true,
"image/apng": true,
"image/gif": true,
"image/jpeg": true,
"image/png": true,
"image/webp": true,
"text/plain": true,
"video/mp4": true,
"video/ogg": true,
"video/webm": true,
}
type Uploader interface { type Uploader interface {
load(filename string) (basename string, modTime time.Time, content io.ReadSeekCloser, err error) load(filename string) (basename string, modTime time.Time, content io.ReadSeekCloser, err error)
store(r io.Reader, username, mimeType, basename string) (outFilename string, err error) store(r io.Reader, username, mimeType, basename string) (outFilename string, err error)
@ -78,7 +99,29 @@ func (h *Handler) fetch(resp http.ResponseWriter, req *http.Request) {
} }
defer content.Close() defer content.Close()
contentDisp := mime.FormatMediaType("attachment", map[string]string{ // Guess MIME type from extension, then from content
contentType := mime.TypeByExtension(path.Ext(basename))
if contentType == "" {
var buf [512]byte
n, _ := io.ReadFull(content, buf[:])
contentType = http.DetectContentType(buf[:n])
_, err := content.Seek(0, io.SeekStart) // rewind to output whole file
if err != nil {
http.Error(resp, "failed to seek file", http.StatusInternalServerError)
return
}
}
if contentType != "" {
resp.Header().Set("Content-Type", contentType)
}
contentDispMode := "attachment"
mimeType, _, _ := mime.ParseMediaType(contentType)
if inlineMIMETypes[mimeType] {
contentDispMode = "inline"
}
contentDisp := mime.FormatMediaType(contentDispMode, map[string]string{
"filename": basename, "filename": basename,
}) })
resp.Header().Set("Content-Disposition", contentDisp) resp.Header().Set("Content-Disposition", contentDisp)