Skip to content

Commit b2d8b71

Browse files
authored
fix: do not generate multiple c2pa.placed actions with settings (#1458)
* fix: handle actions settings after preprocessing * docs: fix typo in comment * test: add test case to confirm one placed action is created
1 parent bb1d834 commit b2d8b71

File tree

1 file changed

+79
-3
lines changed

1 file changed

+79
-3
lines changed

sdk/src/builder.rs

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -919,12 +919,10 @@ impl Builder {
919919

920920
let mut actions: Actions = manifest_assertion.to_assertion()?;
921921

922-
Self::add_actions_assertion_settings(&ingredient_map, &mut actions)?;
923-
924922
let mut updates = Vec::new();
925923
//#[allow(clippy::explicit_counter_loop)]
926924
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
928926
let ids = action.extract_ingredient_ids();
929927

930928
if let Some(ids) = ids {
@@ -998,6 +996,10 @@ impl Builder {
998996
}
999997
}
1000998

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+
10011003
claim.add_assertion(&actions)
10021004
}
10031005
#[allow(deprecated)]
@@ -1887,6 +1889,80 @@ mod tests {
18871889
assert_eq!(test_assertion.answer, 42);
18881890
}
18891891

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+
18901966
#[test]
18911967
fn test_builder_settings_auto_created() {
18921968
#[cfg(target_os = "wasi")]

0 commit comments

Comments
 (0)