23#include <winpr/file.h>
24#include <winpr/json.h>
25#include <winpr/assert.h>
27#if defined(WITH_CJSON)
28#include <cjson/cJSON.h>
30#if defined(WITH_JSONC)
34#if defined(WITH_CJSON)
35#if CJSON_VERSION_MAJOR == 1
36#if (CJSON_VERSION_MINOR < 7) || ((CJSON_VERSION_MINOR == 7) && (CJSON_VERSION_PATCH < 13))
37#define USE_CJSON_COMPAT
42#if defined(WITH_JSONC)
43#if JSON_C_MAJOR_VERSION == 0
44#if JSON_C_MINOR_VERSION < 14
45static struct json_object* json_object_new_null(
void)
53#if defined(USE_CJSON_COMPAT)
54static double cJSON_GetNumberValue(
const cJSON* prop)
59#define COMPAT_NAN_UNDEF
62#define COMPAT_NAN_UNDEF
66 if (!cJSON_IsNumber(prop))
68 char* val = cJSON_GetStringValue(prop);
74 double dval = strtod(val, &endptr);
83#ifdef COMPAT_NAN_UNDEF
88static cJSON* cJSON_ParseWithLength(
const char* value,
size_t buffer_length)
91 const size_t slen = strnlen(value, buffer_length);
92 if (slen >= buffer_length)
94 if (value[buffer_length] !=
'\0')
97 return cJSON_Parse(value);
103#if defined(WITH_JSONC)
104 return _snprintf(buffer, len,
"json-c %s", json_c_version());
105#elif defined(WITH_CJSON)
106 return _snprintf(buffer, len,
"cJSON %s", cJSON_Version());
108 (void)_snprintf(buffer, len,
"JSON support not available");
115#if defined(WITH_JSONC)
116 return json_tokener_parse(value);
117#elif defined(WITH_CJSON)
118 return cJSON_Parse(value);
127#if defined(WITH_JSONC)
128 WINPR_ASSERT(buffer_length <= INT_MAX);
129 json_tokener* tok = json_tokener_new();
132 json_object* obj = json_tokener_parse_ex(tok, value, (
int)buffer_length);
133 json_tokener_free(tok);
135#elif defined(WITH_CJSON)
136 return cJSON_ParseWithLength(value, buffer_length);
139 WINPR_UNUSED(buffer_length);
146#if defined(WITH_JSONC)
147 json_object_put((json_object*)item);
148#elif defined(WITH_CJSON)
149 cJSON_Delete((cJSON*)item);
157#if defined(WITH_JSONC)
158 return json_object_array_get_idx((
const json_object*)array, index);
159#elif defined(WITH_CJSON)
160 WINPR_ASSERT(index <= INT_MAX);
161 return cJSON_GetArrayItem((
const cJSON*)array, (INT)index);
171#if defined(WITH_JSONC)
172 return json_object_array_length((
const json_object*)array);
173#elif defined(WITH_CJSON)
174 const int rc = cJSON_GetArraySize((
const cJSON*)array);
186#if defined(WITH_JSONC)
187 return json_object_object_get((
const json_object*)
object,
string);
188#elif defined(WITH_CJSON)
189 return cJSON_GetObjectItem((
const cJSON*)
object,
string);
191 WINPR_UNUSED(
object);
192 WINPR_UNUSED(
string);
199#if defined(WITH_JSONC)
200 return json_object_object_get((
const json_object*)
object,
string);
201#elif defined(WITH_CJSON)
202 return cJSON_GetObjectItemCaseSensitive((
const cJSON*)
object,
string);
204 WINPR_UNUSED(
object);
205 WINPR_UNUSED(
string);
212#if defined(WITH_JSONC)
213 return json_object_object_get_ex((
const json_object*)
object,
string, NULL);
214#elif defined(WITH_CJSON)
215 return cJSON_HasObjectItem((
const cJSON*)
object,
string);
217 WINPR_UNUSED(
object);
218 WINPR_UNUSED(
string);
225#if defined(WITH_JSONC)
226 return json_util_get_last_err();
227#elif defined(WITH_CJSON)
228 return cJSON_GetErrorPtr();
236#if defined(WITH_JSONC)
237 return json_object_get_string((json_object*)item);
238#elif defined(WITH_CJSON)
239 return cJSON_GetStringValue((cJSON*)item);
248#if defined(WITH_JSONC)
249 return json_object_get_double((
const json_object*)item);
250#elif defined(WITH_CJSON)
251 return cJSON_GetNumberValue((
const cJSON*)item);
260#if defined(WITH_JSONC)
274#elif defined(WITH_CJSON)
275 return cJSON_IsInvalid((
const cJSON*)item);
284#if defined(WITH_JSONC)
285 if (!json_object_is_type((
const json_object*)item, json_type_boolean))
287 json_bool val = json_object_get_boolean((
const json_object*)item);
289#elif defined(WITH_CJSON)
290 return cJSON_IsFalse((
const cJSON*)item);
299#if defined(WITH_JSONC)
300 if (!json_object_is_type((
const json_object*)item, json_type_boolean))
302 json_bool val = json_object_get_boolean((
const json_object*)item);
304#elif defined(WITH_CJSON)
305 return cJSON_IsTrue((
const cJSON*)item);
314#if defined(WITH_JSONC)
315 return json_object_is_type((
const json_object*)item, json_type_boolean);
316#elif defined(WITH_CJSON)
317 return cJSON_IsBool((
const cJSON*)item);
326#if defined(WITH_JSONC)
327 return json_object_is_type((
const json_object*)item, json_type_null);
328#elif defined(WITH_CJSON)
329 return cJSON_IsNull((
const cJSON*)item);
338#if defined(WITH_JSONC)
339 return json_object_is_type((
const json_object*)item, json_type_int) ||
340 json_object_is_type((
const json_object*)item, json_type_double);
341#elif defined(WITH_CJSON)
342 return cJSON_IsNumber((
const cJSON*)item);
351#if defined(WITH_JSONC)
352 return json_object_is_type((
const json_object*)item, json_type_string);
353#elif defined(WITH_CJSON)
354 return cJSON_IsString((
const cJSON*)item);
363#if defined(WITH_JSONC)
364 return json_object_is_type((
const json_object*)item, json_type_array);
365#elif defined(WITH_CJSON)
366 return cJSON_IsArray((
const cJSON*)item);
375#if defined(WITH_JSONC)
376 return json_object_is_type((
const json_object*)item, json_type_object);
377#elif defined(WITH_CJSON)
378 return cJSON_IsObject((
const cJSON*)item);
387#if defined(WITH_JSONC)
388 return json_object_new_null();
389#elif defined(WITH_CJSON)
390 return cJSON_CreateNull();
398#if defined(WITH_JSONC)
399 return json_object_new_boolean(TRUE);
400#elif defined(WITH_CJSON)
401 return cJSON_CreateTrue();
409#if defined(WITH_JSONC)
410 return json_object_new_boolean(FALSE);
411#elif defined(WITH_CJSON)
412 return cJSON_CreateFalse();
420#if defined(WITH_JSONC)
421 return json_object_new_boolean(
boolean);
422#elif defined(WITH_CJSON)
423 return cJSON_CreateBool(
boolean);
425 WINPR_UNUSED(
boolean);
432#if defined(WITH_JSONC)
433 return json_object_new_double(num);
434#elif defined(WITH_CJSON)
435 return cJSON_CreateNumber(num);
444#if defined(WITH_JSONC)
445 return json_object_new_string(
string);
446#elif defined(WITH_CJSON)
447 return cJSON_CreateString(
string);
449 WINPR_UNUSED(
string);
456#if defined(WITH_JSONC)
457 return json_object_new_array();
458#elif defined(WITH_CJSON)
459 return cJSON_CreateArray();
467#if defined(WITH_JSONC)
468 return json_object_new_object();
469#elif defined(WITH_CJSON)
470 return cJSON_CreateObject();
478#if defined(WITH_JSONC)
479 struct json_object* obj = json_object_new_null();
480 if (json_object_object_add((json_object*)
object, name, obj) != 0)
482 json_object_put(obj);
486#elif defined(WITH_CJSON)
487 return cJSON_AddNullToObject((cJSON*)
object, name);
489 WINPR_UNUSED(
object);
497#if defined(WITH_JSONC)
498 struct json_object* obj = json_object_new_boolean(TRUE);
499 if (json_object_object_add((json_object*)
object, name, obj) != 0)
501 json_object_put(obj);
505#elif defined(WITH_CJSON)
506 return cJSON_AddTrueToObject((cJSON*)
object, name);
508 WINPR_UNUSED(
object);
516#if defined(WITH_JSONC)
517 struct json_object* obj = json_object_new_boolean(FALSE);
518 if (json_object_object_add((json_object*)
object, name, obj) != 0)
520 json_object_put(obj);
524#elif defined(WITH_CJSON)
525 return cJSON_AddFalseToObject((cJSON*)
object, name);
527 WINPR_UNUSED(
object);
535#if defined(WITH_JSONC)
536 struct json_object* obj = json_object_new_boolean(
boolean);
537 if (json_object_object_add((json_object*)
object, name, obj) != 0)
539 json_object_put(obj);
543#elif defined(WITH_CJSON)
544 return cJSON_AddBoolToObject((cJSON*)
object, name,
boolean);
546 WINPR_UNUSED(
object);
548 WINPR_UNUSED(
boolean);
555#if defined(WITH_JSONC)
556 struct json_object* obj = json_object_new_double(number);
557 if (json_object_object_add((json_object*)
object, name, obj) != 0)
559 json_object_put(obj);
563#elif defined(WITH_CJSON)
564 return cJSON_AddNumberToObject((cJSON*)
object, name, number);
566 WINPR_UNUSED(
object);
568 WINPR_UNUSED(number);
575#if defined(WITH_JSONC)
576 struct json_object* obj = json_object_new_string(
string);
577 if (json_object_object_add((json_object*)
object, name, obj) != 0)
579 json_object_put(obj);
583#elif defined(WITH_CJSON)
584 return cJSON_AddStringToObject((cJSON*)
object, name,
string);
586 WINPR_UNUSED(
object);
588 WINPR_UNUSED(
string);
595#if defined(WITH_JSONC)
596 struct json_object* obj = json_object_new_object();
597 if (json_object_object_add((json_object*)
object, name, obj) != 0)
599 json_object_put(obj);
603#elif defined(WITH_CJSON)
604 return cJSON_AddObjectToObject((cJSON*)
object, name);
606 WINPR_UNUSED(
object);
614#if defined(WITH_JSONC)
615 const int rc = json_object_array_add((json_object*)array, (json_object*)item);
619#elif defined(WITH_CJSON)
620#if defined(USE_CJSON_COMPAT)
621 if ((array == NULL) || (item == NULL))
623 cJSON_AddItemToArray((cJSON*)array, (cJSON*)item);
626 return cJSON_AddItemToArray((cJSON*)array, (cJSON*)item);
637#if defined(WITH_JSONC)
638 struct json_object* obj = json_object_new_array();
639 if (json_object_object_add((json_object*)
object, name, obj) != 0)
641 json_object_put(obj);
645#elif defined(WITH_CJSON)
646 return cJSON_AddArrayToObject((cJSON*)
object, name);
648 WINPR_UNUSED(
object);
656#if defined(WITH_JSONC)
657 const char* str = json_object_to_json_string_ext((json_object*)item, JSON_C_TO_STRING_PRETTY);
661#elif defined(WITH_CJSON)
662 return cJSON_Print((
const cJSON*)item);
671#if defined(WITH_JSONC)
672 const char* str = json_object_to_json_string_ext((json_object*)item, JSON_C_TO_STRING_PLAIN);
676#elif defined(WITH_CJSON)
677 return cJSON_PrintUnformatted((
const cJSON*)item);
686 FILE* fp = winpr_fopen(filename,
"r");
699 if (fseek(fp, 0, SEEK_END) != 0)
702 const INT64 size = _ftelli64(fp);
706 if (fseek(fp, 0, SEEK_SET) != 0)
709 const size_t usize = WINPR_ASSERTING_INT_CAST(
size_t, size);
710 char* str = calloc(usize + 1,
sizeof(
char));
714 WINPR_JSON* json = NULL;
715 const size_t s = fread(str,
sizeof(
char), usize, fp);
WINPR_JSON * WINPR_JSON_CreateBool(BOOL boolean)
WINPR_JSON_CreateBool.
WINPR_JSON * WINPR_JSON_CreateString(const char *string)
WINPR_JSON_CreateString.
BOOL WINPR_JSON_HasObjectItem(const WINPR_JSON *object, const char *string)
Check if JSON has an object matching the name.
WINPR_JSON * WINPR_JSON_AddNumberToObject(WINPR_JSON *object, const char *name, double number)
WINPR_JSON_AddNumberToObject.
WINPR_JSON * WINPR_JSON_ParseFromFileFP(FILE *fp)
Parse a JSON string read from a FILE.
BOOL WINPR_JSON_IsNull(const WINPR_JSON *item)
Check if JSON item is Null.
WINPR_JSON * WINPR_JSON_GetObjectItem(const WINPR_JSON *object, const char *string)
Return a pointer to an JSON object item.
BOOL WINPR_JSON_IsString(const WINPR_JSON *item)
Check if JSON item is of type String.
BOOL WINPR_JSON_AddItemToArray(WINPR_JSON *array, WINPR_JSON *item)
Add an item to an existing array.
WINPR_JSON * WINPR_JSON_AddArrayToObject(WINPR_JSON *object, const char *name)
WINPR_JSON_AddArrayToObject.
BOOL WINPR_JSON_IsBool(const WINPR_JSON *item)
Check if JSON item is of type BOOL.
double WINPR_JSON_GetNumberValue(const WINPR_JSON *item)
Return the Number value of a JSON item.
WINPR_JSON * WINPR_JSON_AddTrueToObject(WINPR_JSON *object, const char *name)
WINPR_JSON_AddTrueToObject.
WINPR_JSON * WINPR_JSON_CreateObject(void)
WINPR_JSON_CreateObject.
WINPR_JSON * WINPR_JSON_CreateArray(void)
WINPR_JSON_CreateArray.
int WINPR_JSON_version(char *buffer, size_t len)
Get the library version string.
char * WINPR_JSON_Print(WINPR_JSON *item)
Serialize a JSON instance to string for minimal size without formatting see WINPR_JSON_PrintUnformatt...
WINPR_JSON * WINPR_JSON_AddFalseToObject(WINPR_JSON *object, const char *name)
WINPR_JSON_AddFalseToObject.
WINPR_JSON * WINPR_JSON_ParseFromFile(const char *filename)
Parse a JSON string read from a file filename.
BOOL WINPR_JSON_IsNumber(const WINPR_JSON *item)
Check if JSON item is of type Number.
WINPR_JSON * WINPR_JSON_GetArrayItem(const WINPR_JSON *array, size_t index)
Return a pointer to an item in the array.
WINPR_JSON * WINPR_JSON_GetObjectItemCaseSensitive(const WINPR_JSON *object, const char *string)
Same as WINPR_JSON_GetObjectItem but with case insensitive matching.
WINPR_JSON * WINPR_JSON_AddStringToObject(WINPR_JSON *object, const char *name, const char *string)
WINPR_JSON_AddStringToObject.
WINPR_JSON * WINPR_JSON_ParseWithLength(const char *value, size_t buffer_length)
Parse a JSON string.
WINPR_JSON * WINPR_JSON_CreateFalse(void)
WINPR_JSON_CreateFalse.
WINPR_JSON * WINPR_JSON_CreateNumber(double num)
WINPR_JSON_CreateNumber.
BOOL WINPR_JSON_IsObject(const WINPR_JSON *item)
Check if JSON item is of type Object.
WINPR_JSON * WINPR_JSON_AddBoolToObject(WINPR_JSON *object, const char *name, BOOL boolean)
WINPR_JSON_AddBoolToObject.
BOOL WINPR_JSON_IsInvalid(const WINPR_JSON *item)
Check if JSON item is valid.
char * WINPR_JSON_PrintUnformatted(WINPR_JSON *item)
Serialize a JSON instance to string without formatting for human readable formatted output see WINPR_...
WINPR_JSON * WINPR_JSON_CreateNull(void)
WINPR_JSON_CreateNull.
const char * WINPR_JSON_GetStringValue(WINPR_JSON *item)
Return the String value of a JSON item.
WINPR_JSON * WINPR_JSON_AddNullToObject(WINPR_JSON *object, const char *name)
WINPR_JSON_AddNullToObject.
WINPR_JSON * WINPR_JSON_CreateTrue(void)
WINPR_JSON_CreateTrue.
BOOL WINPR_JSON_IsFalse(const WINPR_JSON *item)
Check if JSON item is BOOL value False.
void WINPR_JSON_Delete(WINPR_JSON *item)
Delete a WinPR JSON wrapper object.
size_t WINPR_JSON_GetArraySize(const WINPR_JSON *array)
Get the number of arrayitems from an array.
BOOL WINPR_JSON_IsArray(const WINPR_JSON *item)
Check if JSON item is of type Array.
const char * WINPR_JSON_GetErrorPtr(void)
Return an error string.
WINPR_JSON * WINPR_JSON_AddObjectToObject(WINPR_JSON *object, const char *name)
WINPR_JSON_AddObjectToObject.
WINPR_JSON * WINPR_JSON_Parse(const char *value)
Parse a '\0' terminated JSON string.
BOOL WINPR_JSON_IsTrue(const WINPR_JSON *item)
Check if JSON item is BOOL value True.