OCT 1. 增加协议接口参数字段验证框架
This commit is contained in:
parent
b3a5ae0c6f
commit
095d15f6a5
Binary file not shown.
|
@ -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)
|
||||
|
@ -75,4 +87,22 @@ IF (LIBZLOG STREQUAL "LIBZLOG-NOTFOUND")
|
|||
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 ()
|
|
@ -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 ()
|
||||
|
|
|
@ -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
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"botenanna": "botenannna",
|
||||
"boten": "boten",
|
||||
"wuhu": "wublah",
|
||||
"nullobject": null
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"empty": {},
|
||||
"botenanna": {
|
||||
"annaaaa": "boten"
|
||||
},
|
||||
"nonobject": null
|
||||
}
|
|
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"teststring1": "one",
|
||||
"teststring2": "two",
|
||||
"teststring3": "three",
|
||||
"teststring4": "four",
|
||||
"testinteger1": 1,
|
||||
"testinteger2": 2,
|
||||
"testinteger3": 3,
|
||||
"testinteger4": 4
|
||||
}
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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]
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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": {
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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"]
|
||||
}
|
|
@ -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]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
}
|
|
@ -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": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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*"
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"schema-2-3": {
|
||||
"type": "array",
|
||||
"maxItems": 3,
|
||||
"minItems": 2
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"person": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string", "minLength": 4},
|
||||
"husbands": {"type": "integer"}
|
||||
},
|
||||
"required": ["name"]
|
||||
}
|
||||
},
|
||||
"required": ["person"]
|
||||
}
|
|
@ -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"]}
|
||||
}
|
|
@ -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" } }
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"unique": {
|
||||
"type": "array",
|
||||
"uniqueItems": true
|
||||
},
|
||||
"notunique": {
|
||||
"type": "array",
|
||||
"uniqueItems": false
|
||||
},
|
||||
"schemaerror": {
|
||||
"type": "array",
|
||||
"uniqueItems": 1
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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
|
||||
)
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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(®ex, regex_pattern, REG_EXTENDED);
|
||||
if (reti) {
|
||||
fprintf(stderr, "Could not compile regex\n");
|
||||
return JDAC_REGEX_COMPILE_FAILED;
|
||||
}
|
||||
reti = regexec(®ex, value, 0, NULL, 0);
|
||||
regfree(®ex);
|
||||
if (reti == 0) {
|
||||
return JDAC_REGEX_MATCH;
|
||||
}
|
||||
return JDAC_REGEX_MISMATCH;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue