OCT 1. 增加协议接口参数字段验证框架

This commit is contained in:
huangxin 2023-02-27 10:34:43 +08:00
parent b3a5ae0c6f
commit 095d15f6a5
54 changed files with 5318 additions and 17 deletions

BIN
depend/json-c-0.16.tar.gz Normal file

Binary file not shown.

View File

@ -4,6 +4,14 @@ INCLUDE(FetchContent)
PKG_SEARCH_MODULE(LIBUV QUIET libuv)
PKG_SEARCH_MODULE(LIBCONFIG QUIET libconfig)
FIND_LIBRARY(LIBZLOG zlog PATHS "/usr/local/lib")
PKG_CHECK_MODULES(LIBJSON-C QUIET json-c>=0.13)
IF (NOT LIBJSON-C_FOUND)
FETCHCONTENT_DECLARE(libjson-c
URL file://${CMAKE_SOURCE_DIR}/depend/json-c-0.16.tar.gz
URL_MD5 a549a833f886d427148fb5710c3e613e
)
ENDIF ()
IF (NOT LIBUV_FOUND)
FETCHCONTENT_DECLARE(libuv
@ -35,6 +43,10 @@ IF (LIBZLOG STREQUAL "LIBZLOG-NOTFOUND")
FETCHCONTENT_MAKEAVAILABLE(zlog)
ENDIF ()
IF (NOT LIBJSON-C_FOUND)
FETCHCONTENT_MAKEAVAILABLE(libjson-c)
ENDIF ()
IF (NOT LIBUV_FOUND)
MESSAGE(STATUS "libuv not found, will be used source code to build it ...")
FETCHCONTENT_GETPROPERTIES(libuv)
@ -76,3 +88,21 @@ ELSE ()
MESSAGE(STATUS "zlog found of ${LIBZLOG}")
LIST(APPEND COMMON_LIBS "${LIBZLOG}")
ENDIF ()
IF (NOT LIBJSON-C_FOUND)
MESSAGE(STATUS "json-c not found, will be used source code to build it ...")
FETCHCONTENT_GETPROPERTIES(libjson-c)
IF (NOT libjson-c_POPULATED)
FETCHCONTENT_POPULATE(libjson-c)
ADD_SUBDIRECTORY(${libjson-c_SOURCE_DIR} ${libjson-c_BINARY_DIR})
ENDIF ()
EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory "json-c"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${libjson-c_BINARY_DIR}/json.h" "./json-c/"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${libjson-c_BINARY_DIR}/json_config.h" "."
WORKING_DIRECTORY ${libjson-c_SOURCE_DIR})
INCLUDE_DIRECTORIES(${libjson-c_SOURCE_DIR})
LIST(APPEND COMMON_LIBS "json-c")
ELSE ()
MESSAGE(STATUS "json-c found ${LIBJSON-C_VERSION} at ${LIBJSON-C_LIBRARY_DIRS}")
LIST(APPEND COMMON_LIBS "${LIBJSON-C_LDFLAGS}")
ENDIF ()

View File

@ -2,6 +2,8 @@ SET(LIB_PROJECT_TARGET common)
PROJECT(${LIB_PROJECT_TARGET} VERSION 1.1.0)
ADD_SUBDIRECTORY(./json/json_schema)
STRING(REPLACE ";" ", " BUILD_CONFIG_INFO "${COMMON_DEFINE}")
CONFIGURE_FILE(lib_config.h.in lib_config.h)
@ -62,6 +64,8 @@ ADD_LIBRARY(${LIB_PROJECT_TARGET} ${C_SRC} ${C_HEADS})
TARGET_LINK_LIBRARIES(${LIB_PROJECT_TARGET} ${COMMON_LIBS})
TARGET_LINK_LIBRARIES(${LIB_PROJECT_TARGET} jsoncdac)
IF (USED_OPENDHCPD)
TARGET_LINK_LIBRARIES(${LIB_PROJECT_TARGET} opendhcpd)
ENDIF ()

View File

@ -0,0 +1,130 @@
# json-c d'accord library (libjsoncdac)
jsonc-daccord is a lightweight JSON Schema validation library written in C, and is taking advantage of the libjson-c library.
## Design Goals
The goal is to have a lightweight JSON Schema validation implementation in C using json-c. json-c is popular in OpenWRT communities. Initially I just wanted it to support a small subset of JSON Schema to suit a need to validate simple json files. See the minimum build supports below. However to suit a broader audience, supporting more JSON Schema is important.
Currently the footprint of libjsoncdac.so is 8KB. The keep the footprint from bloating out, new features should be selectable using CMake options.
Minimal build supports:
- all: type, enum, required, properties, const.
- objects:
- strings: minLength, maxLength.
- integers and doubles: minimum, maximum.
- arrays: minItems, maxItems, uniqeItems, items.
## Example Use
Public headers:
See [jsoncdaccord.h](include/jsoncdaccord.h)
```C
int jdac_validate_file(const char *jsonfile, const char *jsonschemafile);
int jdac_validate(json_object *jobj, json_object *jschema);
int jdac_ref_set_localpath(const char *_localpath);
const char* jdac_errorstr(unsigned int jdac_errors);
```
Link your binary to: `-ljsoncdac -ljson-c`
Use the #include header: `#include <jsoncdaccord.h>`
Example C code:
```C
#include <stdio.h>
#include <json-c/json.h>
#include <jsoncdaccord.h>
int main(int argc, char *argv[])
{
char *json_file = "test.json";
char *schema_file = "schema.json";
// optional: load referenced schema files from filesystem
char *localpath = "/my/path/to_json_files/";
jdac_ref_set_localpath(localpath);
printf("validating %s with %s\n", json_file, schema_file);
int err = jdac_validate_file(json_file, schema_file);
if (err==JDAC_ERR_VALID) {
printf("validation ok\n");
} else {
printf("validate failed %d: %s\n", err, jdac_errorstr(err));
}
return err;
}
```
See [jdac-cli.c](libjsoncdac/jdac-cli.c) as well.
## Install
Building from source:
Install json-c and libcmocka-dev (used in the debug builds).
- Release version:
```
git clone --branch libjsoncdac-0.2 https://github.com/domoslabs/jsonc-daccord &&\
cd jsonc-daccord && mkdir build && cd build &&\
cmake .. -DCMAKE_BUILD_TYPE=Release && make && sudo make install
```
- Debug version:
```
git clone --branch libjsoncdac-0.2 https://github.com/domoslabs/jsonc-daccord &&\
cd jsonc-daccord && mkdir build && cd build &&\
cmake .. -DCMAKE_BUILD_TYPE=Debug && make && sudo make install
```
Note: After install you might need to run `sudo ldconfig`.
## CMake Options
build options:
| option | description |
| :------------------------- | :------------------------------------------------------- |
| CMAKE_BUILD_TYPE | Build as Release or Debug. Default: Release. |
| RUN_TEST_SUITE | Run JSON Schema test suite (CMAKE_BUILD_TYPE=Debug Only) |
| BUILD_PATTERN | Support *pattern*. |
| BUILD_PATTERNPROPERTIES | Support *patternProperties* |
| BUILD_ADDITIONALPROPERTIES | Support *additionalProperties* |
| BUILD_PROPERTYNAMES | Support *propertyNames* |
| BUILD_SUBSCHEMALOGIC | Support *allOf*, *anyOf*, *oneOf*, *not*, *if-then-else* |
| BUILD_CONTAINS | Support *contains*, *minContains*, and *maxContains* |
| BUILD_DOWNLOAD | Support downloading referenced schema files |
| BUILD_STORE | Support build a list of schema uri, id, and anchors |
| BUILD_REF | Support *$ref* keyword. load schemas by file. |
Note: All BUILD_* options are selected by default
## Run tests
For debug builds:
```
ctest
ctest -V # to see output of tests
```
Running test suites are currently optional, and are select with `RUN_TEST_SUITE=ON` in the cmake options.
## Command Line Interface
You can try the library with the jdac-cli command.
```/tmp/domos/domosqos-sta_statistics_json
jdac-cli -h
```
## To do
- prevent infinite recursion
## Related links
- https://json-schema.org/specification.html
- https://github.com/json-schema-org/JSON-Schema-Test-Suite
- https://github.com/json-c/json-c

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
{
"botenanna": "botenannna",
"boten": "boten",
"wuhu": "wublah",
"nullobject": null
}

View File

@ -0,0 +1,7 @@
{
"empty": {},
"botenanna": {
"annaaaa": "boten"
},
"nonobject": null
}

View File

@ -0,0 +1,35 @@
{
"test-int": {
"id": 123
},
"test-double": {
"id": 1.23
},
"test-string": {
"id": "1234"
},
"test-boolean": {
"id": true
},
"test-array": [
123,
"1234"
],
"test-array2": [
123,
{}
],
"test-array": {
"anna": [
{
"id": 1
},
{
"id": 2
},
{
"id": 3
}
]
}
}

View File

@ -0,0 +1,10 @@
{
"teststring1": "one",
"teststring2": "two",
"teststring3": "three",
"teststring4": "four",
"testinteger1": 1,
"testinteger2": 2,
"testinteger3": 3,
"testinteger4": 4
}

View File

@ -0,0 +1,53 @@
{
"test1": {
"flowarray": [
{
"key1": 5,
"key2": "hanz"
}
]
},
"wrongtype": {
"flowarray": [
{
"key1": "5",
"key2": "hanz"
}
]
},
"missingkey": {
"flowarray": [
{
"key2": "hanz"
}
]
},
"nestedarray": {
"flowarray": [
{
"key1": "hanz",
"key2": [
1,
2,
3,
4,
5
]
}
]
},
"nestedarrayofstrings": {
"flowarray": [
{
"key1": "hanz",
"key2": [
"1",
"2",
"3",
"4",
"5"
]
}
]
}
}

View File

@ -0,0 +1,7 @@
{
"array-1": [1],
"array-2": [1,2],
"array-3": [1,2,3],
"array-4": [1,2,3,4],
"array-5": [1,2,3,4,5]
}

View File

@ -0,0 +1,57 @@
{
"emptyobject": {},
"testjson": {
"computer": "banana",
"phone": 12345678,
"switch": true
},
"testjsontrue": {
"computer": "banana",
"phone": 12345678,
"switch": true,
"object": {"object":123},
"list": [1,2,3]
},
"testjsonfalse": {
"computer": 12345678,
"phone": "banana",
"switch": [1,2,3],
"object": true,
"list": {"object":123}
},
"testjsonstring-all": {
"computer1": "hansihansi",
"computer2": "hans",
"computer3": "ha",
"computer4": "han"
},
"testjsonstring-all-fail": {
"computer1": "hansihansi",
"computer2": "hansi",
"computer3": "han",
"computer4": "hans"
},
"testjsonstring2": {
"computer4": "ha"
},
"testjsonstring3": {
"computer4": "han"
},
"testjsonstring4": {
"computer4": "hans"
},
"testjsonstring5": {
"computer4": "hansp"
}
}

View File

@ -0,0 +1,36 @@
{
"alltrue": {
"person": {
"name": "Anna",
"husbands": 1
}
},
"nametooshort": {
"person": {
"name": "Ann",
"husbands": 1
}
},
"wrongtype": {
"person": {
"name": "Anna",
"husbands": "1"
}
},
"husbandmissing": {
"person": {
"name": "Anna"
}
},
"namemissing": {
"person": {
}
},
"empty": {
}
}

View File

@ -0,0 +1,11 @@
{
"test-emptyjson": {},
"test-keywords-abc": {"a":"a", "b":"b", "c":"c"},
"test-keywords-bc": {"b":"b", "c":"c"},
"test-keywords-ac": {"a":"a", "c":"c"},
"test-keywords-ab": {"a":"a", "b":"b"},
"test-keywords-a": {"a":"a"},
"test-keywords-b": {"b":"b"},
"test-keywords-c": {"c":"c"},
"test-wrongtype": 123
}

View File

@ -0,0 +1,8 @@
{
"test-object" : {"1":"2"},
"test-array" : [1,2,3],
"test-string" : "101",
"test-integer" : 101,
"test-double" : 101.1,
"test-boolean" : true
}

