summaryrefslogtreecommitdiff
path: root/liblognorm-2.0.0-rhbz1990737-add-skipempty.patch
diff options
context:
space:
mode:
Diffstat (limited to 'liblognorm-2.0.0-rhbz1990737-add-skipempty.patch')
-rw-r--r--liblognorm-2.0.0-rhbz1990737-add-skipempty.patch204
1 files changed, 204 insertions, 0 deletions
diff --git a/liblognorm-2.0.0-rhbz1990737-add-skipempty.patch b/liblognorm-2.0.0-rhbz1990737-add-skipempty.patch
new file mode 100644
index 0000000..290bc94
--- /dev/null
+++ b/liblognorm-2.0.0-rhbz1990737-add-skipempty.patch
@@ -0,0 +1,204 @@
+From eb2299a0897577048205e4d8a331168d82ce09d0 Mon Sep 17 00:00:00 2001
+From: Noriko Hosoi <nhosoi@momo7.localdomain>
+Date: Thu, 26 Jul 2018 17:18:38 -0700
+Subject: [PATCH] Add a parameter skipempty to the json field type.
+
+If skipempty is set as follows, empty json objects are dropped from
+the parsed result.
+ %field_name:json:skipempty%
+
+If any parameter other than "skipempty" is given ("bogus" in this
+example), an error message "invalid flag for JSON parser: bogus"
+is issued.
+---
+ src/parser.c | 127 ++++++++++++++++++++++++++++++++++++++++++
+ src/parser.h | 2 +-
+ src/pdag.c | 2 +-
+ 3 files changed, 129 insertions(+), 2 deletions(-)
+
+diff --git a/src/parser.c b/src/parser.c
+index 77407c6..6736c6f 100644
+--- a/src/parser.c
++++ b/src/parser.c
+@@ -2325,6 +2325,85 @@ PARSER_Parse(v2IPTables)
+ return r;
+ }
+
++/*
++ * Delete children of the given object if it has children and they are empty.
++ *
++ * return 0 if object is not empty
++ * return 1 if object is empty
++ * return < 0 if error
++ *
++ * Caller should do this:
++ * if (jsonSkipEmpty(obj) > 0) {
++ * json_object_put(obj);
++ * obj = NULL;
++ * }
++ * or otherwise not use obj if jsonSkipEmpty returns > 0.
++ */
++static int
++jsonSkipEmpty(struct json_object *__restrict__ json)
++{
++ int rc = 0;
++ struct json_object *val = NULL;
++
++ if(json == NULL) {
++ rc = 1;
++ goto finalize_it;
++ }
++
++ switch (json_object_get_type(json)) {
++ case json_type_string:
++ rc = json_object_get_string_len(json) == 0;
++ break;
++ case json_type_array:
++ {
++ int i;
++ int arrayLen = json_object_array_length(json);
++ for (i = 0 ; i < arrayLen ; ++i) {
++ val = json_object_array_get_idx(json, i);
++ if ((rc = jsonSkipEmpty(val)) > 0) {
++ /* delete the empty item and reset the index and arrayLen */
++ json_object_array_del_idx(json, i--);
++ arrayLen = json_object_array_length(json);
++ } else if (rc < 0) {
++ goto finalize_it;
++ }
++ }
++ rc = json_object_array_length(json) == 0;
++ break;
++ }
++ case json_type_object:
++ {
++ struct json_object_iterator it = json_object_iter_begin(json);
++ struct json_object_iterator itEnd = json_object_iter_end(json);
++ while (!json_object_iter_equal(&it, &itEnd)) {
++ val = json_object_iter_peek_value(&it);
++ if ((rc = jsonSkipEmpty(val)) > 0) {
++ json_object_object_del(json, json_object_iter_peek_name(&it));
++ } else if (rc < 0) {
++ goto finalize_it;
++ }
++ json_object_iter_next(&it);
++ }
++ rc = json_object_object_length(json) == 0;
++ }
++ case json_type_null:
++ case json_type_boolean:
++ case json_type_double:
++ case json_type_int:
++ default: break;
++ }
++finalize_it:
++ return rc;
++}
++
++/*
++ * Parameters for field type json
++ * skipempty - skips empty json objects.
++ * - %field_name:json:skipempty%
++ */
++struct data_JSON {
++ int skipempty;
++};
+ /**
+ * Parse JSON. This parser tries to find JSON data inside a message.
+ * If it finds valid JSON, it will extract it. Extra data after the
+@@ -2340,6 +2419,7 @@ PARSER_Parse(v2IPTables)
+ PARSER_Parse(JSON)
+ const size_t i = *offs;
+ struct json_tokener *tokener = NULL;
++ struct data_JSON *const data = (struct data_JSON*) pdata;
+
+ if(npb->str[i] != '{' && npb->str[i] != ']') {
+ /* this can't be json, see RFC4627, Sect. 2
+@@ -2368,6 +2448,20 @@ PARSER_Parse(JSON)
+ if(value == NULL) {
+ json_object_put(json);
+ } else {
++ if (data && data->skipempty) {
++ int rc = jsonSkipEmpty(json);
++ if (rc < 0) {
++ json_object_put(json);
++ FAIL(LN_WRONGPARSER);
++ } else if (rc > 0) {
++ /*
++ * json value is empty.
++ * E.g., {"message":""}, {"message":[]}, {"message":{}}
++ */
++ json_object_put(json);
++ FAIL(0);
++ }
++ }
+ *value = json;
+ }
+
+@@ -2376,7 +2470,40 @@ PARSER_Parse(JSON)
+ json_tokener_free(tokener);
+ return r;
+ }
++PARSER_Construct(JSON)
++{
++ int r = 0;
++ struct json_object *ed;
++ struct data_JSON *data = NULL;
++ char *flag;
+
++ if(json == NULL)
++ goto done;
++
++ if(json_object_object_get_ex(json, "extradata", &ed) == 0) {
++ /* No JSON parameter */
++ goto done;
++ }
++ data = (struct data_JSON*) calloc(1, sizeof(struct data_JSON));
++ flag = json_object_get_string(ed);
++ if (strcasecmp(flag, "skipempty") == 0) {
++ data->skipempty = 1;
++ } else {
++ ln_errprintf(ctx, 0, "invalid flag for JSON parser: %s", flag);
++ r = LN_BADCONFIG;
++ goto done;
++ }
++ *pdata = data;
++done:
++ if(r != 0) {
++ free(data);
++ }
++ return r;
++}
++PARSER_Destruct(JSON)
++{
++ free(pdata);
++}
+
+ /* check if a char is valid inside a name of a NameValue list
+ * The set of valid characters may be extended if there is good
+diff --git a/src/parser.h b/src/parser.h
+index 38be62d..5b4a821 100644
+--- a/src/parser.h
++++ b/src/parser.h
+@@ -70,7 +70,7 @@ PARSERDEF_NO_DATA(Time24hr);
+ PARSERDEF_NO_DATA(Duration);
+ PARSERDEF_NO_DATA(IPv4);
+ PARSERDEF_NO_DATA(IPv6);
+-PARSERDEF_NO_DATA(JSON);
++PARSERDEF(JSON);
+ PARSERDEF_NO_DATA(CEESyslog);
+ PARSERDEF_NO_DATA(v2IPTables);
+ PARSERDEF_NO_DATA(CiscoInterfaceSpec);
+diff --git a/src/pdag.c b/src/pdag.c
+index 0768e99..9feb755 100644
+--- a/src/pdag.c
++++ b/src/pdag.c
+@@ -90,7 +90,7 @@ static struct ln_parser_info parser_lookup_table[] = {
+ PARSER_ENTRY_NO_DATA("duration", Duration, 16),
+ PARSER_ENTRY_NO_DATA("cisco-interface-spec", CiscoInterfaceSpec, 4),
+ PARSER_ENTRY_NO_DATA("name-value-list", NameValue, 8),
+- PARSER_ENTRY_NO_DATA("json", JSON, 4),
++ PARSER_ENTRY("json", JSON, 4),
+ PARSER_ENTRY_NO_DATA("cee-syslog", CEESyslog, 4),
+ PARSER_ENTRY_NO_DATA("mac48", MAC48, 16),
+ PARSER_ENTRY_NO_DATA("cef", CEF, 4),