commit 5daeb4ed3d388cc397e03c95f9b2e1fc4bae4005
parent 992968f1f8e63f2818bd95d1ef82af50e46eaab2
Author: Gavin Peacock <gpeacock@adobe.com>
Date: Tue, 20 Sep 2022 16:48:20 -0700
manifest_data was missing for remote manifests (#135)
* manifest_data was missing for remote manifests on Ingredient::from_file()
* remove time dependency
Diffstat:
3 files changed, 57 insertions(+), 24 deletions(-)
diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml
@@ -78,7 +78,6 @@ serde-transcode = "1.1.1"
sha2 = "0.10.2"
tempfile = "3.1.0"
thiserror = ">= 1.0.20, < 1.0.32"
-time = ">= 0.2.23"
twoway = "0.2.1"
url = "2.2.2"
uuid = { version = "0.8.1", features = ["serde", "v4", "wasm-bindgen"] }
diff --git a/sdk/src/ingredient.rs b/sdk/src/ingredient.rs
@@ -387,10 +387,7 @@ impl Ingredient {
#[cfg(feature = "file_io")]
fn from_file_impl(path: &Path, options: &dyn IngredientOptions) -> Result<Self> {
// these are declared inside this function in order to isolate them for wasm builds
- use crate::{
- jumbf_io,
- status_tracker::{DetailedStatusTracker, StatusTracker},
- };
+ use crate::status_tracker::{log_item, DetailedStatusTracker, StatusTracker};
#[cfg(feature = "diagnostics")]
let _t = crate::utils::time_it::TimeIt::new("Ingredient:from_file_with_options");
@@ -413,14 +410,39 @@ impl Ingredient {
// optionally generate a hash so we know if the file has changed
ingredient.hash = options.hash(path);
- let mut report = DetailedStatusTracker::new();
+ let mut validation_log = DetailedStatusTracker::new();
+
+ // retrieve the manifest bytes from embedded, sidecar or remote and convert to store if found
+ let (result, manifest_bytes) = match Store::load_jumbf_from_path(path) {
+ Ok(manifest_bytes) => {
+ (
+ Store::from_jumbf(&manifest_bytes, &mut validation_log)
+ .and_then(|mut store| {
+ // verify the store
+ store
+ .verify_from_path(path, &mut validation_log)
+ .map(|_| store)
+ })
+ .map_err(|e| {
+ // add a log entry for the error so we act like verify
+ validation_log.log_silent(
+ log_item!("asset", "error loading file", "Ingredient::from_file")
+ .set_error(&e),
+ );
+ e
+ }),
+ Some(manifest_bytes),
+ )
+ }
+ Err(err) => (Err(err), None),
+ };
// generate a store from the buffer and then validate from the asset path
// load and verify store in single call - no need to call low level jumbf_io functions
- match Store::load_from_asset(path, true, &mut report) {
+ match result {
Ok(store) => {
// generate ValidationStatus from ValidationItems filtering for only errors
- let statuses = status_for_store(&store, &mut report);
+ let statuses = status_for_store(&store, &mut validation_log);
if let Some(claim) = store.provenance_claim() {
// if the parent claim is valid and has a thumbnail, use it
@@ -438,7 +460,7 @@ impl Ingredient {
}
ingredient.active_manifest = Some(claim.label().to_string());
}
- ingredient.manifest_data = jumbf_io::load_jumbf_from_file(path).ok();
+ ingredient.manifest_data = manifest_bytes;
ingredient.validation_status = if statuses.is_empty() {
None
} else {
@@ -453,7 +475,7 @@ impl Ingredient {
// we can ignore the error here because it should have a log entry corresponding to it
debug!("ingredient {:?}", e);
// convert any other error to a validation status
- let statuses: Vec<ValidationStatus> = report
+ let statuses: Vec<ValidationStatus> = validation_log
.get_log()
.iter()
.filter_map(ValidationStatus::from_validation_item)
@@ -886,7 +908,7 @@ mod tests_file_io {
let ingredient = Ingredient::from_file(&ap).expect("from_file");
stats(&ingredient);
- println!("ingredient = {}", ingredient);
+ //println!("ingredient = {}", ingredient);
assert_eq!(ingredient.title(), BAD_SIGNATURE_JPEG);
assert_eq!(ingredient.format(), "image/jpeg");
test_thumbnail(&ingredient, "image/jpeg");
diff --git a/sdk/src/store.rs b/sdk/src/store.rs
@@ -1857,26 +1857,21 @@ impl Store {
}
}
- /// load a CAI store from a file
+ /// load jumbf given a file path
+ ///
+ /// This handles, embedded, sidecar and remote manifests
///
/// in_path - path to source file
/// validation_log - optional vec to contain addition info about the asset
#[cfg(feature = "file_io")]
- fn load_cai_from_file(
- in_path: &Path,
- validation_log: &mut impl StatusTracker,
- ) -> Result<Store> {
+ pub fn load_jumbf_from_path(in_path: &Path) -> Result<Vec<u8>> {
let external_manifest = in_path.with_extension(MANIFEST_STORE_EXT);
match load_jumbf_from_file(in_path) {
- Ok(manifest_bytes) => {
- // load and validate with CAI toolkit and dump if desired
- Store::from_jumbf(&manifest_bytes, validation_log)
- }
+ Ok(manifest_bytes) => Ok(manifest_bytes),
Err(Error::JumbfNotFound) => {
if external_manifest.exists() {
- let external_manifest_bytes = std::fs::read(external_manifest)?;
- Store::from_jumbf(&external_manifest_bytes, validation_log)
+ std::fs::read(external_manifest).map_err(Error::IoError)
} else {
// check for remote manifest
let mut asset_reader = std::fs::File::open(in_path)?;
@@ -1888,8 +1883,7 @@ impl Store {
.provenance
{
if cfg!(feature = "fetch_remote_manifests") {
- let remote_manifest_bytes = Store::fetch_remote_manifest(&ext_ref)?;
- Store::from_jumbf(&remote_manifest_bytes, validation_log)
+ Store::fetch_remote_manifest(&ext_ref)
} else {
// return an error with the url that should be read
Err(Error::RemoteManifestUrl(ext_ref))
@@ -1903,6 +1897,24 @@ impl Store {
}
}
+ /// load a CAI store from a file
+ ///
+ /// in_path - path to source file
+ /// validation_log - optional vec to contain addition info about the asset
+ #[cfg(feature = "file_io")]
+ fn load_cai_from_file(
+ in_path: &Path,
+ validation_log: &mut impl StatusTracker,
+ ) -> Result<Store> {
+ match Self::load_jumbf_from_path(in_path) {
+ Ok(manifest_bytes) => {
+ // load and validate with CAI toolkit
+ Store::from_jumbf(&manifest_bytes, validation_log)
+ }
+ Err(e) => Err(e),
+ }
+ }
+
/// Load Store from claims in an existing asset
/// asset_path: path to input asset
/// verify: determines whether to verify the contents of the provenance claim. Must be set true to use validation_log