View File

@ -0,0 +1,10 @@
{
"array-empty": [],
"array-unique1": [1,2,3,4,5,6],
"array-unique2": ["one","two","three"],
"array-notunique1": [1,2,3,3,5,6],
"array-notunique2": [1,2,3,4,5,5],
"array-notunique3": [1,1,3,4,5,6],
"array-notunique4": [1,1,1,4,5,6],
"array-notunique5": ["one", "two", "two"]
}

View File

@ -0,0 +1,106 @@
{
"truejson":
{
"ID": "lcss_vectors",
"Version": "v01",
"Services": [
{
"Service": "slitherio",
"NetifyName": "gaming.slitherio",
"max_diff": 1,
"max_length": 10,
"ValidPorts": [ [444,445] ],
"vectors": [
{
"ID": "v0",
"CT": 0,
"TT": 0,
"ignore_indices": [0,1],
"proto": "tcp",
"confidence": 10,
"vector": [1,2,3,4,5,6,7,8,9]
}
]
}
]
},
"validport_toohigh":
{
"ID": "lcss_vectors",
"Version": "v01",
"Services": [
{
"Service": "slitherio",
"NetifyName": "gaming.slitherio",
"max_diff": 1,
"max_length": 10,
"ValidPorts": [ [444,445], [50000,100000] ],
"vectors": [
{
"ID": "v0",
"CT": 0,
"TT": 0,
"ignore_indices": [0,1],
"proto": "tcp",
"confidence": 10,
"vector": [1,2,3,4,5,6,7,8,9]
}
]
}
]
},
"ignore_indices_index_too_high":
{
"ID": "lcss_vectors",
"Version": "v01",
"Services": [
{
"Service": "slitherio",
"NetifyName": "gaming.slitherio",
"max_diff": 1,
"max_length": 10,
"ValidPorts": [ [444,445] ],
"vectors": [
{
"ID": "v0",
"CT": 0,
"TT": 0,
"ignore_indices": [0,20],
"proto": "tcp",
"confidence": 10,
"vector": [1,2,3,4,5,6,7,8,9]
}
]
}
]
},
"too_many_vector_elements":
{
"ID": "lcss_vectors",
"Version": "v01",
"Services": [
{
"Service": "slitherio",
"NetifyName": "gaming.slitherio",
"max_diff": 1,
"max_length": 10,
"ValidPorts": [ [444,445] ],
"vectors": [
{
"ID": "v0",
"CT": 0,
"TT": 0,
"ignore_indices": [0,1],
"proto": "tcp",
"confidence": 10,
"vector": [0,1,2,3,4,5,6,7,8,9,10]
}
]
}
]
}
}

View File

@ -0,0 +1,760 @@
{
"ID": "lcss_vectors",
"Version": "v01",
"Services": [
{
"Service": "slitherio",
"NetifyName": "gaming.slitherio",
"ValidPorts": [
[
444,
444
]
],
"vectors": [
{
"ID": "v0",
"CT": 0,
"TT": 0,
"ignore_indices": [
0,
1
],
"proto": "tcp",
"confidence": 10,
"vector": [
0,
0
]
}
]
},
{
"Service": "steamworks",
"NetifyName": "gaming.steamworks",
"ValidPorts": [
[
4380,
4380
],
[
27000,
27100
]
],
"vectors": [
{
"ID": "v0",
"CT": 2,
"TT": 20,
"ignore_indices": [],
"proto": "udp",
"confidence": 10,
"vector": [
1300,
-214
]
},
{
"ID": "v1",
"CT": 2,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 10,
"vector": [
1300,
1300
]
}
]
},
{
"Service": "leagueoflegends",
"NetifyName": "gaming.leagueoflegends",
"ValidPorts": [
[
5000,
5500
]
],
"vectors": [
{
"ID": "v0",
"CT": 2,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 10,
"vector": [
515,
-107
]
},
{
"ID": "v1",
"CT": 2,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 10,
"vector": [
515,
515
]
}
]
},
{
"Service": "apex",
"NetifyName": "gaming.apex",
"ValidPorts": [
[
1024,
1124
],
[
18000,
18000
],
[
29900,
29900
],
[
37000,
40000
]
],
"vectors": [
{
"ID": "v0",
"CT": 2,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 10,
"vector": [
50,
-58
]
},
{
"ID": "v1",
"CT": 2,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 10,
"vector": [
50,
50
]
}
]
},
{
"Service": "rainbow6",
"NetifyName": "gaming.rainbow6",
"ValidPorts": [
[
3074,
3074
],
[
4380,
4380
],
[
6015,
6015
],
[
10000,
10099
]
],
"vectors": [
{
"ID": "v0",
"CT": 2,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 10,
"vector": [
139,
139
]
},
{
"ID": "v1",
"CT": 2,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 10,
"vector": [
139,
-131
]
}
]
},
{
"Service": "iperf3",
"NetifyName": "domos.iperf3",
"ValidPorts": [
[
5201,
5201
]
],
"vectors": [
{
"ID": "v2",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
4,
-4
]
}
]
},
{
"Service": "flent",
"NetifyName": "domos.flent",
"ValidPorts": [
[
2116,
2116
]
],
"vectors": [
{
"ID": "v2",
"ignore_indices": [],
"CT": 0,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
4,
-4
]
}
]
},
{
"Service": "unrealengine4",
"NetifyName": "gaming.unrealengine4",
"ValidPorts": [
[
12000,
65535
]
],
"vectors": [
{
"ID": "v0",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
29,
-29
]
},
{
"ID": "v1",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
29,
29
]
}
]
},
{
"Service": "overwatch",
"NetifyName": "gaming.overwatch",
"ValidPorts": [
[
26400,
27000
]
],
"vectors": [
{
"ID": "v0",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
34,
-34
]
},
{
"ID": "v1",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
34,
34
]
}
]
},
{
"Service": "valorant",
"NetifyName": "gaming.valorant",
"ValidPorts": [
[
7000,
7500
]
],
"vectors": [
{
"ID": "v0",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
53,
-33
]
},
{
"ID": "v1",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
53,
53
]
}
]
},
{
"Service": "seaofthieves",
"NetifyName": "gaming.seaofthieves",
"ValidPorts": [
[
30000,
32000
]
],
"vectors": [
{
"ID": "v0",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
51,
-88
]
},
{
"ID": "v1",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
51,
51
]
},
{
"ID": "v1",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
272,
60
]
}
]
},
{
"Service": "rust",
"NetifyName": "gaming.rust",
"ValidPorts": [
[
28015,
28015
],
[
28225,
28225
]
],
"vectors": [
{
"ID": "v0",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
1372,
-28
]
},
{
"ID": "v1",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
1372,
1372
]
}
]
},
{
"Service": "minecraft",
"NetifyName": "gaming.minecraft",
"ValidPorts": [
[
19132,
19133
],
[
19000,
20000
]
],
"vectors": [
{
"ID": "v0",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
33,
1464
]
},
{
"ID": "v1",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
33,
33
]
}
]
},
{
"Service": "gta5",
"NetifyName": "gaming.gta5",
"ValidPorts": [
[
6672,
6672
],
[
61455,
61458
]
],
"vectors": [
{
"ID": "v0",
"ignore_indices": [
1
],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
221,
0
]
},
{
"ID": "v1",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
221,
-221
]
},
{
"ID": "v3",
"ignore_indices": [
1
],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
237,
0
]
},
{
"ID": "v3",
"ignore_indices": [
1
],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
205,
0
]
},
{
"ID": "v3",
"ignore_indices": [
1
],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
141,
205
]
}
]
},
{
"Service": "starcraft2",
"NetifyName": "gaming.starcraft2",
"ValidPorts": [
[
3724,
3724
]
],
"vectors": [
{
"ID": "v0",
"CT": 2,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 10,
"vector": [
20,
-20
]
},
{
"ID": "v0",
"CT": 2,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 10,
"vector": [
20,
20
]
}
]
},
{
"Service": "video-conferencing",
"NetifyName": "video-conferencing.video-conf",
"ValidPorts": [
[
3478,
3478
]
],
"vectors": [
{
"ID": "v0",
"CT": 0,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 4,
"vector": []
}
]
},
{
"Service": "slack",
"NetifyName": "video-conferencing.slack",
"ValidPorts": [
[
22466,
22466
]
],
"vectors": [
{
"ID": "v0",
"CT": 0,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 6,
"vector": []
}
]
},
{
"Service": "webex",
"NetifyName": "video-conferencing.webex",
"ValidPorts": [
[
9000,
9000
]
],
"vectors": [
{
"ID": "v0",
"CT": 0,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 6,
"vector": []
}
]
},
{
"Service": "meet",
"NetifyName": "video-conferencing.meet",
"ValidPorts": [
[
19302,
19309
]
],
"vectors": [
{
"ID": "v0",
"CT": 0,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 6,
"vector": []
}
]
},
{
"Service": "zoom",
"NetifyName": "video-conferencing.zoom",
"ValidPorts": [
[
3478,
3479
],
[
8801,
8802
]
],
"vectors": [
{
"ID": "v0",
"CT": 0,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 6,
"vector": []
}
]
},
{
"Service": "bluejeans",
"NetifyName": "video-conferencing.bluejeans",
"ValidPorts": [
[
5000,
5000
]
],
"vectors": [
{
"ID": "v0",
"CT": 0,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 6,
"vector": []
}
]
},
{
"Service": "teams/skype",
"NetifyName": "video-conferencing.teams/skype",
"ValidPorts": [
[
3478,
3481
]
],
"vectors": [
{
"ID": "v0",
"CT": 0,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 6,
"vector": []
}
]
}
]
}

View File

@ -0,0 +1,769 @@
{
"ID": "lcss_vectors",
"Version": "v01",
"Services": [
{
"Service": "slitherio",
"NetifyName": "gaming.slitherio",
"max_diff": 1,
"max_length": 10,
"ValidPorts": [
[
444,
444
]
],
"vectors": [
{
"ID": "v0",
"TT": 0,
"ignore_indices": [
0,
1
],
"proto": "tcp",
"confidence": 10,
"vector": [
0,
0
]
}
]
},
{
"Service": "steamworks",
"NetifyName": "gaming.steamworks",
"max_diff": 1,
"max_length": 10,
"ValidPorts": [
[
4380,
4380
],
[
27000,
27100
]
],
"vectors": [
{
"ID": "v0",
"CT": 2,
"TT": 20,
"ignore_indices": [],
"proto": "udp",
"confidence": 10,
"vector": [
1300,
-214
]
},
{
"ID": "v1",
"CT": 2,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 10,
"vector": [
1300,
1300
]
}
]
},
{
"Service": "leagueoflegends",
"NetifyName": "gaming.leagueoflegends",
"max_diff": 1,
"max_length": 10,
"ValidPorts": [
[
5000,
5500
]
],
"vectors": [
{
"ID": "v0",
"CT": 2,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 10,
"vector": [
515,
-107
]
},
{
"ID": "v1",
"CT": 2,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 10,
"vector": [
515,
515
]
}
]
},
{
"Service": "apex",
"NetifyName": "gaming.apex",
"max_diff": 1,
"max_length": 10,
"ValidPorts": [
[
1024,
1124
],
[
18000,
18000
],
[
29900,
29900
],
[
37000,
40000
]
],
"vectors": [
{
"ID": "v0",
"CT": 2,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 10,
"vector": [
50,
-58
]
},
{
"ID": "v1",
"CT": 2,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 10,
"vector": [
50,
50
]
}
]
},
{
"Service": "rainbow6",
"NetifyName": "gaming.rainbow6",
"max_diff": 1,
"max_length": 10,
"ValidPorts": [
[
3074,
3074
],
[
4380,
4380
],
[
6015,
6015
],
[
10000,
10099
]
],
"vectors": [
{
"ID": "v0",
"CT": 2,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 10,
"vector": [
139,
139
]
},
{
"ID": "v1",
"CT": 2,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 10,
"vector": [
139,
-131
]
}
]
},
{
"Service": "iperf3",
"NetifyName": "domos.iperf3",
"ValidPorts": [
[
5201,
5201
]
],
"vectors": [
{
"ID": "v2",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
4,
-4
]
}
]
},
{
"Service": "flent",
"NetifyName": "domos.flent",
"ValidPorts": [
[
2116,
2116
]
],
"vectors": [
{
"ID": "v2",
"ignore_indices": [],
"CT": 0,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
4,
-4
]
}
]
},
{
"Service": "unrealengine4",
"NetifyName": "gaming.unrealengine4",
"ValidPorts": [
[
12000,
65535
]
],
"vectors": [
{
"ID": "v0",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
29,
-29
]
},
{
"ID": "v1",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
29,
29
]
}
]
},
{
"Service": "overwatch",
"NetifyName": "gaming.overwatch",
"ValidPorts": [
[
26400,
27000
]
],
"vectors": [
{
"ID": "v0",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
34,
-34
]
},
{
"ID": "v1",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
34,
34
]
}
]
},
{
"Service": "valorant",
"NetifyName": "gaming.valorant",
"ValidPorts": [
[
7000,
7500
]
],
"vectors": [
{
"ID": "v0",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
53,
-33
]
},
{
"ID": "v1",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
53,
53
]
}
]
},
{
"Service": "seaofthieves",
"NetifyName": "gaming.seaofthieves",
"ValidPorts": [
[
30000,
32000
]
],
"vectors": [
{
"ID": "v0",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
51,
-88
]
},
{
"ID": "v1",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
51,
51
]
},
{
"ID": "v1",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
272,
60
]
}
]
},
{
"Service": "rust",
"NetifyName": "gaming.rust",
"ValidPorts": [
[
28015,
28015
],
[
28225,
28225
]
],
"vectors": [
{
"ID": "v0",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
1372,
-28
]
},
{
"ID": "v1",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
1372,
1372
]
}
]
},
{
"Service": "minecraft",
"NetifyName": "gaming.minecraft",
"ValidPorts": [
[
19132,
19133
],
[
19000,
20000
]
],
"vectors": [
{
"ID": "v0",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
33,
1464
]
},
{
"ID": "v1",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
33,
33
]
}
]
},
{
"Service": "gta5",
"NetifyName": "gaming.gta5",
"ValidPorts": [
[
6672,
6672
],
[
61455,
61458
]
],
"vectors": [
{
"ID": "v0",
"ignore_indices": [
1
],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
221,
0
]
},
{
"ID": "v1",
"ignore_indices": [],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
221,
-221
]
},
{
"ID": "v3",
"ignore_indices": [
1
],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
237,
0
]
},
{
"ID": "v3",
"ignore_indices": [
1
],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
205,
0
]
},
{
"ID": "v3",
"ignore_indices": [
1
],
"CT": 2,
"TT": 0,
"proto": "udp",
"confidence": 10,
"vector": [
141,
205
]
}
]
},
{
"Service": "starcraft2",
"NetifyName": "gaming.starcraft2",
"ValidPorts": [
[
3724,
3724
]
],
"vectors": [
{
"ID": "v0",
"CT": 2,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 10,
"vector": [
20,
-20
]
},
{
"ID": "v0",
"CT": 2,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 10,
"vector": [
20,
20
]
}
]
},
{
"Service": "video-conferencing",
"NetifyName": "video-conferencing.video-conf",
"ValidPorts": [
[
3478,
3478
]
],
"vectors": [
{
"ID": "v0",
"CT": 0,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 4,
"vector": []
}
]
},
{
"Service": "slack",
"NetifyName": "video-conferencing.slack",
"ValidPorts": [
[
22466,
22466
]
],
"vectors": [
{
"ID": "v0",
"CT": 0,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 6,
"vector": []
}
]
},
{
"Service": "webex",
"NetifyName": "video-conferencing.webex",
"ValidPorts": [
[
9000,
9000
]
],
"vectors": [
{
"ID": "v0",
"CT": 0,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 6,
"vector": []
}
]
},
{
"Service": "meet",
"NetifyName": "video-conferencing.meet",
"ValidPorts": [
[
19302,
19309
]
],
"vectors": [
{
"ID": "v0",
"CT": 0,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 6,
"vector": []
}
]
},
{
"Service": "zoom",
"NetifyName": "video-conferencing.zoom",
"ValidPorts": [
[
3478,
3479
],
[
8801,
8802
]
],
"vectors": [
{
"ID": "v0",
"CT": 0,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 6,
"vector": []
}
]
},
{
"Service": "bluejeans",
"NetifyName": "video-conferencing.bluejeans",
"ValidPorts": [
[
5000,
5000
]
],
"vectors": [
{
"ID": "v0",
"CT": 0,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 6,
"vector": []
}
]
},
{
"Service": "teams/skype",
"NetifyName": "video-conferencing.teams/skype",
"ValidPorts": [
[
3478,
3481
]
],
"vectors": [
{
"ID": "v0",
"CT": 0,
"TT": 0,
"ignore_indices": [],
"proto": "udp",
"confidence": 6,
"vector": []
}
]
}
]
}

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,68 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "Represents a collection of flows. For testing ref defs",
"type": "object",
"properties": {
"flows": {
"type": "array",
"items": {
"$ref": "#/$defs/flow"
}
}
},
"required": [
"flows"
],
"$defs": {
"flow": {
"type": "object",
"properties": {
"flow_id": {
"type": "string"
},
"service_name": {
"type": "string"
},
"master_protocol": {
"type": "string"
},
"sport": {
"type": "integer"
},
"dport": {
"type": "integer"
},
"src": {
"type": "string"
},
"dst": {
"type": "string"
},
"proto": {
"type": "string"
},
"alive": {
"type": "string"
},
"active": {
"type": "boolean"
},
"extrakeythatdoesnotexist": {
"type": "string"
}
},
"required": [
"flow_id",
"service_name",
"master_protocol",
"sport",
"dport",
"src",
"dst",
"proto",
"alive",
"active"
]
}
}
}

View File

@ -0,0 +1,12 @@
{
"description": "string pattern side tests",
"schema-non-object": {
"pattern": true
},
"schema-invalid-regex": {
"pattern": "^[a-zA-Z0-9]*@[a-zA-Z0-9-_.]*[.]*?"
},
"schema-valid": {
"pattern": "boten*"
}
}

View File

@ -0,0 +1,23 @@
{
"description": "patternProperties side tests",
"schema-non-object": {
"patternProperties": true
},
"schema-invalid-regex": {
"patternProperties": {
"^[a-zA-Z0-9]*@[a-zA-Z0-9-_.]*[.]*?": {
"type": "object"
}
}
},
"schema-valid": {
"patternProperties": {
"boten*": {
"type": "string"
},
"anna.*": {
"type": "string"
}
}
}
}

View File

@ -0,0 +1,51 @@
{
"acceptstringandinteger": {
"$schema": "https://json-schema.org/draft/2019-09/schema",
"type": "object",
"anyOf": [
{
"properties": {
"id": {
"type": "integer"
}
}
},
{
"properties": {
"id": {
"type": "string"
}
}
}
],
"required": [
"id"
]
},
"inarray": {
"$schema": "https://json-schema.org/draft/2019-09/schema",
"type": "object",
"properties": {
"anna": {
"type": "array",
"items": {
"anyOf": [
{
"type": "object",
"required": [
"id"
]
}
]
}
}
}
},
"anyOfSchemaError": {
"$schema": "https://json-schema.org/draft/2019-09/schema",
"type": "object",
"anyOf": [
"type"
]
}
}

View File

@ -0,0 +1,22 @@
{
"enum-string": {
"type": "string",
"enum": [
"one",
"two",
"three"
]
},
"enum-integer": {
"type": "integer",
"enum": [
1,
2,
3
]
},
"enum-schemaerror": {
"type": "integer",
"enum": "1,2,3"
}
}

View File

@ -0,0 +1,51 @@
{
"test1": {
"type": "object",
"properties": {
"flowarray": {
"type": "array",
"items": {
"type": "object",
"required": [
"key1",
"key2"
],
"properties": {
"key1": {
"type": "integer"
},
"key2": {
"type": "string"
},
}
}
}
}
},
"nested": {
"type": "object",
"properties": {
"flowarray": {
"type": "array",
"items": {
"type": "object",
"required": [
"key1",
"key2"
],
"properties": {
"key1": {
"type": "string"
},
"key2": {
"type": "array",
"items": {
"type": "integer"
}
},
}
}
}
}
}
}

View File

@ -0,0 +1,7 @@
{
"schema-2-3": {
"type": "array",
"maxItems": 3,
"minItems": 2
}
}

View File

@ -0,0 +1,80 @@
{
"noproperties":
{
"type": "object"
},
"emptyproperties":
{
"type": "object",
"properties": {}
},
"typetests":
{
"type": "object",
"properties": {
"computer": {
"type": "string"
},
"phone": {
"type": "integer"
},
"switch": {
"type": "boolean"
},
"object": {
"type": "object"
},
"list": {
"type": "array"
}
}
},
"typetests2":
{
"type": "object",
"properties": {
"computer": {
"type": "string"
},
"phone": {
"type": "integer"
},
"switch": {
"type": "boolean"
},
"object": {
"type": "object"
},
"list": {
"type": "array"
}
}
},
"string-properties":
{
"type": "object",
"properties": {
"computer1": {
"type": "string"
},
"computer2": {
"type": "string",
"maxLength": 4
},
"computer3": {
"type": "string",
"minLength": 2,
"maxLength": 2
},
"computer4": {
"type": "string",
"minLength": 3,
"maxLength": 4
}
}
}
}

View File

@ -0,0 +1,14 @@
{
"type": "object",
"properties": {
"person": {
"type": "object",
"properties": {
"name": {"type": "string", "minLength": 4},
"husbands": {"type": "integer"}
},
"required": ["name"]
}
},
"required": ["person"]
}

View File

@ -0,0 +1,12 @@
{
"test-emptyschema": {},
"test-norequired": {"type": "object"},
"test-required-empty": {"type": "object", "required": []},
"test-require-abc": {"type": "object", "required": ["a","b","c"]},
"test-require-bc": {"type": "object", "required": ["b","c"]},
"test-require-ac": {"type": "object", "required": ["a","c"]},
"test-require-ab": {"type": "object", "required": ["a","b"]},
"test-require-a": {"type": "object", "required": ["a"]},
"test-require-b": {"type": "object", "required": ["b"]},
"test-require-c": {"type": "object", "required": ["c"]}
}

View File

@ -0,0 +1,12 @@
{
"test-object" : {"type": "object"},
"test-array" : {"type": "array"},
"test-string" : {"type": "string"},
"test-integer" : {"type": "integer"},
"test-double" : {"type": "double"},
"test-boolean" : {"type": "boolean"},
"test-nonsense" : {"type": "nonsense"},
"test-nonstring" : {"type": 1 },
"test-nonstring2" : {"type": {"type": "yes" } }
}

View File

@ -0,0 +1,14 @@
{
"unique": {
"type": "array",
"uniqueItems": true
},
"notunique": {
"type": "array",
"uniqueItems": false
},
"schemaerror": {
"type": "array",
"uniqueItems": 1
}
}

View File

@ -0,0 +1,127 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"ID",
"Version",
"Services"
],
"properties": {
"ID": {
"type": "string",
"enum": [
"lcss_vectors"
]
},
"Version": {
"type": "string",
"minLength": 2
},
"Services": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [
"Service",
"NetifyName",
"ValidPorts",
"vectors"
],
"properties": {
"Service": {
"type": "string",
"minLength": 4
},
"NetifyName": {
"type": "string",
"minLength": 4
},
"max_diff": {
"type": "integer"
},
"max_length": {
"type": "integer"
},
"ValidPorts": {
"type": "array",
"minItems": 1,
"items": {
"type": "array",
"minItems": 2,
"maxItems": 2,
"items": {
"type": "integer",
"minimum": 1,
"maximum": 65535
}
}
},
"vectors": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [
"ID",
"CT",
"TT",
"ignore_indices",
"proto",
"confidence",
"vector"
],
"properties": {
"ID": {
"type": "string",
"enum": [
"v0",
"v1",
"v2",
"v3"
]
},
"CT": {
"type": "integer",
"minimum": 0
},
"TT": {
"type": "integer",
"minimum": 0
},
"ignore_indices": {
"type": "array",
"maxItems": 10,
"items": {
"type": "integer",
"minimum": 0,
"maximum": 9
}
},
"proto": {
"type": "string",
"enum": [
"tcp",
"udp"
]
},
"confidence": {
"type": "integer"
},
"vector": {
"type": "array",
"maxItems": 10,
"items": {
"type": "integer",
"minimum": -1500,
"maximum": 1500
}
}
}
}
}
}
}
}
}
}

View File

@ -0,0 +1,26 @@
#ifndef __INTERNAL_H
#define __INTERNAL_H
#include <json-c/json.h>
int _jdac_load(const char *jsonfile, const char *jsonschema);
int __jdac_inspect_type(json_object *jobj, const char *type);
int _jdac_check_type (json_object *jobj, json_object *jschema);
int _jdac_check_required (json_object *jobj, json_object *jschema);
int _jdac_check_properties (json_object *jobj, json_object *jschema);
int _jdac_check_prefixItems_and_items (json_object *jobj, json_object *jschema);
int _jdac_value_is_equal (json_object *jobj1, json_object *jobj2);
int _jdac_check_const (json_object *jobj, json_object *jschema);
int _jdac_check_enums (json_object *jobj, json_object *jschema);
int _jdac_check_uniqueItems (json_object *jobj, json_object *jschema);
int _jdac_check_maxmin_items (json_object *jobj, json_object *jschema);
int _jdac_validate_array (json_object *jobj, json_object *jschema);
int _jdac_validate_object (json_object *jobj, json_object *jschema);
int _jdac_validate_string (json_object *jobj, json_object *jschema);
int _jdac_validate_integer (json_object *jobj, json_object *jschema);
int _jdac_validate_double (json_object *jobj, json_object *jschema);
int _jdac_validate_number (json_object *jobj, json_object *jschema, double value);
int _jdac_validate_boolean (json_object *jobj, json_object *jschema);
int _jdac_validate_instance (json_object *jobj, json_object *jschema);
#endif // __INTERNAL_H

View File

@ -0,0 +1,40 @@
#ifndef __JSONCDACCORD_H
#define __JSONCDACCORD_H
#include <json-c/json.h>
enum jdac_errors {
JDAC_ERR_VALID = 0,
JDAC_ERR_GENERAL_ERROR,
JDAC_ERR_JSON_NOT_FOUND,
JDAC_ERR_SCHEMA_NOT_FOUND,
JDAC_ERR_WRONG_ARGS,
JDAC_ERR_SCHEMA_ERROR,
JDAC_ERR_INVALID,
JDAC_ERR_INVALID_TYPE,
JDAC_ERR_INVALID_REQUIRED,
JDAC_ERR_INVALID_SUBSCHEMALOGIC,
JDAC_ERR_INVALID_CONST,
JDAC_ERR_INVALID_ENUMS,
JDAC_ERR_INVALID_STRLEN,
JDAC_ERR_INVALID_UNIQUEITEMS,
JDAC_ERR_INVALID_PREFIXITEMS,
JDAC_ERR_INVALID_ITEMS,
JDAC_ERR_INVALID_CONTAINS,
JDAC_ERR_INVALID_ARRAYLEN,
JDAC_ERR_INVALID_NUMBER,
JDAC_ERR_INVALID_PATTERNMATCH,
JDAC_ERR_INVALID_REF,
JDAC_REGEX_MISMATCH,
JDAC_REGEX_MATCH,
JDAC_REGEX_COMPILE_FAILED,
JDAC_ERR_MAX
};
int jdac_validate_file(const char *jsonfile, const char *jsonschemafile);
int jdac_validate(json_object *jobj, json_object *jschema);
int jdac_ref_set_localpath(const char *_localpath);
const char *jdac_errorstr(unsigned int jdac_errors);
#endif //__JSONCDACCORD_H

View File

@ -0,0 +1,36 @@
#ifndef __OPTIONAL_H
#define __OPTIONAL_H
#include <json-c/json.h>
typedef struct storage_node {
char JSONPtrURI[128];
char id[128];
char anchor[32];
char dynamicAnchor[32];
json_object *json_instance_ptr;
json_object *json_schema_ptr;
int is_root;
struct storage_node *next;
} storage_node;
int _jdac_match_string_with_regex(const char* regex_pattern, const char* value);
int _jdac_check_pattern(json_object *jobj, json_object *jschema);
int _jdac_check_patternproperties(json_object *jobj, json_object *jschema);
int _jdac_check_additionalproperties(json_object *jobj, json_object *jschema);
int _jdac_check_propertynames(json_object *jobj, json_object *jschema);
int _jdac_check_subschemalogic(json_object *jobj, json_object *jschema);
int _jdac_check_contains_and_minmaxcontains(json_object *jobj, json_object *jschema);
char* _jdac_download_schema(const char *url);
const char* _jdac_download_resolve(const char *uri);
int _jdac_store_traverse_json(storage_node **head, json_object *jschema, char *pathbuffer);
void _jdac_store_free(storage_node **head);
void _jdac_store_print(storage_node *head);
json_object* _jdac_store_resolve(storage_node *list, const char *uri);
storage_node* _jdac_store_get_root_node(storage_node *head);
int _jdac_check_ref(json_object *jobj, json_object *jschema, storage_node *storage_list);
#endif // __OPTIONAL_H

View File

@ -10,6 +10,8 @@ extern "C" {
#endif
#include <s2j/cJSON.h>
#define JSON_SCHEMA_ON (1)
typedef enum {
CRYPTO_NONE = 0,
CRYPTO_BASE64 = 1,
@ -19,7 +21,7 @@ typedef enum {
} PROTO_CRYPTO_TYPE;
const char *proto_create_new(cJSON *pMsgCtx, int httpCode);
const char *proto_decode_context(const char *pString, unsigned int *pVer, unsigned long long *pTm);
const char *proto_decode_context(const char *pString, unsigned int *pVer, unsigned long long *pTm, int *pErrCode);
#ifdef __cplusplus
}
#endif

View File

@ -51,17 +51,18 @@ extern "C" {
ERR_CODE(ERR_MQ_SEND_MSG, 37, "消息队列发送消息失败") \
ERR_CODE(ERR_JSON_CREAT_OBJ, 38, "创建JSON对象失败") \
ERR_CODE(ERR_JSON_PRASE_OBJ, 39, "解析JSON对象失败") \
ERR_CODE(ERR_CREATE_NETIF, 40, "创建网络接口失败") \
ERR_CODE(ERR_CREATE_PPPOE_NETIF, 41, "创建PPPoE网络接口失败") \
ERR_CODE(ERR_CREATE_PPP_SESSION, 42, "创建PPP连接失败") \
ERR_CODE(ERR_MISC_GET_IPADDR, 43, "获取网卡IP地址失败") \
ERR_CODE(ERR_MISC_GET_NETMASK, 44, "获取网卡子网掩码失败") \
ERR_CODE(ERR_MISC_GET_GATEWAY, 45, "获取网卡网关地址失败") \
ERR_CODE(ERR_MISC_GET_MACADDR, 46, "获取网卡MAC地址失败") \
ERR_CODE(ERR_MENU_EXIT, 47, "菜单执行完后自动退出") \
ERR_CODE(ERR_HTTP_UNSUP_METHOD, 48, "不支持的 HTTP 请求方法") \
ERR_CODE(ERR_HTTP_UNSUP_PAGE, 49, "找不到 HTTP 服务") \
ERR_CODE(ERR_PROTO_DECODE, 50, "HTTP 协议解析失败")
ERR_CODE(ERR_JSON_VALID_SCH, 40, "JSON数据验证失败") \
ERR_CODE(ERR_CREATE_NETIF, 41, "创建网络接口失败") \
ERR_CODE(ERR_CREATE_PPPOE_NETIF, 42, "创建PPPoE网络接口失败") \
ERR_CODE(ERR_CREATE_PPP_SESSION, 43, "创建PPP连接失败") \
ERR_CODE(ERR_MISC_GET_IPADDR, 44, "获取网卡IP地址失败") \
ERR_CODE(ERR_MISC_GET_NETMASK, 45, "获取网卡子网掩码失败") \
ERR_CODE(ERR_MISC_GET_GATEWAY, 46, "获取网卡网关地址失败") \
ERR_CODE(ERR_MISC_GET_MACADDR, 47, "获取网卡MAC地址失败") \
ERR_CODE(ERR_MENU_EXIT, 48, "菜单执行完后自动退出") \
ERR_CODE(ERR_HTTP_UNSUP_METHOD, 49, "不支持的 HTTP 请求方法") \
ERR_CODE(ERR_HTTP_UNSUP_PAGE, 50, "找不到 HTTP 服务") \
ERR_CODE(ERR_PROTO_DECODE, 51, "HTTP 协议解析失败")
#define GENERATE_ENUM(ENUM, no, x) ENUM,

View File

@ -0,0 +1,42 @@
INCLUDE_DIRECTORIES(../../include/json_schema)
SET(jsoncdac_SOURCES validate.c)
LIST(APPEND OPTIONAL
pattern patternproperties additionalproperties propertynames subschemalogic
contains store ref)
FOREACH (src ${OPTIONAL})
STRING(TOUPPER ${src} srcupper)
OPTION(BUILD_${srcupper} "${src} option" ON)
IF (BUILD_${srcupper})
LIST(APPEND SUPPORTED_OPTIONAL ${src})
SET(jsoncdac_SOURCES ${jsoncdac_SOURCES} ${src}.c)
ADD_DEFINITIONS(-DJDAC_${srcupper})
ENDIF ()
ENDFOREACH ()
IF (BUILD_PATTERNPROPERTIES OR BUILD_PATTERN)
SET(jsoncdac_SOURCES ${jsoncdac_SOURCES} regex_match.c)
#set(EXTRA_LIBS regex)
ENDIF ()
# always supported
LIST(APPEND SUPPORTED_BASE type enum required properties anyOf minLength maxLength minimum maximum const)
LIST(APPEND SUPPORTED_BASE minItems maxItems uniqueItems items)
STRING(REPLACE ";" "," SUPPORTED_BASE_STR "${SUPPORTED_BASE}")
STRING(REPLACE ";" "," SUPPORTED_OPTIONAL_STR "${SUPPORTED_OPTIONAL}")
ADD_LIBRARY(jsoncdac STATIC ${jsoncdac_SOURCES})
TARGET_COMPILE_DEFINITIONS(jsoncdac PRIVATE "SUPPORTED_KEYWORDS_BASE=\"${SUPPORTED_BASE_STR}\"" "SUPPORTED_KEYWORDS_OPTIONAL=\"${SUPPORTED_OPTIONAL_STR}\"")
TARGET_LINK_LIBRARIES(jsoncdac ${EXTRA_LIBS})
SET_TARGET_PROPERTIES(
jsoncdac
PROPERTIES
OUTPUT_NAME jsoncdac
PUBLIC_HEADER "${HEADER_FILES}"
VERSION 0.0.2
SOVERSION 1
)

View File

@ -0,0 +1,58 @@
#include "jsoncdaccord.h"
#include "internal.h"
#include "optional.h"
int _jdac_check_additionalproperties(json_object *jobj, json_object *jschema) {
json_object *jaddprops = json_object_object_get(jschema, "additionalProperties");
if (!jaddprops) {
return JDAC_ERR_VALID;
}
if (!json_object_is_type(jaddprops, json_type_object) && !json_object_is_type(jaddprops, json_type_boolean)) {
return JDAC_ERR_SCHEMA_ERROR;
}
json_object *jprops = json_object_object_get(jschema, "properties");
#ifdef JDAC_PATTERNPROPERTIES
json_object *jpatprops = json_object_object_get(jschema, "patternProperties");
#endif
json_object_object_foreach(jobj, jobj_key, jobj_val) {
// if an instance key is found in properties, it is not an additional property
if (jprops) {
json_object *jprop = json_object_object_get(jprops, jobj_key);
if (jprop) {
continue; // ignore properties
}
}
// if an instance key has a match in patternProperties, it is not an additional property
#ifdef JDAC_PATTERNPROPERTIES
int foundpatternproperty = 0;
if (jpatprops) {
if (json_object_is_type(jpatprops, json_type_object)) {
json_object_object_foreach(jpatprops, jpat_key, jpat_val) {
int ret = _jdac_match_string_with_regex(jpat_key, jobj_key);
if (ret == JDAC_REGEX_MATCH) {
foundpatternproperty = 1;
break;
}
}
}
if (foundpatternproperty) {
continue;
}
}
#endif
// by this point we consider the instance to be an additional property
int err = _jdac_validate_instance(jobj_val, jaddprops);
if (err) {
return err;
}
}
return JDAC_ERR_VALID;
}

View File

@ -0,0 +1,53 @@
#include "jsoncdaccord.h"
#include "internal.h"
#include "optional.h"
int _jdac_check_contains_and_minmaxcontains(json_object *jobj, json_object *jschema) {
int err;
json_object *jcontains = json_object_object_get(jschema, "contains");
if (!jcontains) {
return JDAC_ERR_VALID;
}
if (!json_object_is_type(jcontains, json_type_object) && !json_object_is_type(jcontains, json_type_boolean)) {
return JDAC_ERR_SCHEMA_ERROR;
}
int arraylen = json_object_array_length(jobj);
int match_count = 0;
for (int i = 0; i < arraylen; i++) {
json_object *iobj = json_object_array_get_idx(jobj, i);
err = _jdac_validate_instance(iobj, jcontains);
if (err == JDAC_ERR_VALID) {
match_count++;
} else if (err == JDAC_ERR_SCHEMA_ERROR) {
return JDAC_ERR_SCHEMA_ERROR;
}
}
json_object *jmaxcontains = json_object_object_get(jschema, "maxContains");
if (jmaxcontains) {
int max = json_object_get_int(jmaxcontains);
if (match_count > max) {
return JDAC_ERR_INVALID_CONTAINS;
}
}
json_object *jmincontains = json_object_object_get(jschema, "minContains");
if (jmincontains) {
int min = json_object_get_int(jmincontains);
if (min == 0) {
return JDAC_ERR_VALID;
} else if (match_count < min) {
return JDAC_ERR_INVALID_CONTAINS;
}
}
if (match_count == 0) {
return JDAC_ERR_INVALID_CONTAINS;
}
return JDAC_ERR_VALID;
}

View File

@ -0,0 +1,55 @@
#include <stdio.h>
#include <string.h>
#include <json-c/json.h>
#include <curl/curl.h>
#include "jsoncdaccord.h"
#include "internal.h"
#include "optional.h"
struct curlmemory {
char *response;
size_t size;
};
static size_t cb(void *data, size_t size, size_t nmemb, void *userp) {
size_t realsize = size * nmemb;
struct curlmemory *mem = (struct curlmemory *)userp;
char *ptr = realloc(mem->response, mem->size + realsize + 1);
if (ptr == NULL) {
return 0; /* out of memory! */
}
mem->response = ptr;
memcpy(&(mem->response[mem->size]), data, realsize);
mem->size += realsize;
mem->response[mem->size] = 0;
return realsize;
}
char *_jdac_download_schema(const char *url) {
struct curlmemory chunk = {0};
CURL *curl = curl_easy_init();
if (curl) {
CURLcode res;
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cb);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
}
curl_easy_cleanup(curl);
}
return chunk.response;
}
const char *_jdac_download_resolve(const char *uri) {
int len = strlen(uri);
if (len > 8 && strncmp(uri, "http", 4) == 0) {
return uri;
}
return NULL;
}

View File

@ -0,0 +1,103 @@
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include "../include/jsoncdaccord.h"
#include "version_config.h"
char *json_file=NULL, *schema_file=NULL;
void usage()
{
printf("\nUsage:\n");
printf(" jdac-cli -j jsonfile -s schemafile [options]\n\n");
printf(" options:\n");
#ifdef JDAC_REF
printf(" --loadlocal, -l referenced schemas at local filelocationl\n");
#endif
printf(" --version, -v Show version and supported JSON Schema keywords\n");
printf(" --help, -h Show this\n\n");
}
void freeall()
{
if (json_file) free(json_file);
if (schema_file) free(schema_file);
}
int main(int argc, char *argv[])
{
int c;
while (1) {
int option_index = 0;
static struct option long_options[] = {
{"json", required_argument, 0, 'j'},
{"schema", required_argument, 0, 's'},
#ifdef JDAC_REF
{"loadlocal", required_argument, 0, 'l'},
#endif
{"version", no_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0 }
};
c = getopt_long(argc, argv, "j:s:l:v",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'j':
json_file = strdup(optarg);
break;
case 's':
schema_file = strdup(optarg);
break;
#ifdef JDAC_REF
case 'l':
jdac_ref_set_localpath(optarg);
break;
#endif
case 'v':
printf("jdac-cli (%s version %s)\n", PROJECT_NAME, PROJECT_VER);
printf("supported keywords:\n");
printf(" - base: %s\n", SUPPORTED_KEYWORDS_BASE);
printf(" - selected: %s\n\n", SUPPORTED_KEYWORDS_OPTIONAL);
freeall();
return 0;
break;
case 'h':
usage();
freeall();
return JDAC_ERR_VALID;
default:
printf("?? getopt returned character code 0%o ??\n", c);
}
}
if (!json_file) {
printf("No json file given\n");
}
if (!schema_file) {
printf("No schema file given");
}
if (!json_file || !schema_file) {
usage();
freeall();
return JDAC_ERR_WRONG_ARGS;
}
printf("validating %s with %s\n", json_file, schema_file);
int err = jdac_validate_file(json_file, schema_file);
if (err==JDAC_ERR_VALID) {
printf("validation ok\n");
} else {
printf("validate failed. err %d: %s\n", err, jdac_errorstr(err));
}
freeall();
return err;
}

View File

@ -0,0 +1,27 @@
#include "jsoncdaccord.h"
#include "internal.h"
#include "optional.h"
int _jdac_check_pattern(json_object *jobj, json_object *jschema) {
json_object *jpat = json_object_object_get(jschema, "pattern");
if (jpat) {
if (!json_object_is_type(jpat, json_type_string)) {
return JDAC_ERR_SCHEMA_ERROR;
}
const char *pattern = json_object_get_string(jpat);
const char *istr = json_object_get_string(jobj);
if (istr) {
int ret = _jdac_match_string_with_regex(pattern, istr);
if (ret == JDAC_REGEX_COMPILE_FAILED) {
return JDAC_ERR_SCHEMA_ERROR;
} else if (ret == JDAC_REGEX_MATCH) {
return JDAC_ERR_VALID;
} else if (ret == JDAC_REGEX_MISMATCH) {
return JDAC_ERR_INVALID_PATTERNMATCH;
}
}
}
return JDAC_ERR_VALID;
}

View File

@ -0,0 +1,32 @@
#include "jsoncdaccord.h"
#include "internal.h"
#include "optional.h"
int _jdac_check_patternproperties(json_object *jobj, json_object *jschema) {
//printf("%s\n", __func__);
// check jobj non object is already checked
json_object *jpatprops = json_object_object_get(jschema, "patternProperties");
if (jpatprops) {
if (!json_object_is_type(jpatprops, json_type_object)) {
return JDAC_ERR_SCHEMA_ERROR;
}
json_object_object_foreach(jpatprops, jprop_key, jprop_val) {
json_object_object_foreach(jobj, jobj_key, jobj_val) {
int ret = _jdac_match_string_with_regex(jprop_key, jobj_key);
if (ret == JDAC_REGEX_COMPILE_FAILED) {
return JDAC_ERR_SCHEMA_ERROR;
} else if (ret == JDAC_REGEX_MATCH) {
int err = _jdac_validate_instance(jobj_val, jprop_val);
if (err) {
return err;
}
} else if (ret == JDAC_REGEX_MISMATCH) {
//
}
}
}
}
return JDAC_ERR_VALID;
}

View File

@ -0,0 +1,26 @@
#include "jsoncdaccord.h"
#include "internal.h"
#include "optional.h"
int _jdac_check_propertynames(json_object *jobj, json_object *jschema) {
json_object *jpropnames_schema = json_object_object_get(jschema, "propertyNames");
if (!jpropnames_schema) {
return JDAC_ERR_VALID;
}
if (!json_object_is_type(jpropnames_schema, json_type_object) &&
!json_object_is_type(jpropnames_schema, json_type_boolean)) {
return JDAC_ERR_SCHEMA_ERROR;
}
json_object_object_foreach(jobj, jprop_key, jprop_val) {
json_object *jprop = json_object_new_string(jprop_key);
int err = _jdac_validate_instance(jprop, jpropnames_schema);
json_object_put(jprop);
if (err) {
return err;
}
}
return JDAC_ERR_VALID;
}

View File

@ -0,0 +1,88 @@
#include <string.h>
#include <stdio.h>
#include "jsoncdaccord.h"
#include "internal.h"
#include "optional.h"
char localpath[256] = {0};
int jdac_ref_set_localpath(const char *_localpath) {
strcpy(localpath, _localpath);
return JDAC_ERR_VALID;
}
const char *_jdac_uri_get_path(const char *uri) {
const char *ptr = uri;
char *schemaseparator = strstr(uri, "://");
if (!schemaseparator) {
//no schema
} else {
//has schema
ptr = schemaseparator + 3;
char *path = strstr(ptr, "/");
if (path) {
return path;
}
}
return NULL;
}
int _jdac_check_ref(json_object *jobj, json_object *jschema, storage_node *storage_list) {
// #ifdef JDAC_STORE
json_object *jref = json_object_object_get(jschema, "$ref");
if (jref) {
const char *refstr = json_object_get_string(jref);
printf("ref is %s\n", refstr);
storage_node *rootnode = _jdac_store_get_root_node(storage_list);
// if there is a rootnode id, compare it to the ref
if (rootnode) {
const char *path_ref = _jdac_uri_get_path(refstr);
const char *path_id = _jdac_uri_get_path(rootnode->id);
if (!path_ref) {
return JDAC_ERR_VALID;
}
if (!path_id) {
char filepath[512];
snprintf(filepath, sizeof(filepath) - 1, "%s.%s", localpath, path_ref);
printf("filepath is %s\n", filepath);
json_object *jschemafromfile = json_object_from_file(filepath);
if (!jschemafromfile) {
return JDAC_ERR_JSON_NOT_FOUND;
}
int err = _jdac_validate_instance(jobj, jschemafromfile);
json_object_put(jschemafromfile);
return err;
}
if (strcmp(path_ref, path_id) != 0 && strlen(localpath) > 0) {
printf("yep\n");
char filepath[512];
snprintf(filepath, sizeof(filepath) - 1, "%s.%s", localpath, path_ref);
printf("filepath is %s\n", filepath);
json_object *jschemafromfile = json_object_from_file(filepath);
if (!jschemafromfile) {
return JDAC_ERR_JSON_NOT_FOUND;
}
int err = _jdac_validate_instance(jobj, jschemafromfile);
json_object_put(jschemafromfile);
return err;
} else if (strcmp(path_ref, path_id) == 0) {
int err = _jdac_validate_instance(jobj, rootnode->json_schema_ptr);
return err;
}
}
// if (refstr) {
// json_object *jschema_from_resolved_uri = _jdac_store_resolve(storage_list, refstr);
// if (!jschema_from_resolved_uri)
// return JDAC_ERR_INVALID_REF;
// int err = _jdac_validate_instance(jobj, jschema_from_resolved_uri);
// return err;
// }
}
// #endif
return JDAC_ERR_VALID;
}

View File

@ -0,0 +1,19 @@
#include <regex.h>
#include <stdio.h>
#include <string.h>
#include "jsoncdaccord.h"
int _jdac_match_string_with_regex(const char *regex_pattern, const char *value) {
regex_t regex;
int reti = regcomp(&regex, regex_pattern, REG_EXTENDED);
if (reti) {
fprintf(stderr, "Could not compile regex\n");
return JDAC_REGEX_COMPILE_FAILED;
}
reti = regexec(&regex, value, 0, NULL, 0);
regfree(&regex);
if (reti == 0) {
return JDAC_REGEX_MATCH;
}
return JDAC_REGEX_MISMATCH;
}

View File

@ -0,0 +1,114 @@
#include <string.h>
#include <stdio.h>
#include "jsoncdaccord.h"
#include "optional.h"
void _jdac_store_append(storage_node **head, storage_node *ref) {
storage_node *new_node = malloc(sizeof(storage_node));
memcpy(new_node, ref, sizeof(storage_node));
new_node->next = *head;
*head = new_node;
}
void _jdac_store_free(storage_node **head) {
while (*head) {
// if ((*head)->is_root==1 && (*head)->json_instance_ptr!=NULL)
// json_object_put((*head)->json_instance_ptr);
storage_node *el = *head;
*head = (*head)->next;
free(el);
}
*head = NULL;
}
int _jdac_store_traverse_json(storage_node **head, json_object *jschema, char *pathbuffer) {
char pathbuf[256];
pathbuf[0] = 0;
storage_node node = {0};
if (pathbuffer == NULL) {
strcpy(pathbuf, "#/");
node.is_root = 1;
} else {
strcpy(pathbuf, pathbuffer);
node.is_root = 0;
}
node.json_instance_ptr = jschema;
json_object *jid = json_object_object_get(jschema, "$id");
json_object *janchor = json_object_object_get(jschema, "$anchor");
json_object *jdynamicanchor = json_object_object_get(jschema, "$dynamicAnchor");
if (jid) {
strcpy(node.id, json_object_get_string(jid));
}
if (janchor) {
strcpy(node.anchor, json_object_get_string(janchor));
}
if (jdynamicanchor) {
strcpy(node.dynamicAnchor, json_object_get_string(jdynamicanchor));
}
// if (jid || janchor || jdynamicanchor || node.is_root==1) {
strcpy(node.JSONPtrURI, pathbuf);
node.json_schema_ptr = jschema;
_jdac_store_append(head, &node);
// }
json_object_object_foreach(jschema, jkey, jval) {
if (json_object_is_type(jval, json_type_object)) {
if (strcmp(jkey, "const") == 0) {
continue;
}
if (pathbuffer == NULL) {
sprintf(pathbuf, "#/%s", jkey);
} else {
sprintf(pathbuf, "%s/%s", pathbuffer, jkey);
}
//printf("%s\n", pathbuf);
_jdac_store_traverse_json(head, jval, pathbuf);
}
}
return JDAC_ERR_VALID;
}
void _jdac_store_print(storage_node *head) {
storage_node *list = head;
printf("%-*s %-*s %-*s %-*s\n", 32, "JSONPtr", 16, "anchor", 16, "dynamicAnchor", 32, "id");
while (list) {
printf("%-*s %-*s %-*s %-*s\n", 32, list->JSONPtrURI, 16, list->anchor, 16, list->dynamicAnchor, 32, list->id);
list = list->next;
}
}
storage_node *_jdac_store_get_root_node(storage_node *head) {
// spool to start of list
storage_node *list = head;
//printf("%-*s %-*s %-*s %-*s\n", 32, "JSONPtr", 16, "anchor", 16, "dynamicAnchor", 32, "id");
while (list) {
//printf("%-*s %-*s %-*s %-*s\n", 32, list->JSONPtrURI, 16, list->anchor, 16, list->dynamicAnchor, 32, list->id);
if (list->next == NULL) {
return list;
}
list = list->next;
}
return NULL;
}
json_object *_jdac_store_resolve(storage_node *list, const char *uri) {
while (list) {
if (strcmp(list->id, uri) == 0) {
return list->json_instance_ptr;
}
if (strcmp(list->JSONPtrURI, uri) == 0) {
return list->json_instance_ptr;
}
list = list->next;
}
return NULL;
}

View File

@ -0,0 +1,116 @@
#include "jsoncdaccord.h"
#include "internal.h"
#include "optional.h"
enum subschematype {
JDAC_ALLOF = 0,
JDAC_ANYOF,
JDAC_ONEOF
};
// shall return valid or invalid based on subschema type
int _jdac_test_subschema_array(json_object *jobj, json_object *jsubschema_array, enum subschematype type) {
if (jsubschema_array == NULL) {
return JDAC_ERR_VALID;
}
// MUST be a non-empty array
if (!json_object_is_type(jsubschema_array, json_type_array)) {
return JDAC_ERR_SCHEMA_ERROR;
}
int arraylen = (int)json_object_array_length(jsubschema_array);
if (arraylen == 0) {
return JDAC_ERR_SCHEMA_ERROR;
}
int number_of_valid_schemas = 0;
for (int i = 0; i < arraylen; i++) {
json_object *jsubschema = json_object_array_get_idx(jsubschema_array, i);
if (!json_object_is_type(jsubschema, json_type_object) && !json_object_is_type(jsubschema, json_type_boolean)) {
return JDAC_ERR_SCHEMA_ERROR;
}
int err = _jdac_validate_instance(jobj, jsubschema);
if (err == JDAC_ERR_VALID) {
number_of_valid_schemas++;
} else if (err == JDAC_ERR_SCHEMA_ERROR) {
return JDAC_ERR_SCHEMA_ERROR;
} else {
// continue
}
}
if (type == JDAC_ALLOF) {
if (number_of_valid_schemas == arraylen) {
return JDAC_ERR_VALID;
}
} else if (type == JDAC_ANYOF) {
if (number_of_valid_schemas > 0) {
return JDAC_ERR_VALID;
}
} else if (type == JDAC_ONEOF) {
if (number_of_valid_schemas == 1) {
return JDAC_ERR_VALID;
}
}
return JDAC_ERR_INVALID_SUBSCHEMALOGIC;
}
int _jdac_check_subschemalogic(json_object *jobj, json_object *jschema) {
int err;
json_object *jarray;
jarray = json_object_object_get(jschema, "allOf");
err = _jdac_test_subschema_array(jobj, jarray, JDAC_ALLOF);
if (err) {
return JDAC_ERR_INVALID_SUBSCHEMALOGIC;
}
jarray = json_object_object_get(jschema, "anyOf");
err = _jdac_test_subschema_array(jobj, jarray, JDAC_ANYOF);
if (err) {
return JDAC_ERR_INVALID_SUBSCHEMALOGIC;
}
jarray = json_object_object_get(jschema, "oneOf");
err = _jdac_test_subschema_array(jobj, jarray, JDAC_ONEOF);
if (err) {
return JDAC_ERR_INVALID_SUBSCHEMALOGIC;
}
json_object *jnot = json_object_object_get(jschema, "not");
if (jnot) {
// "not" is special, and MUST be a json object
if (json_object_is_type(jnot, json_type_object) || json_object_is_type(jnot, json_type_boolean)) {
err = _jdac_validate_instance(jobj, jnot);
if (err == JDAC_ERR_VALID) {
return JDAC_ERR_INVALID_SUBSCHEMALOGIC;
} else if (err == JDAC_ERR_SCHEMA_ERROR) {
return JDAC_ERR_SCHEMA_ERROR;
} else {
return JDAC_ERR_VALID;
}
} else {
return JDAC_ERR_SCHEMA_ERROR;
}
}
json_object *if_schema = json_object_object_get(jschema, "if");
json_object *then_schema = json_object_object_get(jschema, "then");
json_object *else_schema = json_object_object_get(jschema, "else");
if (if_schema) {
err = _jdac_validate_instance(jobj, if_schema);
if (err == JDAC_ERR_VALID && then_schema) {
err = _jdac_validate_instance(jobj, then_schema);
return err;
} else if (err != JDAC_ERR_VALID && else_schema) {
err = _jdac_validate_instance(jobj, else_schema);
return err;
}
}
return JDAC_ERR_VALID;
}

View File

@ -0,0 +1,648 @@
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <json-c/json.h>
#include "jsoncdaccord.h"
#include "internal.h"
#include "optional.h"
json_object *json = NULL;
json_object *schema = NULL;
json_object *defs = NULL;
#ifdef JDAC_STORE
static storage_node *storagelist_head = NULL;
#endif
static char *jdacerrstr[JDAC_ERR_MAX] = {"VALID",
"GENERAL ERROR",
"JSON FILE NOT FOUND",
"SCHEMA FILE NOT FOUND",
"WRONG ARGUEMNTS GIVEN",
"SCHEMA ERROR",
"INVALID",
"INVALID TYPE",
"INVALID REQUIRED",
"INVALID SUBSCHEMA LOGIC (allOf, anyOf, oneOf, or not)",
"INVALID CONST",
"INVALID ENUMS",
"INVALID STRING LENGTH",
"INVALID UNIQUE ITEMS",
"INVALID UNIQUE CONTAINS",
"INVALID PREFIXITEMS",
"INVALID ITEMS",
"INVALID ARRAY LENGTH",
"INVALID NUMBER",
"INVALID REFERENCE",
"PATTERN NO MATCH",
"REGEX MISMATCH",
"REGEX MATCH",
"REGEX COMPILE FAILED"};
const char *jdac_errorstr(unsigned int jdac_errors) {
if (jdac_errors < JDAC_ERR_MAX) {
return jdacerrstr[jdac_errors];
}
return NULL;
}
int _jdac_load(const char *jsonfile, const char *jsonschema) {
json = json_object_from_file(jsonfile);
if (json == NULL) {
return JDAC_ERR_JSON_NOT_FOUND;
}
schema = json_object_from_file(jsonschema);
if (schema == NULL) {
json_object_put(json);
return JDAC_ERR_SCHEMA_NOT_FOUND;
}
return JDAC_ERR_VALID;
}
int __jdac_inspect_type(json_object *jobj, const char *type) {
if (strcmp(type, "object") == 0) {
if (json_object_is_type(jobj, json_type_object)) {
return JDAC_ERR_VALID;
}
} else if (strcmp(type, "array") == 0) {
if (json_object_is_type(jobj, json_type_array)) {
return JDAC_ERR_VALID;
}
} else if (strcmp(type, "string") == 0) {
if (json_object_is_type(jobj, json_type_string)) {
return JDAC_ERR_VALID;
}
} else if (strcmp(type, "integer") == 0) {
if (json_object_is_type(jobj, json_type_int)) {
return JDAC_ERR_VALID;
}
if (json_object_is_type(jobj, json_type_double)) {
double value = json_object_get_double(jobj);
if (value == round(value)) { // "zero fractional part is an integer"
return JDAC_ERR_VALID;
}
}
} else if (strcmp(type, "double") == 0) {
if (json_object_is_type(jobj, json_type_double)) {
return JDAC_ERR_VALID;
}
} else if (strcmp(type, "number") == 0) {
if (json_object_is_type(jobj, json_type_double) || json_object_is_type(jobj, json_type_int)) {
return JDAC_ERR_VALID;
}
} else if (strcmp(type, "boolean") == 0) {
if (json_object_is_type(jobj, json_type_boolean)) {
return JDAC_ERR_VALID;
}
} else if (strcmp(type, "null") == 0) {
if (json_object_is_type(jobj, json_type_null)) {
return JDAC_ERR_VALID;
}
} else {
printf("WARN unknown type in check type %s\n", type);
return JDAC_ERR_SCHEMA_ERROR;
}
return JDAC_ERR_INVALID_TYPE;
}
int _jdac_check_type(json_object *jobj, json_object *jschema) {
json_object *jtype = json_object_object_get(jschema, "type");
if (jtype == NULL) {
return JDAC_ERR_VALID;
} else if (json_object_is_type(jtype, json_type_string)) {
const char *type = json_object_get_string(jtype);
return __jdac_inspect_type(jobj, type);
} else if (json_object_is_type(jtype, json_type_array)) {
int arraylen = json_object_array_length(jtype);
for (int i = 0; i < arraylen; i++) {
json_object *iobj = json_object_array_get_idx(jtype, i);
if (!json_object_is_type(iobj, json_type_string)) {
return JDAC_ERR_SCHEMA_ERROR;
}
const char *type = json_object_get_string(iobj);
int err = __jdac_inspect_type(jobj, type);
if (err == JDAC_ERR_VALID) {
return JDAC_ERR_VALID;
}
}
return JDAC_ERR_INVALID_TYPE;
} else {
return JDAC_ERR_SCHEMA_ERROR;
}
}
int _jdac_check_required(json_object *jobj, json_object *jschema) {
//printf("%s\n%s\n", __func__, json_object_to_json_string(jobj));
json_object *jarray = json_object_object_get(jschema, "required");
int missing_required_key = 0;
if (jarray) {
int arraylen = json_object_array_length(jarray);
for (int i = 0; i < arraylen; i++) {
json_object *iobj = json_object_array_get_idx(jarray, i);
const char *key = json_object_get_string(iobj);
if (key) {
//printf("%s\n", key);
// use json_object_object_get_ex becuase of json_type_null types
json_object *required_object = NULL;
int err = json_object_object_get_ex(jobj, key, &required_object);
if (err == 0) {
printf("required key missing: %s\n", key);
missing_required_key = 1;
}
}
}
}
if (missing_required_key) {
return JDAC_ERR_INVALID_REQUIRED;
} else {
return JDAC_ERR_VALID;
}
}
int _jdac_check_properties(json_object *jobj, json_object *jschema) {
// printf("%s\n", __func__);
json_object *jprops = json_object_object_get(jschema, "properties");
if (jprops) {
json_object_object_foreach(jprops, jprop_key, jprop_val) {
// printf("key of prop is %s\n", jprop_key);
json_object *iobj = json_object_object_get(jobj, jprop_key);
//printf("iobj %s type %d\nkey %s\nval %s\n", json_object_get_string(iobj), json_object_get_type(iobj), jprop_key, json_object_get_string(jprop_val));
if (iobj) {
int err = _jdac_validate_instance(iobj, jprop_val);
if (err) {
return err;
}
}
}
}
return JDAC_ERR_VALID;
}
int _jdac_check_prefixItems_and_items(json_object *jobj, json_object *jschema) {
json_object *jprefixitems = json_object_object_get(jschema, "prefixItems");
json_object *jitems = json_object_object_get(jschema, "items");
int jobj_arraylen = json_object_array_length(jobj);
int prefixitems_arraylen = 0;
if (jprefixitems) {
if (!json_object_is_type(jprefixitems, json_type_array)) {
return JDAC_ERR_SCHEMA_ERROR;
}
prefixitems_arraylen = json_object_array_length(jprefixitems);
for (int i = 0; i < jobj_arraylen && i < prefixitems_arraylen; i++) {
//printf("i=%d prefixitems\n", i);
json_object *iobj = json_object_array_get_idx(jobj, i);
json_object *ischema = json_object_array_get_idx(jprefixitems, i);
int err = _jdac_validate_instance(iobj, ischema);
if (err) {
return JDAC_ERR_INVALID_PREFIXITEMS;
}
}
}
if (jitems) {
if (!json_object_is_type(jitems, json_type_object) && !json_object_is_type(jitems, json_type_boolean)) {
return JDAC_ERR_SCHEMA_ERROR;
}
for (int i = prefixitems_arraylen; i < jobj_arraylen; i++) {
//printf("i=%d items\n", i);
json_object *iobj = json_object_array_get_idx(jobj, i);
int err = _jdac_validate_instance(iobj, jitems);
if (err) {
return JDAC_ERR_INVALID_ITEMS;
}
}
}
return JDAC_ERR_VALID;
}
json_object *_jdac_get_defs_from_ref(json_object *ref) {
char key[128];
if (!json_object_is_type(ref, json_type_string)) {
return NULL;
}
const char *refstr = json_object_get_string(ref);
if (sscanf(refstr, "#/$defs/%s", key) == 1) {
return json_object_object_get(defs, key);
}
return NULL;
}
int _jdac_value_is_equal(json_object *jobj1, json_object *jobj2) {
if (json_object_equal(jobj1, jobj2)) {
return JDAC_ERR_VALID;
}
if (json_object_is_type(jobj1, json_type_double) && json_object_is_type(jobj2, json_type_int)) {
double value = json_object_get_double(jobj1);
double value2 = json_object_get_int64(jobj2);
if (value == round(value) && value == value2) {
return JDAC_ERR_VALID;
}
}
if (json_object_is_type(jobj1, json_type_int) && json_object_is_type(jobj2, json_type_double)) {
double value = json_object_get_double(jobj2);
double value2 = json_object_get_int64(jobj1);
if (value == round(value) && value == value2) {
return JDAC_ERR_VALID;
}
}
return JDAC_ERR_INVALID;
}
int _jdac_check_const(json_object *jobj, json_object *jschema) {
json_object *jconst;
int err = json_object_object_get_ex(jschema, "const", &jconst);
if (err == 0) {
return JDAC_ERR_VALID;
}
err = _jdac_value_is_equal(jobj, jconst);
if (err == JDAC_ERR_VALID) {
return JDAC_ERR_VALID;
}
return JDAC_ERR_INVALID_CONST;
}
int _jdac_check_enums(json_object *jobj, json_object *jschema) {
json_object *jenum_array = json_object_object_get(jschema, "enum");
if (!jenum_array) {
return JDAC_ERR_VALID;
}
if (!json_object_is_type(jenum_array, json_type_array)) {
return JDAC_ERR_SCHEMA_ERROR;
}
int arraylen = json_object_array_length(jenum_array);
for (int i = 0; i < arraylen; i++) {
json_object *ienum = json_object_array_get_idx(jenum_array, i);
int err = _jdac_value_is_equal(jobj, ienum);
if (err == JDAC_ERR_VALID) {
return JDAC_ERR_VALID;
}
}
printf("ERROR: enum check failed (%s not in enum)\n", json_object_to_json_string(jobj));
return JDAC_ERR_INVALID_ENUMS;
}
int _jdac_check_uniqueItems(json_object *jobj, json_object *jschema) {
json_object *juniq = json_object_object_get(jschema, "uniqueItems");
if (juniq) {
if (!json_object_is_type(juniq, json_type_boolean)) {
return JDAC_ERR_SCHEMA_ERROR;
}
if (json_object_get_boolean(juniq) == 0) {
return JDAC_ERR_VALID;
}
int arraylen = json_object_array_length(jobj);
for (int i = 0; i < arraylen - 1; i++) {
json_object *iobj = json_object_array_get_idx(jobj, i);
for (int j = i + 1; j < arraylen; j++) {
json_object *uobj = json_object_array_get_idx(jobj, j);
if (json_object_equal(iobj, uobj) == 1) {
return JDAC_ERR_INVALID_UNIQUEITEMS;
}
}
}
}
return JDAC_ERR_VALID;
}
int _jdac_check_maxmin_items(json_object *jobj, json_object *jschema) {
int err = JDAC_ERR_VALID;
json_object *jmax = json_object_object_get(jschema, "maxItems");
json_object *jmin = json_object_object_get(jschema, "minItems");
int arraylen = json_object_array_length(jobj);
if (jmax) {
if (json_object_is_type(jmax, json_type_int) || json_object_is_type(jmax, json_type_double)) {
int maxitems = json_object_get_double(jmax);
if (arraylen > maxitems) {
err = JDAC_ERR_INVALID_ARRAYLEN;
}
}
}
if (jmin) {
if (json_object_is_type(jmin, json_type_int) || json_object_is_type(jmin, json_type_double)) {
int minitems = json_object_get_double(jmin);
if (arraylen < minitems) {
err = JDAC_ERR_INVALID_ARRAYLEN;
}
}
}
if (err) {
printf("ERROR: failed at maxItems or minItems check\n");
}
return err;
}
int _jdac_validate_array(json_object *jobj, json_object *jschema) {
int err;
err = _jdac_check_prefixItems_and_items(jobj, jschema);
if (err) {
return err;
}
err = _jdac_check_uniqueItems(jobj, jschema);
if (err) {
return err;
}
err = _jdac_check_maxmin_items(jobj, jschema);
if (err) {
return err;
}
#ifdef JDAC_CONTAINS
err = _jdac_check_contains_and_minmaxcontains(jobj, jschema);
if (err) {
return err;
}
#endif
return JDAC_ERR_VALID;
}
int _jdac_validate_object(json_object *jobj, json_object *jschema) {
int err;
if (defs == NULL) {
defs = json_object_object_get(jschema, "$defs");
}
err = _jdac_check_required(jobj, jschema);
if (err) {
return err;
}
err = _jdac_check_properties(jobj, jschema);
if (err) {
return err;
}
#ifdef JDAC_PROPERTYNAMES
err = _jdac_check_propertynames(jobj, jschema);
if (err) {
return err;
}
#endif
#ifdef JDAC_PATTERNPROPERTIES
err = _jdac_check_patternproperties(jobj, jschema);
if (err) {
return err;
}
#endif
#ifdef JDAC_ADDITIONALPROPERTIES
err = _jdac_check_additionalproperties(jobj, jschema);
if (err) {
return err;
}
#endif
return JDAC_ERR_VALID;
}
int utf8_length(const char *str) {
const char *pointer = str;
int len = 0;
while (pointer[0]) {
if ((pointer[0] & 0xC0) != 0x80) {
len++;
}
pointer++;
}
return len;
}
int _jdac_validate_string(json_object *jobj, json_object *jschema) {
const char *str = json_object_get_string(jobj);
//printf("strlen of %s %ld %d %d\n", str, strlen(str), json_object_get_string_len(jobj), utf8_length(str));
json_object *jminlen = json_object_object_get(jschema, "minLength");
if (jminlen) {
int minlen = json_object_get_int64(jminlen);
if (utf8_length(str) < minlen) {
return JDAC_ERR_INVALID_STRLEN;
}
}
json_object *jmaxlen = json_object_object_get(jschema, "maxLength");
if (jmaxlen) {
int maxlen = json_object_get_int64(jmaxlen);
if (utf8_length(str) > maxlen) {
return JDAC_ERR_INVALID_STRLEN;
}
}
int err = _jdac_check_enums(jobj, jschema);
if (err) {
return err;
}
#ifdef JDAC_PATTERN
err = _jdac_check_pattern(jobj, jschema);
if (err) {
return err;
}
#endif
return JDAC_ERR_VALID;
}
int _jdac_validate_integer(json_object *jobj, json_object *jschema) {
double value = (double)json_object_get_int64(jobj);
int err = _jdac_validate_number(jobj, jschema, value);
return err;
}
int _jdac_validate_double(json_object *jobj, json_object *jschema) {
double value = json_object_get_double(jobj);
int err = _jdac_validate_number(jobj, jschema, value);
return err;
}
int _jdac_validate_number(json_object *jobj, json_object *jschema, double value) {
json_object *jmult = json_object_object_get(jschema, "multipleOf");
if (jmult) {
double multipland = (double)json_object_get_double(jmult);
if (multipland == 0.0) {
return JDAC_ERR_SCHEMA_ERROR;
}
double divided = value / multipland;
if (isinf(divided) != 0) {
return JDAC_ERR_INVALID_NUMBER;
}
if (divided != round(divided)) {
return JDAC_ERR_INVALID_NUMBER;
}
}
json_object *jmin = json_object_object_get(jschema, "minimum");
if (jmin) {
double min = (double)json_object_get_double(jmin);
if (value < min) {
return JDAC_ERR_INVALID_NUMBER;
}
}
json_object *jexclmin = json_object_object_get(jschema, "exclusiveMinimum");
if (jexclmin) {
double min = (double)json_object_get_double(jexclmin);
if (value <= min) {
return JDAC_ERR_INVALID_NUMBER;
}
}
json_object *jmax = json_object_object_get(jschema, "maximum");
if (jmax) {
double max = (double)json_object_get_double(jmax);
if (value > max) {
return JDAC_ERR_INVALID_NUMBER;
}
}
json_object *jexclmax = json_object_object_get(jschema, "exclusiveMaximum");
if (jexclmax) {
double max = (double)json_object_get_double(jexclmax);
if (value >= max) {
return JDAC_ERR_INVALID_NUMBER;
}
}
return JDAC_ERR_VALID;
}
int _jdac_validate_boolean(json_object *jobj, json_object *jschema) {
// printf("%s\n", __func__);
return JDAC_ERR_VALID;
}
int _jdac_validate_instance(json_object *jobj, json_object *jschema) {
int err;
// printf("--validate instance--\n");
// printf("%s\n", json_object_get_string(jobj));
// printf("%s\n", json_object_get_string(jschema));
#ifdef JDAC_REF
err = _jdac_check_ref(jobj, jschema, storagelist_head);
if (err) {
return err;
}
#endif
// check if jschema is a bool, true or false
if (json_object_is_type(jschema, json_type_boolean)) {
json_bool value = json_object_get_boolean(jschema);
if (value == 0) {
return JDAC_ERR_INVALID;
}
if (value == 1) {
return JDAC_ERR_VALID;
}
}
err = _jdac_check_type(jobj, jschema);
if (err) {
return err;
}
err = _jdac_check_const(jobj, jschema);
if (err) {
return err;
}
err = _jdac_check_enums(jobj, jschema);
if (err) {
return err;
}
// if (!json_object_is_type(jobj, json_type_null))
// printf("%s\n", json_object_get_string(jobj));
// else
// printf("jobj was null\n");
// if (!json_object_is_type(jschema, json_type_null))
// printf("%s\n", json_object_get_string(jschema));
// else
// printf("jschema was null\n");
#ifdef JDAC_SUBSCHEMALOGIC
err = _jdac_check_subschemalogic(jobj, jschema);
if (err) {
return err;
}
#endif
json_type type = json_object_get_type(jobj);
if (type == json_type_object) {
return _jdac_validate_object(jobj, jschema);
} else if (type == json_type_array) {
return _jdac_validate_array(jobj, jschema);
} else if (type == json_type_string) {
return _jdac_validate_string(jobj, jschema);
} else if (type == json_type_boolean) {
return _jdac_validate_boolean(jobj, jschema);
} else if (type == json_type_int) {
return _jdac_validate_integer(jobj, jschema);
} else if (type == json_type_double) {
return _jdac_validate_double(jobj, jschema);
} else if (type == json_type_null) {
return JDAC_ERR_VALID;
} else {
printf("WARN: type %d not handled\n", type);
}
return JDAC_ERR_VALID;
}
int jdac_validate(json_object *jobj, json_object *jschema) {
#ifdef JDAC_STORE
_jdac_store_traverse_json(&storagelist_head, jschema, NULL);
_jdac_store_print(storagelist_head);
#endif
int err = _jdac_validate_instance(jobj, jschema);
#ifdef JDAC_STORE
_jdac_store_free(&storagelist_head);
#endif
return err;
}
int jdac_validate_file(const char *jsonfile, const char *jsonschemafile) {
int err = _jdac_load(jsonfile, jsonschemafile);
if (err) {
return err;
}
err = jdac_validate(json, schema);
json_object_put(json);
json_object_put(schema);
json = NULL;
schema = NULL;
defs = NULL;
return err;
}

View File

@ -10,6 +10,7 @@
#include "crypto.h"
#include "user_errno.h"
#include "zlog_module.h"
#include "json_schema/jsoncdaccord.h"
#define CURRENT_PROTOCOL_VERSION (1)
@ -21,14 +22,85 @@ typedef struct {
cJSON *msgContend;
} PROTOCOL_WARP, *PPROTOCOL_WARP;
const char *proto_decode_context(const char *pString, unsigned int *pVer, unsigned long long *pTm) {
#ifdef JSON_SCHEMA_ON
typedef struct {
const char *pSchJson;
const char *pErrMsg;
} JSON_SCHEMA_CTX, *PJSON_SCHEMA_CTX;
static JSON_SCHEMA_CTX g_json_sch[] = {
{"{\"type\":\"object\",\"required\":[\"ver\"]}", "Missing required field [ver]" },
{"{\"type\":\"object\",\"required\":[\"cryptoType\"]}", "Missing required field [cryptoType]"},
{"{\"type\":\"object\",\"required\":[\"timeStamp\"]}", "Missing required field [timeStamp]" },
{"{\"type\":\"object\",\"required\":[\"msgContent\"]}", "Missing required field [msgContent]"},
};
const char *proto_schema_validation(const char *pJsonStr) {
int i;
json_object *pJs = json_tokener_parse(pJsonStr);
if (!pJs) {
cJSON *pRspRoot = cJSON_CreateObject();
cJSON_AddNumberToObject(pRspRoot, "status", ERR_JSON_PRASE_OBJ);
cJSON_AddStringToObject(pRspRoot, "message", getErrorEnumDesc(ERR_JSON_PRASE_OBJ));
return proto_create_new(pRspRoot, 200);
}
for (i = 0; i < ARRAY_SIZE(g_json_sch); i++) {
json_object *pSc = json_tokener_parse(g_json_sch[i].pSchJson);
if (!pSc) {
LOG_MOD(error, ZLOG_MOD_PROTO, "Json schema format error: [%s]\n", g_json_sch[i].pSchJson);
continue;
}
if (jdac_validate(pJs, pSc) != JDAC_ERR_VALID) {
cJSON *pRspRoot = cJSON_CreateObject();
cJSON_AddNumberToObject(pRspRoot, "status", ERR_JSON_VALID_SCH);
cJSON_AddStringToObject(pRspRoot, "message", getErrorEnumDesc(ERR_JSON_VALID_SCH));
cJSON_AddStringToObject(pRspRoot, "details", g_json_sch[i].pErrMsg);
json_object_put(pSc);
return proto_create_new(pRspRoot, 200);
}
json_object_put(pSc);
}
json_object_put(pJs);
return NULL;
}
#endif
const char *proto_decode_context(const char *pString, unsigned int *pVer, unsigned long long *pTm, int *pErrCode) {
cJSON *pMsgCtx;
unsigned char *pBase64;
int decodeSize;
unsigned int outSize = 0;
char *pMsgContent = NULL;
cJSON *pRoot = cJSON_Parse(pString);
cJSON *pRoot;
#ifdef JSON_SCHEMA_ON
const char *pSchJson;
#endif
if (pErrCode == NULL) {
return NULL;
}
if (pString == NULL || strlen(pString) == 0) {
*pErrCode = ERR_INPUT_PARAMS;
return NULL;
}
#ifdef JSON_SCHEMA_ON
pSchJson = proto_schema_validation(pString);
if (pSchJson != NULL && strlen(pSchJson) > 0) {
*pErrCode = ERR_JSON_VALID_SCH;
return pSchJson;
}
#endif
pRoot = cJSON_Parse(pString);
if (!pRoot) {
return NULL;
}

View File

@ -47,6 +47,7 @@ static int dhcp_get_user_info(const char **pRsp, const char *pRequest) {
char logBuff[512];
const char *pStrContent;
int k;
int errCode;
dhcpMap::iterator p;
if (pRequest == nullptr || strlen(pRequest) == 0) {
@ -55,7 +56,7 @@ static int dhcp_get_user_info(const char **pRsp, const char *pRequest) {
return ERR_INPUT_PARAMS;
}
pStrContent = proto_decode_context(pRequest, nullptr, nullptr);
pStrContent = proto_decode_context(pRequest, nullptr, nullptr, &errCode);
if (pStrContent == nullptr) {
sprintf(logBuff, "Requeset Json error %s", pRequest);
@ -63,6 +64,13 @@ static int dhcp_get_user_info(const char **pRsp, const char *pRequest) {
return ERR_PROTO_DECODE;
}
#ifdef JSON_SCHEMA_ON
if (errCode == ERR_JSON_VALID_SCH) {
*pRsp = pStrContent;
return ERR_SUCCESS;
}
#endif
cJSON *pRoot = cJSON_Parse(pStrContent);
free((void *)pStrContent);
@ -318,6 +326,7 @@ static int add_dhcpd_rangeset(const char **pRsp, const char *pRequest) {
OBJ_DHCP_RNG range;
cJSON *pRspRoot;
cJSON *pExpandArray;
int errCode;
if (pRequest == nullptr || strlen(pRequest) == 0) {
sprintf(logBuff, "Requeset Json");
@ -325,7 +334,7 @@ static int add_dhcpd_rangeset(const char **pRsp, const char *pRequest) {
return ERR_INPUT_PARAMS;
}
pStrContent = proto_decode_context(pRequest, nullptr, nullptr);
pStrContent = proto_decode_context(pRequest, nullptr, nullptr, &errCode);
if (pStrContent == nullptr) {
sprintf(logBuff, "Requeset Json error %s", pRequest);
@ -333,6 +342,13 @@ static int add_dhcpd_rangeset(const char **pRsp, const char *pRequest) {
return ERR_PROTO_DECODE;
}
#ifdef JSON_SCHEMA_ON
if (errCode == ERR_JSON_VALID_SCH) {
*pRsp = pStrContent;
return ERR_SUCCESS;
}
#endif
cJSON *pRoot = cJSON_Parse(pStrContent);
free((void *)pStrContent);
@ -417,6 +433,7 @@ static int delete_dhcpd_rangeset(const char **pRsp, const char *pRequest) {
data13 dhcpRanges[MAX_DHCP_RANGES];
PHASH_MAP delMap = nullptr;
int resCount = 0;
int errCode;
if (pRequest == nullptr || strlen(pRequest) == 0) {
sprintf(logBuff, "Requeset Json");
@ -424,13 +441,20 @@ static int delete_dhcpd_rangeset(const char **pRsp, const char *pRequest) {
return ERR_INPUT_PARAMS;
}
pStrContent = proto_decode_context(pRequest, nullptr, nullptr);
pStrContent = proto_decode_context(pRequest, nullptr, nullptr, &errCode);
if (pStrContent == nullptr) {
sprintf(logBuff, "Requeset Json error %s", pRequest);
logDHCPMess(logBuff, 1);
return ERR_PROTO_DECODE;
}
#ifdef JSON_SCHEMA_ON
if (errCode == ERR_JSON_VALID_SCH) {
*pRsp = pStrContent;
return ERR_SUCCESS;
}
#endif
cJSON *pRoot = cJSON_Parse(pStrContent);
free((void *)pStrContent);
if (!pRoot) {

View File

@ -0,0 +1,54 @@
//
// Created by xajhuang on 2023/2/23.
//
#include "doctest.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "json_schema/jsoncdaccord.h"
#ifdef __cplusplus
}
#endif
TEST_SUITE("Json schema validator functions") {
TEST_CASE("JSONCDAC VALIDATOR") {
const char *json =
"{\n"
" \"ver\": 3,\n"
" \"cryptoType\": 0,\n"
" \"timeStamp\": 1599187216753,\n"
" \"msgContent\": {\n"
" \"rangeSet\": [\n"
" {\n"
" \"dhcpRange\": \"192.168.30.50-192.168.30.60\",\n"
" \"netmask\": \"255.255.255.0\",\n"
" \"domainServer\": \"114.114.114.114, 8.8.8.8\",\n"
" \"gateway\": \"192.168.30.1\",\n"
" \"leaseTime\": 420\n"
" }\n"
" ]\n"
" }\n"
"}";
const char *sch =
"{\n"
"\t\"type\": \"object\",\n"
"\t\"properties\": {\n"
"\t\t\"ver\": {\n"
"\t\t\t\"type\": \"string\"\t\t\t\n"
"\t\t}\n"
"\t},\n"
"\t\"required\": [\n"
" \"ver\"\n"
" ]\n"
"}";
json_object *pJs = json_tokener_parse(json);
json_object *pSc = json_tokener_parse(sch);
CHECK_NE(pJs, nullptr);
CHECK_NE(pSc, nullptr);
int ret = jdac_validate(pJs, pSc);
CHECK_EQ(JDAC_ERR_VALID, ret);
}
}