Skip to content

Commit d6d3fab

Browse files
authored
Merge pull request #43 from contentauth/gpeacock/manifest_and_stream
feat: Adds Reader.from_manifest_data_and_stream along with set_remote_url and set_no_embed.
2 parents 297e9d2 + 90f2e6e commit d6d3fab

File tree

4 files changed

+59
-4
lines changed

4 files changed

+59
-4
lines changed

c2pa/c2pa_api/c2pa_api.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,12 @@
3636
# reader = Reader("image/jpeg", open("test.jpg", "rb"))
3737
# json = reader.json()
3838
class Reader(api.Reader):
39-
def __init__(self, format, stream):
39+
def __init__(self, format, stream, manifest_data=None):
4040
super().__init__()
41-
self.from_stream(format, C2paStream(stream))
41+
if manifest_data is not None:
42+
self.from_manifest_data_and_stream(format, manifest_data, stream)
43+
else:
44+
self.from_stream(format, C2paStream(stream))
4245

4346
@classmethod
4447
def from_file(cls, path: str, format=None):

src/c2pa.udl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ interface Reader {
5757
[Throws=Error]
5858
string from_stream([ByRef] string format, [ByRef] Stream reader);
5959

60+
[Throws=Error]
61+
string from_manifest_data_and_stream([ByRef] bytes manifest_data, [ByRef] string format, [ByRef] Stream reader);
62+
6063
[Throws=Error]
6164
string json();
6265

@@ -79,6 +82,12 @@ interface Builder {
7982
[Throws=Error]
8083
void with_json([ByRef] string json);
8184

85+
[Throws=Error]
86+
void set_no_embed();
87+
88+
[Throws=Error]
89+
void set_remote_url([ByRef] string url);
90+
8291
[Throws=Error]
8392
void add_resource([ByRef] string uri, [ByRef] Stream stream );
8493

src/lib.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,19 @@ impl Reader {
7777
Ok(json)
7878
}
7979

80+
pub fn from_manifest_data_and_stream(&self, manifest_data: &[u8], format: &str, stream: &dyn Stream) -> Result<String> {
81+
// uniffi doesn't allow mutable parameters, so we we use an adapter
82+
let mut stream = StreamAdapter::from(stream);
83+
let reader = c2pa::Reader::from_manifest_data_and_stream(manifest_data, format, &mut stream)?;
84+
let json = reader.to_string();
85+
if let Ok(mut st) = self.reader.try_write() {
86+
*st = reader;
87+
} else {
88+
return Err(Error::RwLock);
89+
};
90+
Ok(json)
91+
}
92+
8093
pub fn json(&self) -> Result<String> {
8194
if let Ok(st) = self.reader.try_read() {
8295
Ok(st.json())
@@ -121,6 +134,25 @@ impl Builder {
121134
Ok(())
122135
}
123136

137+
/// Set to true to disable embedding a manifest
138+
pub fn set_no_embed(&self) -> Result<()> {
139+
if let Ok(mut builder) = self.builder.try_write() {
140+
builder.set_no_embed(true);
141+
} else {
142+
return Err(Error::RwLock);
143+
};
144+
Ok(())
145+
}
146+
147+
pub fn set_remote_url(&self, remote_url: &str) -> Result<()> {
148+
if let Ok(mut builder) = self.builder.try_write() {
149+
builder.set_remote_url(remote_url);
150+
} else {
151+
return Err(Error::RwLock);
152+
};
153+
Ok(())
154+
}
155+
124156
/// Add a resource to the builder
125157
pub fn add_resource(&self, uri: &str, stream: &dyn Stream) -> Result<()> {
126158
if let Ok(mut builder) = self.builder.try_write() {

tests/unit_tests.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ def test_stream_read_and_parse(self):
4444
title = manifest = manifest_store["manifests"][manifest_store["active_manifest"]]["title"]
4545
self.assertEqual(title, "C.jpg")
4646

47+
4748
def test_json_decode_err(self):
4849
with self.assertRaises(Error.Io):
4950
manifest_store = Reader("image/jpeg","foo")
@@ -92,7 +93,7 @@ def sign(data: bytes) -> bytes:
9293
# Create a local Ps256 signer with certs and a timestamp server
9394
signer = create_signer(sign, SigningAlg.PS256, certs, "http://timestamp.digicert.com")
9495

95-
def test_streams_build(self):
96+
def test_streams_sign(self):
9697
with open(testPath, "rb") as file:
9798
builder = Builder(TestBuilder.manifestDefinition)
9899
output = io.BytesIO(bytearray())
@@ -101,7 +102,7 @@ def test_streams_build(self):
101102
reader = Reader("image/jpeg", output)
102103
self.assertIn("Python Test", reader.json())
103104

104-
def test_streams_build(self):
105+
def test_archive_sign(self):
105106
with open(testPath, "rb") as file:
106107
builder = Builder(TestBuilder.manifestDefinition)
107108
archive = byte_array = io.BytesIO(bytearray())
@@ -113,5 +114,15 @@ def test_streams_build(self):
113114
reader = Reader("image/jpeg", output)
114115
self.assertIn("Python Test", reader.json())
115116

117+
def test_remote_sign(self):
118+
with open(testPath, "rb") as file:
119+
builder = Builder(TestBuilder.manifestDefinition)
120+
builder.set_no_embed()
121+
output = io.BytesIO(bytearray())
122+
manifest_data = builder.sign(TestBuilder.signer, "image/jpeg", file, output)
123+
output.seek(0)
124+
reader = Reader.from_manifest_data_and_stream(manifest_data, "image/jpeg", output)
125+
self.assertIn("Python Test", reader.json())
126+
116127
if __name__ == '__main__':
117128
unittest.main()

0 commit comments

Comments
 (0)