From 6f3536efa989a305eb0c9034e6b076f32cce4ca0 Mon Sep 17 00:00:00 2001 From: Jakob Olsson <Jakob Olsson> Date: Fri, 29 Nov 2019 15:26:33 +0100 Subject: [PATCH] fix compilation warnings --- CMakeLists.txt | 6 +- src/json-validator.cpp | 41 +++++++ src/json-validator.h | 9 +- src/schema.c | 252 ---------------------------------------- src/schema.cpp | 253 +++++++++++++++++++++++++++++++++++++++++ src/schema.h | 22 +++- 6 files changed, 324 insertions(+), 259 deletions(-) delete mode 100644 src/schema.c create mode 100644 src/schema.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index dbfbbe3..418e8ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,7 +65,7 @@ INTERFACE add_library(json-validator SHARED src/json-validator.cpp - src/schema.c + src/schema.cpp ) set_target_properties(json-validator @@ -104,6 +104,10 @@ target_link_libraries(json-validator PUBLIC json-hpp) +target_link_libraries(json-validator + PUBLIC + ${LIBUBOX_LIBRARIES}) + # regex with boost if gcc < 4.9 - default is std::regex if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9.0") diff --git a/src/json-validator.cpp b/src/json-validator.cpp index 20c466e..1020272 100644 --- a/src/json-validator.cpp +++ b/src/json-validator.cpp @@ -14,6 +14,7 @@ #include <json-c/json.h> #include <json-schema.hpp> +#include <regex.h> #include "schema.h" #include "json-validator.h" @@ -36,6 +37,46 @@ int schema_validator_init(void) return 0; } +bool schema_validator_validate(struct json_object *j_object, char *object, char *method, enum schema_call_t type) +{ + struct json_object *definitions, *schema; + struct schema_object *s_object; + struct schema_method *s_method; + int rv = 1; + + s_object = schema_get_object_schema(object); + if (!s_object) + return rv; + + rv = 0; + + s_method = schema_get_method_schema(object, method); + if (!s_method) + goto out; + + if (type == SCHEMA_INPUT_CALL) + schema = json_tokener_parse(s_method->input); + else if (type == SCHEMA_OUTPUT_CALL) + schema = json_tokener_parse(s_method->output); + else + goto out; + + if (!schema) + goto out; + + if (s_object->definitions) { + definitions = json_tokener_parse(s_object->definitions); + if (definitions) + json_object_object_add(schema, "definitions", definitions); + } + + rv = json_object_validate_schema(j_object, schema); + + json_object_put(schema); +out: + return rv; +} + bool json_object_validate_schema_inject_definitions(struct json_object *j_object, struct json_object *definitions, struct json_object *j_schema) { json_object_object_add(j_object, "definitions", definitions); diff --git a/src/json-validator.h b/src/json-validator.h index 279640e..6b3b3f2 100644 --- a/src/json-validator.h +++ b/src/json-validator.h @@ -4,11 +4,18 @@ extern "C" { #endif + +enum schema_call_t { + SCHEMA_INPUT_CALL, + SCHEMA_OUTPUT_CALL +}; + int schema_validator_destroy(void); int schema_validator_init(void); +bool schema_validator_validate(struct json_object *j_object, char *object, char *method, enum schema_call_t type); bool json_object_validate_schema_inject_definitions(struct json_object *j_object, struct json_object *definitions, struct json_object *j_schema); bool json_object_validate_schema(struct json_object *j_obj, struct json_object *j_schema); #ifdef __cplusplus } #endif -#endif \ No newline at end of file +#endif diff --git a/src/schema.c b/src/schema.c deleted file mode 100644 index 8cb39fa..0000000 --- a/src/schema.c +++ /dev/null @@ -1,252 +0,0 @@ -#include <libubox/avl.h> -#include <libubox/avl-cmp.h> -#include <libubox/blobmsg.h> -#include <libubox/blobmsg_json.h> -#include <libubox/utils.h> -#include <libubus.h> -#include <glob.h> -#include <stdio.h> -#include <stdlib.h> - -#include "common.h" -#include "schema.h" - -#define JSON_SCHEMA_DIR "/usr/share/rpcd/schemas" - -struct schema_context s_ctx; - -static void schema_flush_method(struct schema_method *s_method) -{ - lwsl_notice("cleaning method %s\n", (char *)s_method->avl.key); - - if (s_method->input) - free(s_method->input); - if (s_method->output) - free(s_method->output); - if (s_method->avl.key) - free((void *) s_method->avl.key); - - free(s_method); - return; -} - -static void schema_flush_methods(struct schema_object *s_object) -{ - struct schema_method *s_method, *tmp; - - lwsl_notice("flushing all methods of object %s\n", (char *)s_object->avl.key); - - avl_for_each_element_safe(&s_object->schema_methods, s_method, avl, tmp) { - avl_delete(&s_object->schema_methods, &s_method->avl); - schema_flush_method(s_method); - } - - return; -} - -static void schema_flush_object(struct schema_object *s_object) -{ - lwsl_notice("cleaning object %s\n", (char *)s_object->avl.key); - - schema_flush_methods(s_object); - free((void *)s_object->avl.key); - if (s_object->definitions) - free(s_object->definitions); - - if (s_object->regex) - regfree(&s_object->regex_exp); - - free(s_object); - - return; -} - -void schema_flush_objects(void) -{ - struct schema_object *s_object, *tmp; - - lwsl_notice("cleaning all schema objects\n"); - - avl_for_each_element_safe(&s_ctx->schema_objects, s_object, avl, tmp) { - avl_delete(&s_ctx->schema_objects, &s_object->avl); - schema_flush_object(s_object); - } - return; -} - -static void schema_parse_object(struct schema_object *schema_object, struct blob_buf *acl, struct blob_attr *object) -{ - struct blob_attr *method, *properties; - int rem, rem2; - struct schema_method *s_method; - - blobmsg_for_each_attr(properties, object, rem) { - if (strncmp(blobmsg_name(properties), "properties", 11)) - continue; - - //lwsl_notice("%s %d method name = %s\n", __func__, __LINE__, blobmsg_name(object)); - s_method = calloc(1, sizeof(*s_method)); - if (!s_method) - continue; - - s_method->avl.key = strdup(blobmsg_name(object)); - avl_insert(&schema_object->schema_methods, &s_method->avl); - - blobmsg_for_each_attr(method, properties, rem2) { - //lwsl_notice("%s %d name = %s\n", __func__, __LINE__, blobmsg_name(method)); - if (!strncmp(blobmsg_name(method), "input", 6)) { - s_method->input = blobmsg_format_json(method, true); - //lwsl_notice("input = %s\n", s_method->input); - } - else if (!strncmp(blobmsg_name(method), "output", 7)) { - s_method->output = blobmsg_format_json(method, true); - //lwsl_notice("output = %s\n", s_method->output); - } - } - } -} - -static void -schema_setup_file(const char *path) -{ - struct blob_buf acl = { 0 }; - struct blob_attr *root, *object; - int rem, rem2; - struct schema_object *schema_object; - char *definitions = NULL; - - blob_buf_init(&acl, 0); - - if (!blobmsg_add_json_from_file(&acl, path)) { - fprintf(stderr, "Failed to parse %s\n", path); - goto out; - } - - schema_object = calloc(1, sizeof(*schema_object)); - if (!schema_object) - goto out; - - avl_init(&schema_object->schema_methods, avl_strcmp, false, NULL); - - /* find the key properties of root */ - blob_for_each_attr(root, acl.head, rem) { - if (!strncmp(blobmsg_name(root), "regex", 6)) { - schema_object->regex = blobmsg_get_bool(root); - lwsl_notice("%s: regex enabled %d\n", __func__, schema_object->regex); - - } - - if (!strncmp(blobmsg_name(root), "object", 7)) { - schema_object->avl.key = strdup(blobmsg_data(root)); - if (!schema_object->avl.key) - goto out_flush; - } - - if (!strncmp(blobmsg_name(root), "definitions", 12)) - definitions = blobmsg_format_json(root, true); - - if (strncmp(blobmsg_name(root), "properties", 11)) - continue; - - /* iterate all methods */ - blobmsg_for_each_attr(object, root, rem2) { - if (blobmsg_type(object) != BLOBMSG_TYPE_TABLE) - continue; - - schema_parse_object(prog, schema_object, &acl, object); - } - } - - if (schema_object->regex) { - int rv; - lwsl_notice("parsing regex for %s!\n", schema_object->avl.key ); - rv = regcomp(&schema_object->regex_exp, (char *) schema_object->avl.key, 0); - if (rv) { - lwsl_notice("%s: invalid regex: %s, flushing validation schema!\n", __func__, (char *) schema_object->avl.key); - goto out_flush; - } - } - - if (!schema_object->avl.key) - goto out_flush; - - schema_object->definitions = definitions; - avl_insert(&s_ctx->schema_objects, &schema_object->avl); - /*avl_for_each_element(&s_ctx->schema_objects, schema_object, avl) { - lwsl_notice("%s %d key = %s\n", __func__, __LINE__, (char *) schema_object->avl.key); - }*/ -out: - blob_buf_free(&acl); - return; -out_flush: - schema_flush_object(schema_object); -} - -struct schema_method *schema_get_method_schema(const char *object, const char *method) -{ - struct schema_object *s_object; - struct schema_method *s_method; - - lwsl_notice("%s: object = %s method = %s\n", __func__, object, method); - - s_object = schema_get_object_schema(prog, object); - if (!s_object) - return NULL; - - avl_for_each_element(&s_object->schema_methods, s_method, avl) { - lwsl_notice("%s: method = %s, avl.key = %s\n", __func__, method, (char *)s_method->avl.key); - if (!strncmp(method, (char *) s_method->avl.key, METHOD_NAME_MAX_LEN)) - return s_method; - } - return NULL; -} - -const char *schema_get_definitions_schema(const char *object) -{ - struct schema_object *s_object; - - s_object = schema_get_object_schema(prog, object); - if (!s_object) - return NULL; - - return s_object->definitions; -} - -struct schema_object *schema_get_object_schema(const char *object) -{ - struct schema_object *s_object; - - lwsl_notice("%s: object = %s\n", __func__, object); - - avl_for_each_element(&s_ctx->schema_objects, s_object, avl) { - lwsl_notice("%s: object = %s, avl.key = %s, regex = %d\n", __func__, object, (char *)s_object->avl.key, s_object->regex); - if (s_object->regex) { - if (!regexec(&s_object->regex_exp, object, 0, NULL, 0)) - return s_object; - } else { - if (!strncmp(object, (char *) s_object->avl.key, OBJECT_NAME_MAX_LEN)) - return s_object; - } - } - - return NULL; -} - -void -schema_setup_json(void) -{ - int i; - glob_t gl; - - avl_init(&s_ctx->schema_objects, avl_strcmp, false, NULL); - - if (glob(JSON_SCHEMA_DIR "/*.json", 0, NULL, &gl)) - return; - - for (i = 0; i < gl.gl_pathc; i++) { - lwsl_notice("path = %s\n", gl.gl_pathv[i]); - schema_setup_file(prog, gl.gl_pathv[i]); - } - - globfree(&gl); -} diff --git a/src/schema.cpp b/src/schema.cpp new file mode 100644 index 0000000..015911d --- /dev/null +++ b/src/schema.cpp @@ -0,0 +1,253 @@ +#include <libubox/avl.h> +#include <libubox/avl-cmp.h> +#include <libubox/blobmsg.h> +#include <libubox/blobmsg_json.h> +#include <libubox/utils.h> +#include <libubus.h> +#include <glob.h> +#include <stdio.h> +#include <stdlib.h> +#include <regex.h> + +#include "schema.h" + +#define JSON_SCHEMA_DIR "/usr/share/rpcd/schemas" + +struct schema_context s_ctx; + +static void schema_flush_method(struct schema_method *s_method) +{ + fprintf(stderr, "cleaning method %s\n", (char *)s_method->avl.key); + + if (s_method->input) + free(s_method->input); + if (s_method->output) + free(s_method->output); + if (s_method->avl.key) + free((void *) s_method->avl.key); + + free(s_method); + return; +} + +static void schema_flush_methods(struct schema_object *s_object) +{ + struct schema_method *s_method, *tmp; + + fprintf(stderr, "flushing all methods of object %s\n", (char *)s_object->avl.key); + + avl_for_each_element_safe(&s_object->schema_methods, s_method, avl, tmp) { + avl_delete(&s_object->schema_methods, &s_method->avl); + schema_flush_method(s_method); + } + + return; +} + +static void schema_flush_object(struct schema_object *s_object) +{ + fprintf(stderr, "cleaning object %s\n", (char *)s_object->avl.key); + + schema_flush_methods(s_object); + free((void *)s_object->avl.key); + if (s_object->definitions) + free(s_object->definitions); + + if (s_object->regex) + regfree(&s_object->regex_exp); + + free(s_object); + + return; +} + +void schema_flush_objects(void) +{ + struct schema_object *s_object, *tmp; + + fprintf(stderr, "cleaning all schema objects\n"); + + avl_for_each_element_safe(&s_ctx.schema_objects, s_object, avl, tmp) { + avl_delete(&s_ctx.schema_objects, &s_object->avl); + schema_flush_object(s_object); + } + return; +} + +static void schema_parse_object(struct schema_object *schema_object, struct blob_attr *object) +{ + struct blob_attr *method, *properties; + int rem, rem2; + struct schema_method *s_method; + + blobmsg_for_each_attr(properties, object, rem) { + if (strncmp(blobmsg_name(properties), "properties", 11)) + continue; + + //fprintf(stderr, "%s %d method name = %s\n", __func__, __LINE__, blobmsg_name(object)); + s_method = (struct schema_method *)calloc(1, sizeof(*s_method)); + if (!s_method) + continue; + + s_method->avl.key = strdup(blobmsg_name(object)); + avl_insert(&schema_object->schema_methods, &s_method->avl); + + blobmsg_for_each_attr(method, properties, rem2) { + //fprintf(stderr, "%s %d name = %s\n", __func__, __LINE__, blobmsg_name(method)); + if (!strncmp(blobmsg_name(method), "input", 6)) { + s_method->input = blobmsg_format_json(method, true); + //fprintf(stderr, "input = %s\n", s_method->input); + } + else if (!strncmp(blobmsg_name(method), "output", 7)) { + s_method->output = blobmsg_format_json(method, true); + //fprintf(stderr, "output = %s\n", s_method->output); + } + } + } +} + +static void +schema_setup_file(const char *path) +{ + struct blob_buf acl; + struct blob_attr *root, *object; + int rem, rem2; + struct schema_object *schema_object; + char *definitions = NULL; + + memset(&acl, 0, sizeof(acl)); + blob_buf_init(&acl, 0); + + if (!blobmsg_add_json_from_file(&acl, path)) { + fprintf(stderr, "Failed to parse %s\n", path); + goto out; + } + + schema_object = (struct schema_object *) calloc(1, sizeof(*schema_object)); + if (!schema_object) + goto out; + + avl_init(&schema_object->schema_methods, avl_strcmp, false, NULL); + + /* find the key properties of root */ + blob_for_each_attr(root, acl.head, rem) { + if (!strncmp(blobmsg_name(root), "regex", 6)) { + schema_object->regex = blobmsg_get_bool(root); + fprintf(stderr, "%s: regex enabled %d\n", __func__, schema_object->regex); + + } + + if (!strncmp(blobmsg_name(root), "object", 7)) { + schema_object->avl.key = strdup(blobmsg_get_string(root)); + if (!schema_object->avl.key) + goto out_flush; + } + + if (!strncmp(blobmsg_name(root), "definitions", 12)) + definitions = blobmsg_format_json(root, true); + + if (strncmp(blobmsg_name(root), "properties", 11)) + continue; + + /* iterate all methods */ + blobmsg_for_each_attr(object, root, rem2) { + if (blobmsg_type(object) != BLOBMSG_TYPE_TABLE) + continue; + + schema_parse_object(schema_object, object); + } + } + + if (schema_object->regex) { + int rv; + fprintf(stderr, "parsing regex for %s!\n", (char *)schema_object->avl.key ); + rv = regcomp(&schema_object->regex_exp, (char *) schema_object->avl.key, 0); + if (rv) { + fprintf(stderr, "%s: invalid regex: %s, flushing validation schema!\n", __func__, (char *) schema_object->avl.key); + goto out_flush; + } + } + + if (!schema_object->avl.key) + goto out_flush; + + schema_object->definitions = definitions; + avl_insert(&s_ctx.schema_objects, &schema_object->avl); + /*avl_for_each_element(&s_ctx.schema_objects, schema_object, avl) { + fprintf(stderr, "%s %d key = %s\n", __func__, __LINE__, (char *) schema_object->avl.key); + }*/ +out: + blob_buf_free(&acl); + return; +out_flush: + schema_flush_object(schema_object); +} + +struct schema_method *schema_get_method_schema(const char *object, const char *method) +{ + struct schema_object *s_object; + struct schema_method *s_method; + + fprintf(stderr, "%s: object = %s method = %s\n", __func__, object, method); + + s_object = schema_get_object_schema(object); + if (!s_object) + return NULL; + + avl_for_each_element(&s_object->schema_methods, s_method, avl) { + fprintf(stderr, "%s: method = %s, avl.key = %s\n", __func__, method, (char *)s_method->avl.key); + if (!strncmp(method, (char *) s_method->avl.key, METHOD_NAME_MAX_LEN)) + return s_method; + } + return NULL; +} + +const char *schema_get_definitions_schema(const char *object) +{ + struct schema_object *s_object; + + s_object = schema_get_object_schema(object); + if (!s_object) + return NULL; + + return s_object->definitions; +} + +struct schema_object *schema_get_object_schema(const char *object) +{ + struct schema_object *s_object; + + fprintf(stderr, "%s: object = %s\n", __func__, object); + + avl_for_each_element(&s_ctx.schema_objects, s_object, avl) { + fprintf(stderr, "%s: object = %s, avl.key = %s, regex = %d\n", __func__, object, (char *)s_object->avl.key, s_object->regex); + if (s_object->regex) { + if (!regexec(&s_object->regex_exp, object, 0, NULL, 0)) + return s_object; + } else { + if (!strncmp(object, (char *) s_object->avl.key, OBJECT_NAME_MAX_LEN)) + return s_object; + } + } + + return NULL; +} + +void +schema_setup_json(void) +{ + int i; + glob_t gl; + + avl_init(&s_ctx.schema_objects, avl_strcmp, false, NULL); + + if (glob(JSON_SCHEMA_DIR "/*.json", 0, NULL, &gl)) + return; + + for (i = 0; i < gl.gl_pathc; i++) { + fprintf(stderr, "path = %s\n", gl.gl_pathv[i]); + schema_setup_file(gl.gl_pathv[i]); + } + + globfree(&gl); +} diff --git a/src/schema.h b/src/schema.h index 8c2b01a..3fd15f5 100644 --- a/src/schema.h +++ b/src/schema.h @@ -1,6 +1,11 @@ #ifndef SCHEMA_H #define SCHEMA_H +#ifdef __cplusplus +extern "C" +{ +#endif + #define METHOD_NAME_MAX_LEN 64 #define OBJECT_NAME_MAX_LEN 64 @@ -25,14 +30,21 @@ struct schema_object { char *definitions; + bool regex; + regex_t regex_exp; + struct avl_tree schema_methods; struct avl_node avl; }; -struct schema_method *schema_get_method_schema(const char *object, const char *method); -const char *schema_get_definitions_schema(const char *object); -struct schema_object *schema_get_object_schema(const char *object); -void schema_setup_json(); -void schema_flush_objects(); +extern struct schema_method *schema_get_method_schema(const char *object, const char *method); +extern const char *schema_get_definitions_schema(const char *object); +extern struct schema_object *schema_get_object_schema(const char *object); +extern void schema_setup_json(); +extern void schema_flush_objects(); + +#ifdef __cplusplus +} +#endif #endif \ No newline at end of file -- GitLab