diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..77f58a9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/liblognorm-2.0.2.tar.gz diff --git a/.liblognorm.metadata b/.liblognorm.metadata new file mode 100644 index 0000000..a2653f9 --- /dev/null +++ b/.liblognorm.metadata @@ -0,0 +1 @@ +dca441d5384fbba6214c2439fb69d5b99afb82f5 SOURCES/liblognorm-2.0.2.tar.gz diff --git a/SOURCES/liblognorm-2.0.0-rhbz1565219-add-skipempty.patch b/SOURCES/liblognorm-2.0.0-rhbz1565219-add-skipempty.patch new file mode 100644 index 0000000..290bc94 --- /dev/null +++ b/SOURCES/liblognorm-2.0.0-rhbz1565219-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/SPECS/liblognorm.spec b/SPECS/liblognorm.spec new file mode 100644 index 0000000..6b74cd1 --- /dev/null +++ b/SPECS/liblognorm.spec @@ -0,0 +1,138 @@ +%define htmldir %{_docdir}/liblognorm/html + +Name: liblognorm +Version: 2.0.2 +Release: 3%{?dist} +Summary: Fast samples-based log normalization library + +License: LGPLv2+ +URL: http://www.liblognorm.com +Source0: http://www.liblognorm.com/files/download/%{name}-%{version}.tar.gz +Patch0: liblognorm-2.0.0-rhbz1565219-add-skipempty.patch + +BuildRequires: chrpath +#this release contains ABI change used by bz1565219 fix +BuildRequires: libfastjson-devel >= 0.99.4-3 +BuildRequires: libestr-devel +BuildRequires: pcre-devel + +%description +Briefly described, liblognorm is a tool to normalize log data. + +People who need to take a look at logs often have a common problem. Logs from +different machines (from different vendors) usually have different formats for +their logs. Even if it is the same type of log (e.g. from firewalls), the log +entries are so different, that it is pretty hard to read these. This is where +liblognorm comes into the game. With this tool you can normalize all your logs. +All you need is liblognorm and its dependencies and a sample database that fits +the logs you want to normalize. + +%package devel +Summary: Development tools for programs using liblognorm library +Requires: %{name}%{?_isa} = %{version}-%{release} +Requires: libfastjson-devel%{?_isa} +Requires: libestr-devel%{?_isa} + +%description devel +The liblognorm-devel package includes header files, libraries necessary for +developing programs which use liblognorm library. + +%package doc +Summary: HTML documentation for liblognorm +Group: Documentation +BuildRequires: python-sphinx + +%description doc +This sub-package contains documentation for liblognorm in a HTML form. + +%package utils +Summary: Lognormalizer utility for normalizing log files +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description utils +The lognormalizer is the core of liblognorm, it is a utility for normalizing +log files. + +%prep +%setup -q +%patch0 -p1 -b .skipempty + +%build +%configure --enable-regexp --enable-docs --docdir=%{htmldir} + + +%install +make V=1 install INSTALL="install -p" DESTDIR=%{buildroot} +rm -f %{buildroot}/%{_libdir}/*.{a,la} +chrpath -d %{buildroot}%{_bindir}/lognormalizer +chrpath -d %{buildroot}%{_libdir}/liblognorm.so +rm %{buildroot}%{htmldir}/{objects.inv,.buildinfo} + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%files +%{!?_licensedir:%global license %%doc} +%license COPYING +%doc AUTHORS ChangeLog README +%exclude %{htmldir} + +%{_libdir}/lib*.so.* + +%files devel +%{_libdir}/lib*.so +%{_includedir}/*.h +%{_libdir}/pkgconfig/*.pc + +%files doc +%doc %{htmldir} + +%files utils +%{_bindir}/lognormalizer + + + +%changelog +* Fri Aug 03 2018 Jiri Vymazal 2.0.2-3 +RHEL 7.6 erratum +- corrected version for libfastjson build dep + resolves: rhbz#1565219 + +* Mon Jul 30 2018 Jiri Vymazal 2.0.2-2 +RHEL 7.6 erratum +- added patch with skipempty support + resolves: rhbz#1565219 +- removed no longer used patch file + +* Wed Mar 1 2017 Radovan Sroka 2.0.2-1 +- rebase to 2.0.2 +- resolves: rhbz#1420719 + +* Fri Jan 24 2014 Daniel Mach - 0.3.7-3 +- Mass rebuild 2014-01-24 + +* Fri Dec 27 2013 Daniel Mach - 0.3.7-2 +- Mass rebuild 2013-12-27 + +* Wed Jul 31 2013 Tomas Heinrich - 0.3.7-1 +- rebase to 0.3.7 + +* Wed Dec 12 2012 Mahaveer Darade - 0.3.5-1 +- upgrade to upstream version 0.3.5 +- drop patch0, merged upstream + liblognorm-0.3.4-rename-to-lognormalizer.patch +- remove trailing whitespace + +* Fri Oct 05 2012 mdarade - 0.3.4-4 +- Modified description of main & util package + +* Thu Sep 20 2012 Mahaveer Darade - 0.3.4-3 +- Renamed normalizer binary to lognormalizer +- Updated pc file to exclude lee and lestr + +* Mon Aug 27 2012 mdarade - 0.3.4-2 +- Updated BuildRequires to contain libestr-devel + +* Wed Aug 1 2012 Milan Bartos - 0.3.4-1 +- initial port