9fdbf2c7 |
/*
* JSON Object API |
557c712c |
* |
e1cbc270 |
* Copyright (C) 2014-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. |
557c712c |
* |
9fdbf2c7 |
* Authors: Kevin Lin |
557c712c |
* |
9fdbf2c7 |
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation. |
557c712c |
* |
9fdbf2c7 |
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. |
557c712c |
* |
9fdbf2c7 |
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
|
60d8d2c3 |
#include "clamav.h" |
9fdbf2c7 |
#include "others.h"
#include "json_api.h"
#ifdef HAVE_JSON |
557c712c |
cl_error_t cli_json_timeout_cycle_check(cli_ctx *ctx, int *toval) |
20b45621 |
{ |
048a88e6 |
if (SCAN_COLLECT_METADATA) { |
8c338ea9 |
if (*toval <= 0) {
if (cli_checktimelimit(ctx) != CL_SUCCESS) {
cli_errmsg("cli_json_timeout_cycle_check: timeout!\n");
return CL_ETIMEOUT;
}
(*toval)++;
}
if (*toval > JSON_TIMEOUT_SKIP_CYCLES) {
(*toval) = 0; |
20b45621 |
}
}
return CL_SUCCESS;
}
|
557c712c |
cl_error_t cli_json_parse_error(json_object *root, const char *errstr) |
4e2ae35b |
{
json_object *perr;
if (!root)
return CL_SUCCESS; /* CL_ENULLARG? */
perr = cli_jsonarray(root, "ParseErrors");
if (perr == NULL) {
return CL_EMEM;
}
return cli_jsonstr(perr, NULL, errstr);
}
|
557c712c |
cl_error_t cli_jsonnull(json_object *obj, const char *key) |
9fdbf2c7 |
{ |
8f8c5555 |
json_type objty; |
9a7511a1 |
json_object *fpobj = NULL; |
849a2cef |
if (NULL == obj) { |
5d93a537 |
cli_dbgmsg("json: null 'obj' specified to cli_jsonnull\n"); |
849a2cef |
return CL_ENULLARG;
} |
8f8c5555 |
objty = json_object_get_type(obj);
if (objty == json_type_object) {
if (NULL == key) {
cli_dbgmsg("json: null string specified as key to cli_jsonnull\n");
return CL_ENULLARG;
}
json_object_object_add(obj, key, fpobj); |
288057e9 |
} else if (objty == json_type_array) { |
8f8c5555 |
json_object_array_add(obj, fpobj); |
a094a729 |
}
|
9fdbf2c7 |
return CL_SUCCESS;
}
|
557c712c |
cl_error_t cli_jsonstr(json_object *obj, const char *key, const char *s) |
9fdbf2c7 |
{ |
8f8c5555 |
json_type objty; |
a094a729 |
json_object *fpobj; |
849a2cef |
if (NULL == obj) { |
5d93a537 |
cli_dbgmsg("json: null 'obj' specified to cli_jsonstr\n"); |
a094a729 |
return CL_ENULLARG;
} |
8f8c5555 |
objty = json_object_get_type(obj);
if (objty == json_type_object) {
if (NULL == key) {
cli_dbgmsg("json: null string specified as 'key' to cli_jsonstr\n");
return CL_ENULLARG;
} |
288057e9 |
} else if (objty != json_type_array) { |
8f8c5555 |
return CL_EARG; |
a094a729 |
} |
8f8c5555 |
|
a094a729 |
if (NULL == s) { |
5d93a537 |
cli_dbgmsg("json: null string specified as 's' to cli_jsonstr\n"); |
849a2cef |
return CL_ENULLARG;
} |
a094a729 |
fpobj = json_object_new_string(s); |
9fdbf2c7 |
if (NULL == fpobj) { |
a094a729 |
cli_errmsg("json: no memory for json string object\n"); |
9fdbf2c7 |
return CL_EMEM;
} |
8f8c5555 |
if (objty == json_type_object)
json_object_object_add(obj, key, fpobj);
else if (objty == json_type_array)
json_object_array_add(obj, fpobj);
|
9fdbf2c7 |
return CL_SUCCESS;
}
|
557c712c |
cl_error_t cli_jsonstrlen(json_object *obj, const char *key, const char *s, int len) |
0dab1f31 |
{
json_type objty;
json_object *fpobj;
if (NULL == obj) {
cli_dbgmsg("json: null 'obj' specified to cli_jsonstr\n");
return CL_ENULLARG;
}
objty = json_object_get_type(obj);
if (objty == json_type_object) {
if (NULL == key) {
cli_dbgmsg("json: null string specified as 'key' to cli_jsonstr\n");
return CL_ENULLARG;
} |
288057e9 |
} else if (objty != json_type_array) { |
0dab1f31 |
return CL_EARG;
}
if (NULL == s) {
cli_dbgmsg("json: null string specified as 's' to cli_jsonstr\n");
return CL_ENULLARG;
}
fpobj = json_object_new_string_len(s, len);
if (NULL == fpobj) {
cli_errmsg("json: no memory for json string object\n");
return CL_EMEM;
}
if (objty == json_type_object)
json_object_object_add(obj, key, fpobj);
else if (objty == json_type_array)
json_object_array_add(obj, fpobj);
return CL_SUCCESS;
}
|
557c712c |
cl_error_t cli_jsonint(json_object *obj, const char *key, int32_t i) |
9fdbf2c7 |
{ |
8f8c5555 |
json_type objty; |
a094a729 |
json_object *fpobj; |
849a2cef |
if (NULL == obj) { |
5d93a537 |
cli_dbgmsg("json: no parent object specified to cli_jsonint\n"); |
849a2cef |
return CL_ENULLARG;
} |
8f8c5555 |
objty = json_object_get_type(obj);
|
288057e9 |
if (objty == json_type_object) { |
8f8c5555 |
if (NULL == key) {
cli_dbgmsg("json: null string specified as key to cli_jsonint\n");
return CL_ENULLARG;
} |
288057e9 |
} else if (objty != json_type_array) { |
8f8c5555 |
return CL_EARG; |
a094a729 |
}
fpobj = json_object_new_int(i); |
9fdbf2c7 |
if (NULL == fpobj) { |
a094a729 |
cli_errmsg("json: no memory for json int object\n"); |
9fdbf2c7 |
return CL_EMEM;
} |
8f8c5555 |
if (objty == json_type_object)
json_object_object_add(obj, key, fpobj);
else if (objty == json_type_array)
json_object_array_add(obj, fpobj);
|
9fdbf2c7 |
return CL_SUCCESS;
}
#ifdef JSON10 |
557c712c |
cl_error_t cli_jsonint64(json_object *obj, const char *key, int64_t i) |
9fdbf2c7 |
{ |
8f8c5555 |
json_type objty; |
a094a729 |
json_object *fpobj; |
849a2cef |
if (NULL == obj) { |
5d93a537 |
cli_dbgmsg("json: no parent object specified to cli_jsonint64\n"); |
849a2cef |
return CL_ENULLARG;
} |
8f8c5555 |
objty = json_object_get_type(obj);
if (objty == json_type_object) {
if (NULL == key) {
cli_dbgmsg("json: null string specified as key to cli_jsonint64\n");
return CL_ENULLARG;
} |
288057e9 |
} else if (objty != json_type_array) { |
8f8c5555 |
return CL_EARG; |
a094a729 |
}
fpobj = json_object_new_int64(i); |
9fdbf2c7 |
if (NULL == fpobj) {
cli_errmsg("json: no memory for json int object.\n");
return CL_EMEM;
} |
8f8c5555 |
if (objty == json_type_object)
json_object_object_add(obj, key, fpobj);
else if (objty == json_type_array)
json_object_array_add(obj, fpobj);
|
9fdbf2c7 |
return CL_SUCCESS;
}
#else |
557c712c |
cl_error_t cli_jsonint64(json_object *obj, const char *key, int64_t i) |
9fdbf2c7 |
{ |
8f8c5555 |
json_type objty; |
9fdbf2c7 |
int32_t li, hi;
json_object *fpobj0, *fpobj1; |
a094a729 |
json_object *fparr; |
849a2cef |
if (NULL == obj) { |
5d93a537 |
cli_dbgmsg("json: no parent object specified to cli_jsonint64\n"); |
849a2cef |
return CL_ENULLARG;
} |
8f8c5555 |
objty = json_object_get_type(obj);
if (objty == json_type_object) {
if (NULL == key) {
cli_dbgmsg("json: null string specified as key to cli_jsonint64\n");
return CL_ENULLARG;
} |
288057e9 |
} else if (objty != json_type_array) { |
8f8c5555 |
return CL_EARG; |
a094a729 |
}
fparr = json_object_new_array(); |
9fdbf2c7 |
if (NULL == fparr) {
cli_errmsg("json: no memory for json array object.\n");
return CL_EMEM;
}
hi = (uint32_t)((i & 0xFFFFFFFF00000000) >> 32);
li = (uint32_t)(i & 0xFFFFFFFF);
fpobj0 = json_object_new_int(li);
if (NULL == fpobj0) {
cli_errmsg("json: no memory for json int object.\n"); |
849a2cef |
json_object_put(fparr); |
9fdbf2c7 |
return CL_EMEM;
}
fpobj1 = json_object_new_int(hi);
if (NULL == fpobj1) {
cli_errmsg("json: no memory for json int object.\n"); |
849a2cef |
json_object_put(fparr);
json_object_put(fpobj0); |
9fdbf2c7 |
return CL_EMEM;
}
/* little-endian array */
json_object_array_add(fparr, fpobj0);
json_object_array_add(fparr, fpobj1); |
8f8c5555 |
if (objty == json_type_object)
json_object_object_add(obj, key, fparr);
else if (objty == json_type_array)
json_object_array_add(obj, fparr);
|
849a2cef |
return CL_SUCCESS; |
9fdbf2c7 |
}
//#define cli_jsonint64(o,n,i) cli_dbgmsg("%s: %lld [%llx]\n", n, i, i)
#endif
|
557c712c |
cl_error_t cli_jsonbool(json_object *obj, const char *key, int i) |
9fdbf2c7 |
{ |
8f8c5555 |
json_type objty; |
a094a729 |
json_object *fpobj; |
849a2cef |
if (NULL == obj) { |
5d93a537 |
cli_dbgmsg("json: no parent object specified to cli_jsonbool\n"); |
849a2cef |
return CL_ENULLARG;
} |
8f8c5555 |
objty = json_object_get_type(obj);
if (objty == json_type_object) {
if (NULL == key) {
cli_dbgmsg("json: null string specified as key to cli_jsonbool\n");
return CL_ENULLARG;
} |
288057e9 |
} else if (objty != json_type_array) { |
8f8c5555 |
return CL_EARG; |
a094a729 |
}
fpobj = json_object_new_boolean(i); |
9fdbf2c7 |
if (NULL == fpobj) {
cli_errmsg("json: no memory for json boolean object.\n");
return CL_EMEM;
} |
8f8c5555 |
if (objty == json_type_object)
json_object_object_add(obj, key, fpobj);
else if (objty == json_type_array)
json_object_array_add(obj, fpobj);
|
9fdbf2c7 |
return CL_SUCCESS;
}
|
557c712c |
cl_error_t cli_jsondouble(json_object *obj, const char *key, double d) |
9fdbf2c7 |
{ |
8f8c5555 |
json_type objty; |
a094a729 |
json_object *fpobj; |
849a2cef |
if (NULL == obj) { |
5d93a537 |
cli_dbgmsg("json: no parent object specified to cli_jsondouble\n"); |
849a2cef |
return CL_ENULLARG;
} |
8f8c5555 |
objty = json_object_get_type(obj);
if (objty == json_type_object) {
if (NULL == key) {
cli_dbgmsg("json: null string specified as key to cli_jsondouble\n");
return CL_ENULLARG;
} |
288057e9 |
} else if (objty != json_type_array) { |
8f8c5555 |
return CL_EARG; |
a094a729 |
}
fpobj = json_object_new_double(d); |
9fdbf2c7 |
if (NULL == fpobj) { |
849a2cef |
cli_errmsg("json: no memory for json double object.\n"); |
9fdbf2c7 |
return CL_EMEM;
} |
8f8c5555 |
if (objty == json_type_object)
json_object_object_add(obj, key, fpobj);
else if (objty == json_type_array)
json_object_array_add(obj, fpobj);
|
9fdbf2c7 |
return CL_SUCCESS;
} |
a69adec1 |
|
d7ee9b81 |
json_object *cli_jsonarray(json_object *obj, const char *key)
{ |
b6549d30 |
json_type objty; |
d7ee9b81 |
json_object *newobj;
|
8c338ea9 |
/* First check to see if this key exists */ |
165cf21e |
if (obj && key && json_object_object_get_ex(obj, key, &newobj)) { |
8c338ea9 |
return json_object_is_type(newobj, json_type_array) ? newobj : NULL; |
d7ee9b81 |
}
newobj = json_object_new_array();
if (!(newobj))
return NULL;
|
b6549d30 |
if (obj) {
objty = json_object_get_type(obj);
if (key && objty == json_type_object) {
json_object_object_add(obj, key, newobj);
if (!json_object_object_get_ex(obj, key, &newobj))
return NULL;
} else if (objty == json_type_array) {
json_object_array_add(obj, newobj);
} |
d7ee9b81 |
}
return newobj;
}
|
557c712c |
cl_error_t cli_jsonint_array(json_object *obj, int32_t val) |
d7ee9b81 |
{ |
8f8c5555 |
return cli_jsonint(obj, NULL, val); |
d7ee9b81 |
}
json_object *cli_jsonobj(json_object *obj, const char *key)
{ |
b6549d30 |
json_type objty; |
d7ee9b81 |
json_object *newobj;
|
8c338ea9 |
if (obj && key && json_object_object_get_ex(obj, key, &newobj))
return json_object_is_type(newobj, json_type_object) ? newobj : NULL; |
d7ee9b81 |
newobj = json_object_new_object();
if (!(newobj))
return NULL;
|
b6549d30 |
if (obj) {
objty = json_object_get_type(obj);
if (key && objty == json_type_object) {
json_object_object_add(obj, key, newobj);
if (!json_object_object_get_ex(obj, key, &newobj))
return NULL;
} else if (objty == json_type_array) {
json_object_array_add(obj, newobj);
} |
8f94be58 |
} |
d7ee9b81 |
return newobj;
}
|
060a57d2 |
#if HAVE_DEPRECATED_JSON
int json_object_object_get_ex(struct json_object *obj, const char *key, struct json_object **value)
{
struct json_object *res;
if (value != NULL)
*value = NULL;
if (obj == NULL)
return 0;
if (json_object_get_type(obj) != json_type_object)
return 0;
res = json_object_object_get(obj, key);
if (value != NULL) {
*value = res;
return (res != NULL);
}
return (res != NULL);
}
#endif
|
8e586053 |
/* adding an object does NOT increment reference count */ |
557c712c |
cl_error_t cli_json_addowner(json_object *owner, json_object *child, const char *key, int idx) |
8e586053 |
{
json_type objty;
if (NULL == owner) {
cli_dbgmsg("json: no owner object specified to cli_json_addowner\n");
return CL_ENULLARG;
}
if (NULL == child) {
cli_dbgmsg("json: no child object specified to cli_json_addowner\n");
return CL_ENULLARG;
}
objty = json_object_get_type(owner);
if (objty == json_type_object) {
if (NULL == key) {
cli_dbgmsg("json: null string specified as key to cli_addowner\n");
return CL_ENULLARG;
}
json_object_object_add(owner, key, child); |
288057e9 |
} else if (objty == json_type_array) { |
8e586053 |
if (idx < 0 || NULL == json_object_array_get_idx(owner, idx))
json_object_array_add(owner, child);
else if (0 != json_object_array_put_idx(owner, idx, child)) {
/* this shouldn't be possible */
cli_dbgmsg("json: cannot delete idx %d of owner array\n", idx);
return CL_BREAK;
} |
288057e9 |
} else { |
8e586053 |
cli_dbgmsg("json: no owner object cannot hold ownership\n");
return CL_EARG;
}
/* increment reference count */
json_object_get(child);
return CL_SUCCESS;
}
/* deleting an object DOES decrement reference count */ |
557c712c |
cl_error_t cli_json_delowner(json_object *owner, const char *key, int idx) |
8e586053 |
{
json_type objty;
json_object *obj;
if (NULL == owner) {
cli_dbgmsg("json: no owner object specified to cli_json_delowner\n");
return CL_ENULLARG;
}
objty = json_object_get_type(owner);
if (objty == json_type_object) {
if (NULL == key) {
cli_dbgmsg("json: null string specified as key to cli_delowner\n");
return CL_ENULLARG;
}
if (!json_object_object_get_ex(owner, key, &obj)) {
cli_dbgmsg("json: owner array does not have content with key %s\n", key);
return CL_EARG;
}
json_object_object_del(owner, key); |
288057e9 |
} else if (objty == json_type_array) { |
8e586053 |
json_object *empty;
if (NULL == json_object_array_get_idx(owner, idx)) {
cli_dbgmsg("json: owner array does not have content at idx %d\n", idx);
return CL_EARG;
}
/* allocate the empty object to replace target object */
empty = cli_jsonobj(NULL, NULL);
if (NULL == empty)
return CL_EMEM;
if (0 != json_object_array_put_idx(owner, idx, empty)) {
/* this shouldn't be possible */
cli_dbgmsg("json: cannot delete idx %d of owner array\n", idx);
return CL_BREAK;
} |
288057e9 |
} else { |
8e586053 |
cli_dbgmsg("json: no owner object cannot hold ownership\n");
return CL_EARG;
}
return CL_SUCCESS;
}
|
9fdbf2c7 |
#else |
a69adec1 |
|
557c712c |
cl_error_t cli_json_nojson() |
a69adec1 |
{
nojson_func("nojson: json needs to be enabled for this feature\n");
return CL_SUCCESS;
}
|
557c712c |
cl_error_t cli_jsonnull_nojson(const char* key) |
a69adec1 |
{
nojson_func("nojson: %s: null\n", key);
return CL_SUCCESS;
}
|
557c712c |
cl_error_t cli_jsonstr_nojson(const char* key, const char* s) |
a69adec1 |
{
nojson_func("nojson: %s: %s\n", key, s);
return CL_SUCCESS;
}
|
557c712c |
cl_error_t cli_jsonstrlen_nojson(const char* key, const char* s, int len) |
b2743d5d |
{ |
288057e9 |
char* sp = cli_malloc(len + 1); |
32ad1c56 |
if (NULL == sp) { |
288057e9 |
cli_errmsg("json: no memory for json strlen object.\n");
return CL_EMEM; |
32ad1c56 |
} |
b2743d5d |
strncpy(sp, s, len);
sp[len] = '\0';
nojson_func("nojson: %s: %s\n", key, sp);
free(sp);
return CL_SUCCESS;
}
|
557c712c |
cl_error_t cli_jsonint_nojson(const char* key, int32_t i) |
a69adec1 |
{
nojson_func("nojson: %s: %d\n", key, i);
return CL_SUCCESS;
}
|
557c712c |
cl_error_t cli_jsonint64_nojson(const char* key, int64_t i) |
a69adec1 |
{
nojson_func("nojson: %s: %ld\n", key, (long int)i);
return CL_SUCCESS;
}
|
557c712c |
cl_error_t cli_jsonbool_nojson(const char* key, int i) |
a69adec1 |
{ |
288057e9 |
nojson_func("nojson: %s: %s\n", key, i ? "true" : "false"); |
dec128ce |
return CL_SUCCESS; |
a69adec1 |
}
|
557c712c |
cl_error_t cli_jsondouble_nojson(const char* key, double d) |
a69adec1 |
{
nojson_func("nojson: %s: %f\n", key, d); |
dec128ce |
return CL_SUCCESS; |
a69adec1 |
}
|
288057e9 |
void* cli_jsonarray_nojson(const char* key) |
d7ee9b81 |
{
nojson_func("nojson: %s\n", key);
return NULL;
}
|
557c712c |
cl_error_t cli_jsonint_array_nojson(int32_t val) |
d7ee9b81 |
{
nojson_func("nojson: %d\n", val); |
5899095f |
return CL_SUCCESS; |
d7ee9b81 |
}
|
9fdbf2c7 |
#endif |