diff --git a/sdk/src/jumbf_io.rs b/sdk/src/jumbf_io.rs index acd75e97b..ef6b9ee2d 100644 --- a/sdk/src/jumbf_io.rs +++ b/sdk/src/jumbf_io.rs @@ -215,3 +215,17 @@ pub fn object_locations(in_path: &Path) -> Result> { _ => Err(Error::UnsupportedType), } } + +/// removes the C2PA JUMBF from an asset +/// Note: Use with caution since this deletes C2PA data +/// It is useful when creating remote manifests from embedded manifests +/// +/// path - path to file to be updated +/// returns Unsupported type or errors from remove_cai_store +pub fn remove_jumbf_from_file(path: &Path) -> Result<()> { + let ext = get_file_extension(path).ok_or(Error::UnsupportedType)?; + match get_assetio_handler(&ext) { + Some(asset_handler) => asset_handler.remove_cai_store(path), + _ => Err(Error::UnsupportedType), + } +} diff --git a/sdk/src/manifest.rs b/sdk/src/manifest.rs index a14742371..83e494ed6 100644 --- a/sdk/src/manifest.rs +++ b/sdk/src/manifest.rs @@ -1115,8 +1115,8 @@ pub(crate) mod tests { } #[cfg(all(feature = "file_io", feature = "xmp_write"))] - #[actix::test] - async fn test_embed_user_label() { + #[test] + fn test_embed_user_label() { let temp_dir = tempdir().expect("temp dir"); let output = temp_fixture_path(&temp_dir, TEST_SMALL_JPEG); @@ -1134,8 +1134,8 @@ pub(crate) mod tests { } #[cfg(all(feature = "file_io", feature = "xmp_write"))] - #[actix::test] - async fn test_embed_sidecar_user_label() { + #[test] + fn test_embed_sidecar_user_label() { let temp_dir = tempdir().expect("temp dir"); let output = temp_fixture_path(&temp_dir, TEST_SMALL_JPEG); let sidecar = output.with_extension("c2pa"); @@ -1158,4 +1158,30 @@ pub(crate) mod tests { TEST_SMALL_JPEG ); } + + #[cfg(all(feature = "file_io", feature = "xmp_write"))] + #[test] + fn test_embed_sidecar_with_parent_manifest() { + let temp_dir = tempdir().expect("temp dir"); + let source = fixture_path("XCA.jpg"); + let output = temp_dir.path().join("XCAplus.jpg"); + let sidecar = output.with_extension("c2pa"); + let fp = format!("file:/{}", sidecar.to_str().unwrap()); + let url = url::Url::parse(&fp).unwrap(); + + let signer = temp_signer(); + + let parent = Ingredient::from_file(fixture_path("XCA.jpg")).expect("getting parent"); + let mut manifest = test_manifest(); + manifest.set_parent(parent).expect("setting parent"); + manifest.set_remote_manifest(url); + let _c2pa_data = manifest.embed(&source, &output, &signer).expect("embed"); + + //let manifest_store = crate::ManifestStore::from_file(&sidecar).expect("from_file"); + let manifest_store = crate::ManifestStore::from_file(&output).expect("from_file"); + assert_eq!( + manifest_store.get_active().unwrap().title().unwrap(), + "XCAplus.jpg" + ); + } } diff --git a/sdk/src/store.rs b/sdk/src/store.rs index 5afddb52f..8cc05b953 100644 --- a/sdk/src/store.rs +++ b/sdk/src/store.rs @@ -32,7 +32,7 @@ use crate::{ cose_validator::verify_cose, jumbf_io::{ get_file_extension, get_supported_file_extension, is_bmff_format, load_jumbf_from_file, - object_locations, save_jumbf_to_file, + object_locations, remove_jumbf_from_file, save_jumbf_to_file, }, utils::{ hash_utils::{hash256, Exclusion}, @@ -1610,10 +1610,14 @@ impl Store { dest_path.to_path_buf() } crate::claim::RemoteManifest::SideCar => { + // remove any previous c2pa manifest from the asset + remove_jumbf_from_file(dest_path)?; dest_path.with_extension(MANIFEST_STORE_EXT) } crate::claim::RemoteManifest::Remote(_url) => { let d = dest_path.with_extension(MANIFEST_STORE_EXT); + // remove any previous c2pa manifest from the asset + remove_jumbf_from_file(dest_path)?; // even though this block is protected by the outer cfg!(feature = "xmp_write") // the class embedded_xmp is not defined so we have to explicitly exclude it from the build #[cfg(feature = "xmp_write")] @@ -1634,6 +1638,8 @@ impl Store { match pc.remote_manifest() { crate::claim::RemoteManifest::NoRemote => dest_path.to_path_buf(), crate::claim::RemoteManifest::SideCar => { + // remove any previous c2pa manifest from the asset + remove_jumbf_from_file(dest_path)?; dest_path.with_extension(MANIFEST_STORE_EXT) } crate::claim::RemoteManifest::Remote(_)