Skip to content

Commit

Permalink
Merge branch 'main' into gpeacock/makefile_fmt
Browse files Browse the repository at this point in the history
  • Loading branch information
scouten-adobe authored Aug 9, 2022
2 parents 666a55f + a09b013 commit b3940e1
Show file tree
Hide file tree
Showing 5 changed files with 410 additions and 64 deletions.
2 changes: 1 addition & 1 deletion sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,13 @@ 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"] }
x509-parser = "0.11.0"
x509-certificate = "0.12.0"

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
ring = "0.16.20"
url = "2.2.2"
ureq = "2.4.0"
image = { version = "0.24.2", optional = true }
instant = "0.1.0"
Expand Down
11 changes: 8 additions & 3 deletions sdk/src/asset_handlers/c2pa_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@
use std::{fs::File, path::Path};

use crate::{
asset_io::{AssetIO, CAILoader, CAIRead, HashObjectPositions},
asset_io::{AssetIO, CAILoader, CAIRead, HashBlockObjectType, HashObjectPositions},
error::{Error, Result},
};

/// Supports working with ".c2pa" files containing only manifest store data
pub struct C2paIO {}

Expand Down Expand Up @@ -53,7 +52,13 @@ impl AssetIO for C2paIO {
&self,
_asset_path: &std::path::Path,
) -> Result<Vec<HashObjectPositions>> {
Ok(Vec::new())
let hop = HashObjectPositions {
offset: 0,
length: 0,
htype: HashBlockObjectType::Cai,
};

Ok(vec![hop])
}
}

Expand Down
75 changes: 72 additions & 3 deletions sdk/src/claim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@ impl fmt::Debug for ClaimAssertion {
/// that hash is signed to produce the claim signature.
#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)]
pub struct Claim {
// external manifest
#[serde(skip_deserializing, skip_serializing)]
remote_manifest: RemoteManifest,

// root of CAI store
#[serde(skip_deserializing, skip_serializing)]
update_manifest: bool,
Expand Down Expand Up @@ -229,6 +233,20 @@ pub enum AssertionStoreJsonFormat {
OrderedListNoBinary, // list of Assertions as json objects omitting binaries results
}

/// Remote manifest options. Use 'set_remote_manifest' to generate external manifests.
#[derive(Clone, Debug, PartialEq)]
pub enum RemoteManifest {
NoRemote, // No external manifest (default)
SideCar, // Manifest will be saved as a side car file, output asset is untouched.
Remote(String), // Manifest will be saved as a side car file, output asset will contain remote reference
}

impl Default for RemoteManifest {
fn default() -> Self {
Self::NoRemote
}
}

#[derive(Serialize, Deserialize, Debug)]
pub struct JsonOrderedAssertionData {
label: String,
Expand All @@ -247,8 +265,7 @@ impl Claim {
/// Create a new claim.
/// vendor: name used to label the claim (unique instance number is automatically calculated)
/// claim_generator: User agent see c2pa spec for format
// #[cfg(not(target_arch = "wasm32"))]
pub fn new(claim_generator: &str, vendor: Option<&str>) -> Self {
pub fn new<S: Into<String>>(claim_generator: S, vendor: Option<&str>) -> Self {
let urn = Uuid::new_v4();
let l = match vendor {
Some(v) => format!(
Expand All @@ -263,14 +280,15 @@ impl Claim {
};

Claim {
remote_manifest: RemoteManifest::NoRemote,
box_prefix: "self#jumbf".to_string(),
root: jumbf::labels::MANIFEST_STORE.to_string(),
signature_val: Vec::new(),
ingredients_store: HashMap::new(),
label: l,
signature: "".to_string(),

claim_generator: claim_generator.to_string(),
claim_generator: claim_generator.into(),
assertion_store: Vec::new(),
vc_store: Vec::new(),
assertions: Vec::new(),
Expand All @@ -288,6 +306,37 @@ impl Claim {
}
}

/// Create a new claim with a user supplied GUID.
/// user_guid: is user supplied guid conforming the C2PA spec for manifest names
/// claim_generator: User agent see c2pa spec for format
pub fn new_with_user_guid<S: Into<String>>(claim_generator: S, user_guid: S) -> Self {
Claim {
remote_manifest: RemoteManifest::NoRemote,
box_prefix: "self#jumbf".to_string(),
root: jumbf::labels::MANIFEST_STORE.to_string(),
signature_val: Vec::new(),
ingredients_store: HashMap::new(),
label: user_guid.into(), // todo figure out how to validate this
signature: "".to_string(),

claim_generator: claim_generator.into(),
assertion_store: Vec::new(),
vc_store: Vec::new(),
assertions: Vec::new(),
original_bytes: None,
redacted_assertions: None,
alg: Some(BUILD_HASH_ALG.into()),
alg_soft: None,
claim_generator_hints: None,

title: None,
format: "".to_string(),
instance_id: "".to_string(),

update_manifest: false,
}
}

/// Build a claim and verify its integrity.
pub fn build(&mut self) -> Result<()> {
// A claim must have a signature box.
Expand Down Expand Up @@ -381,6 +430,26 @@ impl Claim {
self.update_manifest
}

pub fn set_remote_manifest<S: Into<String> + AsRef<str>>(
&mut self,
remote_url: S,
) -> Result<()> {
url::Url::parse(remote_url.as_ref())
.map_err(|_e| Error::BadParam("remote url is badly formed".to_string()))?;
self.remote_manifest = RemoteManifest::Remote(remote_url.into());

Ok(())
}

pub fn set_external_manifest(&mut self) {
self.remote_manifest = RemoteManifest::SideCar;
}

#[cfg(feature = "file_io")]
pub(crate) fn remote_manifest(&self) -> RemoteManifest {
self.remote_manifest.clone()
}

pub(crate) fn set_update_manifest(&mut self, is_update_manifest: bool) {
self.update_manifest = is_update_manifest;
}
Expand Down
Loading

0 comments on commit b3940e1

Please sign in to comment.