From ab24895f0ab201bcb50b7dc17f01e8eed482c93d Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Thu, 1 Jun 2023 13:56:54 +0000 Subject: [PATCH] util: Implement decoding base64 data and add tests Signed-off-by: Michael Tremer --- src/libpakfire/include/pakfire/util.h | 2 + src/libpakfire/util.c | 86 +++++++++++++++++++++++++++ tests/libpakfire/util.c | 37 ++++++++++++ 3 files changed, 125 insertions(+) diff --git a/src/libpakfire/include/pakfire/util.h b/src/libpakfire/include/pakfire/util.h index fee3ab311..c402b38f5 100644 --- a/src/libpakfire/include/pakfire/util.h +++ b/src/libpakfire/include/pakfire/util.h @@ -125,6 +125,8 @@ int pakfire_compile_regex(struct pakfire* pakfire, pcre2_code** regex, int pakfire_b64encode(struct pakfire* pakfire, char** output, const void* buffer, const size_t length); +int pakfire_b64decode(struct pakfire* pakfire, void** output, size_t* length, + const char* buffer); #endif diff --git a/src/libpakfire/util.c b/src/libpakfire/util.c index 74606f7a0..af58be28b 100644 --- a/src/libpakfire/util.c +++ b/src/libpakfire/util.c @@ -1020,3 +1020,89 @@ ERROR: return r; } + +int pakfire_b64decode(struct pakfire* pakfire, void** output, size_t* length, + const char* buffer) { + char error[OPENSSL_ERROR_MAX]; + char chunk[1024]; + BIO* b64 = NULL; + BIO* bio = NULL; + char* p = NULL; + int r; + + // Reset length + *length = 0; + + // Initialize the base64 decoder + b64 = BIO_new(BIO_f_base64()); + if (!b64) { + ERR_error_string_n(ERR_get_error(), error, sizeof(error)); + + ERROR(pakfire, "Could not initialize the base64 decoder: %s\n", error); + r = 1; + goto ERROR; + } + + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + + // Initialize a memory buffer + bio = BIO_new_mem_buf(buffer, strlen(buffer)); + if (!bio) { + ERR_error_string_n(ERR_get_error(), error, sizeof(error)); + + ERROR(pakfire, "Could not initialize memory buffer: %s\n", error); + r = 1; + goto ERROR; + } + + // Connect both things + bio = BIO_push(b64, bio); + + for (;;) { + // Read a chunk of data + ssize_t bytes_read = BIO_read(bio, chunk, sizeof(chunk)); + + // Handle any errors + if (bytes_read < 0) { + ERR_error_string_n(ERR_get_error(), error, sizeof(error)); + + ERROR(pakfire, "Could not read data: %s\n", error); + r = 1; + goto ERROR; + + // Break if no more data could be read + } else if (bytes_read == 0) { + break; + + // Handle the chunk + } else { + // Update total length of data + *length += bytes_read; + + // Allocate an output buffer + p = realloc(p, *length); + if (!p) { + ERROR(pakfire, "Could not allocate buffer: %m\n"); + r = 1; + goto ERROR; + } + + // Copy the chunk + memcpy(p + *length - bytes_read, chunk, bytes_read); + } + } + + // Set output pointer + *output = p; + + // Success! + r = 0; + +ERROR: + if (r && p) + free(p); + if (bio) + BIO_free_all(bio); + + return r; +} diff --git a/tests/libpakfire/util.c b/tests/libpakfire/util.c index 28f5dcee2..6cf8c8339 100644 --- a/tests/libpakfire/util.c +++ b/tests/libpakfire/util.c @@ -108,11 +108,48 @@ FAIL: return EXIT_FAILURE; } +static int test_base64(const struct test* t) { + int r = EXIT_FAILURE; + + const char data[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; + char* base64 = NULL; + void* output = NULL; + size_t length = 0; + + // Encode data as base64 + ASSERT_SUCCESS(pakfire_b64encode(t->pakfire, &base64, data, sizeof(data))); + + // Print the encoded data + printf("%s\n", base64); + + // Decode the data + ASSERT_SUCCESS(pakfire_b64decode(t->pakfire, &output, &length, base64)); + + // Print the decoded data + printf("%.*s\n", length, output); + + // Check that we encoded the correct amount of data + ASSERT_EQUALS(length, sizeof(data)); + + // Check that the output matches the input + ASSERT(memcmp(data, output, sizeof(data)) == 0); + + // Everything passed + r = EXIT_SUCCESS; + +FAIL: + if (base64) + free(base64); + + return r; +} + int main(int argc, const char* argv[]) { testsuite_add_test(test_basename); testsuite_add_test(test_dirname); testsuite_add_test(test_mkdir); testsuite_add_test(test_path_match); + testsuite_add_test(test_base64); return testsuite_run(argc, argv); } -- 2.39.5