Milestone 5: deliver embedded RDP sessions and lifecycle hardening

This commit is contained in:
Keith Smith
2026-03-03 18:59:26 -07:00
parent 230a401386
commit 36006bd4aa
2941 changed files with 724359 additions and 77 deletions

View File

@@ -0,0 +1,304 @@
/**
* 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 <errno.h>
#include <winpr/file.h>
#include <winpr/json.h>
#include <winpr/assert.h>
#if !defined(WITH_CJSON)
#error "This file must only be compiled when cJSON is enabled"
#endif
#include <cjson/cJSON.h>
#if defined(WITH_CJSON)
#if CJSON_VERSION_MAJOR == 1
#if (CJSON_VERSION_MINOR < 7) || ((CJSON_VERSION_MINOR == 7) && (CJSON_VERSION_PATCH < 13))
#define USE_CJSON_COMPAT
#endif
#endif
#endif
#if defined(USE_CJSON_COMPAT)
static double cJSON_GetNumberValue(const cJSON* 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 = nullptr;
double dval = strtod(val, &endptr);
if (val == endptr)
return NAN;
if (endptr != nullptr)
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 nullptr;
}
return cJSON_Parse(value);
}
#endif
int WINPR_JSON_version(char* buffer, size_t len)
{
return _snprintf(buffer, len, "cJSON %s", cJSON_Version());
}
WINPR_JSON* WINPR_JSON_Parse(const char* value)
{
return cJSON_Parse(value);
}
WINPR_JSON* WINPR_JSON_ParseWithLength(const char* value, size_t buffer_length)
{
return cJSON_ParseWithLength(value, buffer_length);
}
void WINPR_JSON_Delete(WINPR_JSON* item)
{
cJSON_Delete((cJSON*)item);
}
WINPR_JSON* WINPR_JSON_GetArrayItem(const WINPR_JSON* array, size_t index)
{
WINPR_ASSERT(index <= INT_MAX);
return cJSON_GetArrayItem((const cJSON*)array, (INT)index);
}
size_t WINPR_JSON_GetArraySize(const WINPR_JSON* array)
{
const int rc = cJSON_GetArraySize((const cJSON*)array);
if (rc <= 0)
return 0;
return (size_t)rc;
}
WINPR_JSON* WINPR_JSON_GetObjectItem(const WINPR_JSON* object, const char* string)
{
return cJSON_GetObjectItem((const cJSON*)object, string);
}
WINPR_JSON* WINPR_JSON_GetObjectItemCaseSensitive(const WINPR_JSON* object, const char* string)
{
return cJSON_GetObjectItemCaseSensitive((const cJSON*)object, string);
}
BOOL WINPR_JSON_HasObjectItem(const WINPR_JSON* object, const char* string)
{
return cJSON_HasObjectItem((const cJSON*)object, string);
}
const char* WINPR_JSON_GetErrorPtr(void)
{
return cJSON_GetErrorPtr();
}
const char* WINPR_JSON_GetStringValue(WINPR_JSON* item)
{
return cJSON_GetStringValue((cJSON*)item);
}
double WINPR_JSON_GetNumberValue(const WINPR_JSON* item)
{
return cJSON_GetNumberValue((const cJSON*)item);
}
BOOL WINPR_JSON_IsInvalid(const WINPR_JSON* item)
{
return cJSON_IsInvalid((const cJSON*)item);
}
BOOL WINPR_JSON_IsFalse(const WINPR_JSON* item)
{
return cJSON_IsFalse((const cJSON*)item);
}
BOOL WINPR_JSON_IsTrue(const WINPR_JSON* item)
{
return cJSON_IsTrue((const cJSON*)item);
}
BOOL WINPR_JSON_IsBool(const WINPR_JSON* item)
{
return cJSON_IsBool((const cJSON*)item);
}
BOOL WINPR_JSON_IsNull(const WINPR_JSON* item)
{
return cJSON_IsNull((const cJSON*)item);
}
BOOL WINPR_JSON_IsNumber(const WINPR_JSON* item)
{
return cJSON_IsNumber((const cJSON*)item);
}
BOOL WINPR_JSON_IsString(const WINPR_JSON* item)
{
return cJSON_IsString((const cJSON*)item);
}
BOOL WINPR_JSON_IsArray(const WINPR_JSON* item)
{
return cJSON_IsArray((const cJSON*)item);
}
BOOL WINPR_JSON_IsObject(const WINPR_JSON* item)
{
return cJSON_IsObject((const cJSON*)item);
}
WINPR_JSON* WINPR_JSON_CreateNull(void)
{
return cJSON_CreateNull();
}
WINPR_JSON* WINPR_JSON_CreateTrue(void)
{
return cJSON_CreateTrue();
}
WINPR_JSON* WINPR_JSON_CreateFalse(void)
{
return cJSON_CreateFalse();
}
WINPR_JSON* WINPR_JSON_CreateBool(BOOL boolean)
{
return cJSON_CreateBool(boolean);
}
WINPR_JSON* WINPR_JSON_CreateNumber(double num)
{
return cJSON_CreateNumber(num);
}
WINPR_JSON* WINPR_JSON_CreateString(const char* string)
{
return cJSON_CreateString(string);
}
WINPR_JSON* WINPR_JSON_CreateArray(void)
{
return cJSON_CreateArray();
}
WINPR_JSON* WINPR_JSON_CreateObject(void)
{
return cJSON_CreateObject();
}
WINPR_JSON* WINPR_JSON_AddNullToObject(WINPR_JSON* object, const char* name)
{
return cJSON_AddNullToObject((cJSON*)object, name);
}
WINPR_JSON* WINPR_JSON_AddTrueToObject(WINPR_JSON* object, const char* name)
{
return cJSON_AddTrueToObject((cJSON*)object, name);
}
WINPR_JSON* WINPR_JSON_AddFalseToObject(WINPR_JSON* object, const char* name)
{
return cJSON_AddFalseToObject((cJSON*)object, name);
}
WINPR_JSON* WINPR_JSON_AddBoolToObject(WINPR_JSON* object, const char* name, BOOL boolean)
{
return cJSON_AddBoolToObject((cJSON*)object, name, boolean);
}
WINPR_JSON* WINPR_JSON_AddNumberToObject(WINPR_JSON* object, const char* name, double number)
{
return cJSON_AddNumberToObject((cJSON*)object, name, number);
}
WINPR_JSON* WINPR_JSON_AddIntegerToObject(WINPR_JSON* object, const char* name, int64_t number)
{
char str[64] = WINPR_C_ARRAY_INIT;
(void)_snprintf(str, sizeof(str), "%" PRId64, number);
return cJSON_AddRawToObject((cJSON*)object, name, str);
}
WINPR_JSON* WINPR_JSON_AddStringToObject(WINPR_JSON* object, const char* name, const char* string)
{
return cJSON_AddStringToObject((cJSON*)object, name, string);
}
WINPR_JSON* WINPR_JSON_AddObjectToObject(WINPR_JSON* object, const char* name)
{
return cJSON_AddObjectToObject((cJSON*)object, name);
}
BOOL WINPR_JSON_AddItemToArray(WINPR_JSON* array, WINPR_JSON* item)
{
#if defined(USE_CJSON_COMPAT)
if ((array == nullptr) || (item == nullptr))
return FALSE;
cJSON_AddItemToArray((cJSON*)array, (cJSON*)item);
return TRUE;
#else
return cJSON_AddItemToArray((cJSON*)array, (cJSON*)item);
#endif
}
WINPR_JSON* WINPR_JSON_AddArrayToObject(WINPR_JSON* object, const char* name)
{
return cJSON_AddArrayToObject((cJSON*)object, name);
}
char* WINPR_JSON_Print(WINPR_JSON* item)
{
return cJSON_Print((const cJSON*)item);
}
char* WINPR_JSON_PrintUnformatted(WINPR_JSON* item)
{
return cJSON_PrintUnformatted((const cJSON*)item);
}

View File

@@ -0,0 +1,355 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* JSON parser wrapper
*
* Copyright 2025 Armin Novak <anovak@thincast.com>
* Copyright 2025 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 <winpr/file.h>
#include <winpr/json.h>
#include <winpr/assert.h>
#if !defined(WITH_JANSSON)
#error "This file must only be compiled if jansson library is linked in"
#endif
#include <jansson.h>
#if !defined(JANSSON_VERSION_HEX) || (JANSSON_VERSION_HEX < 0x020d00)
#error "The library detected is too old, need >= 2.13.0"
#endif
static WINPR_TLS char lasterror[256] = WINPR_C_ARRAY_INIT;
#if defined(WITH_DEBUG_JANSSON)
#include "../log.h"
#define TAG WINPR_TAG("jansson")
#define ccast(json) ccast_((json), __func__)
static const json_t* ccast_(const WINPR_JSON* json, const char* fkt)
{
const json_t* jansson = (const json_t*)json;
if (!jansson)
WLog_DBG(TAG, "%s: nullptr", fkt);
else
{
WLog_DBG(TAG, "%s: %" PRIuz, fkt, jansson->refcount);
}
return jansson;
}
#define cast(json) cast_((json), __func__)
static json_t* cast_(WINPR_JSON* json, const char* fkt)
{
json_t* jansson = (json_t*)json;
if (!jansson)
WLog_DBG(TAG, "%s: nullptr", fkt);
else
{
WLog_DBG(TAG, "%s: %" PRIuz, fkt, jansson->refcount);
}
return jansson;
}
#define revcast(json) revcast_((json), __func__)
static WINPR_JSON* revcast_(json_t* json, const char* fkt)
{
json_t* jansson = (json_t*)json;
if (!jansson)
WLog_DBG(TAG, "%s: nullptr", fkt);
else
{
WLog_DBG(TAG, "%s: %" PRIuz, fkt, jansson->refcount);
}
return jansson;
}
#else
static inline const json_t* ccast(const WINPR_JSON* json)
{
return WINPR_CXX_COMPAT_CAST(const json_t*, json);
}
static inline json_t* cast(WINPR_JSON* json)
{
return WINPR_CXX_COMPAT_CAST(json_t*, json);
}
static inline WINPR_JSON* revcast(json_t* json)
{
return WINPR_CXX_COMPAT_CAST(WINPR_JSON*, json);
}
#endif
int WINPR_JSON_version(char* buffer, size_t len)
{
return _snprintf(buffer, len, "jansson %s", jansson_version_str());
}
static WINPR_JSON* updateError(WINPR_JSON* json, const json_error_t* error)
{
lasterror[0] = '\0';
if (!json)
(void)_snprintf(lasterror, sizeof(lasterror), "[%d:%d:%d] %s [%s]", error->line,
error->column, error->position, error->text, error->source);
return json;
}
WINPR_JSON* WINPR_JSON_Parse(const char* value)
{
json_error_t error = WINPR_C_ARRAY_INIT;
WINPR_JSON* json = revcast(json_loads(value, JSON_DECODE_ANY, &error));
return updateError(json, &error);
}
WINPR_JSON* WINPR_JSON_ParseWithLength(const char* value, size_t buffer_length)
{
if (!value || (buffer_length == 0))
return nullptr;
json_error_t error = WINPR_C_ARRAY_INIT;
const size_t slen = strnlen(value, buffer_length);
WINPR_JSON* json = revcast(json_loadb(value, slen, JSON_DECODE_ANY, &error));
return updateError(json, &error);
}
void WINPR_JSON_Delete(WINPR_JSON* item)
{
json_delete(cast(item));
}
WINPR_JSON* WINPR_JSON_GetArrayItem(const WINPR_JSON* array, size_t index)
{
return revcast(json_array_get(ccast(array), index));
}
size_t WINPR_JSON_GetArraySize(const WINPR_JSON* array)
{
return json_array_size(ccast(array));
}
WINPR_JSON* WINPR_JSON_GetObjectItem(const WINPR_JSON* object, const char* string)
{
json_t* json = cast(WINPR_CAST_CONST_PTR_AWAY(object, WINPR_JSON*));
void* it = json_object_iter(json);
while (it)
{
const char* name = json_object_iter_key(it);
if (_stricmp(name, string) == 0)
return revcast(json_object_iter_value(it));
it = json_object_iter_next(json, it);
}
return nullptr;
}
WINPR_JSON* WINPR_JSON_GetObjectItemCaseSensitive(const WINPR_JSON* object, const char* string)
{
return revcast(json_object_get(ccast(object), string));
}
BOOL WINPR_JSON_HasObjectItem(const WINPR_JSON* object, const char* string)
{
return json_object_get(ccast(object), string) != nullptr;
}
const char* WINPR_JSON_GetErrorPtr(void)
{
return lasterror;
}
const char* WINPR_JSON_GetStringValue(WINPR_JSON* item)
{
return json_string_value(cast(item));
}
double WINPR_JSON_GetNumberValue(const WINPR_JSON* item)
{
return json_number_value(ccast(item));
}
BOOL WINPR_JSON_IsInvalid(const WINPR_JSON* item)
{
const json_t* jitem = ccast(item);
if (WINPR_JSON_IsArray(jitem))
return FALSE;
if (WINPR_JSON_IsObject(jitem))
return FALSE;
if (WINPR_JSON_IsNull(jitem))
return FALSE;
if (WINPR_JSON_IsNumber(jitem))
return FALSE;
if (WINPR_JSON_IsBool(jitem))
return FALSE;
if (WINPR_JSON_IsString(jitem))
return FALSE;
return TRUE;
}
BOOL WINPR_JSON_IsFalse(const WINPR_JSON* item)
{
return json_is_false(ccast(item));
}
BOOL WINPR_JSON_IsTrue(const WINPR_JSON* item)
{
return json_is_true(ccast(item));
}
BOOL WINPR_JSON_IsBool(const WINPR_JSON* item)
{
return json_is_boolean(ccast(item));
}
BOOL WINPR_JSON_IsNull(const WINPR_JSON* item)
{
return json_is_null(ccast(item));
}
BOOL WINPR_JSON_IsNumber(const WINPR_JSON* item)
{
return json_is_number(ccast(item));
}
BOOL WINPR_JSON_IsString(const WINPR_JSON* item)
{
return json_is_string(ccast(item));
}
BOOL WINPR_JSON_IsArray(const WINPR_JSON* item)
{
return json_is_array(ccast(item));
}
BOOL WINPR_JSON_IsObject(const WINPR_JSON* item)
{
return json_is_object(ccast(item));
}
WINPR_JSON* WINPR_JSON_CreateNull(void)
{
return revcast(json_null());
}
WINPR_JSON* WINPR_JSON_CreateTrue(void)
{
return revcast(json_true());
}
WINPR_JSON* WINPR_JSON_CreateFalse(void)
{
return revcast(json_false());
}
WINPR_JSON* WINPR_JSON_CreateBool(BOOL boolean)
{
return revcast(json_boolean(boolean));
}
WINPR_JSON* WINPR_JSON_CreateNumber(double num)
{
return revcast(json_real(num));
}
WINPR_JSON* WINPR_JSON_CreateString(const char* string)
{
return revcast(json_string(string));
}
WINPR_JSON* WINPR_JSON_CreateArray(void)
{
return revcast(json_array());
}
WINPR_JSON* WINPR_JSON_CreateObject(void)
{
return revcast(json_object());
}
static WINPR_JSON* add_to_object(WINPR_JSON* object, const char* name, json_t* obj)
{
if (!obj)
return nullptr;
const int rc = json_object_set_new(cast(object), name, obj);
if (rc != 0)
return nullptr;
return revcast(obj);
}
WINPR_JSON* WINPR_JSON_AddNullToObject(WINPR_JSON* object, const char* name)
{
json_t* obj = json_null();
return add_to_object(object, name, obj);
}
WINPR_JSON* WINPR_JSON_AddTrueToObject(WINPR_JSON* object, const char* name)
{
json_t* obj = json_true();
return add_to_object(object, name, obj);
}
WINPR_JSON* WINPR_JSON_AddFalseToObject(WINPR_JSON* object, const char* name)
{
json_t* obj = json_false();
return add_to_object(object, name, obj);
}
WINPR_JSON* WINPR_JSON_AddBoolToObject(WINPR_JSON* object, const char* name, BOOL boolean)
{
json_t* obj = json_boolean(boolean);
return add_to_object(object, name, obj);
}
WINPR_JSON* WINPR_JSON_AddNumberToObject(WINPR_JSON* object, const char* name, double number)
{
json_t* obj = json_real(number);
return add_to_object(object, name, obj);
}
WINPR_JSON* WINPR_JSON_AddIntegerToObject(WINPR_JSON* object, const char* name, int64_t number)
{
json_t* obj = json_integer(number);
return add_to_object(object, name, obj);
}
WINPR_JSON* WINPR_JSON_AddStringToObject(WINPR_JSON* object, const char* name, const char* string)
{
json_t* obj = json_string(string);
return add_to_object(object, name, obj);
}
WINPR_JSON* WINPR_JSON_AddObjectToObject(WINPR_JSON* object, const char* name)
{
json_t* obj = json_object();
return add_to_object(object, name, obj);
}
BOOL WINPR_JSON_AddItemToArray(WINPR_JSON* array, WINPR_JSON* item)
{
return json_array_append_new(cast(array), item) == 0;
}
WINPR_JSON* WINPR_JSON_AddArrayToObject(WINPR_JSON* object, const char* name)
{
json_t* obj = json_array();
return add_to_object(object, name, obj);
}
char* WINPR_JSON_Print(WINPR_JSON* item)
{
return json_dumps(cast(item), JSON_INDENT(2) | JSON_ENSURE_ASCII | JSON_SORT_KEYS);
}
char* WINPR_JSON_PrintUnformatted(WINPR_JSON* item)
{
return json_dumps(cast(item), JSON_COMPACT | JSON_ENSURE_ASCII | JSON_SORT_KEYS);
}

View File

@@ -0,0 +1,343 @@
/**
* 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 <errno.h>
#include <winpr/file.h>
#include <winpr/json.h>
#include <winpr/assert.h>
#if !defined(WITH_JSONC)
#error "This file must only be compiled when json-c is enabled"
#endif
#include <json.h>
#if JSON_C_MAJOR_VERSION == 0
#if JSON_C_MINOR_VERSION < 14
static struct json_object* json_object_new_null(void)
{
return nullptr;
}
#endif
#endif
int WINPR_JSON_version(char* buffer, size_t len)
{
return _snprintf(buffer, len, "json-c %s", json_c_version());
}
WINPR_JSON* WINPR_JSON_Parse(const char* value)
{
return json_tokener_parse(value);
}
WINPR_JSON* WINPR_JSON_ParseWithLength(const char* value, size_t buffer_length)
{
WINPR_ASSERT(buffer_length <= INT_MAX);
json_tokener* tok = json_tokener_new();
if (!tok)
return nullptr;
json_object* obj = json_tokener_parse_ex(tok, value, (int)buffer_length);
json_tokener_free(tok);
return obj;
}
void WINPR_JSON_Delete(WINPR_JSON* item)
{
json_object_put((json_object*)item);
}
WINPR_JSON* WINPR_JSON_GetArrayItem(const WINPR_JSON* array, size_t index)
{
return json_object_array_get_idx((const json_object*)array, index);
}
size_t WINPR_JSON_GetArraySize(const WINPR_JSON* array)
{
return json_object_array_length((const json_object*)array);
}
WINPR_JSON* WINPR_JSON_GetObjectItem(const WINPR_JSON* object, const char* string)
{
struct json_object_iterator it = json_object_iter_begin((const json_object*)object);
struct json_object_iterator itEnd = json_object_iter_end((const json_object*)object);
while (!json_object_iter_equal(&it, &itEnd))
{
const char* key = json_object_iter_peek_name(&it);
if (_stricmp(key, string) == 0)
{
return json_object_iter_peek_value(&it);
}
json_object_iter_next(&it);
}
return nullptr;
}
WINPR_JSON* WINPR_JSON_GetObjectItemCaseSensitive(const WINPR_JSON* object, const char* string)
{
return json_object_object_get((const json_object*)object, string);
}
BOOL WINPR_JSON_HasObjectItem(const WINPR_JSON* object, const char* string)
{
return json_object_object_get_ex((const json_object*)object, string, nullptr);
}
const char* WINPR_JSON_GetErrorPtr(void)
{
return json_util_get_last_err();
}
const char* WINPR_JSON_GetStringValue(WINPR_JSON* item)
{
return json_object_get_string((json_object*)item);
}
double WINPR_JSON_GetNumberValue(const WINPR_JSON* item)
{
return json_object_get_double((const json_object*)item);
}
BOOL WINPR_JSON_IsInvalid(const WINPR_JSON* item)
{
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;
}
BOOL WINPR_JSON_IsFalse(const WINPR_JSON* item)
{
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;
}
BOOL WINPR_JSON_IsTrue(const WINPR_JSON* item)
{
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;
}
BOOL WINPR_JSON_IsBool(const WINPR_JSON* item)
{
return json_object_is_type((const json_object*)item, json_type_boolean);
}
BOOL WINPR_JSON_IsNull(const WINPR_JSON* item)
{
return json_object_is_type((const json_object*)item, json_type_null);
}
BOOL WINPR_JSON_IsNumber(const WINPR_JSON* item)
{
return json_object_is_type((const json_object*)item, json_type_int) ||
json_object_is_type((const json_object*)item, json_type_double);
}
BOOL WINPR_JSON_IsString(const WINPR_JSON* item)
{
return json_object_is_type((const json_object*)item, json_type_string);
}
BOOL WINPR_JSON_IsArray(const WINPR_JSON* item)
{
return json_object_is_type((const json_object*)item, json_type_array);
}
BOOL WINPR_JSON_IsObject(const WINPR_JSON* item)
{
return json_object_is_type((const json_object*)item, json_type_object);
}
WINPR_JSON* WINPR_JSON_CreateNull(void)
{
return json_object_new_null();
}
WINPR_JSON* WINPR_JSON_CreateTrue(void)
{
return json_object_new_boolean(TRUE);
}
WINPR_JSON* WINPR_JSON_CreateFalse(void)
{
return json_object_new_boolean(FALSE);
}
WINPR_JSON* WINPR_JSON_CreateBool(BOOL boolean)
{
return json_object_new_boolean(boolean);
}
WINPR_JSON* WINPR_JSON_CreateNumber(double num)
{
return json_object_new_double(num);
}
WINPR_JSON* WINPR_JSON_CreateString(const char* string)
{
return json_object_new_string(string);
}
WINPR_JSON* WINPR_JSON_CreateArray(void)
{
return json_object_new_array();
}
WINPR_JSON* WINPR_JSON_CreateObject(void)
{
return json_object_new_object();
}
WINPR_JSON* WINPR_JSON_AddNullToObject(WINPR_JSON* object, const char* name)
{
struct json_object* obj = json_object_new_null();
if (json_object_object_add((json_object*)object, name, obj) != 0)
{
json_object_put(obj);
return nullptr;
}
return obj;
}
WINPR_JSON* WINPR_JSON_AddTrueToObject(WINPR_JSON* object, const char* name)
{
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 nullptr;
}
return obj;
}
WINPR_JSON* WINPR_JSON_AddFalseToObject(WINPR_JSON* object, const char* name)
{
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 nullptr;
}
return obj;
}
WINPR_JSON* WINPR_JSON_AddBoolToObject(WINPR_JSON* object, const char* name, BOOL boolean)
{
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 nullptr;
}
return obj;
}
WINPR_JSON* WINPR_JSON_AddNumberToObject(WINPR_JSON* object, const char* name, double number)
{
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 nullptr;
}
return obj;
}
WINPR_JSON* WINPR_JSON_AddIntegerToObject(WINPR_JSON* object, const char* name, int64_t number)
{
struct json_object* obj = json_object_new_int64(number);
if (json_object_object_add((json_object*)object, name, obj) != 0)
{
json_object_put(obj);
return nullptr;
}
return obj;
}
WINPR_JSON* WINPR_JSON_AddStringToObject(WINPR_JSON* object, const char* name, const char* string)
{
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 nullptr;
}
return obj;
}
WINPR_JSON* WINPR_JSON_AddObjectToObject(WINPR_JSON* object, const char* name)
{
struct json_object* obj = json_object_new_object();
if (json_object_object_add((json_object*)object, name, obj) != 0)
{
json_object_put(obj);
return nullptr;
}
return obj;
}
BOOL WINPR_JSON_AddItemToArray(WINPR_JSON* array, WINPR_JSON* item)
{
const int rc = json_object_array_add((json_object*)array, (json_object*)item);
if (rc != 0)
return FALSE;
return TRUE;
}
WINPR_JSON* WINPR_JSON_AddArrayToObject(WINPR_JSON* object, const char* name)
{
struct json_object* obj = json_object_new_array();
if (json_object_object_add((json_object*)object, name, obj) != 0)
{
json_object_put(obj);
return nullptr;
}
return obj;
}
char* WINPR_JSON_Print(WINPR_JSON* item)
{
const char* str = json_object_to_json_string_ext((json_object*)item, JSON_C_TO_STRING_PRETTY);
if (!str)
return nullptr;
return _strdup(str);
}
char* WINPR_JSON_PrintUnformatted(WINPR_JSON* item)
{
const char* str = json_object_to_json_string_ext((json_object*)item, JSON_C_TO_STRING_PLAIN);
if (!str)
return nullptr;
return _strdup(str);
}

View File

@@ -0,0 +1,275 @@
/**
* 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 <errno.h>
#include <winpr/file.h>
#include <winpr/json.h>
#include <winpr/assert.h>
int WINPR_JSON_version(char* buffer, size_t len)
{
(void)_snprintf(buffer, len, "JSON support not available");
return -1;
}
WINPR_JSON* WINPR_JSON_Parse(const char* value)
{
WINPR_UNUSED(value);
return nullptr;
}
WINPR_JSON* WINPR_JSON_ParseWithLength(const char* value, size_t buffer_length)
{
WINPR_UNUSED(value);
WINPR_UNUSED(buffer_length);
return nullptr;
}
void WINPR_JSON_Delete(WINPR_JSON* item)
{
WINPR_UNUSED(item);
}
WINPR_JSON* WINPR_JSON_GetArrayItem(const WINPR_JSON* array, size_t index)
{
WINPR_UNUSED(array);
WINPR_UNUSED(index);
return nullptr;
}
size_t WINPR_JSON_GetArraySize(const WINPR_JSON* array)
{
WINPR_UNUSED(array);
return 0;
}
WINPR_JSON* WINPR_JSON_GetObjectItem(const WINPR_JSON* object, const char* string)
{
WINPR_UNUSED(object);
WINPR_UNUSED(string);
return nullptr;
}
WINPR_JSON* WINPR_JSON_GetObjectItemCaseSensitive(const WINPR_JSON* object, const char* string)
{
WINPR_UNUSED(object);
WINPR_UNUSED(string);
return nullptr;
}
BOOL WINPR_JSON_HasObjectItem(const WINPR_JSON* object, const char* string)
{
WINPR_UNUSED(object);
WINPR_UNUSED(string);
return FALSE;
}
const char* WINPR_JSON_GetErrorPtr(void)
{
return nullptr;
}
const char* WINPR_JSON_GetStringValue(WINPR_JSON* item)
{
WINPR_UNUSED(item);
return nullptr;
}
double WINPR_JSON_GetNumberValue(const WINPR_JSON* item)
{
WINPR_UNUSED(item);
return nan("");
}
BOOL WINPR_JSON_IsInvalid(const WINPR_JSON* item)
{
WINPR_UNUSED(item);
return TRUE;
}
BOOL WINPR_JSON_IsFalse(const WINPR_JSON* item)
{
WINPR_UNUSED(item);
return FALSE;
}
BOOL WINPR_JSON_IsTrue(const WINPR_JSON* item)
{
WINPR_UNUSED(item);
return FALSE;
}
BOOL WINPR_JSON_IsBool(const WINPR_JSON* item)
{
WINPR_UNUSED(item);
return FALSE;
}
BOOL WINPR_JSON_IsNull(const WINPR_JSON* item)
{
WINPR_UNUSED(item);
return FALSE;
}
BOOL WINPR_JSON_IsNumber(const WINPR_JSON* item)
{
WINPR_UNUSED(item);
return FALSE;
}
BOOL WINPR_JSON_IsString(const WINPR_JSON* item)
{
WINPR_UNUSED(item);
return FALSE;
}
BOOL WINPR_JSON_IsArray(const WINPR_JSON* item)
{
WINPR_UNUSED(item);
return FALSE;
}
BOOL WINPR_JSON_IsObject(const WINPR_JSON* item)
{
WINPR_UNUSED(item);
return FALSE;
}
WINPR_JSON* WINPR_JSON_CreateNull(void)
{
return nullptr;
}
WINPR_JSON* WINPR_JSON_CreateTrue(void)
{
return nullptr;
}
WINPR_JSON* WINPR_JSON_CreateFalse(void)
{
return nullptr;
}
WINPR_JSON* WINPR_JSON_CreateBool(BOOL boolean)
{
WINPR_UNUSED(boolean);
return nullptr;
}
WINPR_JSON* WINPR_JSON_CreateNumber(double num)
{
WINPR_UNUSED(num);
return nullptr;
}
WINPR_JSON* WINPR_JSON_CreateString(const char* string)
{
WINPR_UNUSED(string);
return nullptr;
}
WINPR_JSON* WINPR_JSON_CreateArray(void)
{
return nullptr;
}
WINPR_JSON* WINPR_JSON_CreateObject(void)
{
return nullptr;
}
WINPR_JSON* WINPR_JSON_AddNullToObject(WINPR_JSON* object, const char* name)
{
WINPR_UNUSED(object);
WINPR_UNUSED(name);
return nullptr;
}
WINPR_JSON* WINPR_JSON_AddTrueToObject(WINPR_JSON* object, const char* name)
{
WINPR_UNUSED(object);
WINPR_UNUSED(name);
return nullptr;
}
WINPR_JSON* WINPR_JSON_AddFalseToObject(WINPR_JSON* object, const char* name)
{
WINPR_UNUSED(object);
WINPR_UNUSED(name);
return nullptr;
}
WINPR_JSON* WINPR_JSON_AddBoolToObject(WINPR_JSON* object, const char* name, BOOL boolean)
{
WINPR_UNUSED(object);
WINPR_UNUSED(name);
WINPR_UNUSED(boolean);
return nullptr;
}
WINPR_JSON* WINPR_JSON_AddNumberToObject(WINPR_JSON* object, const char* name, double number)
{
WINPR_UNUSED(object);
WINPR_UNUSED(name);
WINPR_UNUSED(number);
return nullptr;
}
WINPR_JSON* WINPR_JSON_AddStringToObject(WINPR_JSON* object, const char* name, const char* string)
{
WINPR_UNUSED(object);
WINPR_UNUSED(name);
WINPR_UNUSED(string);
return nullptr;
}
WINPR_JSON* WINPR_JSON_AddObjectToObject(WINPR_JSON* object, const char* name)
{
WINPR_UNUSED(object);
WINPR_UNUSED(name);
return nullptr;
}
BOOL WINPR_JSON_AddItemToArray(WINPR_JSON* array, WINPR_JSON* item)
{
WINPR_UNUSED(array);
WINPR_UNUSED(item);
return FALSE;
}
WINPR_JSON* WINPR_JSON_AddArrayToObject(WINPR_JSON* object, const char* name)
{
WINPR_UNUSED(object);
WINPR_UNUSED(name);
return nullptr;
}
char* WINPR_JSON_Print(WINPR_JSON* item)
{
WINPR_UNUSED(item);
return nullptr;
}
char* WINPR_JSON_PrintUnformatted(WINPR_JSON* item)
{
WINPR_UNUSED(item);
return nullptr;
}

View File

@@ -0,0 +1,63 @@
/**
* 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 <errno.h>
#include <winpr/file.h>
#include <winpr/json.h>
#include <winpr/assert.h>
WINPR_JSON* WINPR_JSON_ParseFromFile(const char* filename)
{
FILE* fp = winpr_fopen(filename, "r");
if (!fp)
return nullptr;
WINPR_JSON* json = WINPR_JSON_ParseFromFileFP(fp);
(void)fclose(fp);
return json;
}
WINPR_JSON* WINPR_JSON_ParseFromFileFP(FILE* fp)
{
if (!fp)
return nullptr;
if (fseek(fp, 0, SEEK_END) != 0)
return nullptr;
const INT64 size = _ftelli64(fp);
if (size < 0)
return nullptr;
if (fseek(fp, 0, SEEK_SET) != 0)
return nullptr;
const size_t usize = WINPR_ASSERTING_INT_CAST(size_t, size);
char* str = calloc(usize + 1, sizeof(char));
if (!str)
return nullptr;
WINPR_JSON* json = nullptr;
const size_t s = fread(str, sizeof(char), usize, fp);
if (s == usize)
json = WINPR_JSON_ParseWithLength(str, usize);
free(str);
return json;
}