mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-14 00:14:11 +09:00
@@ -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)
|
||||
|
||||
@@ -62,14 +62,6 @@ 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)
|
||||
|
||||
@@ -96,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
|
||||
@@ -105,6 +102,7 @@ list(APPEND LIBS
|
||||
sdl_client_res
|
||||
dialogs
|
||||
aad-view
|
||||
sdl_prefs
|
||||
)
|
||||
|
||||
if (NOT WITH_SDL_LINK_SHARED)
|
||||
@@ -116,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)
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <freerdp/channels/channels.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/config.h>
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <freerdp/log.h>
|
||||
@@ -56,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"
|
||||
@@ -1553,7 +1555,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;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "sdl_disp.hpp"
|
||||
#include "sdl_freerdp.hpp"
|
||||
#include "sdl_utils.hpp"
|
||||
#include "sdl_prefs.hpp"
|
||||
|
||||
#include <map>
|
||||
|
||||
|
||||
145
client/SDL/sdl_prefs.cpp
Normal file
145
client/SDL/sdl_prefs.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* SDL Prefs
|
||||
*
|
||||
* Copyright 2022 Armin Novak <armin.novak@thincast.com>
|
||||
*
|
||||
* 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 <fstream>
|
||||
#if __has_include(<filesystem>)
|
||||
#include <filesystem>
|
||||
namespace fs = std::filesystem;
|
||||
#elif __has_include(<experimental/filesystem>)
|
||||
#include <experimental/filesystem>
|
||||
namespace fs = std::experimental::filesystem;
|
||||
#else
|
||||
#error Could not find system header "<filesystem>" or "<experimental/filesystem>"
|
||||
#endif
|
||||
|
||||
#include "sdl_prefs.hpp"
|
||||
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/config.h>
|
||||
#include <freerdp/version.h>
|
||||
#include <winpr/json.h>
|
||||
|
||||
#if defined(WITH_WINPR_JSON)
|
||||
using WINPR_JSONPtr = std::unique_ptr<WINPR_JSON, decltype(&WINPR_JSON_Delete)>;
|
||||
|
||||
static WINPR_JSONPtr get()
|
||||
{
|
||||
auto config = sdl_get_pref_file();
|
||||
|
||||
std::ifstream ifs(config);
|
||||
std::string content((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
|
||||
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(WITH_WINPR_JSON)
|
||||
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(WITH_WINPR_JSON)
|
||||
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(WITH_WINPR_JSON)
|
||||
auto item = get_item(key);
|
||||
if (!item || !WINPR_JSON_IsNumber(item))
|
||||
return fallback;
|
||||
auto val = WINPR_JSON_GetNumberValue(item);
|
||||
return static_cast<int64_t>(val);
|
||||
#else
|
||||
return fallback;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::vector<std::string> sdl_get_pref_array(const std::string& key,
|
||||
const std::vector<std::string>& fallback)
|
||||
{
|
||||
#if defined(WITH_WINPR_JSON)
|
||||
auto item = get_item(key);
|
||||
if (!item || !WINPR_JSON_IsArray(item))
|
||||
return fallback;
|
||||
|
||||
std::vector<std::string> 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<char, decltype(&free)>;
|
||||
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();
|
||||
}
|
||||
32
client/SDL/sdl_prefs.hpp
Normal file
32
client/SDL/sdl_prefs.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* SDL Prefs
|
||||
*
|
||||
* Copyright 2022 Armin Novak <armin.novak@thincast.com>
|
||||
*
|
||||
* 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 <string>
|
||||
#include <vector>
|
||||
|
||||
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<std::string> sdl_get_pref_array(const std::string& key,
|
||||
const std::vector<std::string>& fallback = {});
|
||||
@@ -17,17 +17,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
#if __has_include(<filesystem>)
|
||||
#include <filesystem>
|
||||
namespace fs = std::filesystem;
|
||||
#elif __has_include(<experimental/filesystem>)
|
||||
#include <experimental/filesystem>
|
||||
namespace fs = std::experimental::filesystem;
|
||||
#else
|
||||
#error Could not find system header "<filesystem>" or "<experimental/filesystem>"
|
||||
#endif
|
||||
|
||||
#include <cassert>
|
||||
#include "sdl_utils.hpp"
|
||||
|
||||
@@ -35,11 +24,7 @@ namespace fs = std::experimental::filesystem;
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include <winpr/path.h>
|
||||
#include <freerdp/version.h>
|
||||
#if defined(CJSON_FOUND)
|
||||
#include <cjson/cJSON.h>
|
||||
#endif
|
||||
|
||||
const char* sdl_event_type_str(Uint32 type)
|
||||
{
|
||||
@@ -354,112 +339,3 @@ std::string sdl_window_event_str(Uint8 ev)
|
||||
return "SDL_WINDOWEVENT_UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CJSON_FOUND)
|
||||
using cJSONPtr = std::unique_ptr<cJSON, decltype(&cJSON_Delete)>;
|
||||
|
||||
static cJSONPtr get()
|
||||
{
|
||||
auto config = sdl_get_pref_file();
|
||||
|
||||
std::ifstream ifs(config);
|
||||
std::string content((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
|
||||
return { cJSON_ParseWithLength(content.c_str(), content.size()), cJSON_Delete };
|
||||
}
|
||||
|
||||
static cJSON* get_item(const std::string& key)
|
||||
{
|
||||
static cJSONPtr config{ nullptr, cJSON_Delete };
|
||||
if (!config)
|
||||
config = get();
|
||||
if (!config)
|
||||
return nullptr;
|
||||
return cJSON_GetObjectItem(config.get(), key.c_str());
|
||||
}
|
||||
|
||||
static std::string item_to_str(cJSON* item, const std::string& fallback = "")
|
||||
{
|
||||
if (!item || !cJSON_IsString(item))
|
||||
return fallback;
|
||||
auto str = cJSON_GetStringValue(item);
|
||||
if (!str)
|
||||
return {};
|
||||
return str;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string sdl_get_pref_string(const std::string& key, const std::string& fallback)
|
||||
{
|
||||
#if defined(CJSON_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(CJSON_FOUND)
|
||||
auto item = get_item(key);
|
||||
if (!item || !cJSON_IsBool(item))
|
||||
return fallback;
|
||||
return cJSON_IsTrue(item);
|
||||
#else
|
||||
return fallback;
|
||||
#endif
|
||||
}
|
||||
|
||||
int64_t sdl_get_pref_int(const std::string& key, int64_t fallback)
|
||||
{
|
||||
#if defined(CJSON_FOUND)
|
||||
auto item = get_item(key);
|
||||
if (!item || !cJSON_IsNumber(item))
|
||||
return fallback;
|
||||
auto val = cJSON_GetNumberValue(item);
|
||||
return static_cast<int64_t>(val);
|
||||
#else
|
||||
return fallback;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::vector<std::string> sdl_get_pref_array(const std::string& key,
|
||||
const std::vector<std::string>& fallback)
|
||||
{
|
||||
#if defined(CJSON_FOUND)
|
||||
auto item = get_item(key);
|
||||
if (!item || !cJSON_IsArray(item))
|
||||
return fallback;
|
||||
|
||||
std::vector<std::string> values;
|
||||
for (int x = 0; x < cJSON_GetArraySize(item); x++)
|
||||
{
|
||||
auto cur = cJSON_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<char, decltype(&free)>;
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/wlog.h>
|
||||
|
||||
@@ -102,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<std::string> sdl_get_pref_array(const std::string& key,
|
||||
const std::vector<std::string>& fallback = {});
|
||||
|
||||
27
cmake/FindJSONC.cmake
Normal file
27
cmake/FindJSONC.cmake
Normal file
@@ -0,0 +1,27 @@
|
||||
# - 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_JSONC json-c)
|
||||
endif()
|
||||
|
||||
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})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(JSONC_LIBRARY JSONC_INCLUDE_DIR)
|
||||
@@ -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)
|
||||
|
||||
49
cmake/JsonDetect.cmake
Normal file
49
cmake/JsonDetect.cmake
Normal file
@@ -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()
|
||||
@@ -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")
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <freerdp/utils/aad.h>
|
||||
|
||||
#include <winpr/crypto.h>
|
||||
#include <winpr/json.h>
|
||||
|
||||
#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
|
||||
|
||||
@@ -32,18 +32,6 @@ typedef enum
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
#ifdef WITH_AAD
|
||||
#include <cjson/cJSON.h>
|
||||
|
||||
#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 */
|
||||
|
||||
@@ -53,10 +53,7 @@
|
||||
#include "../utils.h"
|
||||
#include "../redirection.h"
|
||||
|
||||
//#define WITH_AAD
|
||||
#ifdef WITH_AAD
|
||||
#include <cjson/cJSON.h>
|
||||
#endif
|
||||
#include <winpr/json.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -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,34 +820,34 @@ 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);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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 +857,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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@")
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
93
winpr/include/winpr/json.h
Normal file
93
winpr/include/winpr/json.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* JSON parser wrapper
|
||||
*
|
||||
* Copyright 2024 Armin Novak <anovak@thincast.com>
|
||||
* 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 <winpr/winpr.h>
|
||||
#include <winpr/string.h>
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
#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
|
||||
@@ -16,6 +16,7 @@
|
||||
# limitations under the License.
|
||||
|
||||
include(CheckFunctionExists)
|
||||
include(JsonDetect)
|
||||
|
||||
set(WINPR_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(WINPR_SRCS "")
|
||||
|
||||
@@ -16,25 +16,26 @@
|
||||
# limitations under the License.
|
||||
|
||||
include(CheckFunctionExists)
|
||||
include(CMakeDependentOption)
|
||||
|
||||
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()
|
||||
@@ -50,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()
|
||||
|
||||
|
||||
@@ -63,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
|
||||
@@ -85,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
|
||||
@@ -147,44 +148,61 @@ 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()
|
||||
|
||||
include(JsonDetect)
|
||||
if (NOT WITH_JSON_DISABLED)
|
||||
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")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
winpr_module_add(json/json.c)
|
||||
|
||||
winpr_module_add(${SRCS}
|
||||
${COLLECTIONS_SRCS}
|
||||
${WLOG_SRCS}
|
||||
|
||||
651
winpr/libwinpr/utils/json/json.c
Normal file
651
winpr/libwinpr/utils/json/json.c
Normal file
@@ -0,0 +1,651 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* JSON parser wrapper
|
||||
*
|
||||
* Copyright 2024 Armin Novak <anovak@thincast.com>
|
||||
* 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 <math.h>
|
||||
|
||||
#include <winpr/json.h>
|
||||
#include <winpr/assert.h>
|
||||
|
||||
#if defined(WITH_CJSON)
|
||||
#include <cjson/cJSON.h>
|
||||
#endif
|
||||
#if defined(WITH_JSONC)
|
||||
#include <json-c/json.h>
|
||||
#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
|
||||
}
|
||||
Reference in New Issue
Block a user