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/cli-app/cper-convert.c b/cli-app/cper-convert.c
index 942d258..d1caeb6 100644
--- a/cli-app/cper-convert.c
+++ b/cli-app/cper-convert.c
@@ -13,6 +13,8 @@
 #include <libcper/log.h>
 #include <libcper/cper-parse.h>
 #include <libcper/json-schema.h>
+#include <libcper/Cper.h>
+#include <libcper/base64.h>
 
 void cper_to_json(char *in_file, char *out_file, int is_single_section);
 void json_to_cper(const char *in_file, const char *out_file);
@@ -94,12 +96,49 @@
 		return;
 	}
 
+	fseek(cper_file, 0, SEEK_END);
+	long fsize = ftell(cper_file);
+	fseek(cper_file, 0, SEEK_SET);
+
+	char *fbuff = malloc(fsize);
+	size_t readsize = fread(fbuff, 1, (long)fsize, cper_file);
+	if (readsize != (size_t)fsize) {
+		printf("Could not read CPER file '%s', read returned %ld bytes.\n",
+		       in_file, readsize);
+		return;
+	}
+
+	if (!header_valid(fbuff, readsize)) {
+		// Check if it's base64 encoded
+		int32_t decoded_len = 0;
+		UINT8 *decoded = base64_decode(fbuff, readsize, &decoded_len);
+		if (decoded == NULL) {
+			printf("base64 decode failed for CPER file '%s'.\n",
+			       in_file);
+			free(fbuff);
+			free(decoded);
+			return;
+		}
+		if (!header_valid((const char *)decoded, decoded_len)) {
+			printf("Invalid CPER file '%s'.\n", in_file);
+			free(fbuff);
+			free(decoded);
+			return;
+		}
+		// Swap the buffer to the base64 decoded buffer.
+		free(fbuff);
+		fbuff = (char *)decoded;
+
+		fsize = decoded_len;
+		decoded = NULL;
+	}
+
 	//Convert.
 	json_object *ir;
 	if (is_single_section) {
-		ir = cper_single_section_to_ir(cper_file);
+		ir = cper_buf_single_section_to_ir((UINT8 *)fbuff, readsize);
 	} else {
-		ir = cper_to_ir(cper_file);
+		ir = cper_buf_to_ir((UINT8 *)fbuff, fsize);
 	}
 	fclose(cper_file);