@@ -919,12 +919,10 @@ impl Builder {
919
919
920
920
let mut actions: Actions = manifest_assertion. to_assertion ( ) ?;
921
921
922
- Self :: add_actions_assertion_settings ( & ingredient_map, & mut actions) ?;
923
-
924
922
let mut updates = Vec :: new ( ) ;
925
923
//#[allow(clippy::explicit_counter_loop)]
926
924
for ( index, action) in actions. actions_mut ( ) . iter_mut ( ) . enumerate ( ) {
927
- // find and remove the temporary ingredientIds parameter (This h)
925
+ // find and remove the temporary ingredientIds parameter
928
926
let ids = action. extract_ingredient_ids ( ) ;
929
927
930
928
if let Some ( ids) = ids {
@@ -998,6 +996,10 @@ impl Builder {
998
996
}
999
997
}
1000
998
999
+ // Do this at the end of the preprocessing step to ensure all ingredient references
1000
+ // are resolved to their hashed URIs.
1001
+ Self :: add_actions_assertion_settings ( & ingredient_map, & mut actions) ?;
1002
+
1001
1003
claim. add_assertion ( & actions)
1002
1004
}
1003
1005
#[ allow( deprecated) ]
@@ -1887,6 +1889,80 @@ mod tests {
1887
1889
assert_eq ! ( test_assertion. answer, 42 ) ;
1888
1890
}
1889
1891
1892
+ // Ensure multiple `c2pa.placed` actions aren't created.
1893
+ // Source: https://github.com/contentauth/c2pa-rs/pull/1458
1894
+ #[ test]
1895
+ fn test_builder_one_placed_action_via_ingredient_id_ref ( ) {
1896
+ #[ cfg( target_os = "wasi" ) ]
1897
+ Settings :: reset ( ) . unwrap ( ) ;
1898
+
1899
+ Settings :: from_toml (
1900
+ & toml:: toml! {
1901
+ [ builder. actions. auto_placed_action]
1902
+ enabled = true
1903
+ }
1904
+ . to_string ( ) ,
1905
+ )
1906
+ . unwrap ( ) ;
1907
+
1908
+ let mut output = Cursor :: new ( Vec :: new ( ) ) ;
1909
+ let mut builder = Builder :: from_json (
1910
+ & json ! ( {
1911
+ "title" : "Test Manifest" ,
1912
+ "format" : "image/jpeg" ,
1913
+ "ingredients" : [
1914
+ {
1915
+ "title" : "Test Ingredient" ,
1916
+ "format" : "image/jpeg" ,
1917
+ "relationship" : "componentOf" ,
1918
+ "instance_id" : "123"
1919
+ }
1920
+ ] ,
1921
+ "assertions" : [
1922
+ {
1923
+ "label" : "c2pa.actions" ,
1924
+ "data" : {
1925
+ "actions" : [
1926
+ {
1927
+ "action" : "c2pa.placed" ,
1928
+ "instanceId" : "123"
1929
+ }
1930
+ ]
1931
+ }
1932
+ } ,
1933
+ ]
1934
+ } )
1935
+ . to_string ( ) ,
1936
+ )
1937
+ . unwrap ( ) ;
1938
+ builder
1939
+ . sign (
1940
+ & Settings :: signer ( ) . unwrap ( ) ,
1941
+ "image/jpeg" ,
1942
+ & mut Cursor :: new ( TEST_IMAGE ) ,
1943
+ & mut output,
1944
+ )
1945
+ . unwrap ( ) ;
1946
+
1947
+ output. rewind ( ) . unwrap ( ) ;
1948
+ let reader = Reader :: from_stream ( "image/jpeg" , output) . unwrap ( ) ;
1949
+
1950
+ let actions: Actions = reader
1951
+ . active_manifest ( )
1952
+ . unwrap ( )
1953
+ . find_assertion ( Actions :: LABEL )
1954
+ . unwrap ( ) ;
1955
+
1956
+ assert_eq ! ( actions. actions. len( ) , 2 ) ;
1957
+
1958
+ let num_placed_actions = actions
1959
+ . actions
1960
+ . iter ( )
1961
+ . filter ( |action| action. action ( ) == c2pa_action:: PLACED )
1962
+ . count ( ) ;
1963
+ assert_eq ! ( num_placed_actions, 1 ) ;
1964
+ }
1965
+
1890
1966
#[ test]
1891
1967
fn test_builder_settings_auto_created ( ) {
1892
1968
#[ cfg( target_os = "wasi" ) ]
0 commit comments