]> git.ipfire.org Git - pakfire.git/commitdiff
util: Implement decoding base64 data and add tests
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 1 Jun 2023 13:56:54 +0000 (13:56 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 1 Jun 2023 13:56:54 +0000 (13:56 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/include/pakfire/util.h
src/libpakfire/util.c
tests/libpakfire/util.c

index fee3ab311f7cd6a2d88ae833f7fa086796831dd0..c402b38f59f298c42a210ce8f67adcabaf576f33 100644 (file)
@@ -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
 
index 74606f7a0a6e688fdea95034c43f8662a69cc172..af58be28b8b2d82a932454916c9f50938657801c 100644 (file)
@@ -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;
+}
index 28f5dcee280279080437554fa1d8af04ff3538da..6cf8c8339409b9bbbcccc576d562a3e3aa42359e 100644 (file)
@@ -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);
 }