Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(MINOR) IngredientOptions allow override of hash and thumbnail generation; image library is now a default feature #79

Merged
merged 11 commits into from
Jul 19, 2022
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
[workspace]
resolver = "2"
members = ["sdk", "make_test_images"]
9 changes: 8 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@ clippy:
test-local:
cargo test --all-features

test-no-defaults:
cd sdk && cargo test --features="file_io" --no-default-features

test-wasm:
cd sdk && wasm-pack test --node

# Full local validation, build and test all features including wasm
# Run this before pushing a PR to pre-validate
test: check-format check-docs clippy test-local test-wasm
test: check-format check-docs clippy test-local test-no-defaults test-wasm

# Builds and views documentation
doc:
Expand All @@ -44,3 +47,7 @@ images:
# Runs the client example using test image and output to target/tmp/client.jpg
client:
cargo run --example client sdk/tests/fixtures/ca.jpg target/tmp/client.jpg

# Runs the show example
show:
cargo run --example show -- sdk/tests/fixtures/ca.jpg
1 change: 1 addition & 0 deletions make_test_images/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ rust-version = "1.58.0"

[dependencies]
anyhow = "1.0"
blake3 = "1.0.0"
c2pa = { path="../sdk", features = ["file_io", "xmp_write"] }
env_logger = "0.9"
log = "0.4"
Expand Down
42 changes: 36 additions & 6 deletions make_test_images/src/make_test_images.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,26 @@ impl Default for Config {
}
}

/// Generate a blake3 hash over the image in path using a fixed buffer
fn blake3_hash(path: &Path) -> Result<String> {
gpeacock marked this conversation as resolved.
Show resolved Hide resolved
use std::fs::File;
use std::io::Read;
// Hash an input incrementally.
let mut hasher = blake3::Hasher::new();
const BUFFER_LEN: usize = 1024 * 1024;
let mut buffer = [0u8; BUFFER_LEN];
let mut file = File::open(path)?;
loop {
let read_count = file.read(&mut buffer)?;
gpeacock marked this conversation as resolved.
Show resolved Hide resolved
hasher.update(&buffer[..read_count]);
if read_count != BUFFER_LEN {
break;
}
}
let hash = hasher.finalize();
Ok(hash.to_hex().as_str().to_owned())
}

