From 7f306cbede043982eb2d9b1f1c465fb1cee6f85c Mon Sep 17 00:00:00 2001 From: Amin Ben Ramdhane Date: Mon, 13 Jun 2022 16:45:42 +0100 Subject: [PATCH] JSON: Add support for object path value --- README.md | 109 ++++++++++++++++++++++- dmdynamicjson.c | 103 ++++++++++++++++++--- test/files/etc/bbfdm/json/urlfilter.json | 38 +++++++- 3 files changed, 234 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 0e8f90d7..927e7ffd 100644 --- a/README.md +++ b/README.md @@ -440,7 +440,7 @@ The application should bring its JSON file under **'/etc/bbfdm/json/'** path wit **3. Parameter under object with instance:** -- **UCI command:** uci get wireless.@wifi-device[0].country +- **UCI option command:** uci get wireless.@wifi-device[0].country - **@i:** is the number of instance object @@ -471,6 +471,42 @@ The application should bring its JSON file under **'/etc/bbfdm/json/'** path wit } ``` +- **UCI list command:** uci get urlfilter.@profile[0].whitelist_url + +- **@i:** is the number of instance object + +```bash +"WhitelistURL": { + "type": "string", + "version": "2.14", + "read": true, + "write": true, + "protocols": [ + "cwmp", + "usp" + ], + "list": { + "datatype": "string" + }, + "mapping": [ + { + "type": "uci", + "uci": { + "file": "urlfilter", + "section": { + "type": "profile", + "index": "@i-1" + }, + "list": { + "name": "whitelist_url" + } + } + } + ] +} +``` + + - **UBUS command:** ubus call wifi status | jsonfilter -e @.radios[0].noise - **@i:** is the number of instance object @@ -500,7 +536,7 @@ The application should bring its JSON file under **'/etc/bbfdm/json/'** path wit **4. Parameter without instance:** -- **UCI command:** uci get cwmp.cpe.userid +- **UCI option command:** uci get cwmp.cpe.userid ```bash "Username": { @@ -529,6 +565,39 @@ The application should bring its JSON file under **'/etc/bbfdm/json/'** path wit } ``` +- **UCI list command:** uci get urlfilter.globals.blacklist_url + +- **@i:** is the number of instance object + +```bash +"BlacklistURL": { + "type": "string", + "read": true, + "write": true, + "protocols": [ + "cwmp", + "usp" + ], + "list": { + "datatype": "string" + }, + "mapping": [ + { + "type": "uci", + "uci": { + "file": "urlfilter", + "section": { + "name": "globals" + }, + "list": { + "name": "blacklist_url" + } + } + } + ] +} +``` + - **UBUS command:** ubus call system info | jsonfilter -e @.uptime ```bash @@ -579,7 +648,41 @@ The application should bring its JSON file under **'/etc/bbfdm/json/'** path wit } ``` -**5. Object with Event and Operate command:** +**5. Parameter to map another data model Object:** + +- **UCI option command:** uci get urlfilter.@filter[0].profile + +- **linker_obj** is the path name of an object that is stacked immediately below this object + +```bash +"Profile": { + "type": "string", + "read": true, + "write": true, + "protocols": [ + "cwmp", + "usp" + ], + "mapping": [ + { + "type": "uci", + "uci": { + "file": "urlfilter", + "section": { + "type": "filter", + "index": "@i-1" + }, + "option": { + "name": "profile" + } + }, + "linker_obj": "Device.{BBF_VENDOR_PREFIX}URLFilter.Profile." + } + ] +} +``` + +**6. Object with Event and Operate command:** ```bash { diff --git a/dmdynamicjson.c b/dmdynamicjson.c index afc10514..156243df 100644 --- a/dmdynamicjson.c +++ b/dmdynamicjson.c @@ -622,6 +622,8 @@ static char *uci_get_value(json_object *mapping_obj, int json_version, char *ref struct json_object *list = NULL; struct json_object *list_name = NULL; struct json_object *path = NULL; + struct json_object *linker_jobj = NULL; + char *linker = NULL; char *value = ""; json_object_object_get_ex(mapping_obj, "uci", &obj); @@ -634,6 +636,7 @@ static char *uci_get_value(json_object *mapping_obj, int json_version, char *ref json_object_object_get_ex(obj, "list", &list); json_object_object_get_ex(list, "name", &list_name); json_object_object_get_ex(obj, "path", &path); + json_object_object_get_ex(mapping_obj, "linker_obj", &linker_jobj); char *opt_temp = NULL; if (list_name) { @@ -642,6 +645,11 @@ static char *uci_get_value(json_object *mapping_obj, int json_version, char *ref opt_temp = json_object_get_string(option_name); } + if (linker_jobj) { + char *link = json_object_get_string(linker_jobj); + linker = replace_str(link, "{BBF_VENDOR_PREFIX}", BBF_VENDOR_PREFIX); + } + if (file && type && opt_temp && strstr(refparam, "NumberOfEntries")) { if (strcmp(opt_temp, "@Count") != 0 && json_version == JSON_VERSION_1) @@ -664,7 +672,11 @@ static char *uci_get_value(json_object *mapping_obj, int json_version, char *ref char uci_type[32] = {0}; snprintf(uci_type, sizeof(uci_type), "@%s[%ld]", json_object_get_string(type), instance ? DM_STRTOL(instance)-1 : 0); if (option) { - value = dmuci_get_value_by_path(json_object_get_string(path), json_object_get_string(file), uci_type, opt_temp); + char *res = dmuci_get_value_by_path(json_object_get_string(path), json_object_get_string(file), uci_type, opt_temp); + if (linker_jobj) + adm_entry_get_linker_param(ctx, linker, res, &value); + else + value = res; } else { struct uci_list *list_val; dmuci_get_option_value_list(json_object_get_string(file), uci_type, opt_temp, &list_val); @@ -673,7 +685,11 @@ static char *uci_get_value(json_object *mapping_obj, int json_version, char *ref } } else if (file && section_name && opt_temp) { if (option) { - value = dmuci_get_value_by_path(json_object_get_string(path), json_object_get_string(file), json_object_get_string(section_name), opt_temp); + char *res = dmuci_get_value_by_path(json_object_get_string(path), json_object_get_string(file), json_object_get_string(section_name), opt_temp); + if (linker_jobj) + adm_entry_get_linker_param(ctx, linker, res, &value); + else + value = res; } else { struct uci_list *list_val; dmuci_get_option_value_list(json_object_get_string(file), json_object_get_string(section_name), opt_temp, &list_val); @@ -929,6 +945,29 @@ static int ubus_set_operate(json_object *mapping_obj, int json_version, char *re return CMD_SUCCESS; } +static int linker_obj(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker) +{ + struct dm_json_obj *pobj = NULL; + const char **keys = NULL; + + char *obj = generate_path_without_instance(refparam, true); + list_for_each_entry(pobj, &json_list, list) { + if (DM_STRCMP(pobj->name, obj) == 0) { + keys = pobj->event_arg.param; + break; + } + } + + if (keys && keys[0]) { + char param_path[1024] = {0}; + + snprintf(param_path, sizeof(param_path), "%s%s", obj, keys[0]); + getvalue_param(param_path, dmctx, data, instance, linker); + } + + return 0; +} + static int getcommand_param(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { struct dm_json_obj *leaf = NULL; @@ -1231,6 +1270,8 @@ static void uci_set_value(json_object *mapping_obj, int json_version, char *refp struct json_object *list = NULL; struct json_object *list_name = NULL; struct json_object *path = NULL; + struct json_object *linker_jobj = NULL; + char *linker = NULL; json_object_object_get_ex(mapping_obj, "uci", &uci_obj); json_object_object_get_ex(uci_obj, "file", &file); @@ -1242,6 +1283,7 @@ static void uci_set_value(json_object *mapping_obj, int json_version, char *refp json_object_object_get_ex(uci_obj, "list", &list); json_object_object_get_ex(list, "name", &list_name); json_object_object_get_ex(uci_obj, "path", &path); + json_object_object_get_ex(mapping_obj, "linker_obj", &linker_jobj); char *opt_temp = NULL; if (list_name) { @@ -1255,7 +1297,12 @@ static void uci_set_value(json_object *mapping_obj, int json_version, char *refp snprintf(uci_type, sizeof(uci_type), "@%s[%ld]", json_object_get_string(type), instance ? DM_STRTOL(instance)-1 : 0); if (option) { - dmuci_set_value_by_path(json_object_get_string(path), json_object_get_string(file), uci_type, opt_temp, value); + if (linker_jobj) + adm_entry_get_linker_value(ctx, value, &linker); + else + linker = value; + + dmuci_set_value_by_path(json_object_get_string(path), json_object_get_string(file), uci_type, opt_temp, linker); } else { if (value != NULL) { dmuci_delete(json_object_get_string(file), uci_type, opt_temp, NULL); @@ -1269,7 +1316,12 @@ static void uci_set_value(json_object *mapping_obj, int json_version, char *refp } } else if (file && section_name && opt_temp) { if (option) { - dmuci_set_value_by_path(json_object_get_string(path), json_object_get_string(file), json_object_get_string(section_name), opt_temp, value); + if (linker_jobj) + adm_entry_get_linker_value(ctx, value, &linker); + else + linker = value; + + dmuci_set_value_by_path(json_object_get_string(path), json_object_get_string(file), json_object_get_string(section_name), opt_temp, linker); } else { if (value != NULL) { dmuci_delete(json_object_get_string(file), json_object_get_string(section_name), opt_temp, NULL); @@ -1408,12 +1460,12 @@ static bool is_obj(char *object, json_object *jobj) return false; } -static void parse_mapping_obj(char *object, json_object *mapping_obj, int json_version, struct list_head *list) +static void parse_mapping_obj(char *object, json_object *mapping_obj, const char *unique_keys[], int json_version, struct list_head *list) { if (!mapping_obj) return; - save_json_data(list, object, mapping_obj, json_version, NULL, NULL, NULL); + save_json_data(list, object, mapping_obj, json_version, NULL, NULL, unique_keys); } static bool valid_event_param(char *param) @@ -1436,7 +1488,7 @@ static bool valid_event_param(char *param) static char** fill_command_param(int count, struct json_object *obj) { char **res_p = NULL; - if (!obj) + if (!obj || !count) return res_p; res_p = malloc(sizeof(char *) * (count + 1)); @@ -1453,6 +1505,26 @@ static char** fill_command_param(int count, struct json_object *obj) return res_p; } +static char** fill_unique_keys(size_t count, struct json_object *obj) +{ + char **res_p = NULL; + if (!obj || !count) + return res_p; + + res_p = malloc(sizeof(char *) * (count + 1)); + if (res_p) { + res_p[count] = NULL; + + + for (int id = 0; id < count; id++) { + struct json_object *key_val = json_object_array_get_idx(obj, id); + res_p[id] = dm_dynamic_strdup(&json_memhead, json_object_get_string(key_val)); + } + } + + return res_p; +} + static void parse_param(char *object, char *param, json_object *jobj, DMLEAF *pleaf, int i, int json_version, struct list_head *list) { /* PARAM, permission, type, getvalue, setvalue, bbfdm_type(6)*/ @@ -1619,6 +1691,7 @@ static void parse_obj(char *object, json_object *jobj, DMOBJ *pobj, int index, i int obj_number = 0, param_number = 0, i = 0, j = 0; DMOBJ *next_obj = NULL; DMLEAF *next_leaf = NULL; + char **keys_p = NULL; count_obj_param_under_jsonobj(jobj, &obj_number, ¶m_number); char *obj_path = replace_str(object, "{BBF_VENDOR_PREFIX}", BBF_VENDOR_PREFIX); @@ -1668,6 +1741,16 @@ static void parse_obj(char *object, json_object *jobj, DMOBJ *pobj, int index, i pobj[index].bbfdm_type = BBFDM_BOTH; } + if (strcmp(key, "uniqueKeys") == 0) { + //uniqueKeys + size_t n_keys = json_obj ? json_object_array_length(json_obj) : 0; + keys_p = fill_unique_keys(n_keys, json_obj); + pobj[index].unique_keys = (const char **)keys_p; + + //linker + pobj[index].get_linker = n_keys ? linker_obj : NULL; + } + if (strcmp(key, "access") == 0) { //permission pobj[index].permission = json_object_get_boolean(json_obj) ? &DMWRITE : &DMREAD; @@ -1688,10 +1771,8 @@ static void parse_obj(char *object, json_object *jobj, DMOBJ *pobj, int index, i //nextdynamicobj pobj[index].nextdynamicobj = NULL; - - //linker - pobj[index].get_linker = NULL; } + //Version if (strcmp(key,"version") == 0) DM_STRNCPY(pobj[index].version, json_object_get_string(json_obj), 10); @@ -1699,7 +1780,7 @@ static void parse_obj(char *object, json_object *jobj, DMOBJ *pobj, int index, i if (strcmp(key, "mapping") == 0 && ((json_object_get_type(json_obj) == json_type_object && json_version == JSON_VERSION_0) || (json_object_get_type(json_obj) == json_type_array && json_version == JSON_VERSION_1))) { - parse_mapping_obj(full_obj, json_obj, json_version, list); + parse_mapping_obj(full_obj, json_obj, (const char **)keys_p, json_version, list); } if (json_object_get_type(json_obj) == json_type_object && is_obj(key, json_obj)) { diff --git a/test/files/etc/bbfdm/json/urlfilter.json b/test/files/etc/bbfdm/json/urlfilter.json index a78e330c..f95d96b7 100644 --- a/test/files/etc/bbfdm/json/urlfilter.json +++ b/test/files/etc/bbfdm/json/urlfilter.json @@ -115,6 +115,9 @@ "cwmp", "usp" ], + "uniqueKeys": [ + "Name" + ], "access": true, "array": true, "mapping": [ @@ -129,6 +132,36 @@ } } ], + "Name": { + "type": "string", + "read": true, + "write": false, + "version": "2.14", + "protocols": [ + "cwmp", + "usp" + ], + "datatype": "string", + "range": [ + { + "max": 64 + } + ], + "mapping": [ + { + "type": "uci", + "uci": { + "file": "urlfilter", + "section": { + "type": "profile" + }, + "list": { + "name": "@Name" + } + } + } + ] + }, "WhitelistURL": { "type": "string", "version": "2.14", @@ -273,11 +306,12 @@ "option": { "name": "profile" } - } + }, + "linker_obj": "Device.{BBF_VENDOR_PREFIX}URLFilter.Profile." } ] }, - "MacAddress": { + "MACAddress": { "type": "string", "version": "2.14", "read": true,