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