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