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 b146bb7545086656941ae452428aef8c1b3ef6d6
parent 3726b0aaddf3f33b3ab50ddc3cf3698212aa8a4f
Author: Gavin  Peacock <gpeacock@adobe.com>
Date:   Fri,  2 Dec 2022 14:54:10 -0800

Fixes support for instanceId on action and generate parameters.ingredient field when possible (#158)

* Inject action.property.Ingredient based on instance_id
* fixes setting ingredients on actions
Update make_test_images
Diffstat:
Mmake_test_images/src/make_test_images.rs | 11++++-------
Msdk/src/assertions/actions.rs | 14++++++++++----
Msdk/src/manifest.rs | 36++++++++++++++++++++++++++++++++----
3 files changed, 46 insertions(+), 15 deletions(-)

diff --git a/make_test_images/src/make_test_images.rs b/make_test_images/src/make_test_images.rs @@ -218,8 +218,7 @@ impl MakeTestImages { let parent = Ingredient::from_file_with_options(src_path, &ImageOptions::new())?; actions = actions.add_action( - Action::new(c2pa_action::OPENED) - .set_parameter("identifier".to_owned(), parent.instance_id().to_owned())?, + Action::new(c2pa_action::OPENED).set_instance_id(parent.instance_id()), ); manifest.set_parent(parent)?; @@ -279,11 +278,9 @@ impl MakeTestImages { // create and add the ingredient let ingredient = Ingredient::from_file_with_options(ing_path, &ImageOptions::new())?; - actions = - actions.add_action(Action::new(c2pa_action::PLACED).set_parameter( - "identifier".to_owned(), - ingredient.instance_id().to_owned(), - )?); + actions = actions.add_action( + Action::new(c2pa_action::PLACED).set_instance_id(ingredient.instance_id()), + ); manifest.add_ingredient(ingredient); x += width; diff --git a/sdk/src/assertions/actions.rs b/sdk/src/assertions/actions.rs @@ -66,7 +66,7 @@ pub mod c2pa_action { /// the action. /// /// See <https://c2pa.org/specifications/specifications/1.0/specs/C2PA_Specification.html#_actions>. -#[derive(Deserialize, Serialize, Debug, PartialEq, Eq)] +#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq)] pub struct Action { /// The label associated with this action. See ([`c2pa_action`]). action: String, @@ -88,7 +88,7 @@ pub struct Action { changed: Option<String>, /// The value of the `xmpMM:InstanceID` property for the modified (output) resource. - #[serde(rename = "InstanceId", skip_serializing_if = "Option::is_none")] + #[serde(rename = "instanceId", skip_serializing_if = "Option::is_none")] instance_id: Option<String>, /// Additional parameters of the action. These vary by the type of action. @@ -279,6 +279,12 @@ impl Actions { self.metadata.as_ref() } + /// Internal method to update actions to meet spec requirements + pub(crate) fn update_action(mut self, index: usize, action: Action) -> Self { + self.actions[index] = action; + self + } + /// Adds an [`Action`] to this assertion's list of actions. pub fn add_action(mut self, action: Action) -> Self { self.actions.push(action); @@ -463,7 +469,6 @@ pub mod tests { #[test] fn test_binary_round_trip() { let assertion = Actions::new() - // .set_dictionary("http://testdictionary") .add_action( Action::new("c2pa.cropped") .set_parameter( @@ -515,7 +520,8 @@ pub mod tests { } }, { - "action": "c2pa.edited", + "action": "c2pa.opened", + "instanceId": "xmp.iid:7b57930e-2f23-47fc-affe-0400d70b738d", "parameters": { "description": "import" }, diff --git a/sdk/src/manifest.rs b/sdk/src/manifest.rs @@ -591,9 +591,13 @@ impl Manifest { } } + let mut ingredient_map = HashMap::new(); // add all ingredients to the claim for ingredient in &self.ingredients { - ingredient.add_to_claim(&mut claim, self.redactions.clone())?; + ingredient_map.insert( + ingredient.instance_id(), + ingredient.add_to_claim(&mut claim, self.redactions.clone())?, + ); } let salt = DefaultSalt::default(); @@ -602,9 +606,33 @@ impl Manifest { for manifest_assertion in &self.assertions { match manifest_assertion.label() { Actions::LABEL => { - let actions: Actions = manifest_assertion.to_assertion()?; - // todo: fixup parameters field from instance_id to ingredient uri for - // c2pa.transcoded, c2pa.repackaged, and c2pa.placed action + let mut actions: Actions = manifest_assertion.to_assertion()?; + + // fixup parameters field from instance_id to ingredient uri + let needs_ingredient: Vec<(usize, crate::assertions::Action)> = actions + .actions() + .iter() + .enumerate() + .filter_map(|(i, a)| { + if a.instance_id().is_some() && a.get_parameter("ingredient").is_none() + { + Some((i, a.clone())) + } else { + None + } + }) + .collect(); + + for (index, action) in needs_ingredient { + if let Some(id) = action.instance_id() { + if let Some(hash_url) = ingredient_map.get(id) { + let update = + action.set_parameter("ingredient", hash_url.clone())?; + actions = actions.update_action(index, update); + } + } + } + claim.add_assertion(&actions) } CreativeWork::LABEL => {