From 5f07ffda94e2847c585ea3f22762b6cdc1a9e04a Mon Sep 17 00:00:00 2001 From: Ondrej Holy Date: Thu, 25 Apr 2024 13:14:09 +0200 Subject: [PATCH 01/13] [cmake] fix typo in comment --- cmake/Findlodepng.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/Findlodepng.cmake b/cmake/Findlodepng.cmake index 0d3e92514..57484d683 100644 --- a/cmake/Findlodepng.cmake +++ b/cmake/Findlodepng.cmake @@ -1,8 +1,8 @@ # - Try to find lodepng # Once done this will define -# lodepng_FOUND - cJSON was found -# lodepng_INCLUDE_DIRS - cJSON include directories -# lodepng_LIBRARIES - cJSON libraries for linking +# lodepng_FOUND - lodepng was found +# lodepng_INCLUDE_DIRS - lodepng include directories +# lodepng_LIBRARIES - lodepng libraries for linking find_path(lodepng_INCLUDE_DIR NAMES lodepng.h) From 29bb435eccdb59b9b3966d2769b45ff4bfbcb7d8 Mon Sep 17 00:00:00 2001 From: Ondrej Holy Date: Tue, 30 Apr 2024 15:49:46 +0200 Subject: [PATCH 02/13] [cmake] add JSON library find modules * Add module for cJSON * Add module for json-c --- cmake/FindJSONC.cmake | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 cmake/FindJSONC.cmake diff --git a/cmake/FindJSONC.cmake b/cmake/FindJSONC.cmake new file mode 100644 index 000000000..bb0d19464 --- /dev/null +++ b/cmake/FindJSONC.cmake @@ -0,0 +1,24 @@ +# - Try to find JSON-C +# Once done this will define +# +# JSONC_FOUND - JSON-C was found +# JSONC_INCLUDE_DIRS - JSON-C include directories +# JSONC_LIBRARIES - libraries needed for linking + +find_package(PkgConfig) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_JSON json-c) +endif() + +find_path(JSONC_INCLUDE_DIR NAMES json-c/json.h json/json.h) +find_library(JSONC_LIBRARY NAMES json-c) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(JSONC DEFAULT_MSG JSONC_LIBRARY JSONC_INCLUDE_DIR) + +if(JSONC_FOUND) + set(JSONC_LIBRARIES ${JSONC_LIBRARY}) + set(JSONC_INCLUDE_DIRS ${JSONC_INCLUDE_DIR}/json-c) +endif() + +mark_as_advanced(JSONC_LIBRARY JSONC_INCLUDE_DIR) From 1b735a5c1727b99ff1af2127e08f8b79f5d2ae75 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Tue, 14 May 2024 14:58:29 +0200 Subject: [PATCH 03/13] [winpr,utils] add JSON parser wrapper as we now support cJSON and json-c we need to wrap the functions we use. also allows drop in replacements for older cJSON versions lacking certain functions. --- winpr/WinPRConfig.cmake.in | 9 + winpr/include/config/config.h.in | 2 + winpr/include/winpr/json.h | 93 ++++ winpr/libwinpr/utils/CMakeLists.txt | 37 ++ winpr/libwinpr/utils/json/json.c | 651 ++++++++++++++++++++++++++++ 5 files changed, 792 insertions(+) create mode 100644 winpr/include/winpr/json.h create mode 100644 winpr/libwinpr/utils/json/json.c diff --git a/winpr/WinPRConfig.cmake.in b/winpr/WinPRConfig.cmake.in index 00c69c984..ccc3a8869 100644 --- a/winpr/WinPRConfig.cmake.in +++ b/winpr/WinPRConfig.cmake.in @@ -1,9 +1,18 @@ +include(CMakeFindDependencyMacro) +if(NOT "@WITH_JSON_DISABLED@" AND NOT "@BUILD_SHARED_LIBS@") + if("@JSONC_FOUND@" AND NOT "@WITH_CJSON_REQUIRED@") + find_dependency(JSONC) + elseif("@CJSON_FOUND@") + find_dependency(cJSON) + endif() +endif() @PACKAGE_INIT@ set(WinPR_VERSION_MAJOR "@WINPR_VERSION_MAJOR@") set(WinPR_VERSION_MINOR "@WINPR_VERSION_MINOR@") set(WinPR_VERSION_REVISION "@WINPR_VERSION_REVISION@") +set(WITH_WINPR_JSON "@WITH_WINPR_JSON@") set_and_check(WinPR_INCLUDE_DIR "@PACKAGE_WINPR_INCLUDE_DIR@") diff --git a/winpr/include/config/config.h.in b/winpr/include/config/config.h.in index 8d289aa28..e233e56d4 100644 --- a/winpr/include/config/config.h.in +++ b/winpr/include/config/config.h.in @@ -34,6 +34,8 @@ #cmakedefine WITH_INTERNAL_MD4 #cmakedefine WITH_INTERNAL_MD5 +#cmakedefine WITH_WINPR_JSON + #cmakedefine WITH_DEBUG_NTLM #cmakedefine WITH_DEBUG_THREADS #cmakedefine WITH_DEBUG_EVENTS diff --git a/winpr/include/winpr/json.h b/winpr/include/winpr/json.h new file mode 100644 index 000000000..7e276c455 --- /dev/null +++ b/winpr/include/winpr/json.h @@ -0,0 +1,93 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * JSON parser wrapper + * + * Copyright 2024 Armin Novak + * Copyright 2024 Thincast Technologies GmbH + * + * 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 WINPR_UTILS_JSON +#define WINPR_UTILS_JSON + +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + typedef void WINPR_JSON; + + WINPR_API int WINPR_JSON_version(char* buffer, size_t len); + + WINPR_API WINPR_JSON* WINPR_JSON_Parse(const char* value); + WINPR_API WINPR_JSON* WINPR_JSON_ParseWithLength(const char* value, size_t buffer_length); + + WINPR_API void WINPR_JSON_Delete(WINPR_JSON* item); + + WINPR_API size_t WINPR_JSON_GetArraySize(const WINPR_JSON* array); + WINPR_API WINPR_JSON* WINPR_JSON_GetArrayItem(const WINPR_JSON* array, size_t index); + + WINPR_API WINPR_JSON* WINPR_JSON_GetObjectItem(const WINPR_JSON* object, const char* string); + WINPR_API WINPR_JSON* WINPR_JSON_GetObjectItemCaseSensitive(const WINPR_JSON* object, + const char* string); + WINPR_API BOOL WINPR_JSON_HasObjectItem(const WINPR_JSON* object, const char* string); + + WINPR_API const char* WINPR_JSON_GetErrorPtr(void); + + WINPR_API const char* WINPR_JSON_GetStringValue(WINPR_JSON* item); + WINPR_API double WINPR_JSON_GetNumberValue(const WINPR_JSON* item); + + WINPR_API BOOL WINPR_JSON_IsInvalid(const WINPR_JSON* item); + WINPR_API BOOL WINPR_JSON_IsFalse(const WINPR_JSON* item); + WINPR_API BOOL WINPR_JSON_IsTrue(const WINPR_JSON* item); + WINPR_API BOOL WINPR_JSON_IsBool(const WINPR_JSON* item); + WINPR_API BOOL WINPR_JSON_IsNull(const WINPR_JSON* item); + WINPR_API BOOL WINPR_JSON_IsNumber(const WINPR_JSON* item); + WINPR_API BOOL WINPR_JSON_IsString(const WINPR_JSON* item); + WINPR_API BOOL WINPR_JSON_IsArray(const WINPR_JSON* item); + WINPR_API BOOL WINPR_JSON_IsObject(const WINPR_JSON* item); + + WINPR_API WINPR_JSON* WINPR_JSON_CreateNull(void); + WINPR_API WINPR_JSON* WINPR_JSON_CreateTrue(void); + WINPR_API WINPR_JSON* WINPR_JSON_CreateFalse(void); + WINPR_API WINPR_JSON* WINPR_JSON_CreateBool(BOOL boolean); + WINPR_API WINPR_JSON* WINPR_JSON_CreateNumber(double num); + WINPR_API WINPR_JSON* WINPR_JSON_CreateString(const char* string); + WINPR_API WINPR_JSON* WINPR_JSON_CreateArray(void); + WINPR_API WINPR_JSON* WINPR_JSON_CreateObject(void); + + WINPR_API WINPR_JSON* WINPR_JSON_AddNullToObject(WINPR_JSON* object, const char* name); + WINPR_API WINPR_JSON* WINPR_JSON_AddTrueToObject(WINPR_JSON* object, const char* name); + WINPR_API WINPR_JSON* WINPR_JSON_AddFalseToObject(WINPR_JSON* object, const char* name); + WINPR_API WINPR_JSON* WINPR_JSON_AddBoolToObject(WINPR_JSON* object, const char* name, + BOOL boolean); + WINPR_API WINPR_JSON* WINPR_JSON_AddNumberToObject(WINPR_JSON* object, const char* name, + double number); + WINPR_API WINPR_JSON* WINPR_JSON_AddStringToObject(WINPR_JSON* object, const char* name, + const char* string); + WINPR_API WINPR_JSON* WINPR_JSON_AddObjectToObject(WINPR_JSON* object, const char* name); + WINPR_API WINPR_JSON* WINPR_JSON_AddArrayToObject(WINPR_JSON* object, const char* name); + + WINPR_API char* WINPR_JSON_Print(WINPR_JSON* item); + WINPR_API char* WINPR_JSON_PrintUnformatted(WINPR_JSON* item); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/winpr/libwinpr/utils/CMakeLists.txt b/winpr/libwinpr/utils/CMakeLists.txt index 91c7353e8..4b5c54aa9 100644 --- a/winpr/libwinpr/utils/CMakeLists.txt +++ b/winpr/libwinpr/utils/CMakeLists.txt @@ -16,6 +16,7 @@ # limitations under the License. include(CheckFunctionExists) +include(CMakeDependentOption) set(CMAKE_INCLUDE_CURRENT_DIR ON) @@ -185,6 +186,42 @@ if (WINPR_HAVE_UNWIND_H) endif() endif() +option(WITH_JSON_DISABLED "Build without any JSON support" OFF) +CMAKE_DEPENDENT_OPTION(WITH_CJSON_REQUIRED "Build with cJSON (fail if not found)" OFF "NOT WITH_JSON_DISABLED" OFF) +CMAKE_DEPENDENT_OPTION(WITH_JSONC_REQUIRED "Build with JSON-C (fail if not found)" OFF "NOT WITH_JSON_DISABLED" OFF) +if (NOT WITH_JSON_DISABLED) + if (WITH_CJSON_REQUIRED) + find_package(cJSON REQUIRED) + else() + find_package(cJSON) + endif() + if (WITH_JSONC_REQUIRED) + find_package(JSONC REQUIRED) + else() + find_package(JSONC) + endif() + + if (JSONC_FOUND AND NOT WITH_CJSON_REQUIRED) + winpr_library_add_private(${JSONC_LIBRARIES}) + winpr_include_directory_add(${JSONC_INCLUDE_DIRS}) + winpr_definition_add(-DWITH_JSONC) + set(WITH_WINPR_JSON ON CACHE INTERNAL "internal") + elseif (CJSON_FOUND) + winpr_library_add_private(${CJSON_LIBRARIES}) + winpr_include_directory_add(${CJSON_INCLUDE_DIRS}) + winpr_definition_add(-DWITH_CJSON) + set(WITH_WINPR_JSON ON CACHE INTERNAL "internal") + else() + set(WITH_WINPR_JSON OFF CACHE INTERNAL "internal") + message("compiling without JSON support. Install cJSON or json-c to enable") + endif() +else() + set(WITH_WINPR_JSON OFF CACHE INTERNAL "internal") + message("forced compile without JSON support. Set -DWITH_JSON_DISABLED=OFF to enable compile time detection") +endif() + +winpr_module_add(json/json.c) + winpr_module_add(${SRCS} ${COLLECTIONS_SRCS} ${WLOG_SRCS} diff --git a/winpr/libwinpr/utils/json/json.c b/winpr/libwinpr/utils/json/json.c new file mode 100644 index 000000000..4c84812c4 --- /dev/null +++ b/winpr/libwinpr/utils/json/json.c @@ -0,0 +1,651 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * JSON parser wrapper + * + * Copyright 2024 Armin Novak + * Copyright 2024 Thincast Technologies GmbH + * + * 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 + +#if defined(WITH_CJSON) +#include +#endif +#if defined(WITH_JSONC) +#include +#endif + +#if defined(WITH_CJSON) +#if CJSON_VERSION_MAJOR == 1 +#if CJSON_VERSION_MINOR <= 7 +#if CJSON_VERSION_PATCH < 13 +#define USE_CJSON_COMPAT +#endif +#endif +#endif +#endif + +#if defined(USE_CJSON_COMPAT) +static double cJSON_GetNumberValue(const cJSON* const prop) +{ +#ifndef NAN +#ifdef _WIN32 +#define NAN sqrt(-1.0) +#define COMPAT_NAN_UNDEF +#else +#define NAN 0.0 / 0.0 +#define COMPAT_NAN_UNDEF +#endif +#endif + + if (!cJSON_IsNumber(prop)) + return NAN; + char* val = cJSON_GetStringValue(prop); + if (!val) + return NAN; + + errno = 0; + char* endptr = NULL; + double dval = strtod(val, &endptr); + if (val == endptr) + return NAN; + if (endptr != NULL) + return NAN; + if (errno != 0) + return NAN; + return dval; + +#ifdef COMPAT_NAN_UNDEF +#undef NAN +#endif +} + +static cJSON* cJSON_ParseWithLength(const char* value, size_t buffer_length) +{ + // Check for string '\0' termination. + const size_t slen = strnlen(value, buffer_length); + if (slen >= buffer_length) + { + if (value[buffer_length] != '\0') + return NULL; + } + return cJSON_Parse(value); +} +#endif + +int WINPR_JSON_version(char* buffer, size_t len) +{ +#if defined(WITH_JSONC) + return _snprintf(buffer, len, "json-c %s", json_c_version()); +#elif defined(WITH_CJSON) + return _snprintf(buffer, len, "cJSON %s", cJSON_Version()); +#else + return _snprintf(buffer, len, "JSON support not available"); +#endif +} + +WINPR_JSON* WINPR_JSON_Parse(const char* value) +{ +#if defined(WITH_JSONC) + return json_tokener_parse(value); +#elif defined(WITH_CJSON) + return cJSON_Parse(value); +#else + WINPR_UNUSED(value); + return NULL; +#endif +} + +WINPR_JSON* WINPR_JSON_ParseWithLength(const char* value, size_t buffer_length) +{ +#if defined(WITH_JSONC) + WINPR_ASSERT(buffer_length <= INT_MAX); + json_tokener* tok = json_tokener_new(); + if (!tok) + return NULL; + json_object* obj = json_tokener_parse_ex(tok, value, (int)buffer_length); + json_tokener_free(tok); + return obj; +#elif defined(WITH_CJSON) + return cJSON_ParseWithLength(value, buffer_length); +#else + WINPR_UNUSED(value); + WINPR_UNUSED(buffer_length); + return NULL; +#endif +} + +void WINPR_JSON_Delete(WINPR_JSON* item) +{ +#if defined(WITH_JSONC) + json_object_put((json_object*)item); +#elif defined(WITH_CJSON) + cJSON_Delete((cJSON*)item); +#else + WINPR_UNUSED(item); +#endif +} + +WINPR_JSON* WINPR_JSON_GetArrayItem(const WINPR_JSON* array, size_t index) +{ +#if defined(WITH_JSONC) + return json_object_array_get_idx((const json_object*)array, index); +#elif defined(WITH_CJSON) + WINPR_ASSERT(index <= INT_MAX); + return cJSON_GetArrayItem((const cJSON*)array, (INT)index); +#else + WINPR_UNUSED(array); + WINPR_UNUSED(index); + return NULL; +#endif +} + +size_t WINPR_JSON_GetArraySize(const WINPR_JSON* array) +{ +#if defined(WITH_JSONC) + return json_object_array_length((const json_object*)array); +#elif defined(WITH_CJSON) + const int rc = cJSON_GetArraySize((const cJSON*)array); + if (rc <= 0) + return 0; + return (size_t)rc; +#else + WINPR_UNUSED(array); + return 0; +#endif +} + +WINPR_JSON* WINPR_JSON_GetObjectItem(const WINPR_JSON* const object, const char* const string) +{ +#if defined(WITH_JSONC) + return json_object_object_get((const json_object*)object, string); +#elif defined(WITH_CJSON) + return cJSON_GetObjectItem((const cJSON*)object, string); +#else + WINPR_UNUSED(object); + WINPR_UNUSED(string); + return NULL; +#endif +} + +WINPR_JSON* WINPR_JSON_GetObjectItemCaseSensitive(const WINPR_JSON* const object, + const char* const string) +{ +#if defined(WITH_JSONC) + return json_object_object_get((const json_object*)object, string); +#elif defined(WITH_CJSON) + return cJSON_GetObjectItemCaseSensitive((const cJSON*)object, string); +#else + WINPR_UNUSED(object); + WINPR_UNUSED(string); + return NULL; +#endif +} + +BOOL WINPR_JSON_HasObjectItem(const WINPR_JSON* object, const char* string) +{ +#if defined(WITH_JSONC) + return json_object_object_get_ex((const json_object*)object, string, NULL); +#elif defined(WITH_CJSON) + return cJSON_HasObjectItem((const cJSON*)object, string); +#else + WINPR_UNUSED(object); + WINPR_UNUSED(string); + return FALSE; +#endif +} + +const char* WINPR_JSON_GetErrorPtr(void) +{ +#if defined(WITH_JSONC) + return json_util_get_last_err(); +#elif defined(WITH_CJSON) + return cJSON_GetErrorPtr(); +#else + return NULL; +#endif +} + +const char* WINPR_JSON_GetStringValue(WINPR_JSON* item) +{ +#if defined(WITH_JSONC) + return json_object_get_string((json_object*)item); +#elif defined(WITH_CJSON) + return cJSON_GetStringValue((cJSON*)item); +#else + WINPR_UNUSED(item); + return NULL; +#endif +} + +double WINPR_JSON_GetNumberValue(const WINPR_JSON* const item) +{ +#if defined(WITH_JSONC) + return json_object_get_double((const json_object*)item); +#elif defined(WITH_CJSON) + return cJSON_GetNumberValue((const cJSON*)item); +#else + WINPR_UNUSED(item); + return nan(NULL); +#endif +} + +BOOL WINPR_JSON_IsInvalid(const WINPR_JSON* const item) +{ +#if defined(WITH_JSONC) + if (WINPR_JSON_IsArray(item)) + return FALSE; + if (WINPR_JSON_IsObject(item)) + return FALSE; + if (WINPR_JSON_IsNull(item)) + return FALSE; + if (WINPR_JSON_IsNumber(item)) + return FALSE; + if (WINPR_JSON_IsBool(item)) + return FALSE; + if (WINPR_JSON_IsString(item)) + return FALSE; + return TRUE; +#elif defined(WITH_CJSON) + return cJSON_IsInvalid((const cJSON*)item); +#else + WINPR_UNUSED(item); + return TRUE; +#endif +} + +BOOL WINPR_JSON_IsFalse(const WINPR_JSON* const item) +{ +#if defined(WITH_JSONC) + if (!json_object_is_type((const json_object*)item, json_type_boolean)) + return FALSE; + json_bool val = json_object_get_boolean((const json_object*)item); + return val == 0; +#elif defined(WITH_CJSON) + return cJSON_IsFalse((const cJSON*)item); +#else + WINPR_UNUSED(item); + return FALSE; +#endif +} + +BOOL WINPR_JSON_IsTrue(const WINPR_JSON* const item) +{ +#if defined(WITH_JSONC) + if (!json_object_is_type((const json_object*)item, json_type_boolean)) + return FALSE; + json_bool val = json_object_get_boolean((const json_object*)item); + return val != 0; +#elif defined(WITH_CJSON) + return cJSON_IsTrue((const cJSON*)item); +#else + WINPR_UNUSED(item); + return FALSE; +#endif +} + +BOOL WINPR_JSON_IsBool(const WINPR_JSON* const item) +{ +#if defined(WITH_JSONC) + return json_object_is_type((const json_object*)item, json_type_boolean); +#elif defined(WITH_CJSON) + return cJSON_IsBool((const cJSON*)item); +#else + WINPR_UNUSED(item); + return FALSE; +#endif +} + +BOOL WINPR_JSON_IsNull(const WINPR_JSON* const item) +{ +#if defined(WITH_JSONC) + return json_object_is_type((const json_object*)item, json_type_null); +#elif defined(WITH_CJSON) + return cJSON_IsNull((const cJSON*)item); +#else + WINPR_UNUSED(item); + return FALSE; +#endif +} + +BOOL WINPR_JSON_IsNumber(const WINPR_JSON* const item) +{ +#if defined(WITH_JSONC) + return json_object_is_type((const json_object*)item, json_type_int) || + json_object_is_type((const json_object*)item, json_type_double); +#elif defined(WITH_CJSON) + return cJSON_IsNumber((const cJSON*)item); +#else + WINPR_UNUSED(item); + return FALSE; +#endif +} + +BOOL WINPR_JSON_IsString(const WINPR_JSON* const item) +{ +#if defined(WITH_JSONC) + return json_object_is_type((const json_object*)item, json_type_string); +#elif defined(WITH_CJSON) + return cJSON_IsString((const cJSON*)item); +#else + WINPR_UNUSED(item); + return FALSE; +#endif +} + +BOOL WINPR_JSON_IsArray(const WINPR_JSON* const item) +{ +#if defined(WITH_JSONC) + return json_object_is_type((const json_object*)item, json_type_array); +#elif defined(WITH_CJSON) + return cJSON_IsArray((const cJSON*)item); +#else + WINPR_UNUSED(item); + return FALSE; +#endif +} + +BOOL WINPR_JSON_IsObject(const WINPR_JSON* const item) +{ +#if defined(WITH_JSONC) + return json_object_is_type((const json_object*)item, json_type_object); +#elif defined(WITH_CJSON) + return cJSON_IsObject((const cJSON*)item); +#else + WINPR_UNUSED(item); + return FALSE; +#endif +} + +WINPR_JSON* WINPR_JSON_CreateNull(void) +{ +#if defined(WITH_JSONC) + return json_object_new_null(); +#elif defined(WITH_CJSON) + return cJSON_CreateNull(); +#else + return NULL; +#endif +} + +WINPR_JSON* WINPR_JSON_CreateTrue(void) +{ +#if defined(WITH_JSONC) + return json_object_new_boolean(TRUE); +#elif defined(WITH_CJSON) + return cJSON_CreateTrue(); +#else + return NULL; +#endif +} + +WINPR_JSON* WINPR_JSON_CreateFalse(void) +{ +#if defined(WITH_JSONC) + return json_object_new_boolean(FALSE); +#elif defined(WITH_CJSON) + return cJSON_CreateFalse(); +#else + return NULL; +#endif +} + +WINPR_JSON* WINPR_JSON_CreateBool(BOOL boolean) +{ +#if defined(WITH_JSONC) + return json_object_new_boolean(boolean); +#elif defined(WITH_CJSON) + return cJSON_CreateBool(boolean); +#else + WINPR_UNUSED(boolean); + return NULL; +#endif +} + +WINPR_JSON* WINPR_JSON_CreateNumber(double num) +{ +#if defined(WITH_JSONC) + return json_object_new_double(num); +#elif defined(WITH_CJSON) + return cJSON_CreateNumber(num); +#else + WINPR_UNUSED(num); + return NULL; +#endif +} + +WINPR_JSON* WINPR_JSON_CreateString(const char* string) +{ +#if defined(WITH_JSONC) + return json_object_new_string(string); +#elif defined(WITH_CJSON) + return cJSON_CreateString(string); +#else + WINPR_UNUSED(string); + return NULL; +#endif +} + +WINPR_JSON* WINPR_JSON_CreateArray(void) +{ +#if defined(WITH_JSONC) + return json_object_new_array(); +#elif defined(WITH_CJSON) + return cJSON_CreateArray(); +#else + return NULL; +#endif +} + +WINPR_JSON* WINPR_JSON_CreateObject(void) +{ +#if defined(WITH_JSONC) + return json_object_new_object(); +#elif defined(WITH_CJSON) + return cJSON_CreateObject(); +#else + return NULL; +#endif +} + +WINPR_JSON* WINPR_JSON_AddNullToObject(WINPR_JSON* const object, const char* const name) +{ +#if defined(WITH_JSONC) + struct json_object* obj = json_object_new_null(); + if (json_object_object_add((json_object*)object, name, obj) != 0) + { + json_object_put(obj); + return NULL; + } + return obj; +#elif defined(WITH_CJSON) + return cJSON_AddNullToObject((cJSON*)object, name); +#else + WINPR_UNUSED(object); + WINPR_UNUSED(name); + return NULL; +#endif +} + +WINPR_JSON* WINPR_JSON_AddTrueToObject(WINPR_JSON* const object, const char* const name) +{ +#if defined(WITH_JSONC) + struct json_object* obj = json_object_new_boolean(TRUE); + if (json_object_object_add((json_object*)object, name, obj) != 0) + { + json_object_put(obj); + return NULL; + } + return obj; +#elif defined(WITH_CJSON) + return cJSON_AddTrueToObject((cJSON*)object, name); +#else + WINPR_UNUSED(object); + WINPR_UNUSED(name); + return NULL; +#endif +} + +WINPR_JSON* WINPR_JSON_AddFalseToObject(WINPR_JSON* const object, const char* const name) +{ +#if defined(WITH_JSONC) + struct json_object* obj = json_object_new_boolean(FALSE); + if (json_object_object_add((json_object*)object, name, obj) != 0) + { + json_object_put(obj); + return NULL; + } + return obj; +#elif defined(WITH_CJSON) + return cJSON_AddFalseToObject((cJSON*)object, name); +#else + WINPR_UNUSED(object); + WINPR_UNUSED(name); + return NULL; +#endif +} + +WINPR_JSON* WINPR_JSON_AddBoolToObject(WINPR_JSON* const object, const char* const name, + BOOL boolean) +{ +#if defined(WITH_JSONC) + struct json_object* obj = json_object_new_boolean(boolean); + if (json_object_object_add((json_object*)object, name, obj) != 0) + { + json_object_put(obj); + return NULL; + } + return obj; +#elif defined(WITH_CJSON) + return cJSON_AddBoolToObject((cJSON*)object, name, boolean); +#else + WINPR_UNUSED(object); + WINPR_UNUSED(name); + WINPR_UNUSED(boolean); + return NULL; +#endif +} + +WINPR_JSON* WINPR_JSON_AddNumberToObject(WINPR_JSON* const object, const char* const name, + double number) +{ +#if defined(WITH_JSONC) + struct json_object* obj = json_object_new_double(number); + if (json_object_object_add((json_object*)object, name, obj) != 0) + { + json_object_put(obj); + return NULL; + } + return obj; +#elif defined(WITH_CJSON) + return cJSON_AddNumberToObject((cJSON*)object, name, number); +#else + WINPR_UNUSED(object); + WINPR_UNUSED(name); + WINPR_UNUSED(number); + return NULL; +#endif +} + +WINPR_JSON* WINPR_JSON_AddStringToObject(WINPR_JSON* const object, const char* const name, + const char* const string) +{ +#if defined(WITH_JSONC) + struct json_object* obj = json_object_new_string(string); + if (json_object_object_add((json_object*)object, name, obj) != 0) + { + json_object_put(obj); + return NULL; + } + return obj; +#elif defined(WITH_CJSON) + return cJSON_AddStringToObject((cJSON*)object, name, string); +#else + WINPR_UNUSED(object); + WINPR_UNUSED(name); + WINPR_UNUSED(string); + return NULL; +#endif +} + +WINPR_JSON* WINPR_JSON_AddObjectToObject(WINPR_JSON* const object, const char* const name) +{ +#if defined(WITH_JSONC) + struct json_object* obj = json_object_new_object(); + if (json_object_object_add((json_object*)object, name, obj) != 0) + { + json_object_put(obj); + return NULL; + } + return obj; +#elif defined(WITH_CJSON) + return cJSON_AddObjectToObject((cJSON*)object, name); +#else + WINPR_UNUSED(object); + WINPR_UNUSED(name); + return NULL; +#endif +} + +WINPR_JSON* WINPR_JSON_AddArrayToObject(WINPR_JSON* const object, const char* const name) +{ +#if defined(WITH_JSONC) + struct json_object* obj = json_object_new_array(); + if (json_object_object_add((json_object*)object, name, obj) != 0) + { + json_object_put(obj); + return NULL; + } + return obj; +#elif defined(WITH_CJSON) + return cJSON_AddArrayToObject((cJSON*)object, name); +#else + WINPR_UNUSED(object); + WINPR_UNUSED(name); + return NULL; +#endif +} + +char* WINPR_JSON_Print(WINPR_JSON* item) +{ +#if defined(WITH_JSONC) + const char* str = json_object_to_json_string_ext((json_object*)item, JSON_C_TO_STRING_PRETTY); + if (!str) + return NULL; + return _strdup(str); +#elif defined(WITH_CJSON) + return cJSON_Print((const cJSON*)item); +#else + WINPR_UNUSED(item); + return NULL; +#endif +} + +char* WINPR_JSON_PrintUnformatted(WINPR_JSON* item) +{ +#if defined(WITH_JSONC) + const char* str = json_object_to_json_string_ext((json_object*)item, JSON_C_TO_STRING_PLAIN); + if (!str) + return NULL; + return _strdup(str); +#elif defined(WITH_CJSON) + return cJSON_PrintUnformatted((const cJSON*)item); +#else + WINPR_UNUSED(item); + return NULL; +#endif +} From aaded541d9b2ce57753c53f69fcbe6edff4fcad0 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Tue, 14 May 2024 17:41:06 +0200 Subject: [PATCH 04/13] [core,client] replace cJSON with WinPR wrapper use the new WinPR JSON wrapper API --- CMakeLists.txt | 5 +- client/SDL/CMakeLists.txt | 6 -- client/SDL/sdl_freerdp.cpp | 3 +- client/SDL/sdl_utils.cpp | 47 ++++++------- libfreerdp/CMakeLists.txt | 25 ++----- libfreerdp/FreeRDPConfig.cmake.in | 4 +- libfreerdp/core/aad.c | 104 ++++++++------------------- libfreerdp/core/aad.h | 16 ----- libfreerdp/core/gateway/arm.c | 113 +++++++++++++++--------------- 9 files changed, 116 insertions(+), 207 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d90c215a0..2ca415cf6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -561,9 +561,6 @@ endif() find_feature(PCSC ${PCSC_FEATURE_TYPE} ${PCSC_FEATURE_PURPOSE} ${PCSC_FEATURE_DESCRIPTION}) -find_package(cJSON) -option(WITH_AAD "Compile with support for Azure AD authentication" ${cJSON_FOUND}) - if (WITH_DSP_FFMPEG OR WITH_VIDEO_FFMPEG OR WITH_FFMPEG) set(FFMPEG_FEATURE_TYPE "REQUIRED" ) endif() @@ -730,6 +727,8 @@ else() include_directories(${WinPR_INCLUDE_DIR}) endif() +option(WITH_AAD "Compile with support for Azure AD authentication" ${WITH_WINPR_JSON}) + # Include directories include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_BINARY_DIR}/include) diff --git a/client/SDL/CMakeLists.txt b/client/SDL/CMakeLists.txt index 0b3aa1bc0..c1bb2881d 100644 --- a/client/SDL/CMakeLists.txt +++ b/client/SDL/CMakeLists.txt @@ -62,14 +62,8 @@ endif() find_package(SDL2 REQUIRED COMPONENTS) include_directories(${SDL2_INCLUDE_DIR}) include_directories(${SDL2_INCLUDE_DIRS}) -find_package(cJSON) set(LIBS "") -if (cJSON_FOUND) - include_directories(${CJSON_INCLUDE_DIRS}) - list(APPEND LIBS ${CJSON_LIBRARIES}) - add_compile_definitions(CJSON_FOUND) -endif() find_package(Threads REQUIRED) diff --git a/client/SDL/sdl_freerdp.cpp b/client/SDL/sdl_freerdp.cpp index b157d3d02..972063dd1 100644 --- a/client/SDL/sdl_freerdp.cpp +++ b/client/SDL/sdl_freerdp.cpp @@ -40,6 +40,7 @@ #include #include +#include #include #include #include @@ -1553,7 +1554,7 @@ static void SDLCALL winpr_LogOutputFunction(void* userdata, int category, SDL_Lo static void print_config_file_help() { -#if defined(CJSON_FOUND) +#if defined(WITH_WINPR_JSON) std::cout << "CONFIGURATION FILE" << std::endl; std::cout << std::endl; std::cout << " The SDL client supports some user defined configuration options." << std::endl; diff --git a/client/SDL/sdl_utils.cpp b/client/SDL/sdl_utils.cpp index c3bd2cf8d..27150e105 100644 --- a/client/SDL/sdl_utils.cpp +++ b/client/SDL/sdl_utils.cpp @@ -36,10 +36,9 @@ namespace fs = std::experimental::filesystem; #include #include +#include #include -#if defined(CJSON_FOUND) -#include -#endif +#include const char* sdl_event_type_str(Uint32 type) { @@ -355,33 +354,33 @@ std::string sdl_window_event_str(Uint8 ev) } } -#if defined(CJSON_FOUND) -using cJSONPtr = std::unique_ptr; +#if defined(WINPR_JSON_FOUND) +using WINPR_JSONPtr = std::unique_ptr; -static cJSONPtr get() +static WINPR_JSONPtr get() { auto config = sdl_get_pref_file(); std::ifstream ifs(config); std::string content((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); - return { cJSON_ParseWithLength(content.c_str(), content.size()), cJSON_Delete }; + return { WINPR_JSON_ParseWithLength(content.c_str(), content.size()), WINPR_JSON_Delete }; } -static cJSON* get_item(const std::string& key) +static WINPR_JSON* get_item(const std::string& key) { - static cJSONPtr config{ nullptr, cJSON_Delete }; + static WINPR_JSONPtr config{ nullptr, WINPR_JSON_Delete }; if (!config) config = get(); if (!config) return nullptr; - return cJSON_GetObjectItem(config.get(), key.c_str()); + return WINPR_JSON_GetObjectItem(config.get(), key.c_str()); } -static std::string item_to_str(cJSON* item, const std::string& fallback = "") +static std::string item_to_str(WINPR_JSON* item, const std::string& fallback = "") { - if (!item || !cJSON_IsString(item)) + if (!item || !WINPR_JSON_IsString(item)) return fallback; - auto str = cJSON_GetStringValue(item); + auto str = WINPR_JSON_GetStringValue(item); if (!str) return {}; return str; @@ -390,7 +389,7 @@ static std::string item_to_str(cJSON* item, const std::string& fallback = "") std::string sdl_get_pref_string(const std::string& key, const std::string& fallback) { -#if defined(CJSON_FOUND) +#if defined(WINPR_JSON_FOUND) auto item = get_item(key); return item_to_str(item, fallback); #else @@ -400,11 +399,11 @@ std::string sdl_get_pref_string(const std::string& key, const std::string& fallb bool sdl_get_pref_bool(const std::string& key, bool fallback) { -#if defined(CJSON_FOUND) +#if defined(WINPR_JSON_FOUND) auto item = get_item(key); - if (!item || !cJSON_IsBool(item)) + if (!item || !WINPR_JSON_IsBool(item)) return fallback; - return cJSON_IsTrue(item); + return WINPR_JSON_IsTrue(item); #else return fallback; #endif @@ -412,11 +411,11 @@ bool sdl_get_pref_bool(const std::string& key, bool fallback) int64_t sdl_get_pref_int(const std::string& key, int64_t fallback) { -#if defined(CJSON_FOUND) +#if defined(WINPR_JSON_FOUND) auto item = get_item(key); - if (!item || !cJSON_IsNumber(item)) + if (!item || !WINPR_JSON_IsNumber(item)) return fallback; - auto val = cJSON_GetNumberValue(item); + auto val = WINPR_JSON_GetNumberValue(item); return static_cast(val); #else return fallback; @@ -426,15 +425,15 @@ int64_t sdl_get_pref_int(const std::string& key, int64_t fallback) std::vector sdl_get_pref_array(const std::string& key, const std::vector& fallback) { -#if defined(CJSON_FOUND) +#if defined(WINPR_JSON_FOUND) auto item = get_item(key); - if (!item || !cJSON_IsArray(item)) + if (!item || !WINPR_JSON_IsArray(item)) return fallback; std::vector values; - for (int x = 0; x < cJSON_GetArraySize(item); x++) + for (int x = 0; x < WINPR_JSON_GetArraySize(item); x++) { - auto cur = cJSON_GetArrayItem(item, x); + auto cur = WINPR_JSON_GetArrayItem(item, x); values.push_back(item_to_str(cur)); } diff --git a/libfreerdp/CMakeLists.txt b/libfreerdp/CMakeLists.txt index 54c9cd1bf..01ac8d892 100644 --- a/libfreerdp/CMakeLists.txt +++ b/libfreerdp/CMakeLists.txt @@ -248,23 +248,9 @@ if(FAAC_FOUND) endif() if (WITH_AAD) - if (NOT cJSON_FOUND) - find_package(PkgConfig REQUIRED) - pkg_check_modules(CJSON libcjson) - endif() - if (NOT CJSON_LIBRARIES OR NOT CJSON_INCLUDE_DIRS) - find_path(CJSON_INCLUDE_DIRS - NAMES cjson/cJSON.h - REQUIRED - ) - find_library(CJSON_LIBRARIES - NAMES cjson - REQUIRED - ) - endif() - - freerdp_library_add(${CJSON_LIBRARIES}) - include_directories(${CJSON_INCLUDE_DIRS}) + if (NOT WITH_WINPR_JSON) + message(FATAL_ERROR "Trying to build -DWITH_AAD=ON but WITH_WINPR_JSON is not defined") + endif() endif() if(WITH_NEON) @@ -424,10 +410,7 @@ set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/libfreerdp") include(pkg-config-install-prefix) set(FREERDP_REQUIRES_PRIVATE "") -if(cJSON_FOUND) - string(APPEND FREERDP_REQUIRES_PRIVATE " libcjson") - list(APPEND FREERDP_PC_PRIVATE_LIBS "-lcjson") -endif() + if(WITH_SMARTCARD_EMULATE) string(APPEND FREERDP_REQUIRES_PRIVATE " zlib") list(APPEND FREERDP_PC_PRIVATE_LIBS "-lz") diff --git a/libfreerdp/FreeRDPConfig.cmake.in b/libfreerdp/FreeRDPConfig.cmake.in index 0052c3d3a..e59bb1df6 100644 --- a/libfreerdp/FreeRDPConfig.cmake.in +++ b/libfreerdp/FreeRDPConfig.cmake.in @@ -1,8 +1,6 @@ include(CMakeFindDependencyMacro) find_dependency(WinPR @FREERDP_VERSION@) -if("@cJSON_FOUND@" AND NOT "@BUILD_SHARED_LIBS@") - find_dependency(cJSON) -endif() + if("@WITH_SMARTCARD_EMULATE@" AND NOT "@BUILD_SHARED_LIBS@") find_dependency(ZLIB) endif() diff --git a/libfreerdp/core/aad.c b/libfreerdp/core/aad.c index 00593a039..6f946230d 100644 --- a/libfreerdp/core/aad.c +++ b/libfreerdp/core/aad.c @@ -29,6 +29,7 @@ #include #include +#include #include "transport.h" @@ -78,18 +79,18 @@ static SSIZE_T stream_sprintf(wStream* s, WINPR_FORMAT_ARG const char* fmt, ...) return rc2; } -static BOOL json_get_object(wLog* wlog, cJSON* json, const char* key, cJSON** obj) +static BOOL json_get_object(wLog* wlog, WINPR_JSON* json, const char* key, WINPR_JSON** obj) { WINPR_ASSERT(json); WINPR_ASSERT(key); - if (!cJSON_HasObjectItem(json, key)) + if (!WINPR_JSON_HasObjectItem(json, key)) { WLog_Print(wlog, WLOG_ERROR, "[json] does not contain a key '%s'", key); return FALSE; } - cJSON* prop = cJSON_GetObjectItem(json, key); + WINPR_JSON* prop = WINPR_JSON_GetObjectItem(json, key); if (!prop) { WLog_Print(wlog, WLOG_ERROR, "[json] object for key '%s' is NULL", key); @@ -99,80 +100,45 @@ static BOOL json_get_object(wLog* wlog, cJSON* json, const char* key, cJSON** ob return TRUE; } -#if defined(USE_CJSON_COMPAT) -static double cJSON_GetNumberValue(const cJSON* const prop) -{ -#ifndef NAN -#ifdef _WIN32 -#define NAN sqrt(-1.0) -#define COMPAT_NAN_UNDEF -#else -#define NAN 0.0 / 0.0 -#define COMPAT_NAN_UNDEF -#endif -#endif - - if (!cJSON_IsNumber(prop)) - return NAN; - char* val = cJSON_GetStringValue(prop); - if (!val) - return NAN; - - errno = 0; - char* endptr = NULL; - double dval = strtod(val, &endptr); - if (val == endptr) - return NAN; - if (endptr != NULL) - return NAN; - if (errno != 0) - return NAN; - return dval; - -#ifdef COMPAT_NAN_UNDEF -#undef NAN -#endif -} -#endif - -static BOOL json_get_number(wLog* wlog, cJSON* json, const char* key, double* result) +static BOOL json_get_number(wLog* wlog, WINPR_JSON* json, const char* key, double* result) { BOOL rc = FALSE; - cJSON* prop = NULL; + WINPR_JSON* prop = NULL; if (!json_get_object(wlog, json, key, &prop)) return FALSE; - if (!cJSON_IsNumber(prop)) + if (!WINPR_JSON_IsNumber(prop)) { WLog_Print(wlog, WLOG_ERROR, "[json] object for key '%s' is NOT a NUMBER", key); goto fail; } - *result = cJSON_GetNumberValue(prop); + *result = WINPR_JSON_GetNumberValue(prop); rc = TRUE; fail: return rc; } -static BOOL json_get_const_string(wLog* wlog, cJSON* json, const char* key, const char** result) +static BOOL json_get_const_string(wLog* wlog, WINPR_JSON* json, const char* key, + const char** result) { BOOL rc = FALSE; WINPR_ASSERT(result); *result = NULL; - cJSON* prop = NULL; + WINPR_JSON* prop = NULL; if (!json_get_object(wlog, json, key, &prop)) return FALSE; - if (!cJSON_IsString(prop)) + if (!WINPR_JSON_IsString(prop)) { WLog_Print(wlog, WLOG_ERROR, "[json] object for key '%s' is NOT a STRING", key); goto fail; } - const char* str = cJSON_GetStringValue(prop); + const char* str = WINPR_JSON_GetStringValue(prop); if (!str) WLog_Print(wlog, WLOG_ERROR, "[json] object for key '%s' is NULL", key); *result = str; @@ -182,7 +148,7 @@ fail: return rc; } -static BOOL json_get_string_alloc(wLog* wlog, cJSON* json, const char* key, char** result) +static BOOL json_get_string_alloc(wLog* wlog, WINPR_JSON* json, const char* key, char** result) { const char* str = NULL; if (!json_get_const_string(wlog, json, key, &str)) @@ -194,20 +160,6 @@ static BOOL json_get_string_alloc(wLog* wlog, cJSON* json, const char* key, char return *result != NULL; } -#if defined(USE_CJSON_COMPAT) -cJSON* cJSON_ParseWithLength(const char* value, size_t buffer_length) -{ - // Check for string '\0' termination. - const size_t slen = strnlen(value, buffer_length); - if (slen >= buffer_length) - { - if (value[buffer_length] != '\0') - return NULL; - } - return cJSON_Parse(value); -} -#endif - static INLINE const char* aad_auth_result_to_string(DWORD code) { #define ERROR_CASE(cd, x) \ @@ -232,7 +184,7 @@ static BOOL aad_get_nonce(rdpAad* aad) BYTE* response = NULL; long resp_code = 0; size_t response_length = 0; - cJSON* json = NULL; + WINPR_JSON* json = NULL; if (!freerdp_http_request("https://login.microsoftonline.com/common/oauth2/v2.0/token", "grant_type=srv_challenge", &resp_code, &response, &response_length)) @@ -250,7 +202,7 @@ static BOOL aad_get_nonce(rdpAad* aad) goto fail; } - json = cJSON_ParseWithLength((const char*)response, response_length); + json = WINPR_JSON_ParseWithLength((const char*)response, response_length); if (!json) { WLog_Print(aad->log, WLOG_ERROR, "Failed to parse nonce response"); @@ -264,7 +216,7 @@ static BOOL aad_get_nonce(rdpAad* aad) fail: free(response); - cJSON_Delete(json); + WINPR_JSON_Delete(json); return ret; } @@ -536,12 +488,12 @@ static int aad_parse_state_initial(rdpAad* aad, wStream* s) const size_t jlen = Stream_GetRemainingLength(s); const char* ts_nonce = NULL; int ret = -1; - cJSON* json = NULL; + WINPR_JSON* json = NULL; if (!Stream_SafeSeek(s, jlen)) goto fail; - json = cJSON_ParseWithLength(jstr, jlen); + json = WINPR_JSON_ParseWithLength(jstr, jlen); if (!json) goto fail; @@ -550,7 +502,7 @@ static int aad_parse_state_initial(rdpAad* aad, wStream* s) ret = aad_send_auth_request(aad, ts_nonce); fail: - cJSON_Delete(json); + WINPR_JSON_Delete(json); return ret; } @@ -559,14 +511,14 @@ static int aad_parse_state_auth(rdpAad* aad, wStream* s) int rc = -1; double result = 0; DWORD error_code = 0; - cJSON* json = NULL; + WINPR_JSON* 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); + json = WINPR_JSON_ParseWithLength(jstr, jlength); if (!json) goto fail; @@ -583,7 +535,7 @@ static int aad_parse_state_auth(rdpAad* aad, wStream* s) aad->state = AAD_STATE_FINAL; rc = 1; fail: - cJSON_Delete(json); + WINPR_JSON_Delete(json); return rc; } @@ -846,10 +798,10 @@ BOOL aad_is_supported(void) char* freerdp_utils_aad_get_access_token(wLog* log, const char* data, size_t length) { char* token = NULL; - cJSON* access_token_prop = NULL; + WINPR_JSON* access_token_prop = NULL; const char* access_token_str = NULL; - cJSON* json = cJSON_ParseWithLength(data, length); + WINPR_JSON* json = WINPR_JSON_ParseWithLength(data, length); if (!json) { WLog_Print(log, WLOG_ERROR, "Failed to parse access token response [got %" PRIuz " bytes", @@ -857,14 +809,14 @@ char* freerdp_utils_aad_get_access_token(wLog* log, const char* data, size_t len goto cleanup; } - access_token_prop = cJSON_GetObjectItem(json, "access_token"); + access_token_prop = WINPR_JSON_GetObjectItem(json, "access_token"); if (!access_token_prop) { WLog_Print(log, WLOG_ERROR, "Response has no \"access_token\" property"); goto cleanup; } - access_token_str = cJSON_GetStringValue(access_token_prop); + access_token_str = WINPR_JSON_GetStringValue(access_token_prop); if (!access_token_str) { WLog_Print(log, WLOG_ERROR, "Invalid value for \"access_token\""); @@ -874,7 +826,7 @@ char* freerdp_utils_aad_get_access_token(wLog* log, const char* data, size_t len token = _strdup(access_token_str); cleanup: - cJSON_Delete(json); + WINPR_JSON_Delete(json); return token; } #endif diff --git a/libfreerdp/core/aad.h b/libfreerdp/core/aad.h index 3b93e6688..797043ced 100644 --- a/libfreerdp/core/aad.h +++ b/libfreerdp/core/aad.h @@ -32,18 +32,6 @@ typedef enum #include #include -#ifdef WITH_AAD -#include - -#if CJSON_VERSION_MAJOR == 1 -#if CJSON_VERSION_MINOR <= 7 -#if CJSON_VERSION_PATCH < 13 -#define USE_CJSON_COMPAT -#endif -#endif -#endif -#endif - FREERDP_LOCAL BOOL aad_is_supported(void); FREERDP_LOCAL int aad_client_begin(rdpAad* aad); @@ -56,8 +44,4 @@ FREERDP_LOCAL void aad_free(rdpAad* aad); WINPR_ATTR_MALLOC(aad_free, 1) FREERDP_LOCAL rdpAad* aad_new(rdpContext* context, rdpTransport* transport); -#if defined(USE_CJSON_COMPAT) -FREERDP_API cJSON* cJSON_ParseWithLength(const char* value, size_t buffer_length); -#endif - #endif /* FREERDP_LIB_CORE_AAD_H */ diff --git a/libfreerdp/core/gateway/arm.c b/libfreerdp/core/gateway/arm.c index d506c7595..c2785ab7b 100644 --- a/libfreerdp/core/gateway/arm.c +++ b/libfreerdp/core/gateway/arm.c @@ -53,10 +53,7 @@ #include "../utils.h" #include "../redirection.h" -//#define WITH_AAD -#ifdef WITH_AAD -#include -#endif +#include #include @@ -296,10 +293,10 @@ static char* arm_create_request_json(rdpArm* arm) WINPR_ASSERT(arm); - cJSON* json = cJSON_CreateObject(); + WINPR_JSON* json = WINPR_JSON_CreateObject(); if (!json) goto arm_create_cleanup; - cJSON_AddStringToObject( + WINPR_JSON_AddStringToObject( json, "application", freerdp_settings_get_string(arm->context->settings, FreeRDP_RemoteApplicationProgram)); @@ -313,14 +310,14 @@ static char* arm_create_request_json(rdpArm* arm) freerdp_settings_get_uint32(arm->context->settings, FreeRDP_LoadBalanceInfoLength); memcpy(lbi, freerdp_settings_get_pointer(arm->context->settings, FreeRDP_LoadBalanceInfo), len); - cJSON_AddStringToObject(json, "loadBalanceInfo", lbi); - cJSON_AddNullToObject(json, "LogonToken"); - cJSON_AddNullToObject(json, "gatewayLoadBalancerToken"); + WINPR_JSON_AddStringToObject(json, "loadBalanceInfo", lbi); + WINPR_JSON_AddNullToObject(json, "LogonToken"); + WINPR_JSON_AddNullToObject(json, "gatewayLoadBalancerToken"); - message = cJSON_PrintUnformatted(json); + message = WINPR_JSON_PrintUnformatted(json); arm_create_cleanup: if (json) - cJSON_Delete(json); + WINPR_JSON_Delete(json); free(lbi); return message; } @@ -529,17 +526,17 @@ out: * base64.b64decode( base64.b64decode(input).decode('utf-16') ) * in python */ -static BOOL arm_pick_base64Utf16Field(const cJSON* json, const char* name, BYTE** poutput, +static BOOL arm_pick_base64Utf16Field(const WINPR_JSON* json, const char* name, BYTE** poutput, size_t* plen) { *poutput = NULL; *plen = 0; - const cJSON* node = cJSON_GetObjectItemCaseSensitive(json, name); - if (!node || !cJSON_IsString(node)) + WINPR_JSON* node = WINPR_JSON_GetObjectItemCaseSensitive(json, name); + if (!node || !WINPR_JSON_IsString(node)) return TRUE; - char* nodeValue = cJSON_GetStringValue(node); + const char* nodeValue = WINPR_JSON_GetStringValue(node); if (!nodeValue) return TRUE; @@ -600,27 +597,27 @@ static BOOL arm_pick_base64Utf16Field(const cJSON* json, const char* name, BYTE* static BOOL arm_treat_azureInstanceNetworkMetadata(const char* metadata, rdpSettings* settings) { BOOL ret = FALSE; - cJSON* json = cJSON_Parse(metadata); + WINPR_JSON* json = WINPR_JSON_Parse(metadata); if (!json) { WLog_ERR(TAG, "invalid azureInstanceNetworkMetadata"); return FALSE; } - const cJSON* iface = cJSON_GetObjectItem(json, "interface"); + WINPR_JSON* iface = WINPR_JSON_GetObjectItem(json, "interface"); if (!iface) { ret = TRUE; goto out; } - if (!cJSON_IsArray(iface)) + if (!WINPR_JSON_IsArray(iface)) { WLog_ERR(TAG, "expecting interface to be an Array"); goto out; } - int interfaceSz = cJSON_GetArraySize(iface); + size_t interfaceSz = WINPR_JSON_GetArraySize(iface); if (interfaceSz == 0) { WLog_WARN(TAG, "no addresses in azure instance metadata"); @@ -628,32 +625,32 @@ static BOOL arm_treat_azureInstanceNetworkMetadata(const char* metadata, rdpSett goto out; } - for (int i = 0; i < interfaceSz; i++) + for (size_t i = 0; i < interfaceSz; i++) { - const cJSON* interN = cJSON_GetArrayItem(iface, i); + WINPR_JSON* interN = WINPR_JSON_GetArrayItem(iface, i); if (!interN) continue; - const cJSON* ipv4 = cJSON_GetObjectItem(interN, "ipv4"); + WINPR_JSON* ipv4 = WINPR_JSON_GetObjectItem(interN, "ipv4"); if (!ipv4) continue; - const cJSON* ipAddress = cJSON_GetObjectItem(ipv4, "ipAddress"); - if (!ipAddress || !cJSON_IsArray(ipAddress)) + WINPR_JSON* ipAddress = WINPR_JSON_GetObjectItem(ipv4, "ipAddress"); + if (!ipAddress || !WINPR_JSON_IsArray(ipAddress)) continue; - int naddresses = cJSON_GetArraySize(ipAddress); - for (int j = 0; j < naddresses; j++) + size_t naddresses = WINPR_JSON_GetArraySize(ipAddress); + for (size_t j = 0; j < naddresses; j++) { - const cJSON* adressN = cJSON_GetArrayItem(ipAddress, j); + WINPR_JSON* adressN = WINPR_JSON_GetArrayItem(ipAddress, j); if (!adressN) continue; - const cJSON* publicIpNode = cJSON_GetObjectItem(adressN, "publicIpAddress"); - if (!publicIpNode || !cJSON_IsString(publicIpNode)) + WINPR_JSON* publicIpNode = WINPR_JSON_GetObjectItem(adressN, "publicIpAddress"); + if (!publicIpNode || !WINPR_JSON_IsString(publicIpNode)) continue; - char* publicIp = cJSON_GetStringValue(publicIpNode); + const char* publicIp = WINPR_JSON_GetStringValue(publicIpNode); if (publicIp && strlen(publicIp) && freerdp_settings_set_string(settings, FreeRDP_RedirectionTargetFQDN, publicIp)) { @@ -667,11 +664,11 @@ static BOOL arm_treat_azureInstanceNetworkMetadata(const char* metadata, rdpSett ret = TRUE; out: - cJSON_Delete(json); + WINPR_JSON_Delete(json); return ret; } -static BOOL arm_fill_rdstls(rdpArm* arm, rdpSettings* settings, const cJSON* json) +static BOOL arm_fill_rdstls(rdpArm* arm, rdpSettings* settings, const WINPR_JSON* json) { BOOL ret = TRUE; BYTE* cert = NULL; @@ -681,12 +678,12 @@ static BOOL arm_fill_rdstls(rdpArm* arm, rdpSettings* settings, const cJSON* jso do { /* redirectedAuthGuid */ - const cJSON* redirectedAuthGuidNode = - cJSON_GetObjectItemCaseSensitive(json, "redirectedAuthGuid"); - if (!redirectedAuthGuidNode || !cJSON_IsString(redirectedAuthGuidNode)) + WINPR_JSON* redirectedAuthGuidNode = + WINPR_JSON_GetObjectItemCaseSensitive(json, "redirectedAuthGuid"); + if (!redirectedAuthGuidNode || !WINPR_JSON_IsString(redirectedAuthGuidNode)) break; - char* redirectedAuthGuid = cJSON_GetStringValue(redirectedAuthGuidNode); + const char* redirectedAuthGuid = WINPR_JSON_GetStringValue(redirectedAuthGuidNode); if (!redirectedAuthGuid) break; @@ -750,34 +747,35 @@ static BOOL arm_fill_gateway_parameters(rdpArm* arm, const char* message, size_t WINPR_ASSERT(arm->context); WINPR_ASSERT(message); - cJSON* json = cJSON_ParseWithLength(message, len); + WINPR_JSON* json = WINPR_JSON_ParseWithLength(message, len); BOOL status = FALSE; if (!json) return FALSE; rdpSettings* settings = arm->context->settings; - const cJSON* gwurl = cJSON_GetObjectItemCaseSensitive(json, "gatewayLocation"); - if (cJSON_IsString(gwurl) && (gwurl->valuestring != NULL)) + WINPR_JSON* gwurl = WINPR_JSON_GetObjectItemCaseSensitive(json, "gatewayLocation"); + const char* gwurlstr = WINPR_JSON_GetStringValue(gwurl); + if (gwurlstr != NULL) { - WLog_DBG(TAG, "extracted target url %s", gwurl->valuestring); - if (!freerdp_settings_set_string(settings, FreeRDP_GatewayUrl, gwurl->valuestring)) + WLog_DBG(TAG, "extracted target url %s", gwurlstr); + if (!freerdp_settings_set_string(settings, FreeRDP_GatewayUrl, gwurlstr)) status = FALSE; else status = TRUE; } - const cJSON* serverNameNode = cJSON_GetObjectItem(json, "redirectedServerName"); + WINPR_JSON* serverNameNode = WINPR_JSON_GetObjectItem(json, "redirectedServerName"); if (serverNameNode) { - char* serverName = cJSON_GetStringValue(serverNameNode); + const char* serverName = WINPR_JSON_GetStringValue(serverNameNode); if (serverName) status = freerdp_settings_set_string(settings, FreeRDP_ServerHostname, serverName); } - const cJSON* azureMeta = cJSON_GetObjectItem(json, "azureInstanceNetworkMetadata"); - if (azureMeta && cJSON_IsString(azureMeta)) + WINPR_JSON* azureMeta = WINPR_JSON_GetObjectItem(json, "azureInstanceNetworkMetadata"); + if (azureMeta && WINPR_JSON_IsString(azureMeta)) { - if (!arm_treat_azureInstanceNetworkMetadata(cJSON_GetStringValue(azureMeta), settings)) + if (!arm_treat_azureInstanceNetworkMetadata(WINPR_JSON_GetStringValue(azureMeta), settings)) { WLog_ERR(TAG, "error when treating azureInstanceNetworkMetadata"); } @@ -791,7 +789,7 @@ static BOOL arm_fill_gateway_parameters(rdpArm* arm, const char* message, size_t status = arm_fill_rdstls(arm, settings, json); } - cJSON_Delete(json); + WINPR_JSON_Delete(json); return status; } @@ -822,10 +820,10 @@ static BOOL arm_handle_bad_request(rdpArm* arm, const HttpResponse* response, BO WLog_DBG(TAG, "Got HTTP Response data: %s", msg); - cJSON* json = cJSON_ParseWithLength(msg, len); + WINPR_JSON* json = WINPR_JSON_ParseWithLength(msg, len); if (json == NULL) { - const char* error_ptr = cJSON_GetErrorPtr(); + const char* error_ptr = WINPR_JSON_GetErrorPtr(); if (error_ptr != NULL) { WLog_ERR(TAG, "NullPoException: %s", error_ptr); @@ -833,23 +831,24 @@ static BOOL arm_handle_bad_request(rdpArm* arm, const HttpResponse* response, BO } } - const cJSON* gateway_code_str = cJSON_GetObjectItemCaseSensitive(json, "Code"); - if (!cJSON_IsString(gateway_code_str) || (gateway_code_str->valuestring == NULL)) + WINPR_JSON* gateway_code_obj = WINPR_JSON_GetObjectItemCaseSensitive(json, "Code"); + const char* gw_code_str = WINPR_JSON_GetStringValue(gateway_code_obj); + if (gw_code_str == NULL) { WLog_ERR(TAG, "Response has no \"Code\" property"); http_response_log_error_status(WLog_Get(TAG), WLOG_ERROR, response); goto fail; } - if (strcmp(gateway_code_str->valuestring, "E_PROXY_ORCHESTRATION_LB_SESSIONHOST_DEALLOCATED") == - 0) + if (strcmp(gw_code_str, "E_PROXY_ORCHESTRATION_LB_SESSIONHOST_DEALLOCATED") == 0) { *retry = TRUE; - const cJSON* message = cJSON_GetObjectItemCaseSensitive(json, "Message"); - if (!cJSON_IsString(message) || !message->valuestring) + WINPR_JSON* message = WINPR_JSON_GetObjectItemCaseSensitive(json, "Message"); + const char* msgstr = WINPR_JSON_GetStringValue(message); + if (!msgstr) WLog_WARN(TAG, "Starting your VM. It may take up to 5 minutes"); else - WLog_WARN(TAG, "%s", message->valuestring); + WLog_WARN(TAG, "%s", msgstr); } else { @@ -859,7 +858,7 @@ static BOOL arm_handle_bad_request(rdpArm* arm, const HttpResponse* response, BO rc = TRUE; fail: - cJSON_Delete(json); + WINPR_JSON_Delete(json); return rc; } From 8bdf92ca52ac0fcc40ab060a207185f43a27414a Mon Sep 17 00:00:00 2001 From: akallabeth Date: Tue, 14 May 2024 19:57:12 +0200 Subject: [PATCH 05/13] [utils] link m library if required --- libfreerdp/utils/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libfreerdp/utils/CMakeLists.txt b/libfreerdp/utils/CMakeLists.txt index d644837a8..2102501ae 100644 --- a/libfreerdp/utils/CMakeLists.txt +++ b/libfreerdp/utils/CMakeLists.txt @@ -47,6 +47,12 @@ if(WIN32) freerdp_library_add(cfgmgr32) endif() +CHECK_LIBRARY_EXISTS(m pow "" HAVE_LIB_M) + +if (HAVE_LIB_M) + freerdp_library_add(m) +endif() + if(BUILD_TESTING) add_subdirectory(test) endif() From de49d320046034a9947bfe60315ad78ecfd5a573 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Tue, 14 May 2024 20:56:53 +0200 Subject: [PATCH 06/13] [cmake] fallback detection for cJSON --- winpr/libwinpr/utils/CMakeLists.txt | 108 +++++++++++++++++----------- 1 file changed, 66 insertions(+), 42 deletions(-) diff --git a/winpr/libwinpr/utils/CMakeLists.txt b/winpr/libwinpr/utils/CMakeLists.txt index 4b5c54aa9..e81e58ca2 100644 --- a/winpr/libwinpr/utils/CMakeLists.txt +++ b/winpr/libwinpr/utils/CMakeLists.txt @@ -22,20 +22,20 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) option(WITH_LODEPNG "build WinPR with PNG support" OFF) if (WITH_LODEPNG) - find_package(lodepng REQUIRED) + find_package(lodepng REQUIRED) - winpr_definition_add(-DWITH_LODEPNG) - set(WINPR_WITH_PNG ON CACHE BOOL "build cache") + winpr_definition_add(-DWITH_LODEPNG) + set(WINPR_WITH_PNG ON CACHE BOOL "build cache") - winpr_include_directory_add(${lodepng_INCLUDE_DIRS}) - winpr_library_add_private(${lodepng_LIBRARIES}) + winpr_include_directory_add(${lodepng_INCLUDE_DIRS}) + winpr_library_add_private(${lodepng_LIBRARIES}) endif() option(WINPR_UTILS_IMAGE_PNG "Add PNG <--> BMP conversion support to clipboard" OFF) if (WINPR_UTILS_IMAGE_PNG) find_package(PNG REQUIRED) - set(WINPR_WITH_PNG ON CACHE BOOL "build cache") + set(WINPR_WITH_PNG ON CACHE BOOL "build cache") winpr_include_directory_add(${PNG_INCLUDE_DIRS}) winpr_library_add_private(${PNG_LIBRARIES}) endif() @@ -51,11 +51,11 @@ endif() option(WINPR_UTILS_IMAGE_JPEG "Add Jpeg <--> BMP conversion support to clipboard" OFF) if (WINPR_UTILS_IMAGE_JPEG) - find_package(PkgConfig REQUIRED) - pkg_check_modules(JPEG libjpeg REQUIRED) + find_package(PkgConfig REQUIRED) + pkg_check_modules(JPEG libjpeg REQUIRED) - winpr_include_directory_add(${JPEG_INCLUDE_DIRS}) - winpr_library_add_private(${JPEG_LIBRARIES}) + winpr_include_directory_add(${JPEG_INCLUDE_DIRS}) + winpr_library_add_private(${JPEG_LIBRARIES}) endif() @@ -64,7 +64,7 @@ set(COLLECTIONS_SRCS collections/Queue.c collections/Stack.c collections/PubSub.c - collections/BitStream.c + collections/BitStream.c collections/ArrayList.c collections/LinkedList.c collections/HashTable.c @@ -86,16 +86,16 @@ endif() find_package(libsystemd) option(WITH_SYSTEMD "allows to export wLog to systemd journal" ${libsystemd_FOUND}) if(WITH_LIBSYSTEMD) - find_package(libsystemd REQUIRED) - set(WINPR_HAVE_JOURNALD_H TRUE) - set(JOURNALD_SRCS + find_package(libsystemd REQUIRED) + set(WINPR_HAVE_JOURNALD_H TRUE) + set(JOURNALD_SRCS wlog/JournaldAppender.c wlog/JournaldAppender.h - ) + ) winpr_include_directory_add(${LIBSYSTEMD_INCLUDE_DIR}) winpr_library_add_private(${LIBSYSTEMD_LIBRARY}) else() - unset(WINPR_HAVE_JOURNALD_H) + unset(WINPR_HAVE_JOURNALD_H) endif() set(WLOG_SRCS @@ -148,52 +148,76 @@ set(SRCS if (ANDROID) list(APPEND SRCS android.h android.c) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) - if (NOT WINPR_HAVE_UNWIND_H) - message("[backtrace] android NDK without unwind.h, falling back to corkscrew") - set(WINPR_HAVE_CORKSCREW 1) - endif() + if (NOT WINPR_HAVE_UNWIND_H) + message("[backtrace] android NDK without unwind.h, falling back to corkscrew") + set(WINPR_HAVE_CORKSCREW 1) + endif() endif() if (WINPR_HAVE_CORKSCREW) - list(APPEND SRCS - corkscrew/debug.c - corkscrew/debug.h) + list(APPEND SRCS + corkscrew/debug.c + corkscrew/debug.h) endif() if (WIN32) - list(APPEND SRCS - windows/debug.c - windows/debug.h) + list(APPEND SRCS + windows/debug.c + windows/debug.h) endif() if (WINPR_HAVE_EXECINFO_H) - option(USE_EXECINFO "Use execinfo.h to generate backtraces" ON) - if (USE_EXECINFO) - winpr_definition_add(-DUSE_EXECINFO) - list(APPEND SRCS - execinfo/debug.c - execinfo/debug.h) - endif() + option(USE_EXECINFO "Use execinfo.h to generate backtraces" ON) + if (USE_EXECINFO) + winpr_definition_add(-DUSE_EXECINFO) + list(APPEND SRCS + execinfo/debug.c + execinfo/debug.h) + endif() endif() if (WINPR_HAVE_UNWIND_H) - option(USE_UNWIND "Use unwind.h to generate backtraces" ON) - if (USE_UNWIND) - winpr_definition_add(-DUSE_UNWIND) - list(APPEND SRCS - unwind/debug.c - unwind/debug.h) - endif() + option(USE_UNWIND "Use unwind.h to generate backtraces" ON) + if (USE_UNWIND) + winpr_definition_add(-DUSE_UNWIND) + list(APPEND SRCS + unwind/debug.c + unwind/debug.h) + endif() endif() option(WITH_JSON_DISABLED "Build without any JSON support" OFF) CMAKE_DEPENDENT_OPTION(WITH_CJSON_REQUIRED "Build with cJSON (fail if not found)" OFF "NOT WITH_JSON_DISABLED" OFF) CMAKE_DEPENDENT_OPTION(WITH_JSONC_REQUIRED "Build with JSON-C (fail if not found)" OFF "NOT WITH_JSON_DISABLED" OFF) if (NOT WITH_JSON_DISABLED) + find_package(cJSON) + + # Fallback detection: + # older ubuntu releases did not ship CMake or pkg-config files + # for cJSON. Be optimistic and try pkg-config and as last resort + # try manual detection + if (NOT cJSON_FOUND) + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_check_modules(CJSON libcjson) + endif() + + if (NOT CJSON_LIBRARIES OR NOT CJSON_INCLUDE_DIRS) + find_path(CJSON_INCLUDE_DIRS + NAMES cjson/cJSON.h + ) + find_library(CJSON_LIBRARIES + NAMES cjson + ) + endif() + endif() + if (WITH_CJSON_REQUIRED) - find_package(cJSON REQUIRED) + if (NOT CJSON_FOUND) + message(FATAL_ERROR "cJSON was requested but not found") + endif() else() - find_package(cJSON) + endif() if (WITH_JSONC_REQUIRED) find_package(JSONC REQUIRED) From 4bdc9ad9503785634b6d14548756b61d1afdaf08 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 15 May 2024 11:37:38 +0200 Subject: [PATCH 07/13] [winpr,utils] fix cJSON fallback detection --- winpr/libwinpr/utils/CMakeLists.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/winpr/libwinpr/utils/CMakeLists.txt b/winpr/libwinpr/utils/CMakeLists.txt index e81e58ca2..17f96905c 100644 --- a/winpr/libwinpr/utils/CMakeLists.txt +++ b/winpr/libwinpr/utils/CMakeLists.txt @@ -196,7 +196,7 @@ if (NOT WITH_JSON_DISABLED) # older ubuntu releases did not ship CMake or pkg-config files # for cJSON. Be optimistic and try pkg-config and as last resort # try manual detection - if (NOT cJSON_FOUND) + if (NOT CJSON_FOUND) find_package(PkgConfig) if (PKG_CONFIG_FOUND) pkg_check_modules(CJSON libcjson) @@ -209,6 +209,9 @@ if (NOT WITH_JSON_DISABLED) find_library(CJSON_LIBRARIES NAMES cjson ) + if (NOT "${CJSON_LIBRARIES}" EQUAL "CJSON_LIBRARIES-NOTFOUND" AND NOT "${CJSON_INCLUDE_DIRS}" EQUAL "CJSON_INCLUDE_DIRS-NOTFOUND") + set(CJSON_FOUND ON) + endif() endif() endif() @@ -216,9 +219,8 @@ if (NOT WITH_JSON_DISABLED) if (NOT CJSON_FOUND) message(FATAL_ERROR "cJSON was requested but not found") endif() - else() - endif() + if (WITH_JSONC_REQUIRED) find_package(JSONC REQUIRED) else() From 702acc93c6b0e9e825c3e0b48713dedd55d92678 Mon Sep 17 00:00:00 2001 From: Ondrej Holy Date: Fri, 26 Apr 2024 10:37:48 +0200 Subject: [PATCH 08/13] [client,sdl] remove duplicated include statement --- client/SDL/sdl_utils.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/SDL/sdl_utils.hpp b/client/SDL/sdl_utils.hpp index 75cb4615a..48a150d8e 100644 --- a/client/SDL/sdl_utils.hpp +++ b/client/SDL/sdl_utils.hpp @@ -19,8 +19,6 @@ #pragma once -#include - #include #include From 9aca06e0b7916cd54fbc7a652e91c808330f081a Mon Sep 17 00:00:00 2001 From: Ondrej Holy Date: Tue, 7 May 2024 09:19:54 +0200 Subject: [PATCH 09/13] [core,gateway] always return in case of error Currently, the `arm_handle_bad_request` function returns `FALSE` when the `cJSON_ParseWithLength` function fails to parse the message, but only when the `cJSON_GetErrorPtr` returns a valid pointer. It would be better to return regardless of the `cJSON_GetErrorPtr` return value. --- libfreerdp/core/gateway/arm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libfreerdp/core/gateway/arm.c b/libfreerdp/core/gateway/arm.c index c2785ab7b..0dc7b925d 100644 --- a/libfreerdp/core/gateway/arm.c +++ b/libfreerdp/core/gateway/arm.c @@ -825,10 +825,9 @@ static BOOL arm_handle_bad_request(rdpArm* arm, const HttpResponse* response, BO { const char* error_ptr = WINPR_JSON_GetErrorPtr(); if (error_ptr != NULL) - { WLog_ERR(TAG, "NullPoException: %s", error_ptr); - return FALSE; - } + + return FALSE; } WINPR_JSON* gateway_code_obj = WINPR_JSON_GetObjectItemCaseSensitive(json, "Code"); From 15c78a27f25d325a6b3f2220c4fd5724048b9517 Mon Sep 17 00:00:00 2001 From: Ondrej Holy Date: Wed, 15 May 2024 15:31:22 +0200 Subject: [PATCH 10/13] [cmake] really use pkg_check_modules results for json-c Although, the `pkg_check_modules` function is used when finding the json-c library, the results are never used. Let's add the `HINTS` params for the `find_path` and `find_library` functions. --- cmake/FindJSONC.cmake | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/cmake/FindJSONC.cmake b/cmake/FindJSONC.cmake index bb0d19464..464f0359c 100644 --- a/cmake/FindJSONC.cmake +++ b/cmake/FindJSONC.cmake @@ -7,18 +7,21 @@ find_package(PkgConfig) if(PKG_CONFIG_FOUND) - pkg_check_modules(PC_JSON json-c) + pkg_check_modules(PC_JSONC json-c) endif() -find_path(JSONC_INCLUDE_DIR NAMES json-c/json.h json/json.h) -find_library(JSONC_LIBRARY NAMES json-c) +find_path(JSONC_INCLUDE_DIR NAMES json.h + HINTS ${PC_JSONC_INCLUDE_DIRS} + PATH_SUFFIXES json-c) +find_library(JSONC_LIBRARY NAMES json-c + HINTS ${PC_JSONC_LIBRARY_DIRS}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(JSONC DEFAULT_MSG JSONC_LIBRARY JSONC_INCLUDE_DIR) if(JSONC_FOUND) set(JSONC_LIBRARIES ${JSONC_LIBRARY}) - set(JSONC_INCLUDE_DIRS ${JSONC_INCLUDE_DIR}/json-c) + set(JSONC_INCLUDE_DIRS ${JSONC_INCLUDE_DIR}) endif() mark_as_advanced(JSONC_LIBRARY JSONC_INCLUDE_DIR) From e197d27c8d7952081f6e25864ef27924e707dc6c Mon Sep 17 00:00:00 2001 From: Ondrej Holy Date: Fri, 26 Apr 2024 10:36:24 +0200 Subject: [PATCH 11/13] [client,sdl] move prefs to static lib This is in preparation for the subsequent commit adding test case for the prefs functionality to avoid building the code twice. --- client/SDL/CMakeLists.txt | 11 ++- client/SDL/sdl_freerdp.cpp | 1 + client/SDL/sdl_kbd.cpp | 1 + client/SDL/sdl_prefs.cpp | 145 +++++++++++++++++++++++++++++++++++++ client/SDL/sdl_prefs.hpp | 32 ++++++++ client/SDL/sdl_utils.cpp | 123 ------------------------------- client/SDL/sdl_utils.hpp | 9 --- 7 files changed, 187 insertions(+), 135 deletions(-) create mode 100644 client/SDL/sdl_prefs.cpp create mode 100644 client/SDL/sdl_prefs.hpp diff --git a/client/SDL/CMakeLists.txt b/client/SDL/CMakeLists.txt index c1bb2881d..526655b57 100644 --- a/client/SDL/CMakeLists.txt +++ b/client/SDL/CMakeLists.txt @@ -63,8 +63,6 @@ find_package(SDL2 REQUIRED COMPONENTS) include_directories(${SDL2_INCLUDE_DIR}) include_directories(${SDL2_INCLUDE_DIRS}) -set(LIBS "") - find_package(Threads REQUIRED) add_subdirectory(dialogs) @@ -90,8 +88,13 @@ set(SRCS sdl_window.cpp ) +add_library(sdl_prefs STATIC + sdl_prefs.hpp + sdl_prefs.cpp +) + add_subdirectory(aad) -list(APPEND LIBS +set(LIBS winpr freerdp freerdp-client @@ -99,6 +102,7 @@ list(APPEND LIBS sdl_client_res dialogs aad-view + sdl_prefs ) if (NOT WITH_SDL_LINK_SHARED) @@ -110,6 +114,7 @@ endif() AddTargetWithResourceFile(${PROJECT_NAME} "${WIN32_GUI_FLAG}" "${PROJECT_VERSION}" SRCS) target_link_libraries(${PROJECT_NAME} PRIVATE ${LIBS}) +target_link_libraries(sdl_prefs winpr) set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER "Client/SDL") install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client) diff --git a/client/SDL/sdl_freerdp.cpp b/client/SDL/sdl_freerdp.cpp index 972063dd1..7bb9e6364 100644 --- a/client/SDL/sdl_freerdp.cpp +++ b/client/SDL/sdl_freerdp.cpp @@ -57,6 +57,7 @@ #include "sdl_kbd.hpp" #include "sdl_touch.hpp" #include "sdl_pointer.hpp" +#include "sdl_prefs.hpp" #include "dialogs/sdl_dialogs.hpp" #include "aad/sdl_webview.hpp" diff --git a/client/SDL/sdl_kbd.cpp b/client/SDL/sdl_kbd.cpp index c6e668df3..f45b75855 100644 --- a/client/SDL/sdl_kbd.cpp +++ b/client/SDL/sdl_kbd.cpp @@ -21,6 +21,7 @@ #include "sdl_disp.hpp" #include "sdl_freerdp.hpp" #include "sdl_utils.hpp" +#include "sdl_prefs.hpp" #include diff --git a/client/SDL/sdl_prefs.cpp b/client/SDL/sdl_prefs.cpp new file mode 100644 index 000000000..1d06c8784 --- /dev/null +++ b/client/SDL/sdl_prefs.cpp @@ -0,0 +1,145 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * SDL Prefs + * + * Copyright 2022 Armin Novak + * + * 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 +#if __has_include() +#include +namespace fs = std::filesystem; +#elif __has_include() +#include +namespace fs = std::experimental::filesystem; +#else +#error Could not find system header "" or "" +#endif + +#include "sdl_prefs.hpp" + +#include +#include +#include +#include + +#if defined(WINPR_JSON_FOUND) +using WINPR_JSONPtr = std::unique_ptr; + +static WINPR_JSONPtr get() +{ + auto config = sdl_get_pref_file(); + + std::ifstream ifs(config); + std::string content((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); + return { WINPR_JSON_ParseWithLength(content.c_str(), content.size()), WINPR_JSON_Delete }; +} + +static WINPR_JSON* get_item(const std::string& key) +{ + static WINPR_JSONPtr config{ nullptr, WINPR_JSON_Delete }; + if (!config) + config = get(); + if (!config) + return nullptr; + return WINPR_JSON_GetObjectItem(config.get(), key.c_str()); +} + +static std::string item_to_str(WINPR_JSON* item, const std::string& fallback = "") +{ + if (!item || !WINPR_JSON_IsString(item)) + return fallback; + auto str = WINPR_JSON_GetStringValue(item); + if (!str) + return {}; + return str; +} +#endif + +std::string sdl_get_pref_string(const std::string& key, const std::string& fallback) +{ +#if defined(WINPR_JSON_FOUND) + auto item = get_item(key); + return item_to_str(item, fallback); +#else + return fallback; +#endif +} + +bool sdl_get_pref_bool(const std::string& key, bool fallback) +{ +#if defined(WINPR_JSON_FOUND) + auto item = get_item(key); + if (!item || !WINPR_JSON_IsBool(item)) + return fallback; + return WINPR_JSON_IsTrue(item); +#else + return fallback; +#endif +} + +int64_t sdl_get_pref_int(const std::string& key, int64_t fallback) +{ +#if defined(WINPR_JSON_FOUND) + auto item = get_item(key); + if (!item || !WINPR_JSON_IsNumber(item)) + return fallback; + auto val = WINPR_JSON_GetNumberValue(item); + return static_cast(val); +#else + return fallback; +#endif +} + +std::vector sdl_get_pref_array(const std::string& key, + const std::vector& fallback) +{ +#if defined(WINPR_JSON_FOUND) + auto item = get_item(key); + if (!item || !WINPR_JSON_IsArray(item)) + return fallback; + + std::vector values; + for (int x = 0; x < WINPR_JSON_GetArraySize(item); x++) + { + auto cur = WINPR_JSON_GetArrayItem(item, x); + values.push_back(item_to_str(cur)); + } + + return values; +#else + return fallback; +#endif +} + +std::string sdl_get_pref_dir() +{ + using CStringPtr = std::unique_ptr; + CStringPtr path(GetKnownPath(KNOWN_PATH_XDG_CONFIG_HOME), free); + if (!path) + return {}; + + fs::path config{ path.get() }; + config /= FREERDP_VENDOR; + config /= FREERDP_PRODUCT; + return config.string(); +} + +std::string sdl_get_pref_file() +{ + fs::path config{ sdl_get_pref_dir() }; + config /= "sdl-freerdp.json"; + return config.string(); +} diff --git a/client/SDL/sdl_prefs.hpp b/client/SDL/sdl_prefs.hpp new file mode 100644 index 000000000..d7924f28c --- /dev/null +++ b/client/SDL/sdl_prefs.hpp @@ -0,0 +1,32 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * SDL Prefs + * + * Copyright 2022 Armin Novak + * + * 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. + */ + +#pragma once + +#include +#include + +std::string sdl_get_pref_dir(); +std::string sdl_get_pref_file(); + +std::string sdl_get_pref_string(const std::string& key, const std::string& fallback = ""); +int64_t sdl_get_pref_int(const std::string& key, int64_t fallback = 0); +bool sdl_get_pref_bool(const std::string& key, bool fallback = false); +std::vector sdl_get_pref_array(const std::string& key, + const std::vector& fallback = {}); \ No newline at end of file diff --git a/client/SDL/sdl_utils.cpp b/client/SDL/sdl_utils.cpp index 27150e105..d02837ef3 100644 --- a/client/SDL/sdl_utils.cpp +++ b/client/SDL/sdl_utils.cpp @@ -17,17 +17,6 @@ * limitations under the License. */ -#include -#if __has_include() -#include -namespace fs = std::filesystem; -#elif __has_include() -#include -namespace fs = std::experimental::filesystem; -#else -#error Could not find system header "" or "" -#endif - #include #include "sdl_utils.hpp" @@ -35,10 +24,7 @@ namespace fs = std::experimental::filesystem; #include -#include -#include #include -#include const char* sdl_event_type_str(Uint32 type) { @@ -353,112 +339,3 @@ std::string sdl_window_event_str(Uint8 ev) return "SDL_WINDOWEVENT_UNKNOWN"; } } - -#if defined(WINPR_JSON_FOUND) -using WINPR_JSONPtr = std::unique_ptr; - -static WINPR_JSONPtr get() -{ - auto config = sdl_get_pref_file(); - - std::ifstream ifs(config); - std::string content((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); - return { WINPR_JSON_ParseWithLength(content.c_str(), content.size()), WINPR_JSON_Delete }; -} - -static WINPR_JSON* get_item(const std::string& key) -{ - static WINPR_JSONPtr config{ nullptr, WINPR_JSON_Delete }; - if (!config) - config = get(); - if (!config) - return nullptr; - return WINPR_JSON_GetObjectItem(config.get(), key.c_str()); -} - -static std::string item_to_str(WINPR_JSON* item, const std::string& fallback = "") -{ - if (!item || !WINPR_JSON_IsString(item)) - return fallback; - auto str = WINPR_JSON_GetStringValue(item); - if (!str) - return {}; - return str; -} -#endif - -std::string sdl_get_pref_string(const std::string& key, const std::string& fallback) -{ -#if defined(WINPR_JSON_FOUND) - auto item = get_item(key); - return item_to_str(item, fallback); -#else - return fallback; -#endif -} - -bool sdl_get_pref_bool(const std::string& key, bool fallback) -{ -#if defined(WINPR_JSON_FOUND) - auto item = get_item(key); - if (!item || !WINPR_JSON_IsBool(item)) - return fallback; - return WINPR_JSON_IsTrue(item); -#else - return fallback; -#endif -} - -int64_t sdl_get_pref_int(const std::string& key, int64_t fallback) -{ -#if defined(WINPR_JSON_FOUND) - auto item = get_item(key); - if (!item || !WINPR_JSON_IsNumber(item)) - return fallback; - auto val = WINPR_JSON_GetNumberValue(item); - return static_cast(val); -#else - return fallback; -#endif -} - -std::vector sdl_get_pref_array(const std::string& key, - const std::vector& fallback) -{ -#if defined(WINPR_JSON_FOUND) - auto item = get_item(key); - if (!item || !WINPR_JSON_IsArray(item)) - return fallback; - - std::vector values; - for (int x = 0; x < WINPR_JSON_GetArraySize(item); x++) - { - auto cur = WINPR_JSON_GetArrayItem(item, x); - values.push_back(item_to_str(cur)); - } - - return values; -#else - return fallback; -#endif -} - -std::string sdl_get_pref_dir() -{ - using CStringPtr = std::unique_ptr; - CStringPtr path(GetKnownPath(KNOWN_PATH_XDG_CONFIG_HOME), free); - if (!path) - return {}; - - fs::path config{ path.get() }; - config /= FREERDP_VENDOR; - config /= FREERDP_PRODUCT; - return config.string(); -} - -std::string sdl_get_pref_file() -{ - fs::path config{ sdl_get_pref_dir() }; - config /= "sdl-freerdp.json"; - return config.string(); -} diff --git a/client/SDL/sdl_utils.hpp b/client/SDL/sdl_utils.hpp index 48a150d8e..8ff40af19 100644 --- a/client/SDL/sdl_utils.hpp +++ b/client/SDL/sdl_utils.hpp @@ -100,12 +100,3 @@ const char* sdl_error_string(Uint32 res); #define sdl_log_error(res, log, what) sdl_log_error_ex(res, log, what, __FILE__, __LINE__, __func__) BOOL sdl_log_error_ex(Uint32 res, wLog* log, const char* what, const char* file, size_t line, const char* fkt); - -std::string sdl_get_pref_dir(); -std::string sdl_get_pref_file(); - -std::string sdl_get_pref_string(const std::string& key, const std::string& fallback = ""); -int64_t sdl_get_pref_int(const std::string& key, int64_t fallback = 0); -bool sdl_get_pref_bool(const std::string& key, bool fallback = false); -std::vector sdl_get_pref_array(const std::string& key, - const std::vector& fallback = {}); From 945c496812fb8bfba2a7706ec089554c0bf47003 Mon Sep 17 00:00:00 2001 From: Ondrej Holy Date: Wed, 15 May 2024 15:23:08 +0200 Subject: [PATCH 12/13] [client,sdl] use WITH_WINPR_JSON instead of WINPR_JSON_FOUND The WINPR_JSON_FOUND macro is never defined currently. Consequently, the SDL prefs always use the fallback implementation. Let's use the WITH_WINPR_JSON instead to really parse the sdl-freerdp.json file. --- client/SDL/sdl_prefs.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/SDL/sdl_prefs.cpp b/client/SDL/sdl_prefs.cpp index 1d06c8784..e7e696b6a 100644 --- a/client/SDL/sdl_prefs.cpp +++ b/client/SDL/sdl_prefs.cpp @@ -35,7 +35,7 @@ namespace fs = std::experimental::filesystem; #include #include -#if defined(WINPR_JSON_FOUND) +#if defined(WITH_WINPR_JSON) using WINPR_JSONPtr = std::unique_ptr; static WINPR_JSONPtr get() @@ -70,7 +70,7 @@ static std::string item_to_str(WINPR_JSON* item, const std::string& fallback = " std::string sdl_get_pref_string(const std::string& key, const std::string& fallback) { -#if defined(WINPR_JSON_FOUND) +#if defined(WITH_WINPR_JSON) auto item = get_item(key); return item_to_str(item, fallback); #else @@ -80,7 +80,7 @@ std::string sdl_get_pref_string(const std::string& key, const std::string& fallb bool sdl_get_pref_bool(const std::string& key, bool fallback) { -#if defined(WINPR_JSON_FOUND) +#if defined(WITH_WINPR_JSON) auto item = get_item(key); if (!item || !WINPR_JSON_IsBool(item)) return fallback; @@ -92,7 +92,7 @@ bool sdl_get_pref_bool(const std::string& key, bool fallback) int64_t sdl_get_pref_int(const std::string& key, int64_t fallback) { -#if defined(WINPR_JSON_FOUND) +#if defined(WITH_WINPR_JSON) auto item = get_item(key); if (!item || !WINPR_JSON_IsNumber(item)) return fallback; @@ -106,7 +106,7 @@ int64_t sdl_get_pref_int(const std::string& key, int64_t fallback) std::vector sdl_get_pref_array(const std::string& key, const std::vector& fallback) { -#if defined(WINPR_JSON_FOUND) +#if defined(WITH_WINPR_JSON) auto item = get_item(key); if (!item || !WINPR_JSON_IsArray(item)) return fallback; From 4b3ecfac476b053f79de8a387fe55e32b3162715 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Thu, 16 May 2024 11:54:38 +0200 Subject: [PATCH 13/13] [winpr,utils] fix cJSON detection * pkg-config sets CJSON_FOUND, check for that instead of the paths, which might be unset or set to -NOTFOUND * move detection to own file. find_package targets are meant to be used in same directory or below, but we define the WinPR target one above, so include it in parent --- cmake/JsonDetect.cmake | 49 +++++++++++++++++++++++++++++ winpr/libwinpr/CMakeLists.txt | 1 + winpr/libwinpr/utils/CMakeLists.txt | 47 +-------------------------- 3 files changed, 51 insertions(+), 46 deletions(-) create mode 100644 cmake/JsonDetect.cmake diff --git a/cmake/JsonDetect.cmake b/cmake/JsonDetect.cmake new file mode 100644 index 000000000..1066421f1 --- /dev/null +++ b/cmake/JsonDetect.cmake @@ -0,0 +1,49 @@ +option(WITH_JSON_DISABLED "Build without any JSON support" OFF) +CMAKE_DEPENDENT_OPTION(WITH_CJSON_REQUIRED "Build with cJSON (fail if not found)" OFF "NOT WITH_JSON_DISABLED" OFF) +CMAKE_DEPENDENT_OPTION(WITH_JSONC_REQUIRED "Build with JSON-C (fail if not found)" OFF "NOT WITH_JSON_DISABLED" OFF) +if (NOT WITH_JSON_DISABLED) + find_package(cJSON) + + # Fallback detection: + # older ubuntu releases did not ship CMake or pkg-config files + # for cJSON. Be optimistic and try pkg-config and as last resort + # try manual detection + if (NOT CJSON_FOUND) + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_check_modules(CJSON libcjson) + endif() + + if (NOT CJSON_FOUND) + find_path(CJSON_INCLUDE_DIRS + NAMES cjson/cJSON.h + ) + find_library(CJSON_LIBRARIES + NAMES cjson + ) + if (NOT "${CJSON_LIBRARIES}" EQUAL "CJSON_LIBRARIES-NOTFOUND" AND NOT "${CJSON_INCLUDE_DIRS}" EQUAL "CJSON_INCLUDE_DIRS-NOTFOUND") + set(CJSON_FOUND ON) + endif() + endif() + endif() + + if (WITH_CJSON_REQUIRED) + if (NOT CJSON_FOUND) + message(FATAL_ERROR "cJSON was requested but not found") + endif() + endif() + + if (WITH_JSONC_REQUIRED) + find_package(JSONC REQUIRED) + else() + find_package(JSONC) + endif() + + if (NOT JSONC_FOUND AND NOT CJSON_FOUND) + set(WITH_WINPR_JSON OFF CACHE INTERNAL "internal") + message("compiling without JSON support. Install cJSON or json-c to enable") + endif() +else() + set(WITH_WINPR_JSON OFF CACHE INTERNAL "internal") + message("forced compile without JSON support. Set -DWITH_JSON_DISABLED=OFF to enable compile time detection") +endif() diff --git a/winpr/libwinpr/CMakeLists.txt b/winpr/libwinpr/CMakeLists.txt index 1c85d37f5..91d0e0176 100644 --- a/winpr/libwinpr/CMakeLists.txt +++ b/winpr/libwinpr/CMakeLists.txt @@ -16,6 +16,7 @@ # limitations under the License. include(CheckFunctionExists) +include(JsonDetect) set(WINPR_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(WINPR_SRCS "") diff --git a/winpr/libwinpr/utils/CMakeLists.txt b/winpr/libwinpr/utils/CMakeLists.txt index 17f96905c..2c5efb329 100644 --- a/winpr/libwinpr/utils/CMakeLists.txt +++ b/winpr/libwinpr/utils/CMakeLists.txt @@ -186,47 +186,8 @@ if (WINPR_HAVE_UNWIND_H) endif() endif() -option(WITH_JSON_DISABLED "Build without any JSON support" OFF) -CMAKE_DEPENDENT_OPTION(WITH_CJSON_REQUIRED "Build with cJSON (fail if not found)" OFF "NOT WITH_JSON_DISABLED" OFF) -CMAKE_DEPENDENT_OPTION(WITH_JSONC_REQUIRED "Build with JSON-C (fail if not found)" OFF "NOT WITH_JSON_DISABLED" OFF) +include(JsonDetect) if (NOT WITH_JSON_DISABLED) - find_package(cJSON) - - # Fallback detection: - # older ubuntu releases did not ship CMake or pkg-config files - # for cJSON. Be optimistic and try pkg-config and as last resort - # try manual detection - if (NOT CJSON_FOUND) - find_package(PkgConfig) - if (PKG_CONFIG_FOUND) - pkg_check_modules(CJSON libcjson) - endif() - - if (NOT CJSON_LIBRARIES OR NOT CJSON_INCLUDE_DIRS) - find_path(CJSON_INCLUDE_DIRS - NAMES cjson/cJSON.h - ) - find_library(CJSON_LIBRARIES - NAMES cjson - ) - if (NOT "${CJSON_LIBRARIES}" EQUAL "CJSON_LIBRARIES-NOTFOUND" AND NOT "${CJSON_INCLUDE_DIRS}" EQUAL "CJSON_INCLUDE_DIRS-NOTFOUND") - set(CJSON_FOUND ON) - endif() - endif() - endif() - - if (WITH_CJSON_REQUIRED) - if (NOT CJSON_FOUND) - message(FATAL_ERROR "cJSON was requested but not found") - endif() - endif() - - if (WITH_JSONC_REQUIRED) - find_package(JSONC REQUIRED) - else() - find_package(JSONC) - endif() - if (JSONC_FOUND AND NOT WITH_CJSON_REQUIRED) winpr_library_add_private(${JSONC_LIBRARIES}) winpr_include_directory_add(${JSONC_INCLUDE_DIRS}) @@ -237,13 +198,7 @@ if (NOT WITH_JSON_DISABLED) winpr_include_directory_add(${CJSON_INCLUDE_DIRS}) winpr_definition_add(-DWITH_CJSON) set(WITH_WINPR_JSON ON CACHE INTERNAL "internal") - else() - set(WITH_WINPR_JSON OFF CACHE INTERNAL "internal") - message("compiling without JSON support. Install cJSON or json-c to enable") endif() -else() - set(WITH_WINPR_JSON OFF CACHE INTERNAL "internal") - message("forced compile without JSON support. Set -DWITH_JSON_DISABLED=OFF to enable compile time detection") endif() winpr_module_add(json/json.c)