fix #221: scale image pastes, drop text box, fix raw view and size
- image pastes render the image scaled to fit the viewer box (aspect ratio preserved, max-height 70vh), no text/code box below it - link pill moved under the image as a small inline chip - /raw serves image attachment bytes as an image instead of empty text - view details size reports the actual attachment file size
This commit is contained in:
@@ -91,6 +91,17 @@ func (l *limitReader) Read(p []byte) (int, error) {
|
||||
return n, err
|
||||
}
|
||||
|
||||
// isImageMime reports whether the sniffed mime is a raster image the viewer
|
||||
// can render inline (#221). SVG is excluded: it is forced to text/plain on
|
||||
// serving by the active-content rule and must never render as an image.
|
||||
func isImageMime(mime string) bool {
|
||||
switch mime {
|
||||
case "image/png", "image/jpeg", "image/gif", "image/webp":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// handleCreatePasteMultipart implements POST /api/pastes with
|
||||
// multipart/form-data (#38). Fields mirror the JSON create path; a 'file'
|
||||
// part makes the paste a file paste (1 file = 1 paste: if text content is
|
||||
|
||||
@@ -451,6 +451,22 @@ func (a *apiServer) handleRaw(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "not found", 404)
|
||||
return
|
||||
}
|
||||
// #221: raw view of an image paste serves the image bytes themselves as
|
||||
// an image, not the (empty) text content.
|
||||
if att, err := a.store.GetAttachmentForPaste(row.ID); err == nil && att != nil && isImageMime(att.Mime) {
|
||||
blobs := a.store.Blobs()
|
||||
if blobs != nil {
|
||||
if blob, err := blobs.Get(row.ID + "/" + att.SHA256); err == nil {
|
||||
defer blob.Close()
|
||||
a.store.IncrementViews(row.ID, "", 0) // raw views always count (#49/#95)
|
||||
w.Header().Set("Content-Type", att.Mime)
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
w.Header().Set("Content-Length", fmt.Sprintf("%d", att.Size))
|
||||
http.ServeContent(w, r, "", time.Unix(att.CreatedAt, 0), blob)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
// #34: content_type is attacker-controlled via the create API. Serving it
|
||||
// verbatim let a paste be stored with text/html (or image/svg+xml) and
|
||||
// render as active content on this origin when fetched from /raw —
|
||||
|
||||
Reference in New Issue
Block a user