c2pa-rs

A fork of https://github.com/contentauth/c2pa-rs/
git clone git://archive.git.mtrnord.blog/mtrnords-photography-manager/c2pa-rs.git
Log | Files | Refs | README

commit 039ebf423fc6b587346e3155fb59cf57302715b9
parent 95ee921eab0faf17b0a8cd695ec32f91ebe37785
Author: Gavin  Peacock <gpeacock@adobe.com>
Date:   Tue, 12 Mar 2024 09:21:50 -0700

Adds a Manifest::composed manifest method (#424)

* Adds ComposableManifest support to c2pa_io

* Adds Manifest::composed_manifest()
Provides a way to pre-format a manifest store for injection into a given file format.

* Remove self from Store::get_composed_manifest
Diffstat:
Msdk/src/asset_handlers/c2pa_io.rs | 15++++++++++++++-
Msdk/src/manifest.rs | 14++++++++++++--
Msdk/src/store.rs | 10+++++-----
3 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/sdk/src/asset_handlers/c2pa_io.rs b/sdk/src/asset_handlers/c2pa_io.rs @@ -14,7 +14,9 @@ use std::{fs::File, path::Path}; use crate::{ - asset_io::{AssetIO, CAIRead, CAIReader, HashBlockObjectType, HashObjectPositions}, + asset_io::{ + AssetIO, CAIRead, CAIReader, ComposedManifestRef, HashBlockObjectType, HashObjectPositions, + }, error::{Error, Result}, }; @@ -90,6 +92,17 @@ impl AssetIO for C2paIO { fn supported_types(&self) -> &[&str] { &SUPPORTED_TYPES } + + fn composed_data_ref(&self) -> Option<&dyn ComposedManifestRef> { + Some(self) + } +} + +impl ComposedManifestRef for C2paIO { + // Return entire CAI block as Vec<u8> + fn compose_manifest(&self, manifest_data: &[u8], _format: &str) -> Result<Vec<u8>> { + Ok(manifest_data.to_vec()) + } } #[cfg(test)] diff --git a/sdk/src/manifest.rs b/sdk/src/manifest.rs @@ -1242,10 +1242,17 @@ impl Manifest { let mut store = self.to_store()?; let mut cm = store.get_box_hashed_embeddable_manifest(signer)?; if let Some(format) = format { - cm = store.get_composed_manifest(&cm, format)?; + cm = Store::get_composed_manifest(&cm, format)?; } Ok(cm) } + + /// Formats a signed manifest for embedding in the given format + /// + /// For instance, this would return one or JPEG App11 segments containing the manifest + pub fn composed_manifest(manifest_bytes: &[u8], format: &str) -> Result<Vec<u8>> { + Store::get_composed_manifest(manifest_bytes, format) + } } impl std::fmt::Display for Manifest { @@ -2388,12 +2395,15 @@ pub(crate) mod tests { .data_hash_embeddable_manifest_remote( &dh, signer.as_ref(), - "image/jpeg", + "c2pa", // force an uncomposed manifest - you could send this to the cloud Some(&mut output_file), ) .await .unwrap(); + // test composed manifest here to ensure it works + let signed_manifest = + Manifest::composed_manifest(&signed_manifest, "image/jpeg").expect("composed_manifest"); use std::io::{Seek, SeekFrom, Write}; // path in new composed manifest diff --git a/sdk/src/store.rs b/sdk/src/store.rs @@ -1795,7 +1795,7 @@ impl Store { let jumbf_bytes = self.to_jumbf_internal(reserve_size)?; - let composed = self.get_composed_manifest(&jumbf_bytes, format)?; + let composed = Self::get_composed_manifest(&jumbf_bytes, format)?; Ok(composed) } @@ -1850,7 +1850,7 @@ impl Store { patch_bytes(jumbf_bytes, sig_placeholder, sig).map_err(|_| Error::JumbfCreationError)?; - self.get_composed_manifest(jumbf_bytes, format) + Self::get_composed_manifest(jumbf_bytes, format) } /// Returns a finalized, signed manifest. The manifest are only supported @@ -2020,7 +2020,7 @@ impl Store { /// Returns the supplied manifest composed to be directly compatible with the desired format. /// For example, if format is JPEG function will return the set of APP11 segments that contains /// the manifest. Similarly for PNG it would be the PNG chunk complete with header and CRC. - pub fn get_composed_manifest(&self, manifest_bytes: &[u8], format: &str) -> Result<Vec<u8>> { + pub fn get_composed_manifest(manifest_bytes: &[u8], format: &str) -> Result<Vec<u8>> { if let Some(h) = get_assetio_handler(format) { if let Some(composed_data_handler) = h.composed_data_ref() { return composed_data_handler.compose_manifest(manifest_bytes, format); @@ -4874,7 +4874,7 @@ pub mod tests { .unwrap(); // get composed version for embedding to JPEG - let cm = store.get_composed_manifest(&em, "jpg").unwrap(); + let cm = Store::get_composed_manifest(&em, "jpg").unwrap(); // insert manifest into output asset let jpeg_io = get_assetio_handler_from_path(&ap).unwrap(); @@ -4955,7 +4955,7 @@ pub mod tests { .unwrap(); // get composed version for embedding to JPEG - let cm = store.get_composed_manifest(&em, "jpg").unwrap(); + let cm = Store::get_composed_manifest(&em, "jpg").unwrap(); // insert manifest into output asset let jpeg_io = get_assetio_handler_from_path(&ap).unwrap();