Two related changes that ensure remote images render inline in timelines
instead of as clickable links.
reverse_proxy: always force inline for whitelisted content types
When `inline_content_types` is configured as a whitelist, the upstream's
`content-disposition` header used to be passed through unchanged. Some
origins send `content-disposition: attachment` for media we want
embedded, so the proxy now always emits `content-disposition: inline`
for whitelisted types (overriding the upstream header), deriving a
filename from `MIME.extensions/1` (e.g. `inline.gif`) so browsers have
something to use for "Save As". When the type has no known extension,
the bare token `inline` is emitted. The `inline_content_types: true`
(pass-through) and `:false` (always attachment) behaviours are
unchanged.
ActivityPub: sniff MIME type for extensionless/generic attachments
Some remotes (e.g. extensionless Cloudflare Images URLs) ship
attachments with no usable `mediaType` (missing, empty, or
`application/octet-stream`), which would render as links instead of
inline images. `AttachmentValidator.fix_media_type/1` now fetches the
first 8 KB of the URL and runs it through libmagic when the declared
type carries no real information. Only `image/*` results replace the
declared type; any other result, non-2xx response, transport error, or
exception yields `nil` and the original type is kept, so ingestion
never blocks and non-image media is never reclassified. Present real
types are left untouched (no fetch is attempted).
The new logic lives in `Pleroma.Web.ActivityPub.ObjectValidators.AttachmentTypeSniffer`.
Tests: comprehensive coverage of both changes, including a dedicated
suite for the sniffer covering happy paths, non-image bodies, HTTP
failures, raised exceptions, guard clauses, and verification that the
Range header is sent; AttachmentValidator tests for mimeType fallback,
empty-string mediaType, multi-URL sniffing, and HTTP-failure fallback;
ReverseProxy tests for inline_content_types `true`/`false`/custom
whitelists, bare-inline for types without a MIME extension, and
attachment_name handling.