Skip to content

Commit 048abc0

Browse files
Jérémie Jourdinfrikilax
authored andcommitted
Add support for 'xml' keyword in liblognorm.
1 parent 2053745 commit 048abc0

File tree

7 files changed

+143
-2
lines changed

7 files changed

+143
-2
lines changed

configure.ac

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ AC_SUBST(LIBLOGNORM_LIBS)
6565
# modules we require
6666
PKG_CHECK_MODULES(LIBESTR, libestr >= 0.0.0)
6767
PKG_CHECK_MODULES(JSON_C, libfastjson,, )
68+
PKG_CHECK_MODULES(LIBXML2, libxml2,, )
6869
# add libestr flags to pkgconfig file for static linking
6970
AC_SUBST(pkg_config_libs_private, $LIBESTR_LIBS)
7071

src/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ liblognorm_la_SOURCES += \
4343
v1_samp.c
4444

4545
liblognorm_la_CPPFLAGS = $(JSON_C_CFLAGS) $(WARN_CFLAGS) $(LIBESTR_CFLAGS) $(PCRE_CFLAGS)
46-
liblognorm_la_LIBADD = $(rt_libs) $(JSON_C_LIBS) $(LIBESTR_LIBS) $(PCRE_LIBS) -lestr
46+
liblognorm_la_LIBADD = $(rt_libs) $(JSON_C_LIBS) $(LIBESTR_LIBS) $(PCRE_LIBS) -lestr -lxml2
4747
# info on version-info:
4848
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
4949
# Note: v2 now starts at version 5, as v1 previously also had 4

src/parser.c

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@
4747
#include <errno.h>
4848
#endif
4949

50+
#include <libxml/xmlmemory.h>
51+
#include <libxml/parser.h>
52+
5053

5154
/* how should output values be formatted? */
5255
enum FMT_MODE {
@@ -75,6 +78,38 @@ hParseInt(const unsigned char **buf, size_t *lenBuf)
7578
return i;
7679
}
7780

81+
/* Credits to https://github.com/katie-snow/xml2json-c
82+
This code is under GPL-3.0 License
83+
*/
84+
static inline void
85+
xml2jsonc_convert_elements(xmlNode *anode, json_object *jobj)
86+
{
87+
xmlNode *cur_node = NULL;
88+
json_object *cur_jobj = NULL;
89+
json_object *cur_jstr = NULL;
90+
91+
for (cur_node = anode; cur_node; cur_node = cur_node->next)
92+
{
93+
if (cur_node->type == XML_ELEMENT_NODE)
94+
{
95+
if (xmlChildElementCount(cur_node) == 0)
96+
{
97+
/* JSON string object */
98+
cur_jobj = json_object_new_object();
99+
cur_jstr = json_object_new_string((const char *)xmlNodeGetContent(cur_node));
100+
json_object_object_add(jobj, (const char *)cur_node->name, cur_jstr);
101+
}
102+
else
103+
{
104+
/* JSON object */
105+
cur_jobj = json_object_new_object();
106+
json_object_object_add(jobj, (const char *)cur_node->name, json_object_get(cur_jobj));
107+
}
108+
}
109+
xml2jsonc_convert_elements(cur_node->children, cur_jobj);
110+
}
111+
}
112+
78113
/* parser _parse interface
79114
*
80115
* All parsers receive
@@ -2325,6 +2360,69 @@ PARSER_Parse(v2IPTables)
23252360
return r;
23262361
}
23272362

2363+
/**
2364+
* Parse XML. This parser tries to find XML data inside a message.
2365+
* If it finds valid XML, it will extract it.
2366+
*
2367+
* Note: The XML Parser expects a string that begins with '<' and
2368+
* ends with '>'. whitespace or any other character at the
2369+
* beginning or at the end of the string will cause a parse failure
2370+
*
2371+
* Note: Is there is extra content after the XML content
2372+
* the parser will fail. A hack consist of finding the
2373+
* last '>' in the string and ignore the rest.
2374+
*
2375+
* added 2021-02-01 by [email protected]
2376+
*/
2377+
PARSER_Parse(XML)
2378+
xmlDocPtr doc = NULL;
2379+
xmlNodePtr root_element = NULL;
2380+
2381+
/* Find the last occurence of '>' in the string */
2382+
char * pch;
2383+
pch=strrchr((const char *) npb->str + *offs, '>');
2384+
2385+
/* Truncate the string after the last occurence of '>' */
2386+
int newLen = pch - (npb->str + *offs) + 1;
2387+
char *cstr = strndup(npb->str + *offs, newLen);
2388+
CHKN(cstr);
2389+
2390+
doc=xmlParseDoc((xmlChar*) cstr);
2391+
free(cstr);
2392+
2393+
/* Invalid XML string */
2394+
if (doc == NULL) {
2395+
goto done;
2396+
}
2397+
2398+
/* Now convert XML document into JSON document */
2399+
root_element = xmlDocGetRootElement(doc);
2400+
json_object *json = NULL;
2401+
json = json_object_new_object();
2402+
xml2jsonc_convert_elements(root_element, json);
2403+
2404+
if(json == NULL)
2405+
goto done;
2406+
2407+
/* parsing OK */
2408+
*parsed = newLen ;
2409+
r = 0;
2410+
2411+
if(value == NULL) {
2412+
json_object_put(json);
2413+
} else {
2414+
*value = json;
2415+
}
2416+
2417+
done:
2418+
if(doc != NULL)
2419+
xmlFreeDoc(doc);
2420+
xmlCleanupParser();
2421+
return r;
2422+
}
2423+
2424+
2425+
23282426
/**
23292427
* Parse JSON. This parser tries to find JSON data inside a message.
23302428
* If it finds valid JSON, it will extract it. Extra data after the

src/parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ PARSERDEF_NO_DATA(MAC48);
7878
PARSERDEF_NO_DATA(CEF);
7979
PARSERDEF(CheckpointLEA);
8080
PARSERDEF_NO_DATA(NameValue);
81+
PARSERDEF_NO_DATA(XML);
8182

8283
#undef PARSERDEF_NO_DATA
8384

src/pdag.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ static struct ln_parser_info parser_lookup_table[] = {
9999
PARSER_ENTRY("string-to", StringTo, 32),
100100
PARSER_ENTRY("char-to", CharTo, 32),
101101
PARSER_ENTRY("char-sep", CharSeparated, 32),
102-
PARSER_ENTRY("string", String, 32)
102+
PARSER_ENTRY("string", String, 32),
103+
PARSER_ENTRY_NO_DATA("xml", XML, 4)
103104
};
104105
#define NPARSERS (sizeof(parser_lookup_table)/sizeof(struct ln_parser_info))
105106
#define DFLT_USR_PARSER_PRIO 30000 /**< default priority if user has not specified it */

src/pdag.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ struct ln_type_pdag;
6767
#define PRS_STRING_TO 27
6868
#define PRS_CHAR_TO 28
6969
#define PRS_CHAR_SEP 29
70+
#define PRS_XML 30
7071
#endif
7172

7273
#define PRS_CUSTOM_TYPE 254

src/v1_parser.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
#include <errno.h>
4444
#endif
4545

46+
#include <libxml/xmlmemory.h>
47+
#include <libxml/parser.h>
4648

4749
/* some helpers */
4850
static inline int
@@ -63,6 +65,38 @@ hParseInt(const unsigned char **buf, size_t *lenBuf)
6365
return i;
6466
}
6567

68+
/* Credits to https://github.com/katie-snow/xml2json-c
69+
This code is under GPL-3.0 License
70+
*/
71+
static inline void
72+
xml2jsonc_convert_elements(xmlNode *anode, json_object *jobj)
73+
{
74+
xmlNode *cur_node = NULL;
75+
json_object *cur_jobj = NULL;
76+
json_object *cur_jstr = NULL;
77+
78+
for (cur_node = anode; cur_node; cur_node = cur_node->next)
79+
{
80+
if (cur_node->type == XML_ELEMENT_NODE)
81+
{
82+
if (xmlChildElementCount(cur_node) == 0)
83+
{
84+
/* JSON string object */
85+
cur_jobj = json_object_new_object();
86+
cur_jstr = json_object_new_string((const char *)xmlNodeGetContent(cur_node));
87+
json_object_object_add(jobj, (const char *)cur_node->name, cur_jstr);
88+
}
89+
else
90+
{
91+
/* JSON object */
92+
cur_jobj = json_object_new_object();
93+
json_object_object_add(jobj, (const char *)cur_node->name, json_object_get(cur_jobj));
94+
}
95+
}
96+
xml2jsonc_convert_elements(cur_node->children, cur_jobj);
97+
}
98+
}
99+
66100
/* parsers for the primitive types
67101
*
68102
* All parsers receive
@@ -2540,6 +2574,9 @@ PARSER(v2IPTables)
25402574
return r;
25412575
}
25422576

2577+
2578+
2579+
25432580
/**
25442581
* Parse JSON. This parser tries to find JSON data inside a message.
25452582
* If it finds valid JSON, it will extract it. Extra data after the
@@ -2593,6 +2630,8 @@ PARSER(JSON)
25932630
}
25942631

25952632

2633+
2634+
25962635
/* check if a char is valid inside a name of a NameValue list
25972636
* The set of valid characters may be extended if there is good
25982637
* need to do so. We have selected the current set carefully, but

0 commit comments

Comments
 (0)