Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions sdk/src/asset_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,15 @@ pub struct HashObjectPositions {
pub htype: HashBlockObjectType, // type of hash block object
}

#[cfg(not(target_arch = "wasm32"))]
pub trait CAIRead: Read + Seek + Send {}
#[cfg(target_arch = "wasm32")]
pub trait CAIRead: Read + Seek {}

#[cfg(not(target_arch = "wasm32"))]
impl<T> CAIRead for T where T: Read + Seek + Send {}
#[cfg(target_arch = "wasm32")]
impl<T> CAIRead for T where T: Read + Seek {}

impl From<String> for Box<dyn CAIRead> {
fn from(val: String) -> Self {
Expand Down
49 changes: 26 additions & 23 deletions sdk/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,33 +229,36 @@ struct StructuredAction {
/// }
///
/// # fn main() -> Result<()> {
/// let manifest_json = json!({
/// "claim_generator_info": [
/// {
/// "name": "c2pa_test",
/// "version": "1.0.0"
/// }
/// ],
/// "title": "Test_Manifest"
/// }).to_string();
/// #[cfg(feature = "file_io")]
/// {
/// let manifest_json = json!({
/// "claim_generator_info": [
/// {
/// "name": "c2pa_test",
/// "version": "1.0.0"
/// }
/// ],
/// "title": "Test_Manifest"
/// }).to_string();
///
/// let mut builder = Builder::from_json(&manifest_json)?;
/// builder.add_assertion("org.contentauth.test", &Test { my_tag: 42 })?;
/// let mut builder = Builder::from_json(&manifest_json)?;
/// builder.add_assertion("org.contentauth.test", &Test { my_tag: 42 })?;
///
/// let source = PathBuf::from("tests/fixtures/C.jpg");
/// let dir = tempdir()?;
/// let dest = dir.path().join("test_file.jpg");
/// let source = PathBuf::from("tests/fixtures/C.jpg");
/// let dir = tempdir()?;
/// let dest = dir.path().join("test_file.jpg");
///
/// // Create a ps256 signer using certs and key files. TO DO: Update example.
/// let signcert_path = "tests/fixtures/certs/ps256.pub";
/// let pkey_path = "tests/fixtures/certs/ps256.pem";
/// let signer = create_signer::from_files(signcert_path, pkey_path, SigningAlg::Ps256, None)?;
/// // Create a ps256 signer using certs and key files. TO DO: Update example.
/// let signcert_path = "tests/fixtures/certs/ps256.pub";
/// let pkey_path = "tests/fixtures/certs/ps256.pem";
/// let signer = create_signer::from_files(signcert_path, pkey_path, SigningAlg::Ps256, None)?;
///
/// // embed a manifest using the signer
/// builder.sign_file(
/// signer.as_ref(),
/// &source,
/// &dest)?;
/// // embed a manifest using the signer
/// builder.sign_file(
/// signer.as_ref(),
/// &source,
/// &dest)?;
/// }
/// # Ok(())
/// # }
/// ```
Expand Down
15 changes: 15 additions & 0 deletions sdk/src/jumbf_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ where
}
}

#[cfg(not(target_arch = "wasm32"))]
pub(crate) fn object_locations_from_stream<R>(
format: &str,
stream: &mut R,
Expand All @@ -332,7 +333,21 @@ where
R: Read + Seek + Send + ?Sized,
{
let mut reader = CAIReadAdapter { reader: stream };
match get_caiwriter_handler(format) {
Some(handler) => handler.get_object_locations_from_stream(&mut reader),
_ => Err(Error::UnsupportedType),
}
}

#[cfg(target_arch = "wasm32")]
pub(crate) fn object_locations_from_stream<R>(
format: &str,
stream: &mut R,
) -> Result<Vec<HashObjectPositions>>
where
R: Read + Seek + ?Sized,
{
let mut reader = CAIReadAdapter { reader: stream };
match get_caiwriter_handler(format) {
Some(handler) => handler.get_object_locations_from_stream(&mut reader),
_ => Err(Error::UnsupportedType),
Expand Down
35 changes: 19 additions & 16 deletions sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,24 +62,27 @@
//! }
//!
//! # fn main() -> Result<()> {
//! let mut builder = Builder::from_json(r#"{"title": "Test"}"#)?;
//! builder.add_assertion("org.contentauth.test", &Test { my_tag: 42 })?;
//! #[cfg(feature = "file_io")]
//! {
//! let mut builder = Builder::from_json(r#"{"title": "Test"}"#)?;
//! builder.add_assertion("org.contentauth.test", &Test { my_tag: 42 })?;
//!
//! // Create a ps256 signer using certs and key files
//! let signer = create_signer::from_files(
//! "tests/fixtures/certs/ps256.pub",
//! "tests/fixtures/certs/ps256.pem",
//! SigningAlg::Ps256,
//! None,
//! )?;
//! // Create a ps256 signer using certs and key files
//! let signer = create_signer::from_files(
//! "tests/fixtures/certs/ps256.pub",
//! "tests/fixtures/certs/ps256.pem",
//! SigningAlg::Ps256,
//! None,
//! )?;
//!
//! // embed a manifest using the signer
//! std::fs::remove_file("../target/tmp/lib_sign.jpg"); // ensure the file does not exist
//! builder.sign_file(
//! &*signer,
//! "tests/fixtures/C.jpg",
//! "../target/tmp/lib_sign.jpg",
//! )?;
//! // embed a manifest using the signer
//! std::fs::remove_file("../target/tmp/lib_sign.jpg"); // ensure the file does not exist
//! builder.sign_file(
//! &*signer,
//! "tests/fixtures/C.jpg",
//! "../target/tmp/lib_sign.jpg",
//! )?;
//! }
//! # Ok(())
//! # }
//! ```
Expand Down
13 changes: 8 additions & 5 deletions sdk/src/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,11 +441,14 @@ impl Manifest {
/// # use c2pa::Result;
/// use c2pa::{assertions::Actions, Manifest, Reader};
/// # fn main() -> Result<()> {
/// let reader = Reader::from_file("tests/fixtures/CA.jpg")?;
/// let manifest = reader.active_manifest().unwrap();
/// let actions: Actions = manifest.find_assertion(Actions::LABEL)?;
/// for action in actions.actions {
/// println!("{}", action.action());
/// #[cfg(feature = "file_io")]
/// {
/// let reader = Reader::from_file("tests/fixtures/CA.jpg")?;
/// let manifest = reader.active_manifest().unwrap();
/// let actions: Actions = manifest.find_assertion(Actions::LABEL)?;
/// for action in actions.actions {
/// println!("{}", action.action());
/// }
/// }
/// # Ok(())
/// # }
Expand Down
29 changes: 24 additions & 5 deletions sdk/src/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ impl Reader {
/// println!("{}", reader.json());
/// ```
#[async_generic()]
#[cfg(not(target_arch = "wasm32"))]
pub fn from_stream(format: &str, mut stream: impl Read + Seek + Send) -> Result<Reader> {
let verify = get_settings_value::<bool>("verify.verify_after_reading")?; // defaults to true
let mut validation_log = StatusTracker::default();
Expand All @@ -139,6 +140,21 @@ impl Reader {
Self::from_store(store, &validation_log)
}

#[async_generic()]
#[cfg(target_arch = "wasm32")]
pub fn from_stream(format: &str, mut stream: impl Read + Seek) -> Result<Reader> {
let verify = get_settings_value::<bool>("verify.verify_after_reading")?; // defaults to true
let mut validation_log = StatusTracker::default();

let store = if _sync {
Store::from_stream(format, &mut stream, verify, &mut validation_log)
} else {
Store::from_stream_async(format, &mut stream, verify, &mut validation_log).await
}?;

Self::from_store(store, &validation_log)
}

#[cfg(feature = "file_io")]
/// Create a manifest store [`Reader`] from a file.
/// If the `fetch_remote_manifests` feature is enabled, and the asset refers to a remote manifest, the function fetches a remote manifest.
Expand Down Expand Up @@ -559,11 +575,14 @@ impl Reader {
/// # Example
/// ```no_run
/// use c2pa::Reader;
/// let stream = std::io::Cursor::new(Vec::new());
/// let reader = Reader::from_file("path/to/file.jpg").unwrap();
/// let manifest = reader.active_manifest().unwrap();
/// let uri = &manifest.thumbnail_ref().unwrap().identifier;
/// let bytes_written = reader.resource_to_stream(uri, stream).unwrap();
/// #[cfg(feature = "file_io")]
/// {
/// let stream = std::io::Cursor::new(Vec::new());
/// let reader = Reader::from_file("path/to/file.jpg").unwrap();
/// let manifest = reader.active_manifest().unwrap();
/// let uri = &manifest.thumbnail_ref().unwrap().identifier;
/// let bytes_written = reader.resource_to_stream(uri, stream).unwrap();
/// }
/// ```
/// TODO: Fix the example to not read from a file.
pub fn resource_to_stream(
Expand Down
68 changes: 68 additions & 0 deletions sdk/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4029,6 +4029,7 @@ impl Store {

/// Load store from a stream
#[async_generic]
#[cfg(not(target_arch = "wasm32"))]
pub fn from_stream(
format: &str,
mut stream: impl Read + Seek + Send,
Expand Down Expand Up @@ -4066,8 +4067,49 @@ impl Store {
Ok(store)
}

/// Load store from a stream
#[async_generic]
#[cfg(target_arch = "wasm32")]
pub fn from_stream(
format: &str,
mut stream: impl Read + Seek,
verify: bool,
validation_log: &mut StatusTracker,
) -> Result<Self> {
let (manifest_bytes, remote_url) = Store::load_jumbf_from_stream(format, &mut stream)?;

let store = if _sync {
Self::from_manifest_data_and_stream(
&manifest_bytes,
format,
&mut stream,
verify,
validation_log,
)
} else {
Self::from_manifest_data_and_stream_async(
&manifest_bytes,
format,
&mut stream,
verify,
validation_log,
)
.await
};

let mut store = store?;
if remote_url.is_none() {
store.embedded = true;
} else {
store.remote_url = remote_url;
}

Ok(store)
}

/// Load store from a manifest data and stream
#[async_generic()]
#[cfg(not(target_arch = "wasm32"))]
pub fn from_manifest_data_and_stream(
c2pa_data: &[u8],
format: &str,
Expand All @@ -4091,6 +4133,32 @@ impl Store {
Ok(store)
}

/// Load store from a manifest data and stream
#[async_generic()]
#[cfg(target_arch = "wasm32")]
pub fn from_manifest_data_and_stream(
c2pa_data: &[u8],
format: &str,
mut stream: impl Read + Seek,
verify: bool,
validation_log: &mut StatusTracker,
) -> Result<Self> {
// first we convert the JUMBF into a usable store
let store = Store::from_jumbf(c2pa_data, validation_log)?;

//let verify = get_settings_value::<bool>("verify.verify_after_reading")?; // defaults to true

if verify {
let mut asset_data = ClaimAssetData::Stream(&mut stream, format);
if _sync {
Store::verify_store(&store, &mut asset_data, validation_log)
} else {
Store::verify_store_async(&store, &mut asset_data, validation_log).await
}?;
}
Ok(store)
}

/// Load Store from a in-memory asset
/// asset_type: asset extension or mime type
/// data: reference to bytes of the the file
Expand Down