diff --git a/docs/README.md b/docs/README.md index 62dce223..2e802249 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2846,6 +2846,58 @@ char *str = mg_json_get_str(json, "$.a"); // str = "hi" free(str); ``` +### mg\_json\_get\_hex() + +```c +char *mg_json_get_hex(struct mg_str json, const char *path, int *len); +``` + +Fetch hex-encoded buffer from the json string `json` at JSON path +`path`. If found, a buffer is allocated using `calloc()`, decoded, +and returned to the caller. It is the caller's responsibility to +`free()` the returned string. Returned buffer is 0-terminated. + +Parameters: +- `json` - a string containing valid JSON +- `path` - a JSON path. Must start with `$` +- `len` - a pointer that receives decoded length. Can be NULL + +Return value: non-NULL on success, NULL on error + +Usage example: + +```c +struct mg_str json = mg_str("{\"a\": \"6869\"}"); // json = {"a": "6869"} +char *str = mg_json_get_hex(json, "$.a", NULL); // str = "hi" +free(str); +``` + +### mg\_json\_get\_b64() + +```c +char *mg_json_get_b4(struct mg_str json, const char *path, int *len); +``` + +Fetch base64-encoded buffer from the json string `json` at JSON path +`path`. If found, a buffer is allocated using `calloc()`, decoded, +and returned to the caller. It is the caller's responsibility to +`free()` the returned string. Returned buffer is 0-terminated. + +Parameters: +- `json` - a string containing valid JSON +- `path` - a JSON path. Must start with `$` +- `len` - a pointer that receives decoded length. Can be NULL + +Return value: non-NULL on success, NULL on error + +Usage example: + +```c +struct mg_str json = mg_str("{\"a\": \"YWJj\"}"); // json = {"a": "YWJj"} +char *str = mg_json_get_b64(json, "$.a", NULL); // str = "abc" +free(str); +``` + ## Utility ### mg\_call() diff --git a/mongoose.c b/mongoose.c index 371d4a2c..a34e7592 100644 --- a/mongoose.c +++ b/mongoose.c @@ -2026,6 +2026,7 @@ void mg_iobuf_free(struct mg_iobuf *io) { #endif + static const char *escapeseq(int esc) { return esc ? "\b\f\n\r\t\\\"" : "bfnrt\\\""; } @@ -2246,6 +2247,31 @@ char *mg_json_get_str(struct mg_str json, const char *path) { return result; } +char *mg_json_get_b64(struct mg_str json, const char *path, int *len) { + int n, toklen; + char *result = NULL; + if ((n = mg_json_get(json.ptr, (int) json.len, path, &toklen)) >= 0 && + json.ptr[n] == '"' && toklen > 1 && + (result = (char *) calloc(1, (size_t) toklen)) != NULL) { + int k = mg_base64_decode(json.ptr + n + 1, toklen - 2, result); + if (len != NULL) *len = k; + } + return result; +} + +char *mg_json_get_hex(struct mg_str json, const char *path, int *len) { + int n, toklen; + char *result = NULL; + if ((n = mg_json_get(json.ptr, (int) json.len, path, &toklen)) >= 0 && + json.ptr[n] == '"' && toklen > 1 && + (result = (char *) calloc(1, (size_t) toklen / 2)) != NULL) { + mg_unhex(json.ptr + n + 1, (size_t) (toklen - 2), (uint8_t *) result); + result[(toklen - 2) / 2] = '\0'; + if (len != NULL) *len = (toklen - 2) / 2; + } + return result; +} + #ifdef MG_ENABLE_LINES #line 1 "src/log.c" #endif diff --git a/mongoose.h b/mongoose.h index 5cea0b62..54628b1b 100644 --- a/mongoose.h +++ b/mongoose.h @@ -1310,7 +1310,8 @@ int mg_json_get(const char *buf, int len, const char *path, int *toklen); bool mg_json_get_num(struct mg_str json, const char *path, double *v); bool mg_json_get_bool(struct mg_str json, const char *path, bool *v); char *mg_json_get_str(struct mg_str json, const char *path); -char *mg_json_get_hex(struct mg_str json, const char *path); +char *mg_json_get_hex(struct mg_str json, const char *path, int *len); +char *mg_json_get_b64(struct mg_str json, const char *path, int *len); diff --git a/src/json.c b/src/json.c index 21ece7ef..d6b736a7 100644 --- a/src/json.c +++ b/src/json.c @@ -1,4 +1,5 @@ #include "json.h" +#include "base64.h" static const char *escapeseq(int esc) { return esc ? "\b\f\n\r\t\\\"" : "bfnrt\\\""; @@ -219,3 +220,28 @@ char *mg_json_get_str(struct mg_str json, const char *path) { } return result; } + +char *mg_json_get_b64(struct mg_str json, const char *path, int *len) { + int n, toklen; + char *result = NULL; + if ((n = mg_json_get(json.ptr, (int) json.len, path, &toklen)) >= 0 && + json.ptr[n] == '"' && toklen > 1 && + (result = (char *) calloc(1, (size_t) toklen)) != NULL) { + int k = mg_base64_decode(json.ptr + n + 1, toklen - 2, result); + if (len != NULL) *len = k; + } + return result; +} + +char *mg_json_get_hex(struct mg_str json, const char *path, int *len) { + int n, toklen; + char *result = NULL; + if ((n = mg_json_get(json.ptr, (int) json.len, path, &toklen)) >= 0 && + json.ptr[n] == '"' && toklen > 1 && + (result = (char *) calloc(1, (size_t) toklen / 2)) != NULL) { + mg_unhex(json.ptr + n + 1, (size_t) (toklen - 2), (uint8_t *) result); + result[(toklen - 2) / 2] = '\0'; + if (len != NULL) *len = (toklen - 2) / 2; + } + return result; +} diff --git a/src/json.h b/src/json.h index 454153cf..45c9b415 100644 --- a/src/json.h +++ b/src/json.h @@ -14,4 +14,5 @@ int mg_json_get(const char *buf, int len, const char *path, int *toklen); bool mg_json_get_num(struct mg_str json, const char *path, double *v); bool mg_json_get_bool(struct mg_str json, const char *path, bool *v); char *mg_json_get_str(struct mg_str json, const char *path); -char *mg_json_get_hex(struct mg_str json, const char *path); +char *mg_json_get_hex(struct mg_str json, const char *path, int *len); +char *mg_json_get_b64(struct mg_str json, const char *path, int *len); diff --git a/test/unit_test.c b/test/unit_test.c index 4b8c15d1..1c7c55d6 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -2363,6 +2363,7 @@ static void test_json(void) { { double d = 0; bool b = false; + int len; const char *json = "{\"a\": \"hi\\nthere\",\"b\": [12345, true]}"; char *str = mg_json_get_str(mg_str(json), "$.a"); @@ -2379,6 +2380,14 @@ static void test_json(void) { ASSERT(mg_json_get_bool(mg_str(json), "$.b[0]", &b) == false); ASSERT(mg_json_get_bool(mg_str(json), "$.b[1]", &b) == true); ASSERT(b == true); + + json = "[\"YWJj\", \"0100026869\"]"; + ASSERT((str = mg_json_get_b64(mg_str(json), "$[0]", &len)) != NULL); + ASSERT(len == 3 && memcmp(str, "abc", (size_t) len) == 0); + free(str); + ASSERT((str = mg_json_get_hex(mg_str(json), "$[1]", &len)) != NULL); + ASSERT(len == 5 && memcmp(str, "\x01\x00\x02hi", (size_t) len) == 0); + free(str); } }