|
47 | 47 | #include <errno.h> |
48 | 48 | #endif |
49 | 49 |
|
| 50 | +#include <libxml/xmlmemory.h> |
| 51 | +#include <libxml/parser.h> |
| 52 | + |
50 | 53 |
|
51 | 54 | /* how should output values be formatted? */ |
52 | 55 | enum FMT_MODE { |
@@ -75,6 +78,38 @@ hParseInt(const unsigned char **buf, size_t *lenBuf) |
75 | 78 | return i; |
76 | 79 | } |
77 | 80 |
|
| 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 | + |
78 | 113 | /* parser _parse interface |
79 | 114 | * |
80 | 115 | * All parsers receive |
@@ -2325,6 +2360,69 @@ PARSER_Parse(v2IPTables) |
2325 | 2360 | return r; |
2326 | 2361 | } |
2327 | 2362 |
|
| 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 | + |
2328 | 2426 | /** |
2329 | 2427 | * Parse JSON. This parser tries to find JSON data inside a message. |
2330 | 2428 | * If it finds valid JSON, it will extract it. Extra data after the |
|
0 commit comments