Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
29 changes: 29 additions & 0 deletions c2pa_c_ffi/src/c_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,30 @@ pub unsafe extern "C" fn c2pa_reader_detailed_json(reader_ptr: *mut C2paReader)
to_c_string(c2pa_reader.detailed_json())
}

/// Returns a raw JUMBF byte array generated from a C2paReader.
///
/// # Safety
/// The returned value MUST be released by calling c2pa_string_free
/// and it is no longer valid after that call.
#[no_mangle]
pub unsafe extern "C" fn c2pa_reader_raw_jumbf(
reader_ptr: *mut C2paReader,
manifest_bytes_ptr: *mut *const c_uchar,
) -> i64 {
check_or_return_int!(reader_ptr);
check_or_return_int!(manifest_bytes_ptr);
let c2pa_reader = guard_boxed!(reader_ptr);
let result = c2pa_reader.jumbf_manifest();
ok_or_return_int!(result, |manifest_bytes: Vec<u8>| {
let len = manifest_bytes.len() as i64;
if !manifest_bytes_ptr.is_null() {
*manifest_bytes_ptr =
Box::into_raw(manifest_bytes.into_boxed_slice()) as *const c_uchar;
};
len
})
}

/// Returns the remote url of the manifest if it was obtained remotely.
///
/// # Parameters
Expand Down Expand Up @@ -1836,6 +1860,11 @@ mod tests {
assert!(json_content.contains("manifest"));
assert!(json_content.contains("com.example.test-action"));

let mut manifest_bytes_ptr = std::ptr::null();
let raw_jumbf_result = unsafe { c2pa_reader_raw_jumbf(reader, &mut manifest_bytes_ptr) };
assert!(raw_jumbf_result > 0);
assert!(!manifest_bytes_ptr.is_null());

TestC2paStream::drop_c_stream(source_stream);
TestC2paStream::drop_c_stream(read_stream);
unsafe {
Expand Down
10 changes: 4 additions & 6 deletions sdk/src/crypto/asn1/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,8 @@ mod tests {

// Helper to load test certificate
fn load_test_cert_pem(name: &str) -> Vec<u8> {
let path = format!("tests/fixtures/certs/{}", name);
std::fs::read(&path).unwrap_or_else(|_| panic!("Failed to read test certificate: {}", path))
let path = format!("tests/fixtures/certs/{name}");
std::fs::read(&path).unwrap_or_else(|_| panic!("Failed to read test certificate: {path}"))
}

// Helper to parse PEM and extract DER certificate
Expand Down Expand Up @@ -622,13 +622,11 @@ mod tests {
// Verify we got valid DER data for each cert type
assert!(
!cert_der.is_empty(),
"Certificate {} DER should not be empty",
cert_name
"Certificate {cert_name} DER should not be empty"
);
assert_eq!(
cert_der[0], 0x30,
"Certificate {} should start with SEQUENCE tag",
cert_name
"Certificate {cert_name} should start with SEQUENCE tag"
);
}

Expand Down
6 changes: 6 additions & 0 deletions sdk/src/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,12 @@ impl Reader {
}
}

/// Get the Reader as a raw JUMBF Manifest
/// This just calls to_jumbf_internal on the store with no min_reserved_size
pub fn jumbf_manifest(&self) -> Result<Vec<u8>> {
self.store.to_jumbf_internal(0)
}

/// Returns the remote url of the manifest if this [`Reader`] obtained the manifest remotely.
pub fn remote_url(&self) -> Option<&str> {
self.store.remote_url()
Expand Down
Loading