use c2pa::{identity::validator::CawgValidator, Ingredient, Reader, Relationship};
use tokio::runtime::Builder;
use crate::{Error, Result, SignerInfo};
#[allow(deprecated)]
pub fn read_file(path: &str, data_dir: Option<String>) -> Result<String> {
let mut reader = Reader::from_file(path).map_err(Error::from_c2pa_error)?;
#[cfg(target_arch = "wasm32")]
let runtime = Builder::new_current_thread()
.enable_all()
.build()
.map_err(|e| Error::Other(e.to_string()))?;
#[cfg(not(target_arch = "wasm32"))]
let runtime = Builder::new_multi_thread()
.enable_all()
.build()
.map_err(|e| Error::Other(e.to_string()))?;
runtime
.block_on(reader.post_validate_async(&CawgValidator {}))
.map_err(Error::from_c2pa_error)?;
Ok(if let Some(dir) = data_dir {
let json = reader.json();
reader.to_folder(&dir).map_err(Error::from_c2pa_error)?;
json
} else {
reader.json()
})
}
#[allow(deprecated)]
pub fn sign_file(
source: &str,
dest: &str,
manifest_json: &str,
signer_info: &SignerInfo,
data_dir: Option<String>,
) -> Result<Vec<u8>> {
let mut builder = c2pa::Builder::from_json(manifest_json).map_err(Error::from_c2pa_error)?;
if let Some(path) = data_dir {
builder.set_base_path(path);
}
if !builder.definition.ingredients.iter().any(|i| i.is_parent()) {
let mut source_ingredient =
Ingredient::from_file(source).map_err(Error::from_c2pa_error)?;
if source_ingredient.manifest_data().is_some() {
source_ingredient.set_relationship(Relationship::ParentOf);
builder.add_ingredient(source_ingredient);
}
}
let signer = signer_info.signer()?;
builder
.sign_file(&*signer, source, dest)
.map_err(Error::from_c2pa_error)
}
#[cfg(test)]
#[allow(deprecated)]
mod tests {
use std::{ffi::CString, fs::remove_dir_all, path::PathBuf};
use c2pa::settings::Settings;
use super::*;
use crate::c_api::c2pa_load_settings;
pub fn test_path(path: &str) -> String {
let base = env!("CARGO_MANIFEST_DIR");
format!("{base}/../sdk/{path}")
}
#[test]
fn test_verify_from_file_no_base() {
let _ = Settings::from_toml(include_str!("../../sdk/tests/fixtures/test_settings.toml"));
let path = test_path("tests/fixtures/C.jpg");
let result = read_file(&path, None);
assert!(result.is_ok());
let json_report = result.unwrap();
println!("{json_report}");
assert!(json_report.contains("C.jpg"));
assert!(!json_report.contains("validation_status"));
}
#[test]
fn test_read_from_file_with_base() {
let _ = Settings::from_toml(include_str!("../../sdk/tests/fixtures/test_settings.toml"));
let path = test_path("tests/fixtures/C.jpg");
let data_dir = "../target/data_dir";
if PathBuf::from(data_dir).exists() {
remove_dir_all(data_dir).unwrap();
}
let result = read_file(&path, Some(data_dir.to_owned()));
let json_report = result.unwrap();
println!("{json_report}");
assert!(json_report.contains("C.jpg"));
assert!(PathBuf::from(data_dir).exists());
assert!(json_report.contains("thumbnail"));
}
#[test]
fn test_verify_from_file_cawg_identity() {
let settings = CString::new(include_bytes!(
"../../cli/tests/fixtures/trust/cawg_test_settings.toml"
))
.unwrap();
let format = CString::new("toml").unwrap();
let result = unsafe { c2pa_load_settings(settings.as_ptr(), format.as_ptr()) };
assert_eq!(result, 0);
let path = test_path("tests/fixtures/C_with_CAWG_data.jpg");
let result = read_file(&path, None);
dbg!(&result);
assert!(result.is_ok());
let json_report = result.unwrap();
println!("{json_report}");
assert!(json_report.contains("cawg.identity"));
assert!(json_report.contains("cawg.identity.well-formed"));
}
}