Allow dropping empty json objects
Resolves: RHEL-39979
This commit is contained in:
parent
49823bff4f
commit
e539472e79
204
liblognorm-2.0.0-rhbz1990737-add-skipempty.patch
Normal file
204
liblognorm-2.0.0-rhbz1990737-add-skipempty.patch
Normal file
@ -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),
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Name: liblognorm
|
Name: liblognorm
|
||||||
Version: 2.0.6
|
Version: 2.0.6
|
||||||
Release: 13%{?dist}
|
Release: 14%{?dist}
|
||||||
Summary: Fast samples-based log normalization library
|
Summary: Fast samples-based log normalization library
|
||||||
License: LGPL-2.1-or-later AND Apache-2.0
|
License: LGPL-2.1-or-later AND Apache-2.0
|
||||||
URL: http://www.liblognorm.com
|
URL: http://www.liblognorm.com
|
||||||
@ -20,6 +20,7 @@ BuildRequires: libtool
|
|||||||
Patch0: liblognorm-2.0.6-rhbz2105934-sphinx5.patch
|
Patch0: liblognorm-2.0.6-rhbz2105934-sphinx5.patch
|
||||||
Patch1: liblognorm-configure-glitch.patch
|
Patch1: liblognorm-configure-glitch.patch
|
||||||
Patch2: liblognorm-2.0.6-rhbz2128320.patch
|
Patch2: liblognorm-2.0.6-rhbz2128320.patch
|
||||||
|
Patch3: liblognorm-2.0.0-rhbz1990737-add-skipempty.patch
|
||||||
|
|
||||||
%description
|
%description
|
||||||
Briefly described, liblognorm is a tool to normalize log data.
|
Briefly described, liblognorm is a tool to normalize log data.
|
||||||
@ -64,6 +65,7 @@ log files.
|
|||||||
%patch -P 0 -p1 -b .sphinx5
|
%patch -P 0 -p1 -b .sphinx5
|
||||||
%patch -P 1 -p1 -b .configure-glitch
|
%patch -P 1 -p1 -b .configure-glitch
|
||||||
%patch -P 2 -p1 -b .pcre2
|
%patch -P 2 -p1 -b .pcre2
|
||||||
|
%patch -P 3 -p1
|
||||||
|
|
||||||
%build
|
%build
|
||||||
# Prevent rebuild of the configure script.
|
# Prevent rebuild of the configure script.
|
||||||
@ -102,6 +104,10 @@ rm %{buildroot}%{htmldir}/{objects.inv,.buildinfo}
|
|||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Tue Aug 06 2024 Attila Lakatos <alakatos@redhat.com> - 2.0.6-14
|
||||||
|
- Allow dropping empty json objects
|
||||||
|
Resolves: RHEL-39979
|
||||||
|
|
||||||
* Mon Jun 24 2024 Troy Dawson <tdawson@redhat.com> - 2.0.6-13
|
* Mon Jun 24 2024 Troy Dawson <tdawson@redhat.com> - 2.0.6-13
|
||||||
- Bump release for June 2024 mass rebuild
|
- Bump release for June 2024 mass rebuild
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user