pub const RENDER_IMAGE: u32 = 1 << 0; pub const RENDER_VIDEO: u32 = 1 << 1; pub const RENDER_AUDIO: u32 = 1 << 2; pub const RENDER_MARKDOWN: u32 = 1 << 3; pub const RENDER_TEXT: u32 = 1 << 4; pub const RENDER_DOCUMENT: u32 = 1 << 5; pub const RENDER_EXECUTABLE: u32 = 1 << 6; pub const RENDER_DANGEROUS: u32 = 1 << 7; pub const RENDER_NO_INLINE: u32 = 1 << 8; const DANGEROUS_EXTENSIONS: &[&str] = &[ "exe", "scr", "bat", "cmd", "sh", "dll", "so", "dylib", "jar", "msi", "com", "app", "apk", ]; const DANGEROUS_MIME_TYPES: &[&str] = &[ "text/html", "text/javascript", "text/css", "application/javascript", "application/ecmascript", ]; pub fn detect_mime_type(data: &[u8], file_name: &str) -> String { if let Some(kind) = infer::get(data) { let mime = kind.mime_type(); if !mime.is_empty() && mime != "application/octet-stream" { return mime.to_string(); } } mime_guess::from_path(file_name) .first_or_octet_stream() .to_string() } pub fn compute_render_flags(mime_type: &str, file_name: &str, data: &[u8]) -> u32 { let mut flags = 0u32; if mime_type.starts_with("image/") { flags |= RENDER_IMAGE; } else if mime_type.starts_with("video/") { flags |= RENDER_VIDEO; } else if mime_type.starts_with("audio/") { flags |= RENDER_AUDIO; } else if mime_type == "text/markdown" || file_name.ends_with(".md") || file_name.ends_with(".markdown") { flags |= RENDER_MARKDOWN | RENDER_TEXT; } else if mime_type.starts_with("text/") { flags |= RENDER_TEXT; } else if mime_type == "application/pdf" || mime_type.starts_with("application/vnd.") { flags |= RENDER_DOCUMENT; } if DANGEROUS_MIME_TYPES.contains(&mime_type) { flags |= RENDER_DANGEROUS | RENDER_NO_INLINE; } let ext = file_name.rsplit('.').next().unwrap_or("").to_lowercase(); if DANGEROUS_EXTENSIONS.contains(&ext.as_str()) { flags |= RENDER_EXECUTABLE | RENDER_DANGEROUS | RENDER_NO_INLINE; } if let Some(kind) = infer::get(data) { let mime = kind.mime_type(); if mime == "application/x-executable" || mime == "application/x-msdownload" || mime == "application/x-pie-executable" { flags |= RENDER_EXECUTABLE | RENDER_DANGEROUS | RENDER_NO_INLINE; } } if flags & (RENDER_EXECUTABLE | RENDER_DANGEROUS) != 0 { flags |= RENDER_NO_INLINE; } flags } pub fn is_dangerous(flags: u32) -> bool { flags & RENDER_DANGEROUS != 0 } pub fn should_inline(flags: u32) -> bool { flags & RENDER_NO_INLINE == 0 }