/// Tool for building test case images for C2PA
pub struct MakeTestImages {
config: Config,
Expand Down Expand Up @@ -162,10 +182,18 @@ impl MakeTestImages {
// keep track of all actions here
let mut actions = Actions::new();

let options = IngredientOptions {
make_hash: true,
title: None,
};
struct ImageOptions {}
impl ImageOptions {
fn new() -> Self {
ImageOptions {}
}
}

impl IngredientOptions for ImageOptions {
fn hash(&self, path: &Path) -> Option<String> {
blake3_hash(path).ok()
}
}

let generator = format!("{}/{}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));
let mut manifest = Manifest::new(generator);
Expand All @@ -183,7 +211,8 @@ impl MakeTestImages {
Some(src) => {
let src_path = &self.make_path(src);

let parent = Ingredient::from_file_with_options(src_path, &options)?;
let parent = Ingredient::from_file_with_options(src_path, &ImageOptions::new())?;

actions = actions.add_action(
Action::new(c2pa_action::OPENED)
.set_parameter("identifier".to_owned(), parent.instance_id().to_owned())?,
Expand Down Expand Up @@ -244,7 +273,8 @@ impl MakeTestImages {
image::imageops::overlay(&mut img, &img_small, x, 0);

// create and add the ingredient
let ingredient = Ingredient::from_file_with_options(ing_path, &options)?;
let ingredient =
Ingredient::from_file_with_options(ing_path, &ImageOptions::new())?;
actions =
actions.add_action(Action::new(c2pa_action::PLACED).set_parameter(
"identifier".to_owned(),
Expand Down
20 changes: 17 additions & 3 deletions sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[features]
default = ["add_thumbnails"]
add_thumbnails = ["image"]
async_signer = ["async-trait", "file_io"]
bmff = [] # Work in progress support for BMFF-based containers
file_io = ["openssl"]
Expand All @@ -27,15 +29,27 @@ xmp_write = ["xmp_toolkit"]
# It enables some low-overhead timing features used in our development cycle.
diagnostics = []

#[cfg(not(target_arch = "wasm32"))]
[[example]]
name = "client"
required-features = ["file_io"]

[[example]]
name = "show"
required-features = ["file_io"]

[[example]]
name = "custom_assertion"


[lib]
crate-type = ["cdylib", "rlib"]

[dependencies]
async-trait = { version = "0.1.48", optional = true }
atree = "0.5.2"
base64 = "0.13.0"
bcder = "0.6.0"
blake3 = "1.0.0"
bcder = "0.6.0"
bytes = "1.1.0"
byteorder = "1.3.4"
chrono = { version = "0.4.19", features = ["wasmbind"] }
Expand All @@ -44,7 +58,6 @@ conv = "0.3.3"
coset = "0.3.1"
extfmt = "0.1.1"
hex = "0.4.3"
image = "0.23.10"
img-parts = "0.2.3"
log = "0.4.8"
multibase = "0.9.0"
Expand Down Expand Up @@ -72,6 +85,7 @@ x509-certificate = "0.12.0"
ring = "0.16.20"
url = "2.2.2"
ureq = "2.4.0"
image = { version = "0.24.2", optional = true }
instant = "0.1.0"
openssl = { version = "0.10.31", features = ["vendored"], optional = true }
xmp_toolkit = { version = "0.5.1", optional = true }
Expand Down
8 changes: 4 additions & 4 deletions sdk/examples/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ pub fn main() -> Result<()> {
"target/tmp/client.jpg",
),
};

let source = PathBuf::from(src);
let dest = PathBuf::from(dst);

// if a filepath was provided on the command line, read it as a parent file
let parent = Ingredient::from_file(source.as_path())?;

Expand All @@ -109,10 +109,10 @@ pub fn main() -> Result<()> {
.add_assertion(&creative_work)?;

// sign and embed into the target file
let signcert_path = "../sdk/tests/fixtures/certs.ps256.pem";
let pkey_path = "../sdk/tests/fixtures/certs.ps256.pub";
let signer = create_signer::from_files(signcert_path, pkey_path, "ps256", None)?;
let signcert_path = "sdk/tests/fixtures/certs/es256.pub";
let pkey_path = "sdk/tests/fixtures/certs/es256.pem";

let signer = create_signer::from_files(signcert_path, pkey_path, "es256", None)?;
manifest.embed(&source, &dest, &*signer)?;

let manifest_store = ManifestStore::from_file(&dest)?;
Expand Down
28 changes: 28 additions & 0 deletions sdk/examples/show.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2022 Adobe. All rights reserved.
// This file is licensed to you under the Apache License,
// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
// or the MIT license (http://opensource.org/licenses/MIT),
// at your option.

// Unless required by applicable law or agreed to in writing,
// this software is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
// implied. See the LICENSE-MIT and LICENSE-APACHE files for the
// specific language governing permissions and limitations under
// each license.

//! Example App that generates a manifest store listing for a given file
use anyhow::Result;
use c2pa::ManifestStore;

#[cfg(not(target_arch = "wasm32"))]
fn main() -> Result<()> {
let args: Vec<String> = std::env::args().collect();
if args.len() > 1 {
let ms = ManifestStore::from_file(&args[1])?;
println!("{}", ms);
} else {
println!("Prints a manifest report (requires a file path argument)")
}
Ok(())
}
1 change: 1 addition & 0 deletions sdk/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ pub enum Error {
JsonError(#[from] serde_json::Error),

#[error(transparent)]
#[cfg(all(not(target_arch = "wasm32"), feature = "add_thumbnails"))]
ImageError(#[from] image::ImageError),

#[error(transparent)]
Expand Down
Loading