media: check detected content-type against MSC2702
only return `inline` if the detected content-type is an allowed inline content-type as defined by MSC2702 Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
parent
9b096cc67b
commit
f11103b43b
1 changed files with 36 additions and 19 deletions
|
@ -1,5 +1,3 @@
|
|||
use infer::MatcherType;
|
||||
|
||||
use crate::debug_info;
|
||||
|
||||
const ATTACHMENT: &str = "attachment";
|
||||
|
@ -7,34 +5,53 @@ const INLINE: &str = "inline";
|
|||
const APPLICATION_OCTET_STREAM: &str = "application/octet-stream";
|
||||
const IMAGE_SVG_XML: &str = "image/svg+xml";
|
||||
|
||||
/// as defined by MSC2702
|
||||
const ALLOWED_INLINE_CONTENT_TYPES: [&str; 26] = [
|
||||
"text/css",
|
||||
"text/plain",
|
||||
"text/csv",
|
||||
"application/json",
|
||||
"application/ld+json",
|
||||
"image/jpeg",
|
||||
"image/gif",
|
||||
"image/png",
|
||||
"image/apng",
|
||||
"image/webp",
|
||||
"image/avif",
|
||||
"video/mp4",
|
||||
"video/webm",
|
||||
"video/ogg",
|
||||
"video/quicktime",
|
||||
"audio/mp4",
|
||||
"audio/webm",
|
||||
"audio/aac",
|
||||
"audio/mpeg",
|
||||
"audio/ogg",
|
||||
"audio/wave",
|
||||
"audio/wav",
|
||||
"audio/x-wav",
|
||||
"audio/x-pn-wav",
|
||||
"audio/flac",
|
||||
"audio/x-flac",
|
||||
];
|
||||
|
||||
/// Returns a Content-Disposition of `attachment` or `inline`, depending on the
|
||||
/// *parsed* contents of the file uploaded via format magic keys using `infer`
|
||||
/// crate (basically libmagic without needing libmagic).
|
||||
///
|
||||
/// This forbids trusting what the client or remote server says the file is from
|
||||
/// their `Content-Type` and we try to detect it ourselves. Also returns
|
||||
/// `attachment` if the Content-Type does not match what we detected.
|
||||
///
|
||||
/// TODO: add a "strict" function for comparing the Content-Type with what we
|
||||
/// detected: `file_type.mime_type() != content_type`
|
||||
#[must_use]
|
||||
#[tracing::instrument(skip(buf))]
|
||||
pub fn content_disposition_type(buf: &[u8], content_type: &Option<String>) -> &'static str {
|
||||
let Some(file_type) = infer::get(buf) else {
|
||||
debug_info!("Failed to infer the file's contents, assuming attachment for Content-Disposition");
|
||||
return ATTACHMENT;
|
||||
};
|
||||
|
||||
debug_info!("MIME type: {}", file_type.mime_type());
|
||||
debug_info!("detected MIME type: {}", file_type.mime_type());
|
||||
|
||||
match file_type.matcher_type() {
|
||||
MatcherType::Image | MatcherType::Audio | MatcherType::Text | MatcherType::Video => {
|
||||
if file_type.mime_type().contains("xml") {
|
||||
ATTACHMENT
|
||||
} else {
|
||||
if ALLOWED_INLINE_CONTENT_TYPES.contains(&file_type.mime_type()) {
|
||||
INLINE
|
||||
}
|
||||
},
|
||||
_ => ATTACHMENT,
|
||||
} else {
|
||||
ATTACHMENT
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue