Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion sdk/src/asset_handlers/bmff_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,16 @@ const FULL_BOX_TYPES: &[&str; 80] = &[
"txtC", "mime", "uri ", "uriI", "hmhd", "sthd", "vvhd", "medc",
];

static SUPPORTED_TYPES: [&str; 15] = [
static SUPPORTED_TYPES: [&str; 19] = [
"avif",
"heif",
"heic",
"mp4",
"m4a",
"mov",
"m4v",
"3gp",
"3g2",
"application/mp4",
"audio/mp4",
"image/avif",
Expand All @@ -87,6 +89,8 @@ static SUPPORTED_TYPES: [&str; 15] = [
"video/mp4",
"video/quicktime",
"video/x-m4v",
"video/3gpp",
"video/3g2",
];

macro_rules! boxtype {
Expand Down Expand Up @@ -1718,6 +1722,27 @@ impl AssetIO for BmffIO {
fn supported_types(&self) -> &[&str] {
&SUPPORTED_TYPES
}

fn get_handler_type_from_bytes(&self, data: &[u8]) -> Option<&'static str> {
if data.len() < 12 || &data[4..8] != crate::utils::signatures::BMFF_FTYP {
return None;
}
let brand = &data[8..12];
match brand {
b"mp41" | b"mp42" | b"isom" | b"iso2" | b"iso3" | b"iso4" | b"iso5" | b"iso6"
| b"avc1" | b"mp71" => Some("video/mp4"),
b"m4a " => Some("audio/mp4"),
b"m4v " => Some("video/x-m4v"),
b"heic" | b"heix" | b"mif1" | b"msf1" => Some("image/heic"),
b"hevc" | b"hevx" => Some("image/heif"),
b"avif" | b"avis" => Some("image/avif"),
b"qt " => Some("video/quicktime"),
b"3gp1" | b"3gp2" | b"3gp3" | b"3gp4" | b"3gp5" | b"3gp6" | b"3gr6" | b"3gs6"
| b"3ge6" => Some("video/3gpp"),
b"3g2a" | b"3g2b" | b"3g2c" => Some("video/3g2"),
_ => None,
}
}
}

impl CAIWriter for BmffIO {
Expand Down
11 changes: 11 additions & 0 deletions sdk/src/asset_handlers/c2pa_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,17 @@ impl AssetIO for C2paIO {
&SUPPORTED_TYPES
}

fn get_handler_type_from_bytes(&self, data: &[u8]) -> Option<&'static str> {
// JUMBF starts with a box size then 'jumb'
if data.len() < 8 {
return None;
}
if &data[4..8] == crate::utils::signatures::JUMBF_TYPE {
return Some("application/c2pa");
}
None
}

fn composed_data_ref(&self) -> Option<&dyn ComposedManifestRef> {
Some(self)
}
Expand Down
9 changes: 9 additions & 0 deletions sdk/src/asset_handlers/gif_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,15 @@ impl AssetIO for GifIO {
fn supported_types(&self) -> &[&str] {
&["gif", "image/gif"]
}

fn get_handler_type_from_bytes(&self, data: &[u8]) -> Option<&'static str> {
if data.starts_with(crate::utils::signatures::GIF87A)
|| data.starts_with(crate::utils::signatures::GIF89A)
{
return Some("image/gif");
}
None
}
}

impl GifIO {
Expand Down
10 changes: 10 additions & 0 deletions sdk/src/asset_handlers/jpeg_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,16 @@ impl AssetIO for JpegIO {
fn supported_types(&self) -> &[&str] {
&SUPPORTED_TYPES
}

fn get_handler_type_from_bytes(&self, data: &[u8]) -> Option<&'static str> {
if data.len() < 3 {
return None;
}
if data.starts_with(crate::utils::signatures::JPEG) {
return Some("image/jpeg");
}
None
}
}

impl RemoteRefEmbed for JpegIO {
Expand Down
14 changes: 14 additions & 0 deletions sdk/src/asset_handlers/mp3_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,20 @@ impl AssetIO for Mp3IO {
fn supported_types(&self) -> &[&str] {
&SUPPORTED_TYPES
}

fn get_handler_type_from_bytes(&self, data: &[u8]) -> Option<&'static str> {
if data.len() < 3 {
return None;
}
if data.starts_with(crate::utils::signatures::MP3_ID3) {
return Some("audio/mpeg");
}
// MP3 sync frame (simplified)
if data.len() >= 2 && data[0] == 0xff && (data[1] & 0xe0) == 0xe0 {
return Some("audio/mpeg");
}
None
}
}

impl CAIWriter for Mp3IO {
Expand Down
7 changes: 7 additions & 0 deletions sdk/src/asset_handlers/pdf_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@ impl AssetIO for PdfIO {
&SUPPORTED_TYPES
}

fn get_handler_type_from_bytes(&self, data: &[u8]) -> Option<&'static str> {
if data.starts_with(crate::utils::signatures::PDF) {
return Some("application/pdf");
}
None
}

fn composed_data_ref(&self) -> Option<&dyn ComposedManifestRef> {
Some(self)
}
Expand Down
10 changes: 10 additions & 0 deletions sdk/src/asset_handlers/png_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,16 @@ impl AssetIO for PngIO {
fn supported_types(&self) -> &[&str] {
&SUPPORTED_TYPES
}

fn get_handler_type_from_bytes(&self, data: &[u8]) -> Option<&'static str> {
if data.len() < 8 {
return None;
}
if data.starts_with(crate::utils::signatures::PNG) {
return Some("image/png");
}
None
}
}

fn get_xmp_insertion_point(asset_reader: &mut dyn CAIRead) -> Option<(u64, u32)> {
Expand Down
17 changes: 17 additions & 0 deletions sdk/src/asset_handlers/riff_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,23 @@ impl AssetIO for RiffIO {
fn supported_types(&self) -> &[&str] {
&SUPPORTED_TYPES
}

fn get_handler_type_from_bytes(&self, data: &[u8]) -> Option<&'static str> {
if data.len() < 12 || &data[0..4] != crate::utils::signatures::RIFF {
return None;
}
let form_type = &data[8..12];
if form_type == crate::utils::signatures::AVI {
return Some("video/avi");
}
if form_type == crate::utils::signatures::WEBP {
return Some("image/webp");
}
if form_type == crate::utils::signatures::WAVE {
return Some("audio/wav");
}
None
}
}

impl CAIWriter for RiffIO {
Expand Down
15 changes: 15 additions & 0 deletions sdk/src/asset_handlers/svg_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,21 @@ impl AssetIO for SvgIO {
fn supported_types(&self) -> &[&str] {
&SUPPORTED_TYPES
}

fn get_handler_type_from_bytes(&self, data: &[u8]) -> Option<&'static str> {
// Check for "<svg" or "<?xml" followed by "<svg"
let header_len = std::cmp::min(data.len(), 512);
if let Ok(header) = std::str::from_utf8(&data[..header_len]) {
let header = header.trim_start();
if header.starts_with(crate::utils::signatures::SVG_TAG)
|| (header.starts_with(crate::utils::signatures::SVG_XML_TAG)
&& header.contains(crate::utils::signatures::SVG_TAG))
{
return Some("image/svg+xml");
}
}
None
}
}

// create manifest entry
Expand Down
12 changes: 12 additions & 0 deletions sdk/src/asset_handlers/tiff_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1678,6 +1678,18 @@ impl AssetIO for TiffIO {
fn supported_types(&self) -> &[&str] {
&SUPPORTED_TYPES
}

fn get_handler_type_from_bytes(&self, data: &[u8]) -> Option<&'static str> {
if data.len() < 4 {
return None;
}
if data.starts_with(crate::utils::signatures::TIFF_LE)
|| data.starts_with(crate::utils::signatures::TIFF_BE)
{
return Some("image/tiff");
}
None
}
}

impl CAIWriter for TiffIO {
Expand Down
5 changes: 5 additions & 0 deletions sdk/src/asset_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ pub trait AssetIO: Sync + Send {

// OPTIONAL INTERFACES

// Checks if the data matches the file signature for this handler and returns the mime type.
fn get_handler_type_from_bytes(&self, _data: &[u8]) -> Option<&'static str> {
None
}

// Returns [`AssetPatch`] trait if this I/O handler supports patching.
#[allow(dead_code)] // this here for wasm builds to pass clippy (todo: remove)
fn asset_patch_ref(&self) -> Option<&dyn AssetPatch> {
Expand Down
7 changes: 4 additions & 3 deletions sdk/src/ingredient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,9 +548,10 @@ impl Ingredient {
.unwrap_or_else(|| "".into())
.to_lowercase();

let format = extension_to_mime(&extension)
.unwrap_or("application/octet-stream")
.to_owned();
let format = crate::utils::mime::detect_format_from_path(path)
.or_else(|| extension_to_mime(&extension).map(|m| m.to_owned()))
.unwrap_or_else(|| "application/octet-stream".to_owned());

(title, extension, format)
}

Expand Down
Loading