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 2ba7c8bbc1302fca7be1a88442617caf24cd0afe
parent c884f30e3d4000171b5fabefbc4b73b38b9c1338
Author: nick <nickyboy04@icloud.com>
Date:   Mon, 10 Jun 2024 10:57:19 -0400

Implement `Debug` w/ detailed manifest for `Reader` (#473)

* Add `Store` field to `ManifestStore`

* Serializable `Reader` + detailed manifest from `Debug`

* Fix clippy lints

* Remove `Serialize` from `Reader`

* Require `UnwindSafe` + `RefUnwindSafe` on `TrustHandlerConfig` trait
Diffstat:
Msdk/src/manifest_store.rs | 38++++++++++++++++++++++++--------------
Msdk/src/reader.rs | 13++++++++++---
Msdk/src/trust_handler.rs | 7++++++-
3 files changed, 40 insertions(+), 18 deletions(-)

diff --git a/sdk/src/manifest_store.rs b/sdk/src/manifest_store.rs @@ -45,6 +45,9 @@ pub struct ManifestStore { #[serde(skip_serializing_if = "Option::is_none")] /// ValidationStatus generated when loading the ManifestStore from an asset validation_status: Option<Vec<ValidationStatus>>, + #[serde(skip)] + /// The internal store representing the manifest store + store: Store, } impl ManifestStore { @@ -54,6 +57,7 @@ impl ManifestStore { active_manifest: None, manifests: HashMap::<String, Manifest>::new(), validation_status: None, + store: Store::new(), } } @@ -112,7 +116,7 @@ impl ManifestStore { } /// creates a ManifestStore from a Store with validation - pub(crate) fn from_store(store: &Store, validation_log: &impl StatusTracker) -> ManifestStore { + pub(crate) fn from_store(store: Store, validation_log: &impl StatusTracker) -> ManifestStore { Self::from_store_impl( store, validation_log, @@ -124,7 +128,7 @@ impl ManifestStore { /// creates a ManifestStore from a Store writing resources to resource_path #[cfg(feature = "file_io")] pub(crate) fn from_store_with_resources( - store: &Store, + store: Store, validation_log: &impl StatusTracker, resource_path: &Path, ) -> ManifestStore { @@ -133,15 +137,17 @@ impl ManifestStore { // internal implementation of from_store fn from_store_impl( - store: &Store, + store: Store, validation_log: &impl StatusTracker, #[cfg(feature = "file_io")] resource_path: Option<&Path>, ) -> ManifestStore { - let mut statuses = status_for_store(store, validation_log); + let mut statuses = status_for_store(&store, validation_log); let mut manifest_store = ManifestStore::new(); manifest_store.active_manifest = store.provenance_label(); + manifest_store.store = store; + let store = &manifest_store.store; for claim in store.claims() { let manifest_label = claim.label(); #[cfg(feature = "file_io")] @@ -167,13 +173,17 @@ impl ManifestStore { manifest_store } + pub(crate) fn store(&self) -> &Store { + &self.store + } + /// Creates a new Manifest Store from a Manifest #[allow(dead_code)] pub fn from_manifest(manifest: &Manifest) -> Result<Self> { use crate::status_tracker::OneShotStatusTracker; let store = manifest.to_store()?; Ok(Self::from_store_impl( - &store, + store, &OneShotStatusTracker::new(), #[cfg(feature = "file_io")] manifest.resources().base_path(), @@ -186,7 +196,7 @@ impl ManifestStore { let mut validation_log = DetailedStatusTracker::new(); Store::load_from_memory(format, image_bytes, verify, &mut validation_log) - .map(|store| Self::from_store(&store, &validation_log)) + .map(|store| Self::from_store(store, &validation_log)) } /// Generate a Store from a format string and stream. @@ -221,7 +231,7 @@ impl ManifestStore { .await?; } } - Ok(Self::from_store(&store, &validation_log)) + Ok(Self::from_store(store, &validation_log)) } #[cfg(feature = "file_io")] @@ -242,7 +252,7 @@ impl ManifestStore { let mut validation_log = DetailedStatusTracker::new(); let store = Store::load_from_asset(path.as_ref(), true, &mut validation_log)?; - Ok(Self::from_store(&store, &validation_log)) + Ok(Self::from_store(store, &validation_log)) } #[cfg(feature = "file_io")] @@ -270,7 +280,7 @@ impl ManifestStore { let store = Store::load_from_asset(path.as_ref(), true, &mut validation_log)?; Ok(Self::from_store_with_resources( - &store, + store, &validation_log, resource_path.as_ref(), )) @@ -287,7 +297,7 @@ impl ManifestStore { Store::load_from_memory_async(format, image_bytes, verify, &mut validation_log) .await - .map(|store| Self::from_store(&store, &validation_log)) + .map(|store| Self::from_store(store, &validation_log)) } /// Loads a ManifestStore from an init segment and fragment. This @@ -309,7 +319,7 @@ impl ManifestStore { &mut validation_log, ) .await - .map(|store| Self::from_store(&store, &validation_log)) + .map(|store| Self::from_store(store, &validation_log)) } /// Asynchronously loads a manifest from a buffer holding a binary manifest (.c2pa) and validates against an asset buffer @@ -348,7 +358,7 @@ impl ManifestStore { ) .await?; - Ok(Self::from_store(&store, &validation_log)) + Ok(Self::from_store(store, &validation_log)) } /// Synchronously loads a manifest from a buffer holding a binary manifest (.c2pa) and validates against an asset buffer @@ -384,7 +394,7 @@ impl ManifestStore { &mut validation_log, )?; - Ok(Self::from_store(&store, &validation_log)) + Ok(Self::from_store(store, &validation_log)) } } @@ -463,7 +473,7 @@ mod tests { fn manifest_report() { let store = create_test_store().expect("creating test store"); - let manifest_store = ManifestStore::from_store(&store, &OneShotStatusTracker::new()); + let manifest_store = ManifestStore::from_store(store, &OneShotStatusTracker::new()); assert!(manifest_store.active_manifest.is_some()); assert!(!manifest_store.manifests.is_empty()); let manifest = manifest_store.get_active().unwrap(); diff --git a/sdk/src/reader.rs b/sdk/src/reader.rs @@ -25,11 +25,10 @@ use crate::error::Error; use crate::{ claim::ClaimAssetData, error::Result, manifest_store::ManifestStore, settings::get_settings_value, status_tracker::DetailedStatusTracker, store::Store, - validation_status::ValidationStatus, Manifest, + validation_status::ValidationStatus, Manifest, ManifestStoreReport, }; /// A reader for the manifest store. -#[derive(Debug)] pub struct Reader { pub(crate) manifest_store: ManifestStore, } @@ -150,7 +149,7 @@ impl Reader { } Ok(Reader { - manifest_store: ManifestStore::from_store(&store, &validation_log), + manifest_store: ManifestStore::from_store(store, &validation_log), }) } @@ -235,3 +234,11 @@ impl std::fmt::Display for Reader { f.write_str(self.json().as_str()) } } + +impl std::fmt::Debug for Reader { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let report = ManifestStoreReport::from_store(self.manifest_store.store()) + .map_err(|_| std::fmt::Error)?; + f.write_str(&report.to_string()) + } +} diff --git a/sdk/src/trust_handler.rs b/sdk/src/trust_handler.rs @@ -14,6 +14,7 @@ use std::{ collections::HashSet, io::{read_to_string, Cursor, Read}, + panic::{RefUnwindSafe, UnwindSafe}, str::FromStr, }; @@ -27,7 +28,10 @@ pub(crate) static OCSP_SIGNING_OID: Oid<'static> = oid!(1.3.6 .1 .5 .5 .7 .3 .9) pub(crate) static DOCUMENT_SIGNING_OID: Oid<'static> = oid!(1.3.6 .1 .5 .5 .7 .3 .36); // Trait for supply configuration and handling of trust lists and EKU configuration store -pub(crate) trait TrustHandlerConfig: Sync + Send { +// +// `RefUnwindSafe` + `UnwindSafe` were added to ensure `Store` is unwind safe and to preserve +// backwards compatbility. +pub(crate) trait TrustHandlerConfig: RefUnwindSafe + UnwindSafe + Sync + Send { fn new() -> Self where Self: Sized; @@ -122,6 +126,7 @@ pub(crate) fn load_trust_from_data(trust_data: &[u8]) -> Result<Vec<Vec<u8>>> { // Pass through trust for the case of claim signer usage since it has known trust with context // configured to all email protection, timestamping, ocsp signing and document signing +#[derive(Debug)] pub(crate) struct TrustPassThrough { allowed_cert_set: HashSet<String>, config_store: Vec<u8>,