Skip to content
Open
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
19 changes: 16 additions & 3 deletions include/c2pa.h
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,19 @@ int c2pa_reader_resource_to_stream(struct C2paReader *reader_ptr,
const char *uri,
struct CStream *stream);

/**
* Writes all the resources in a Reader to a folder.
*
* # Parameters
* * reader_ptr: pointer to a Reader.
* * folder_path: pointer to a C string with the path to the folder.
*
* # Errors
* Returns -1 if there were errors, otherwise returns 0.
* The error string can be retrieved by calling c2pa_error.
*/
IMPORT extern int c2pa_reader_to_folder(struct C2paReader *reader_ptr, const char *folder_path);

/**
* Creates a C2paBuilder from a JSON manifest definition string.
*
Expand Down Expand Up @@ -662,7 +675,7 @@ struct CStream *c2pa_create_stream(struct StreamContext *context,
IMPORT extern void c2pa_release_stream(struct CStream *stream);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
} // extern "C"
#endif // __cplusplus

#endif /* c2pa_bindings_h */
#endif /* c2pa_bindings_h */
7 changes: 7 additions & 0 deletions include/c2pa.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,13 @@ namespace c2pa
/// @return The number of bytes written.
/// @throws C2pa::Exception for errors encountered by the C2PA library.
int get_resource(const string &uri, std::ostream &stream);

/// @brief Write the manifest json and all resources to a folder.
/// @details There is no stream version of this function.
/// @param path The path to write the folder to.
///
/// @throws C2pa::Exception for errors encountered by the C2PA library.
void to_folder(const std::filesystem::path &path);
};

/// @brief Signer Callback function type.
Expand Down
9 changes: 9 additions & 0 deletions src/c2pa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,15 @@ namespace c2pa
return result;
}

void Reader::to_folder(const std::filesystem::path &path)
{
int result = c2pa_reader_to_folder(c2pa_reader, path.c_str());
if (result < 0)
{
throw Exception();
}
}

intptr_t signer_passthrough(const void *context, const unsigned char *data, uintptr_t len, unsigned char *signature, uintptr_t sig_max_len)
{
try
Expand Down
27 changes: 27 additions & 0 deletions src/c_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,33 @@ pub unsafe extern "C" fn c2pa_reader_resource_to_stream(
}
}

/// Writes all the resources in a Reader to a folder.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Writes all the resources in a Reader to a folder.
/// Writes all the resources from a Reader to a folder.

Your non-native reviewer got confused by the wording, but maybe my grammer is off.

///
/// # Parameters
/// * reader_ptr: pointer to a Reader.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like to add if the memory pointed to is actually modified or used read-only.
Here it's read-only, so not sure if it's worth adding?

/// * folder_path: pointer to a C string with the path to the folder.
///
/// # Errors
/// Returns -1 if there were errors, otherwise returns 0.
/// The error string can be retrieved by calling c2pa_error.
#[no_mangle]
pub unsafe extern "C" fn c2pa_reader_to_folder(
reader_ptr: *mut C2paReader,
folder_path: *const c_char,
) -> c_int {
let c2pa_reader: Box<C2paReader> = Box::from_raw(reader_ptr);
let folder_path = from_cstr_null_check_int!(folder_path);
let result = c2pa_reader.to_folder(folder_path);
let _ = Box::into_raw(c2pa_reader);
match result {
Ok(_) => 0,
Err(err) => {
Error::from_c2pa_error(err).set_last();
-1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not saying we should, but we could return more precise error codes in the future (not for this PR).

}
}
}

/// Creates a C2paBuilder from a JSON manifest definition string.
///
/// # Errors
Expand Down
2 changes: 1 addition & 1 deletion tests/builder.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ TEST(Builder, SignStream)
dest.seekp(0, std::ios::beg);
auto reader = c2pa::Reader("image/jpeg", dest);
auto json = reader.json();
ASSERT_TRUE(json.find("c2pa.training-mining") != std::string::npos);
ASSERT_TRUE(json.find("cawg.training-mining") != std::string::npos);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack -
But our test cases could also have both during the transition period.

}
catch (c2pa::Exception const &e)
{
Expand Down
25 changes: 24 additions & 1 deletion tests/reader.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@
// specific language governing permissions and limitations under
// each license.

#include <c2pa.hpp>

#include <gtest/gtest.h>
#include <filesystem>
#include <fstream>
#include <nlohmann/json.hpp>
#include <c2pa.hpp>

namespace fs = std::filesystem;

using nlohmann::json;

Expand All @@ -33,6 +38,24 @@ TEST(Reader, FileWithManifest)
EXPECT_TRUE(manifest_store_json.find("C.jpg") != std::string::npos);
};

TEST(Reader, ToFolder)
{
// Define the target directory
fs::path target_dir = "../../target/dest";

// Delete the target directory if it exists
if (fs::exists(target_dir)) {
fs::remove_all(target_dir);
}

auto reader = c2pa::Reader("../../tests/fixtures/C.jpg");

reader.to_folder(target_dir);

// Expect the manifest.json file to exist in the target directory
EXPECT_TRUE(fs::exists(target_dir / "manifest.json"));
};

TEST(Reader, FileNoManifest)
{
EXPECT_THROW({ auto reader = c2pa::Reader("../../tests/fixtures/A.jpg"); }, c2pa::Exception);
Expand Down