diff --git a/xml_converter/src/string_helper.cpp b/xml_converter/src/string_helper.cpp index a8c7ca32..3f0056f2 100644 --- a/xml_converter/src/string_helper.cpp +++ b/xml_converter/src/string_helper.cpp @@ -144,41 +144,41 @@ static const char base64_chars[] = std::string base64_encode(uint8_t const* buf, unsigned int bufLen) { std::string ret; - int i = 0; - int j = 0; - uint8_t char_array_3[3]; - uint8_t char_array_4[4]; + int input_chunk_index = 0; + int output_chunk_index = 0; + uint8_t input_chunk[3]; + uint8_t output_chunk[4]; while (bufLen--) { - char_array_3[i++] = *(buf++); - if (i == 3) { - char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; - char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); - char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); - char_array_4[3] = char_array_3[2] & 0x3f; - - for (i = 0; (i < 4); i++) { - ret += base64_chars[char_array_4[i]]; + input_chunk[input_chunk_index++] = *(buf++); + if (input_chunk_index == 3) { + output_chunk[0] = (input_chunk[0] & 0xfc) >> 2; + output_chunk[1] = ((input_chunk[0] & 0x03) << 4) + ((input_chunk[1] & 0xf0) >> 4); + output_chunk[2] = ((input_chunk[1] & 0x0f) << 2) + ((input_chunk[2] & 0xc0) >> 6); + output_chunk[3] = input_chunk[2] & 0x3f; + + for (output_chunk_index = 0; output_chunk_index < 4; output_chunk_index++) { + ret += base64_chars[output_chunk[output_chunk_index]]; } - i = 0; + input_chunk_index = 0; } } - if (i) { - for (j = i; j < 3; j++) { - char_array_3[j] = '\0'; + if (input_chunk_index > 0) { + for (output_chunk_index = input_chunk_index; output_chunk_index < 3; output_chunk_index++) { + input_chunk[output_chunk_index] = 0; } - char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; - char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); - char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); - char_array_4[3] = char_array_3[2] & 0x3f; + output_chunk[0] = (input_chunk[0] & 0xfc) >> 2; + output_chunk[1] = ((input_chunk[0] & 0x03) << 4) + ((input_chunk[1] & 0xf0) >> 4); + output_chunk[2] = ((input_chunk[1] & 0x0f) << 2) + ((input_chunk[2] & 0xc0) >> 6); + output_chunk[3] = input_chunk[2] & 0x3f; - for (j = 0; (j < i + 1); j++) { - ret += base64_chars[char_array_4[j]]; + for (output_chunk_index = 0; (output_chunk_index < input_chunk_index + 1); output_chunk_index++) { + ret += base64_chars[output_chunk[output_chunk_index]]; } - while (i++ < 3) { + while (input_chunk_index++ < 3) { ret += '='; } } @@ -239,6 +239,7 @@ std::vector base64_decode(std::string const& encoded_string) { if (char_array_4[i] == 255) { // TODO: Throw an error or something + std::cerr << "Found an invalid letter when decoding base64" << std::endl; return std::vector(); } } @@ -259,6 +260,7 @@ std::vector base64_decode(std::string const& encoded_string) { if (char_array_4[i] == 255) { // TODO: Throw an error or something + std::cerr << "Found an invalid letter when decoding base64" << std::endl; return std::vector(); } } diff --git a/xml_converter/tests/test_base64.cpp b/xml_converter/tests/test_base64.cpp new file mode 100644 index 00000000..a7a996b5 --- /dev/null +++ b/xml_converter/tests/test_base64.cpp @@ -0,0 +1,67 @@ +#include "../src/string_helper.hpp" +#include + +class Base64Test : public ::testing::Test {}; + +// Test Strip Bits + +//////////////////////////////////////////////////////////////////////////////// +// Test Double Strip Bits +// +// When there are `len%4 = 2` there are 4 extra bits stored in the base64 string +// This means that decoding and encoding that data will result in slightly +// different data bsecause those 4 extra bits get stripped off. This tests all +// of those different values so that we can be sure everything is happening +// deterministically. +//////////////////////////////////////////////////////////////////////////////// +TEST_F(Base64Test, DoubleStripBits00) { + // These are all of the base 64 characters which start with the binary + // digits 00 and end with nonzero digits. + std::string b64_00_characters = "BCDEFGHIJKLMNOP"; + + for (size_t i = 0; i < b64_00_characters.size(); i++) { + std::string input = "A_"; + input[1] = b64_00_characters[i]; + std::vector decoded_value = base64_decode(input); + std::string output = base64_encode(&decoded_value[0], decoded_value.size()); + EXPECT_EQ(output, "AA=="); + } +} +TEST_F(Base64Test, DoubleStripBits01) { + // These are all of the base 64 characters which start with the binary + // digits 01 and end with nonzero digits. + std::string b64_00_characters = "RSTUVWXYZabcdef"; + + for (size_t i = 0; i < b64_00_characters.size(); i++) { + std::string input = "A_"; + input[1] = b64_00_characters[i]; + std::vector decoded_value = base64_decode(input); + std::string output = base64_encode(&decoded_value[0], decoded_value.size()); + EXPECT_EQ(output, "AQ=="); + } +} +TEST_F(Base64Test, DoubleStripBits10) { + // These are all of the base 64 characters which start with the binary + // digits 10 and end with nonzero digits. + std::string b64_00_characters = "hijklmnopqrstuv"; + + for (size_t i = 0; i < b64_00_characters.size(); i++) { + std::string input = "A_"; + input[1] = b64_00_characters[i]; + std::vector decoded_value = base64_decode(input); + std::string output = base64_encode(&decoded_value[0], decoded_value.size()); + EXPECT_EQ(output, "Ag=="); + } +} +TEST_F(Base64Test, DoubleStripBits11) { + // These are all of the base 64 characters which start with the binary + // digits 11 and end with nonzero digits. + std::string b64_00_characters = "xyz0123456789+/"; + for (size_t i = 0; i < b64_00_characters.size(); i++) { + std::string input = "A_"; + input[1] = b64_00_characters[i]; + std::vector decoded_value = base64_decode(input); + std::string output = base64_encode(&decoded_value[0], decoded_value.size()); + EXPECT_EQ(output, "Aw=="); + } +}