Allow parsing base64 files
Redfish outputs base64 strings. It would be useful if the CLI app could
read those strings in directly.
This commit breaks out a new method "header_valid" to allow tooling to
do an initial reading of a buffer to determine if it appears to be
correct before going further. This allows the CLI app to attempt to
parse as a buffer, if that fails, attempt to parse as base64.
To support as many inputs as possible, this commit makes padding
optional. It also allows a trailing \n as is present in many files.
Change-Id: I4fb759ecefc8ce1c757f1a9e7c4a2b2d220105d0
Signed-off-by: Ed Tanous <etanous@nvidia.com>
diff --git a/base64.c b/base64.c
index 5ed39c6..7ace17a 100644
--- a/base64.c
+++ b/base64.c
@@ -95,59 +95,70 @@
*/
UINT8 *base64_decode(const CHAR8 *src, INT32 len, INT32 *out_len)
{
- UINT8 *out;
- UINT8 *pos;
+ UINT8 *out = NULL;
+ UINT8 *pos = NULL;
UINT8 block[4];
- UINT8 tmp;
- INT32 block_index;
- INT32 src_index;
- UINT32 pad_count = 0;
+ INT32 block_index = 0;
+ INT32 src_index = 0;
if (!out_len) {
- return NULL;
+ goto error;
}
// Malloc might be up to 2 larger dependent on padding
- *out_len = len / 4 * 3;
+ *out_len = len / 4 * 3 + 2;
pos = out = malloc(*out_len);
if (out == NULL) {
- return NULL;
+ goto error;
}
block_index = 0;
for (src_index = 0; src_index < len; src_index++) {
- tmp = decode_table[(UINT8)src[src_index]];
- if (tmp == 0x80) {
- free(out);
- return NULL;
+ char current_char = src[src_index];
+ if (current_char == '=') {
+ break;
+ }
+ // If the final character is a newline, as can occur in many editors
+ // then ignore it.
+ if (src_index + 1 == len && current_char == '\n') {
+ printf("Ignoring trailing newline.\n");
+ break;
}
- if (src[src_index] == '=') {
- pad_count++;
+ block[block_index] = decode_table[(UINT8)current_char];
+ if (block[block_index] == 0x80) {
+ printf("Invalid character \"%c\".\n", current_char);
+ goto error;
}
- block[block_index] = tmp;
block_index++;
if (block_index == 4) {
*pos++ = (block[0] << 2) | (block[1] >> 4);
*pos++ = (block[1] << 4) | (block[2] >> 2);
*pos++ = (block[2] << 6) | block[3];
- if (pad_count > 0) {
- if (pad_count == 1) {
- pos--;
- } else if (pad_count == 2) {
- pos -= 2;
- } else {
- /* Invalid pad_counting */
- free(out);
- return NULL;
- }
- break;
- }
block_index = 0;
}
}
+ if (block_index == 0) {
+ // mod 4 Even number of characters, no padding.
+ } else if (block_index == 1) {
+ printf("Invalid base64 input length. Last character truncated.\n");
+ goto error;
+ } else if (block_index == 2) {
+ *pos++ = (block[0] << 2) | (block[1] >> 4);
+ } else if (block_index == 3) {
+ *pos++ = (block[0] << 2) | (block[1] >> 4);
+ *pos++ = (block[1] << 4) | (block[2] >> 2);
+ } else {
+ /* Invalid pad_counting */
+ printf("Invalid base64 input length %d.\n", block_index);
+ goto error;
+ }
*out_len = pos - out;
return out;
+
+error:
+ free(out);
+ return NULL;
}