From 157d71e802eb5bcbf25bfcfd7486e8126f8612d0 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Wed, 8 Mar 2023 15:18:00 +0100 Subject: [PATCH] [core,aad] migrate to cJSON parser library --- include/freerdp/utils/json.h | 64 --- libfreerdp/core/CMakeLists.txt | 5 + libfreerdp/core/aad.c | 182 +++++--- libfreerdp/utils/CMakeLists.txt | 2 +- libfreerdp/utils/json.c | 663 --------------------------- libfreerdp/utils/test/CMakeLists.txt | 2 +- libfreerdp/utils/test/TestJSON.c | 82 ---- 7 files changed, 130 insertions(+), 870 deletions(-) delete mode 100644 include/freerdp/utils/json.h delete mode 100644 libfreerdp/utils/json.c delete mode 100644 libfreerdp/utils/test/TestJSON.c diff --git a/include/freerdp/utils/json.h b/include/freerdp/utils/json.h deleted file mode 100644 index 1bbe0f056..000000000 --- a/include/freerdp/utils/json.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * - * Simple JSON parser - * - * Copyright 2023 Isaac Klein - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FREERDP_UTILS_JSON_H -#define FREERDP_UTILS_JSON_H - -#include - -enum JSON_TYPE -{ - JSON_TYPE_FALSE, - JSON_TYPE_NULL, - JSON_TYPE_TRUE, - JSON_TYPE_OBJECT, - JSON_TYPE_ARRAY, - JSON_TYPE_NUMBER, - JSON_TYPE_STRING -}; - -typedef struct JSON JSON; - -#ifdef __cplusplus -extern "C" -{ -#endif - - FREERDP_API JSON* json_parse(const char* str); - FREERDP_API JSON* json_new(enum JSON_TYPE type); - FREERDP_API void json_free(JSON* json); - - FREERDP_API enum JSON_TYPE json_get_type(JSON* json); - - FREERDP_API int json_object_set_prop(JSON* object, const char* prop, JSON* value); - FREERDP_API int json_array_add(JSON* array, JSON* value); - FREERDP_API int json_number_set(JSON* json, double value); - FREERDP_API int json_string_set(JSON* json, const char* value); - - FREERDP_API int json_object_get_prop(JSON* object, const char* prop, JSON** value); - FREERDP_API int json_array_get(JSON* array, size_t index, JSON** value); - FREERDP_API int json_number_get(JSON* json, double* value); - FREERDP_API int json_string_get(JSON* json, const char** value); - -#ifdef __cplusplus -} -#endif - -#endif /* FREERDP_UTILS_JSON_H */ diff --git a/libfreerdp/core/CMakeLists.txt b/libfreerdp/core/CMakeLists.txt index 43a5e4690..e35162166 100644 --- a/libfreerdp/core/CMakeLists.txt +++ b/libfreerdp/core/CMakeLists.txt @@ -18,6 +18,11 @@ set(MODULE_NAME "freerdp-core") set(MODULE_PREFIX "FREERDP_CORE") +find_package(cJSON REQUIRED) + +freerdp_include_directory_add(${CJSON_INCLUDE_DIRS}) +freerdp_library_add(${CJSON_LIBRARIES}) + freerdp_definition_add(-DEXT_PATH="${FREERDP_EXTENSION_PATH}") freerdp_include_directory_add(${OPENSSL_INCLUDE_DIR}) diff --git a/libfreerdp/core/aad.c b/libfreerdp/core/aad.c index e2eccfac9..8a111d0c7 100644 --- a/libfreerdp/core/aad.c +++ b/libfreerdp/core/aad.c @@ -22,7 +22,9 @@ #include #include -#include + +#include + #include #include @@ -124,6 +126,58 @@ rdpAad* aad_new(rdpContext* context, rdpTransport* transport) return aad; } +static BOOL json_get_number(cJSON* json, const char* key, double* result) +{ + WINPR_ASSERT(json); + WINPR_ASSERT(key); + WINPR_ASSERT(result); + + if (!cJSON_HasObjectItem(json, key)) + return FALSE; + + cJSON* prop = cJSON_GetObjectItem(json, key); + if (!prop) + return FALSE; + + if (!cJSON_IsNumber(prop)) + return FALSE; + *result = cJSON_GetNumberValue(prop); + return TRUE; +} + +static BOOL json_get_const_string(cJSON* json, const char* key, const char** result) +{ + WINPR_ASSERT(json); + WINPR_ASSERT(key); + WINPR_ASSERT(result); + + *result = NULL; + + if (!cJSON_HasObjectItem(json, key)) + return FALSE; + + cJSON* prop = cJSON_GetObjectItem(json, key); + if (!prop) + return FALSE; + + if (!cJSON_IsString(prop)) + return FALSE; + + const char* str = cJSON_GetStringValue(prop); + *result = str; + return *result != NULL; +} + +static BOOL json_get_string_alloc(cJSON* json, const char* key, char** result) +{ + const char* str = NULL; + if (!json_get_const_string(json, key, &str)) + return FALSE; + free(*result); + *result = _strdup(str); + return *result != NULL; +} + int aad_client_begin(rdpAad* aad) { int ret = -1; @@ -136,8 +190,8 @@ int aad_client_begin(rdpAad* aad) char* p = NULL; const char* token = NULL; long status_code; - JSON* json = NULL; - JSON* prop = NULL; + cJSON* json = NULL; + cJSON* prop = NULL; WINPR_ASSERT(aad); WINPR_ASSERT(aad->rdpcontext); @@ -205,15 +259,15 @@ int aad_client_begin(rdpAad* aad) LOG_ERROR_AND_GOTO(fail, "Received status code: %li", status_code); /* Extract the access token from the JSON response */ - if (!(json = json_parse(buffer))) + json = cJSON_ParseWithLength(buffer, length); + if (!json) LOG_ERROR_AND_GOTO(fail, "Failed to parse JSON response"); - if (!json_object_get_prop(json, "access_token", &prop) || !json_string_get(prop, &token)) + + if (!json_get_string_alloc(json, "access_token", &aad->access_token)) LOG_ERROR_AND_GOTO(fail, "Could not find \"access_token\" property in JSON response"); - if (!(aad->access_token = _strdup(token))) - goto fail; XFREE(buffer); - json_free(json); + cJSON_free(json); json = NULL; /* Send the nonce request message */ @@ -235,17 +289,17 @@ int aad_client_begin(rdpAad* aad) LOG_ERROR_AND_GOTO(fail, "Received status code: %li", status_code); /* Extract the nonce from the response */ - if (!(json = json_parse(buffer))) + json = cJSON_ParseWithLength(buffer, length); + if (!json) LOG_ERROR_AND_GOTO(fail, "Failed to parse JSON response"); - if (!json_object_get_prop(json, "Nonce", &prop) || !json_string_get(prop, &token)) + + if (!json_get_string_alloc(json, "Nonce", &aad->nonce)) LOG_ERROR_AND_GOTO(fail, "Could not find \"Nonce\" property in JSON response"); - if (!(aad->nonce = _strdup(token))) - goto fail; ret = 1; fail: - json_free(json); + cJSON_free(json); free(buffer); free(req_body); free(req_header); @@ -354,60 +408,70 @@ fail: return ret; } +static int aad_parse_state_initial(rdpAad* aad, wStream* s) +{ + const char* jstr = Stream_PointerAs(s, char); + const size_t jlen = Stream_GetRemainingLength(s); + const char* ts_nonce = NULL; + int ret = -1; + cJSON* json = NULL; + + if (!Stream_SafeSeek(s, jlen)) + goto fail; + + json = cJSON_ParseWithLength(jstr, jlen); + if (!json) + goto fail; + + if (!json_get_const_string(json, "ts_nonce", &ts_nonce)) + goto fail; + + ret = aad_send_auth_request(aad, ts_nonce); +fail: + cJSON_free(json); + return ret; +} + +static int aad_parse_state_auth(rdpAad* aad, wStream* s) +{ + int rc = -1; + double result = 0; + cJSON* json = NULL; + const char* jstr = Stream_PointerAs(s, char); + const size_t jlength = Stream_GetRemainingLength(s); + + if (!Stream_SafeSeek(s, jlength)) + goto fail; + + json = cJSON_ParseWithLength(jstr, jlength); + if (!json) + goto fail; + + if (!json_get_number(json, "authentication_result", &result)) + goto fail; + + rc = 1; +fail: + cJSON_free(json); + + if (result != 0.0) + LOG_ERROR_AND_RETURN(-1, "Authentication result: %d", (int)result); + + aad->state = AAD_STATE_FINAL; + return rc; +} int aad_recv(rdpAad* aad, wStream* s) { - JSON* json; - JSON* prop; + cJSON* json; + cJSON* prop; WINPR_ASSERT(aad); WINPR_ASSERT(s); if (aad->state == AAD_STATE_INITIAL) - { - const char* ts_nonce = NULL; - int ret = 0; - - if (!(json = json_parse(Stream_PointerAs(s, char)))) - LOG_ERROR_AND_RETURN(-1, "Failed to parse Server Nonce PDU"); - - if (!json_object_get_prop(json, "ts_nonce", &prop) || !json_string_get(prop, &ts_nonce)) - { - json_free(json); - WLog_ERR(TAG, "Failed to find ts_nonce in PDU"); - return -1; - } - - Stream_Seek(s, Stream_Length(s)); - - ret = aad_send_auth_request(aad, ts_nonce); - json_free(json); - return ret; - } + return aad_parse_state_initial(aad, s); else if (aad->state == AAD_STATE_AUTH) - { - double result = 0; - - if (!(json = json_parse(Stream_PointerAs(s, char)))) - LOG_ERROR_AND_RETURN(-1, "Failed to parse Authentication Result PDU"); - - if (!json_object_get_prop(json, "authentication_result", &prop) || - !json_number_get(prop, &result)) - { - json_free(json); - WLog_ERR(TAG, "Failed to find authentication_result in PDU"); - return -1; - } - - json_free(json); - - Stream_Seek(s, Stream_Length(s)); - - if (result != 0) - LOG_ERROR_AND_RETURN(-1, "Authentication result: %d", (int)result); - - aad->state = AAD_STATE_FINAL; - return 1; - } + return aad_parse_state_auth(aad, s); else LOG_ERROR_AND_RETURN(-1, "Invalid state"); } diff --git a/libfreerdp/utils/CMakeLists.txt b/libfreerdp/utils/CMakeLists.txt index a6d4b0233..2dc823d60 100644 --- a/libfreerdp/utils/CMakeLists.txt +++ b/libfreerdp/utils/CMakeLists.txt @@ -33,7 +33,7 @@ set(${MODULE_PREFIX}_SRCS smartcard_pack.c smartcard_call.c stopwatch.c - json.c) +) freerdp_module_add(${${MODULE_PREFIX}_SRCS}) diff --git a/libfreerdp/utils/json.c b/libfreerdp/utils/json.c deleted file mode 100644 index 3289ada94..000000000 --- a/libfreerdp/utils/json.c +++ /dev/null @@ -1,663 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * - * Simple JSON parser - * - * Copyright 2023 Isaac Klein - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -const char* whitespace = " \t\n\r"; - -struct JSON_OBJECT -{ - struct JSON_PROP** props; - size_t count; - size_t capacity; -}; - -struct JSON_PROP -{ - char* name; - struct JSON* value; -}; - -struct JSON_ARRAY -{ - struct JSON** values; - size_t count; - size_t capacity; -}; - -struct JSON -{ - enum JSON_TYPE type; - union - { - struct JSON_OBJECT object; - struct JSON_ARRAY array; - double number; - char* string; - } value; -}; - -static JSON* json_parse_value(const char* ptr, const char** tailptr); -static JSON* json_parse_object(const char* ptr, const char** tailptr); -static JSON* json_parse_array(const char* ptr, const char** tailptr); -static JSON* json_parse_number(const char* ptr, const char** tailptr); -static JSON* json_parse_string(const char* ptr, const char** tailptr); -static char* json_parse_raw_string(const char* str, const char** tailptr); - -JSON* json_parse(const char* str) -{ - JSON* json = NULL; - - if (!str) - return NULL; - - /* A JSON text is a single value surrounded by optional whitespace */ - str = str + strspn(str, whitespace); - json = json_parse_value(str, &str); - str = str + strspn(str, whitespace); - - /* Text must be fully consumed */ - if (*str != '\0') - { - json_free(json); - return NULL; - } - - return json; -} - -JSON* json_new(enum JSON_TYPE type) -{ - struct JSON* json = calloc(1, sizeof(struct JSON)); - if (json) - json->type = type; - - if (type == JSON_TYPE_OBJECT) - { - json->value.object.props = malloc(4 * sizeof(struct JSON_PROP*)); - if (!json->value.object.props) - { - free(json); - return NULL; - } - json->value.object.capacity = 4; - } - else if (type == JSON_TYPE_ARRAY) - { - json->value.array.values = malloc(4 * sizeof(struct JSON_OBJECT*)); - if (!json->value.array.values) - { - free(json); - return NULL; - } - json->value.array.capacity = 4; - } - else if (type == JSON_TYPE_STRING) - { - json->value.string = _strdup(""); - if (!json->value.string) - { - free(json); - return NULL; - } - } - - return json; -} - -void json_free(struct JSON* json) -{ - if (!json) - return; - - if (json->type == JSON_TYPE_OBJECT) - { - for (size_t i = 0; i < json->value.object.count; i++) - { - free(json->value.object.props[i]->name); - json_free(json->value.object.props[i]->value); - free(json->value.object.props[i]); - } - free(json->value.object.props); - } - else if (json->type == JSON_TYPE_ARRAY) - { - for (size_t i = 0; i < json->value.array.count; i++) - json_free(json->value.array.values[i]); - free(json->value.array.values); - } - else if (json->type == JSON_TYPE_STRING) - { - free(json->value.string); - } - - free(json); -} - -enum JSON_TYPE json_get_type(struct JSON* json) -{ - if (!json) - return JSON_TYPE_NULL; - return json->type; -} - -int json_object_set_prop(struct JSON* json, const char* name, JSON* value) -{ - struct JSON_OBJECT* object; - struct JSON_PROP* new_prop; - - if (!json || !name || !value || json->type != JSON_TYPE_OBJECT) - return 0; - object = &json->value.object; - - /* If we reached capacity, double it */ - if (object->capacity <= object->count) - { - size_t new_size = object->capacity * 2; - struct JSON_PROP** tmp = realloc(object->props, new_size * sizeof(struct JSON_PROP*)); - if (!tmp) - return 0; - object->capacity = new_size; - object->props = tmp; - } - - new_prop = calloc(1, sizeof(struct JSON_PROP)); - if (!new_prop) - return 0; - - new_prop->name = _strdup(name); - if (!new_prop->name) - { - free(new_prop); - return 0; - } - new_prop->value = value; - - object->props[object->count++] = new_prop; - return 1; -} - -int json_array_add(JSON* json, JSON* value) -{ - struct JSON_ARRAY* array; - - if (!json || !value || json->type != JSON_TYPE_ARRAY) - return 0; - array = &json->value.array; - - /* If we reached capacity, double it */ - if (array->capacity <= array->count) - { - size_t new_size = array->capacity * 2; - struct JSON** tmp = realloc(array->values, new_size * sizeof(struct JSON*)); - if (!tmp) - return 0; - array->capacity = new_size; - array->values = tmp; - } - - array->values[array->count++] = value; - return 1; -} - -int json_number_set(struct JSON* json, double value) -{ - if (!json || json->type != JSON_TYPE_NUMBER) - return 0; - json->value.number = value; - return 1; -} - -int json_string_set(struct JSON* json, const char* value) -{ - char* tmp; - - if (!json || json->type != JSON_TYPE_STRING) - return 0; - - tmp = _strdup(value); - if (!tmp) - return 0; - free(json->value.string); - json->value.string = tmp; - return 1; -} - -int json_object_get_prop(struct JSON* json, const char* name, JSON** value) -{ - struct JSON_OBJECT* object; - - if (!json || !name || !value || json->type != JSON_TYPE_OBJECT) - return 0; - object = &json->value.object; - - for (size_t i = 0; i < object->count; i++) - { - if (strcmp(object->props[i]->name, name) == 0) - { - *value = object->props[i]->value; - return 1; - } - } - - return 0; -} - -int json_array_get(struct JSON* json, size_t index, JSON** value) -{ - struct JSON_ARRAY* array; - - if (!json || !value) - return 0; - array = &json->value.array; - - if (index >= array->count) - return 0; - - *value = array->values[index]; - return 1; -} - -int json_number_get(struct JSON* json, double* value) -{ - if (!json || !value) - return 0; - *value = json->value.number; - return 1; -} - -int json_string_get(struct JSON* json, const char** value) -{ - if (!json || !value) - return 0; - *value = json->value.string; - return 1; -} - -static JSON* json_parse_value(const char* ptr, const char** tailptr) -{ - struct JSON* json = NULL; - - if (!ptr) - return NULL; - - /* Check what type of value to expect */ - if (*ptr == '{') - { - json = json_parse_object(ptr, &ptr); - } - else if (*ptr == '[') - { - json = json_parse_array(ptr, &ptr); - } - else if (*ptr == '"') - { - json = json_parse_string(ptr, &ptr); - } - else if (isdigit(*ptr) || *ptr == '-') - { - json = json_parse_number(ptr, &ptr); - } - else if (strncmp(ptr, "false", 5) == 0) - { - json = json_new(JSON_TYPE_FALSE); - ptr += 5; - } - else if (strncmp(ptr, "null", 4) == 0) - { - json = json_new(JSON_TYPE_NULL); - ptr += 4; - } - else if (strncmp(ptr, "true", 4) == 0) - { - json = json_new(JSON_TYPE_TRUE); - ptr += 4; - } - /* If all these checks fail json remains null */ - - if (tailptr) - *tailptr = ptr; - - return json; -} - -static JSON* json_parse_object(const char* ptr, const char** tailptr) -{ - struct JSON* json; - char* prop_name = NULL; - - if (!ptr) - return NULL; - - /* Objects begin with a '{' character surrounded by optional whitespace */ - ptr += strspn(ptr, whitespace); - if (*ptr++ != '{') - return NULL; - ptr += strspn(ptr, whitespace); - - json = json_new(JSON_TYPE_OBJECT); - if (!json) - return NULL; - - /* Objects can be empty */ - /* Any leading whitespace has been consumed together with trailing whitespace of '{' above */ - if (*ptr == '}') - { - /* Consume '}' and any trailing whitespace */ - ptr++; - if (tailptr) - *tailptr = ptr + strspn(ptr, whitespace); - return json; - } - - while (*ptr) - { - const char* cur; - - prop_name = json_parse_raw_string(ptr, &ptr); - if (!prop_name) - break; - - /* Property names must be followd by a ':' character with optional surrounding whitespace */ - ptr += strspn(ptr, whitespace); - if (*ptr++ != ':') - break; - ptr += strspn(ptr, whitespace); - - if (!json_object_set_prop(json, prop_name, json_parse_value(ptr, &ptr))) - break; - - free(prop_name); - prop_name = NULL; - - /* Consume any whitespace before either a '}' or ',' character */ - ptr += strspn(ptr, whitespace); - - cur = ptr++; - if (*cur == '}') - { - /* Consume any space following '}' and parsing is complete */ - if (tailptr) - *tailptr = ptr + strspn(ptr, whitespace); - return json; - } - else if (*cur == ',') - { - /* Consume any space following ',' and continue to the next property */ - ptr += strspn(ptr, whitespace); - continue; - } - else - break; - } - - /* If we got here, something failed */ - free(prop_name); - json_free(json); - return NULL; -} - -static JSON* json_parse_array(const char* ptr, const char** tailptr) -{ - struct JSON* json; - - if (!ptr) - return NULL; - - /* Arrays start with '[', with optional surrounding whitespace */ - ptr += strspn(ptr, whitespace); - if (*ptr++ != '[') - return NULL; - ptr += strspn(ptr, whitespace); - - json = json_new(JSON_TYPE_ARRAY); - if (!json) - return NULL; - - /* Arrays can be empty */ - /* Any leading whitespace has been consumed together with trailing whitespace of '[' above */ - if (*ptr == ']') - { - /* Consume ']' and any trailing whitespace */ - ptr++; - if (tailptr) - *tailptr = ptr + strspn(ptr, whitespace); - return json; - } - - while (*ptr) - { - const char* cur; - - if (!json_array_add(json, json_parse_value(ptr, &ptr))) - break; - - /* Consume any whitespace leading ']' or ',' */ - ptr += strspn(ptr, whitespace); - - cur = ptr++; - if (*cur == ']') - { - /* The array is completely parsed */ - if (tailptr) - *tailptr = ptr + strspn(ptr, whitespace); - return json; - } - else if (*cur == ',') - { - ptr += strspn(ptr, whitespace); - continue; - } - else - break; - } - - json_free(json); - return NULL; -} - -static JSON* json_parse_number(const char* ptr, const char** tailptr) -{ - struct JSON* json; - char* tail; - double value; - - if (!ptr) - return NULL; - - value = strtod(ptr, &tail); - if (tail == ptr) - return NULL; - - json = json_new(JSON_TYPE_NUMBER); - if (!json) - return NULL; - - json_number_set(json, value); - - if (tailptr) - *tailptr = tail; - - return json; -} - -static JSON* json_parse_string(const char* ptr, const char** tailptr) -{ - struct JSON* json; - char *string = NULL; - - if (!ptr) - return NULL; - - json = json_new(JSON_TYPE_STRING); - if (!json) - return NULL; - - string = json_parse_raw_string(ptr, &ptr); - - if (!json_string_set(json, string)) - { - json_free(json); - json = NULL; - } - - free(string); - - if (tailptr) - *tailptr = ptr; - - return json; -} - -static uint16_t get_utf16_code_point(const char* str) -{ - char hexdig[5] = { 0 }; - char* tailptr; - uint16_t cp; - - for (int i = 0; i < 4 && isxdigit(str[i]); i++) - hexdig[i] = str[i]; - if (strlen(hexdig) != 4) - return 0; - - cp = (uint16_t)strtoul(hexdig, &tailptr, 16); - if (tailptr != hexdig + 4) - return 0; - - return cp; -} - -static char* json_parse_raw_string(const char* str, const char** tailptr) -{ - char* buffer; - char* ptr; - size_t str_len = strlen(str); - int escaped = 0; - - /* Strings must begin with '"' */ - if (!str || *str++ != '"') - return NULL; - - /* The string cannot be longer than the rest of the JSON text */ - if (!(buffer = malloc(str_len))) - return NULL; - ptr = buffer; - - /* Read until we encounter an unescaped end-quote or we reach the end of the text */ - while (*str && (escaped || *str != '"')) - { - if (escaped) - { - char cur = *str++; - - if (cur == 'u') - { - uint32_t cp; - uint16_t surrogate; - - cp = get_utf16_code_point(str); - if (cp == 0) - break; - str += 4; - - /* Check if this might be the high surrogate of a pair */ - if (cp >= 0xD800 && cp < 0xDC00 && str[0] == '\\' && str[1] == 'u') - { - surrogate = get_utf16_code_point(str + 2); - if (surrogate >= 0xDC00 && surrogate < 0xE000) - { - cp = (((cp & 0x3FF) << 10) & (surrogate & 0x3FF)) + 0x10000; - str += 6; - } - } - - /* Encode the character as utf-8 */ - if (cp < 0x80) - *ptr++ = cp; - else if (cp < 0x800) - { - *ptr++ = 0xC0 | (cp >> 6); - *ptr++ = 0x80 | (cp & 0x3F); - } - else if (cp < 0x10000) - { - *ptr++ = 0xE0 | (cp >> 12); - *ptr++ = 0x80 | ((cp >> 6) & 0x3F); - *ptr++ = 0x80 | (cp & 0x3F); - } - else - { - *ptr++ = 0xF0 | (cp >> 18); - *ptr++ = 0x80 | ((cp >> 12) & 0x3F); - *ptr++ = 0x80 | ((cp >> 6) & 0x3F); - *ptr++ = 0x80 | (cp & 0x3F); - } - } - else if (cur == '"') - *ptr++ = '"'; - else if (cur == '\\') - *ptr++ = '\\'; - else if (cur == '/') - *ptr++ = '/'; - else if (cur == 'b') - *ptr++ = '\b'; - else if (cur == 'f') - *ptr++ = '\f'; - else if (cur == 'n') - *ptr++ = '\n'; - else if (cur == 'r') - *ptr++ = '\r'; - else if (cur == 't') - *ptr++ = '\t'; - else - break; - escaped = 0; - } - else if (*str == '\\') - { - str++; - escaped = 1; - } - else - *ptr++ = *str++; - } - *ptr++ = '\0'; - - if (escaped || *str++ != '"') - { - free(buffer); - return NULL; - } - else - { - /* Try to not tie up a potentially large amount of unused memory */ - char* tmp = realloc(buffer, ptr - buffer); - if (tmp) - buffer = tmp; - } - - if (tailptr) - *tailptr = str; - - return buffer; -} diff --git a/libfreerdp/utils/test/CMakeLists.txt b/libfreerdp/utils/test/CMakeLists.txt index e8d0d2f1d..f2b697786 100644 --- a/libfreerdp/utils/test/CMakeLists.txt +++ b/libfreerdp/utils/test/CMakeLists.txt @@ -7,7 +7,7 @@ set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c) set(${MODULE_PREFIX}_TESTS TestRingBuffer.c TestPodArrays.c - TestJSON.c) +) create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} diff --git a/libfreerdp/utils/test/TestJSON.c b/libfreerdp/utils/test/TestJSON.c deleted file mode 100644 index eb80417e0..000000000 --- a/libfreerdp/utils/test/TestJSON.c +++ /dev/null @@ -1,82 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * TestJSON - * - * Copyright 2023 Isaac Klein - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -const char* valid_json = " {\n\t\"string\" :\"two\\nlines \\\"with quotes\\\"\" , \"number\": " - "-12.3, \n \"true\" : true ,\"array\":[1,\"two\", {\"three\":3}]}"; - -int TestJSON(int argc, char* argv[]) -{ - JSON* j = NULL; - const char* s = NULL; - double n = 0; - JSON* a = NULL; - JSON* json = json_parse(valid_json); - if (!json) - return -1; - - if (json_get_type(json) != JSON_TYPE_OBJECT) - return -2; - - if (!json_object_get_prop(json, "string", &j)) - return -3; - if (json_get_type(j) != JSON_TYPE_STRING) - return -4; - - if (!json_string_get(j, &s)) - return -5; - if (strcmp(s, "two\nlines \"with quotes\"") != 0) - return -6; - - if (!json_object_get_prop(json, "number", &j)) - return -7; - if (json_get_type(j) != JSON_TYPE_NUMBER) - return -8; - - if (!json_number_get(j, &n)) - return -9; - if (n != -12.3) - return -10; - - if (!json_object_get_prop(json, "true", &j)) - return -11; - if (json_get_type(j) != JSON_TYPE_TRUE) - return -12; - - if (!json_object_get_prop(json, "array", &a)) - return -13; - if (json_get_type(a) != JSON_TYPE_ARRAY) - return -14; - - if (!json_array_get(a, 0, &j)) - return -15; - if (json_get_type(j) != JSON_TYPE_NUMBER) - return -16; - - if (json_array_get(a, 3, &j) != 0) - return -17; - - if (json_object_get_prop(json, "notfound", &j) != 0) - return -18; - - json_free(json); - - return 0; -}