xref: /freebsd-src/contrib/wpa/src/utils/xml_libxml2.c (revision c1d255d3ffdbe447de3ab875bf4e7d7accc5bfc5)
15b9c547cSRui Paulo /*
25b9c547cSRui Paulo  * XML wrapper for libxml2
35b9c547cSRui Paulo  * Copyright (c) 2012-2013, Qualcomm Atheros, Inc.
45b9c547cSRui Paulo  *
55b9c547cSRui Paulo  * This software may be distributed under the terms of the BSD license.
65b9c547cSRui Paulo  * See README for more details.
75b9c547cSRui Paulo  */
85b9c547cSRui Paulo 
95b9c547cSRui Paulo #include "includes.h"
105b9c547cSRui Paulo #define LIBXML_VALID_ENABLED
115b9c547cSRui Paulo #include <libxml/tree.h>
125b9c547cSRui Paulo #include <libxml/xmlschemastypes.h>
135b9c547cSRui Paulo 
145b9c547cSRui Paulo #include "common.h"
155b9c547cSRui Paulo #include "base64.h"
165b9c547cSRui Paulo #include "xml-utils.h"
175b9c547cSRui Paulo 
185b9c547cSRui Paulo 
195b9c547cSRui Paulo struct xml_node_ctx {
205b9c547cSRui Paulo 	void *ctx;
215b9c547cSRui Paulo };
225b9c547cSRui Paulo 
235b9c547cSRui Paulo 
245b9c547cSRui Paulo struct str_buf {
255b9c547cSRui Paulo 	char *buf;
265b9c547cSRui Paulo 	size_t len;
275b9c547cSRui Paulo };
285b9c547cSRui Paulo 
295b9c547cSRui Paulo #define MAX_STR 1000
305b9c547cSRui Paulo 
add_str(void * ctx_ptr,const char * fmt,...)315b9c547cSRui Paulo static void add_str(void *ctx_ptr, const char *fmt, ...)
325b9c547cSRui Paulo {
335b9c547cSRui Paulo 	struct str_buf *str = ctx_ptr;
345b9c547cSRui Paulo 	va_list ap;
355b9c547cSRui Paulo 	char *n;
365b9c547cSRui Paulo 	int len;
375b9c547cSRui Paulo 
385b9c547cSRui Paulo 	n = os_realloc(str->buf, str->len + MAX_STR + 2);
395b9c547cSRui Paulo 	if (n == NULL)
405b9c547cSRui Paulo 		return;
415b9c547cSRui Paulo 	str->buf = n;
425b9c547cSRui Paulo 
435b9c547cSRui Paulo 	va_start(ap, fmt);
445b9c547cSRui Paulo 	len = vsnprintf(str->buf + str->len, MAX_STR, fmt, ap);
455b9c547cSRui Paulo 	va_end(ap);
465b9c547cSRui Paulo 	if (len >= MAX_STR)
475b9c547cSRui Paulo 		len = MAX_STR - 1;
485b9c547cSRui Paulo 	str->len += len;
495b9c547cSRui Paulo 	str->buf[str->len] = '\0';
505b9c547cSRui Paulo }
515b9c547cSRui Paulo 
525b9c547cSRui Paulo 
xml_validate(struct xml_node_ctx * ctx,xml_node_t * node,const char * xml_schema_fname,char ** ret_err)535b9c547cSRui Paulo int xml_validate(struct xml_node_ctx *ctx, xml_node_t *node,
545b9c547cSRui Paulo 		 const char *xml_schema_fname, char **ret_err)
555b9c547cSRui Paulo {
565b9c547cSRui Paulo 	xmlDocPtr doc;
575b9c547cSRui Paulo 	xmlNodePtr n;
585b9c547cSRui Paulo 	xmlSchemaParserCtxtPtr pctx;
595b9c547cSRui Paulo 	xmlSchemaValidCtxtPtr vctx;
605b9c547cSRui Paulo 	xmlSchemaPtr schema;
615b9c547cSRui Paulo 	int ret;
625b9c547cSRui Paulo 	struct str_buf errors;
635b9c547cSRui Paulo 
645b9c547cSRui Paulo 	if (ret_err)
655b9c547cSRui Paulo 		*ret_err = NULL;
665b9c547cSRui Paulo 
675b9c547cSRui Paulo 	doc = xmlNewDoc((xmlChar *) "1.0");
685b9c547cSRui Paulo 	if (doc == NULL)
695b9c547cSRui Paulo 		return -1;
705b9c547cSRui Paulo 	n = xmlDocCopyNode((xmlNodePtr) node, doc, 1);
715b9c547cSRui Paulo 	if (n == NULL) {
725b9c547cSRui Paulo 		xmlFreeDoc(doc);
735b9c547cSRui Paulo 		return -1;
745b9c547cSRui Paulo 	}
755b9c547cSRui Paulo 	xmlDocSetRootElement(doc, n);
765b9c547cSRui Paulo 
775b9c547cSRui Paulo 	os_memset(&errors, 0, sizeof(errors));
785b9c547cSRui Paulo 
795b9c547cSRui Paulo 	pctx = xmlSchemaNewParserCtxt(xml_schema_fname);
805b9c547cSRui Paulo 	xmlSchemaSetParserErrors(pctx, (xmlSchemaValidityErrorFunc) add_str,
815b9c547cSRui Paulo 				 (xmlSchemaValidityWarningFunc) add_str,
825b9c547cSRui Paulo 				 &errors);
835b9c547cSRui Paulo 	schema = xmlSchemaParse(pctx);
845b9c547cSRui Paulo 	xmlSchemaFreeParserCtxt(pctx);
855b9c547cSRui Paulo 
865b9c547cSRui Paulo 	vctx = xmlSchemaNewValidCtxt(schema);
875b9c547cSRui Paulo 	xmlSchemaSetValidErrors(vctx, (xmlSchemaValidityErrorFunc) add_str,
885b9c547cSRui Paulo 				(xmlSchemaValidityWarningFunc) add_str,
895b9c547cSRui Paulo 				&errors);
905b9c547cSRui Paulo 
915b9c547cSRui Paulo 	ret = xmlSchemaValidateDoc(vctx, doc);
925b9c547cSRui Paulo 	xmlSchemaFreeValidCtxt(vctx);
935b9c547cSRui Paulo 	xmlFreeDoc(doc);
945b9c547cSRui Paulo 	xmlSchemaFree(schema);
955b9c547cSRui Paulo 
965b9c547cSRui Paulo 	if (ret == 0) {
975b9c547cSRui Paulo 		os_free(errors.buf);
985b9c547cSRui Paulo 		return 0;
995b9c547cSRui Paulo 	} else if (ret > 0) {
1005b9c547cSRui Paulo 		if (ret_err)
1015b9c547cSRui Paulo 			*ret_err = errors.buf;
1025b9c547cSRui Paulo 		else
1035b9c547cSRui Paulo 			os_free(errors.buf);
1045b9c547cSRui Paulo 		return -1;
1055b9c547cSRui Paulo 	} else {
1065b9c547cSRui Paulo 		if (ret_err)
1075b9c547cSRui Paulo 			*ret_err = errors.buf;
1085b9c547cSRui Paulo 		else
1095b9c547cSRui Paulo 			os_free(errors.buf);
1105b9c547cSRui Paulo 		return -1;
1115b9c547cSRui Paulo 	}
1125b9c547cSRui Paulo }
1135b9c547cSRui Paulo 
1145b9c547cSRui Paulo 
xml_validate_dtd(struct xml_node_ctx * ctx,xml_node_t * node,const char * dtd_fname,char ** ret_err)1155b9c547cSRui Paulo int xml_validate_dtd(struct xml_node_ctx *ctx, xml_node_t *node,
1165b9c547cSRui Paulo 		     const char *dtd_fname, char **ret_err)
1175b9c547cSRui Paulo {
1185b9c547cSRui Paulo 	xmlDocPtr doc;
1195b9c547cSRui Paulo 	xmlNodePtr n;
1205b9c547cSRui Paulo 	xmlValidCtxt vctx;
1215b9c547cSRui Paulo 	xmlDtdPtr dtd;
1225b9c547cSRui Paulo 	int ret;
1235b9c547cSRui Paulo 	struct str_buf errors;
1245b9c547cSRui Paulo 
1255b9c547cSRui Paulo 	if (ret_err)
1265b9c547cSRui Paulo 		*ret_err = NULL;
1275b9c547cSRui Paulo 
1285b9c547cSRui Paulo 	doc = xmlNewDoc((xmlChar *) "1.0");
1295b9c547cSRui Paulo 	if (doc == NULL)
1305b9c547cSRui Paulo 		return -1;
1315b9c547cSRui Paulo 	n = xmlDocCopyNode((xmlNodePtr) node, doc, 1);
1325b9c547cSRui Paulo 	if (n == NULL) {
1335b9c547cSRui Paulo 		xmlFreeDoc(doc);
1345b9c547cSRui Paulo 		return -1;
1355b9c547cSRui Paulo 	}
1365b9c547cSRui Paulo 	xmlDocSetRootElement(doc, n);
1375b9c547cSRui Paulo 
1385b9c547cSRui Paulo 	os_memset(&errors, 0, sizeof(errors));
1395b9c547cSRui Paulo 
1405b9c547cSRui Paulo 	dtd = xmlParseDTD(NULL, (const xmlChar *) dtd_fname);
1415b9c547cSRui Paulo 	if (dtd == NULL) {
1425b9c547cSRui Paulo 		xmlFreeDoc(doc);
1435b9c547cSRui Paulo 		return -1;
1445b9c547cSRui Paulo 	}
1455b9c547cSRui Paulo 
1465b9c547cSRui Paulo 	os_memset(&vctx, 0, sizeof(vctx));
1475b9c547cSRui Paulo 	vctx.userData = &errors;
1485b9c547cSRui Paulo 	vctx.error = add_str;
1495b9c547cSRui Paulo 	vctx.warning = add_str;
1505b9c547cSRui Paulo 	ret = xmlValidateDtd(&vctx, doc, dtd);
1515b9c547cSRui Paulo 	xmlFreeDoc(doc);
1525b9c547cSRui Paulo 	xmlFreeDtd(dtd);
1535b9c547cSRui Paulo 
1545b9c547cSRui Paulo 	if (ret == 1) {
1555b9c547cSRui Paulo 		os_free(errors.buf);
1565b9c547cSRui Paulo 		return 0;
1575b9c547cSRui Paulo 	} else {
1585b9c547cSRui Paulo 		if (ret_err)
1595b9c547cSRui Paulo 			*ret_err = errors.buf;
1605b9c547cSRui Paulo 		else
1615b9c547cSRui Paulo 			os_free(errors.buf);
1625b9c547cSRui Paulo 		return -1;
1635b9c547cSRui Paulo 	}
1645b9c547cSRui Paulo }
1655b9c547cSRui Paulo 
1665b9c547cSRui Paulo 
xml_node_free(struct xml_node_ctx * ctx,xml_node_t * node)1675b9c547cSRui Paulo void xml_node_free(struct xml_node_ctx *ctx, xml_node_t *node)
1685b9c547cSRui Paulo {
1695b9c547cSRui Paulo 	xmlFreeNode((xmlNodePtr) node);
1705b9c547cSRui Paulo }
1715b9c547cSRui Paulo 
1725b9c547cSRui Paulo 
xml_node_get_parent(struct xml_node_ctx * ctx,xml_node_t * node)1735b9c547cSRui Paulo xml_node_t * xml_node_get_parent(struct xml_node_ctx *ctx, xml_node_t *node)
1745b9c547cSRui Paulo {
1755b9c547cSRui Paulo 	return (xml_node_t *) ((xmlNodePtr) node)->parent;
1765b9c547cSRui Paulo }
1775b9c547cSRui Paulo 
1785b9c547cSRui Paulo 
xml_node_from_buf(struct xml_node_ctx * ctx,const char * buf)1795b9c547cSRui Paulo xml_node_t * xml_node_from_buf(struct xml_node_ctx *ctx, const char *buf)
1805b9c547cSRui Paulo {
1815b9c547cSRui Paulo 	xmlDocPtr doc;
1825b9c547cSRui Paulo 	xmlNodePtr node;
1835b9c547cSRui Paulo 
1845b9c547cSRui Paulo 	doc = xmlParseMemory(buf, strlen(buf));
1855b9c547cSRui Paulo 	if (doc == NULL)
1865b9c547cSRui Paulo 		return NULL;
1875b9c547cSRui Paulo 	node = xmlDocGetRootElement(doc);
1885b9c547cSRui Paulo 	node = xmlCopyNode(node, 1);
1895b9c547cSRui Paulo 	xmlFreeDoc(doc);
1905b9c547cSRui Paulo 
1915b9c547cSRui Paulo 	return (xml_node_t *) node;
1925b9c547cSRui Paulo }
1935b9c547cSRui Paulo 
1945b9c547cSRui Paulo 
xml_node_get_localname(struct xml_node_ctx * ctx,xml_node_t * node)1955b9c547cSRui Paulo const char * xml_node_get_localname(struct xml_node_ctx *ctx,
1965b9c547cSRui Paulo 				    xml_node_t *node)
1975b9c547cSRui Paulo {
1985b9c547cSRui Paulo 	return (const char *) ((xmlNodePtr) node)->name;
1995b9c547cSRui Paulo }
2005b9c547cSRui Paulo 
2015b9c547cSRui Paulo 
xml_node_to_str(struct xml_node_ctx * ctx,xml_node_t * node)2025b9c547cSRui Paulo char * xml_node_to_str(struct xml_node_ctx *ctx, xml_node_t *node)
2035b9c547cSRui Paulo {
2045b9c547cSRui Paulo 	xmlChar *buf;
2055b9c547cSRui Paulo 	int bufsiz;
2065b9c547cSRui Paulo 	char *ret, *pos;
2075b9c547cSRui Paulo 	xmlNodePtr n = (xmlNodePtr) node;
2085b9c547cSRui Paulo 	xmlDocPtr doc;
2095b9c547cSRui Paulo 
2105b9c547cSRui Paulo 	doc = xmlNewDoc((xmlChar *) "1.0");
2115b9c547cSRui Paulo 	n = xmlDocCopyNode(n, doc, 1);
2125b9c547cSRui Paulo 	xmlDocSetRootElement(doc, n);
2135b9c547cSRui Paulo 	xmlDocDumpFormatMemory(doc, &buf, &bufsiz, 0);
2145b9c547cSRui Paulo 	xmlFreeDoc(doc);
215780fb4a2SCy Schubert 	if (!buf)
216780fb4a2SCy Schubert 		return NULL;
2175b9c547cSRui Paulo 	pos = (char *) buf;
2185b9c547cSRui Paulo 	if (strncmp(pos, "<?xml", 5) == 0) {
2195b9c547cSRui Paulo 		pos = strchr(pos, '>');
2205b9c547cSRui Paulo 		if (pos)
2215b9c547cSRui Paulo 			pos++;
2225b9c547cSRui Paulo 		while (pos && (*pos == '\r' || *pos == '\n'))
2235b9c547cSRui Paulo 			pos++;
2245b9c547cSRui Paulo 	}
2255b9c547cSRui Paulo 	if (pos)
2265b9c547cSRui Paulo 		ret = os_strdup(pos);
2275b9c547cSRui Paulo 	else
2285b9c547cSRui Paulo 		ret = NULL;
2295b9c547cSRui Paulo 	xmlFree(buf);
2305b9c547cSRui Paulo 
2315b9c547cSRui Paulo 	if (ret) {
2325b9c547cSRui Paulo 		pos = ret;
2335b9c547cSRui Paulo 		if (pos[0]) {
2345b9c547cSRui Paulo 			while (pos[1])
2355b9c547cSRui Paulo 				pos++;
2365b9c547cSRui Paulo 		}
2375b9c547cSRui Paulo 		while (pos >= ret && *pos == '\n')
2385b9c547cSRui Paulo 			*pos-- = '\0';
2395b9c547cSRui Paulo 	}
2405b9c547cSRui Paulo 
2415b9c547cSRui Paulo 	return ret;
2425b9c547cSRui Paulo }
2435b9c547cSRui Paulo 
2445b9c547cSRui Paulo 
xml_node_detach(struct xml_node_ctx * ctx,xml_node_t * node)2455b9c547cSRui Paulo void xml_node_detach(struct xml_node_ctx *ctx, xml_node_t *node)
2465b9c547cSRui Paulo {
2475b9c547cSRui Paulo 	xmlUnlinkNode((xmlNodePtr) node);
2485b9c547cSRui Paulo }
2495b9c547cSRui Paulo 
2505b9c547cSRui Paulo 
xml_node_add_child(struct xml_node_ctx * ctx,xml_node_t * parent,xml_node_t * child)2515b9c547cSRui Paulo void xml_node_add_child(struct xml_node_ctx *ctx, xml_node_t *parent,
2525b9c547cSRui Paulo 			xml_node_t *child)
2535b9c547cSRui Paulo {
2545b9c547cSRui Paulo 	xmlAddChild((xmlNodePtr) parent, (xmlNodePtr) child);
2555b9c547cSRui Paulo }
2565b9c547cSRui Paulo 
2575b9c547cSRui Paulo 
xml_node_create_root(struct xml_node_ctx * ctx,const char * ns_uri,const char * ns_prefix,xml_namespace_t ** ret_ns,const char * name)2585b9c547cSRui Paulo xml_node_t * xml_node_create_root(struct xml_node_ctx *ctx, const char *ns_uri,
2595b9c547cSRui Paulo 				  const char *ns_prefix,
2605b9c547cSRui Paulo 				  xml_namespace_t **ret_ns, const char *name)
2615b9c547cSRui Paulo {
2625b9c547cSRui Paulo 	xmlNodePtr node;
2635b9c547cSRui Paulo 	xmlNsPtr ns = NULL;
2645b9c547cSRui Paulo 
2655b9c547cSRui Paulo 	node = xmlNewNode(NULL, (const xmlChar *) name);
2665b9c547cSRui Paulo 	if (node == NULL)
2675b9c547cSRui Paulo 		return NULL;
2685b9c547cSRui Paulo 	if (ns_uri) {
2695b9c547cSRui Paulo 		ns = xmlNewNs(node, (const xmlChar *) ns_uri,
2705b9c547cSRui Paulo 			      (const xmlChar *) ns_prefix);
2715b9c547cSRui Paulo 		xmlSetNs(node, ns);
2725b9c547cSRui Paulo 	}
2735b9c547cSRui Paulo 
2745b9c547cSRui Paulo 	if (ret_ns)
2755b9c547cSRui Paulo 		*ret_ns = (xml_namespace_t *) ns;
2765b9c547cSRui Paulo 
2775b9c547cSRui Paulo 	return (xml_node_t *) node;
2785b9c547cSRui Paulo }
2795b9c547cSRui Paulo 
2805b9c547cSRui Paulo 
xml_node_create(struct xml_node_ctx * ctx,xml_node_t * parent,xml_namespace_t * ns,const char * name)2815b9c547cSRui Paulo xml_node_t * xml_node_create(struct xml_node_ctx *ctx, xml_node_t *parent,
2825b9c547cSRui Paulo 			     xml_namespace_t *ns, const char *name)
2835b9c547cSRui Paulo {
2845b9c547cSRui Paulo 	xmlNodePtr node;
2855b9c547cSRui Paulo 	node = xmlNewChild((xmlNodePtr) parent, (xmlNsPtr) ns,
2865b9c547cSRui Paulo 			   (const xmlChar *) name, NULL);
2875b9c547cSRui Paulo 	return (xml_node_t *) node;
2885b9c547cSRui Paulo }
2895b9c547cSRui Paulo 
2905b9c547cSRui Paulo 
xml_node_create_text(struct xml_node_ctx * ctx,xml_node_t * parent,xml_namespace_t * ns,const char * name,const char * value)2915b9c547cSRui Paulo xml_node_t * xml_node_create_text(struct xml_node_ctx *ctx,
2925b9c547cSRui Paulo 				  xml_node_t *parent, xml_namespace_t *ns,
2935b9c547cSRui Paulo 				  const char *name, const char *value)
2945b9c547cSRui Paulo {
2955b9c547cSRui Paulo 	xmlNodePtr node;
2965b9c547cSRui Paulo 	node = xmlNewTextChild((xmlNodePtr) parent, (xmlNsPtr) ns,
2975b9c547cSRui Paulo 			       (const xmlChar *) name, (const xmlChar *) value);
2985b9c547cSRui Paulo 	return (xml_node_t *) node;
2995b9c547cSRui Paulo }
3005b9c547cSRui Paulo 
3015b9c547cSRui Paulo 
xml_node_create_text_ns(struct xml_node_ctx * ctx,xml_node_t * parent,const char * ns_uri,const char * name,const char * value)3025b9c547cSRui Paulo xml_node_t * xml_node_create_text_ns(struct xml_node_ctx *ctx,
3035b9c547cSRui Paulo 				     xml_node_t *parent, const char *ns_uri,
3045b9c547cSRui Paulo 				     const char *name, const char *value)
3055b9c547cSRui Paulo {
3065b9c547cSRui Paulo 	xmlNodePtr node;
3075b9c547cSRui Paulo 	xmlNsPtr ns;
3085b9c547cSRui Paulo 
3095b9c547cSRui Paulo 	node = xmlNewTextChild((xmlNodePtr) parent, NULL,
3105b9c547cSRui Paulo 			       (const xmlChar *) name, (const xmlChar *) value);
3115b9c547cSRui Paulo 	ns = xmlNewNs(node, (const xmlChar *) ns_uri, NULL);
3125b9c547cSRui Paulo 	xmlSetNs(node, ns);
3135b9c547cSRui Paulo 	return (xml_node_t *) node;
3145b9c547cSRui Paulo }
3155b9c547cSRui Paulo 
3165b9c547cSRui Paulo 
xml_node_set_text(struct xml_node_ctx * ctx,xml_node_t * node,const char * value)3175b9c547cSRui Paulo void xml_node_set_text(struct xml_node_ctx *ctx, xml_node_t *node,
3185b9c547cSRui Paulo 		       const char *value)
3195b9c547cSRui Paulo {
3205b9c547cSRui Paulo 	/* TODO: escape XML special chars in value */
3215b9c547cSRui Paulo 	xmlNodeSetContent((xmlNodePtr) node, (xmlChar *) value);
3225b9c547cSRui Paulo }
3235b9c547cSRui Paulo 
3245b9c547cSRui Paulo 
xml_node_add_attr(struct xml_node_ctx * ctx,xml_node_t * node,xml_namespace_t * ns,const char * name,const char * value)3255b9c547cSRui Paulo int xml_node_add_attr(struct xml_node_ctx *ctx, xml_node_t *node,
3265b9c547cSRui Paulo 		      xml_namespace_t *ns, const char *name, const char *value)
3275b9c547cSRui Paulo {
3285b9c547cSRui Paulo 	xmlAttrPtr attr;
3295b9c547cSRui Paulo 
3305b9c547cSRui Paulo 	if (ns) {
3315b9c547cSRui Paulo 		attr = xmlNewNsProp((xmlNodePtr) node, (xmlNsPtr) ns,
3325b9c547cSRui Paulo 				    (const xmlChar *) name,
3335b9c547cSRui Paulo 				    (const xmlChar *) value);
3345b9c547cSRui Paulo 	} else {
3355b9c547cSRui Paulo 		attr = xmlNewProp((xmlNodePtr) node, (const xmlChar *) name,
3365b9c547cSRui Paulo 				  (const xmlChar *) value);
3375b9c547cSRui Paulo 	}
3385b9c547cSRui Paulo 
3395b9c547cSRui Paulo 	return attr ? 0 : -1;
3405b9c547cSRui Paulo }
3415b9c547cSRui Paulo 
3425b9c547cSRui Paulo 
xml_node_get_attr_value(struct xml_node_ctx * ctx,xml_node_t * node,char * name)3435b9c547cSRui Paulo char * xml_node_get_attr_value(struct xml_node_ctx *ctx, xml_node_t *node,
3445b9c547cSRui Paulo 			       char *name)
3455b9c547cSRui Paulo {
3465b9c547cSRui Paulo 	return (char *) xmlGetNoNsProp((xmlNodePtr) node,
3475b9c547cSRui Paulo 				       (const xmlChar *) name);
3485b9c547cSRui Paulo }
3495b9c547cSRui Paulo 
3505b9c547cSRui Paulo 
xml_node_get_attr_value_ns(struct xml_node_ctx * ctx,xml_node_t * node,const char * ns_uri,char * name)3515b9c547cSRui Paulo char * xml_node_get_attr_value_ns(struct xml_node_ctx *ctx, xml_node_t *node,
3525b9c547cSRui Paulo 				  const char *ns_uri, char *name)
3535b9c547cSRui Paulo {
3545b9c547cSRui Paulo 	return (char *) xmlGetNsProp((xmlNodePtr) node, (const xmlChar *) name,
3555b9c547cSRui Paulo 				     (const xmlChar *) ns_uri);
3565b9c547cSRui Paulo }
3575b9c547cSRui Paulo 
3585b9c547cSRui Paulo 
xml_node_get_attr_value_free(struct xml_node_ctx * ctx,char * val)3595b9c547cSRui Paulo void xml_node_get_attr_value_free(struct xml_node_ctx *ctx, char *val)
3605b9c547cSRui Paulo {
3615b9c547cSRui Paulo 	if (val)
3625b9c547cSRui Paulo 		xmlFree((xmlChar *) val);
3635b9c547cSRui Paulo }
3645b9c547cSRui Paulo 
3655b9c547cSRui Paulo 
xml_node_first_child(struct xml_node_ctx * ctx,xml_node_t * parent)3665b9c547cSRui Paulo xml_node_t * xml_node_first_child(struct xml_node_ctx *ctx,
3675b9c547cSRui Paulo 				  xml_node_t *parent)
3685b9c547cSRui Paulo {
3695b9c547cSRui Paulo 	return (xml_node_t *) ((xmlNodePtr) parent)->children;
3705b9c547cSRui Paulo }
3715b9c547cSRui Paulo 
3725b9c547cSRui Paulo 
xml_node_next_sibling(struct xml_node_ctx * ctx,xml_node_t * node)3735b9c547cSRui Paulo xml_node_t * xml_node_next_sibling(struct xml_node_ctx *ctx,
3745b9c547cSRui Paulo 				   xml_node_t *node)
3755b9c547cSRui Paulo {
3765b9c547cSRui Paulo 	return (xml_node_t *) ((xmlNodePtr) node)->next;
3775b9c547cSRui Paulo }
3785b9c547cSRui Paulo 
3795b9c547cSRui Paulo 
xml_node_is_element(struct xml_node_ctx * ctx,xml_node_t * node)3805b9c547cSRui Paulo int xml_node_is_element(struct xml_node_ctx *ctx, xml_node_t *node)
3815b9c547cSRui Paulo {
3825b9c547cSRui Paulo 	return ((xmlNodePtr) node)->type == XML_ELEMENT_NODE;
3835b9c547cSRui Paulo }
3845b9c547cSRui Paulo 
3855b9c547cSRui Paulo 
xml_node_get_text(struct xml_node_ctx * ctx,xml_node_t * node)3865b9c547cSRui Paulo char * xml_node_get_text(struct xml_node_ctx *ctx, xml_node_t *node)
3875b9c547cSRui Paulo {
3885b9c547cSRui Paulo 	if (xmlChildElementCount((xmlNodePtr) node) > 0)
3895b9c547cSRui Paulo 		return NULL;
3905b9c547cSRui Paulo 	return (char *) xmlNodeGetContent((xmlNodePtr) node);
3915b9c547cSRui Paulo }
3925b9c547cSRui Paulo 
3935b9c547cSRui Paulo 
xml_node_get_text_free(struct xml_node_ctx * ctx,char * val)3945b9c547cSRui Paulo void xml_node_get_text_free(struct xml_node_ctx *ctx, char *val)
3955b9c547cSRui Paulo {
3965b9c547cSRui Paulo 	if (val)
3975b9c547cSRui Paulo 		xmlFree((xmlChar *) val);
3985b9c547cSRui Paulo }
3995b9c547cSRui Paulo 
4005b9c547cSRui Paulo 
xml_node_get_base64_text(struct xml_node_ctx * ctx,xml_node_t * node,int * ret_len)4015b9c547cSRui Paulo char * xml_node_get_base64_text(struct xml_node_ctx *ctx, xml_node_t *node,
4025b9c547cSRui Paulo 				int *ret_len)
4035b9c547cSRui Paulo {
4045b9c547cSRui Paulo 	char *txt;
4055b9c547cSRui Paulo 	unsigned char *ret;
4065b9c547cSRui Paulo 	size_t len;
4075b9c547cSRui Paulo 
4085b9c547cSRui Paulo 	txt = xml_node_get_text(ctx, node);
4095b9c547cSRui Paulo 	if (txt == NULL)
4105b9c547cSRui Paulo 		return NULL;
4115b9c547cSRui Paulo 
412*c1d255d3SCy Schubert 	ret = base64_decode(txt, strlen(txt), &len);
4135b9c547cSRui Paulo 	if (ret_len)
4145b9c547cSRui Paulo 		*ret_len = len;
4155b9c547cSRui Paulo 	xml_node_get_text_free(ctx, txt);
4165b9c547cSRui Paulo 	if (ret == NULL)
4175b9c547cSRui Paulo 		return NULL;
4185b9c547cSRui Paulo 	txt = os_malloc(len + 1);
4195b9c547cSRui Paulo 	if (txt == NULL) {
4205b9c547cSRui Paulo 		os_free(ret);
4215b9c547cSRui Paulo 		return NULL;
4225b9c547cSRui Paulo 	}
4235b9c547cSRui Paulo 	os_memcpy(txt, ret, len);
4245b9c547cSRui Paulo 	txt[len] = '\0';
4255b9c547cSRui Paulo 	return txt;
4265b9c547cSRui Paulo }
4275b9c547cSRui Paulo 
4285b9c547cSRui Paulo 
xml_node_copy(struct xml_node_ctx * ctx,xml_node_t * node)4295b9c547cSRui Paulo xml_node_t * xml_node_copy(struct xml_node_ctx *ctx, xml_node_t *node)
4305b9c547cSRui Paulo {
4315b9c547cSRui Paulo 	if (node == NULL)
4325b9c547cSRui Paulo 		return NULL;
4335b9c547cSRui Paulo 	return (xml_node_t *) xmlCopyNode((xmlNodePtr) node, 1);
4345b9c547cSRui Paulo }
4355b9c547cSRui Paulo 
4365b9c547cSRui Paulo 
xml_node_init_ctx(void * upper_ctx,const void * env)4375b9c547cSRui Paulo struct xml_node_ctx * xml_node_init_ctx(void *upper_ctx,
4385b9c547cSRui Paulo 					const void *env)
4395b9c547cSRui Paulo {
4405b9c547cSRui Paulo 	struct xml_node_ctx *xctx;
4415b9c547cSRui Paulo 
4425b9c547cSRui Paulo 	xctx = os_zalloc(sizeof(*xctx));
4435b9c547cSRui Paulo 	if (xctx == NULL)
4445b9c547cSRui Paulo 		return NULL;
4455b9c547cSRui Paulo 	xctx->ctx = upper_ctx;
4465b9c547cSRui Paulo 
4475b9c547cSRui Paulo 	LIBXML_TEST_VERSION
4485b9c547cSRui Paulo 
4495b9c547cSRui Paulo 	return xctx;
4505b9c547cSRui Paulo }
4515b9c547cSRui Paulo 
4525b9c547cSRui Paulo 
xml_node_deinit_ctx(struct xml_node_ctx * ctx)4535b9c547cSRui Paulo void xml_node_deinit_ctx(struct xml_node_ctx *ctx)
4545b9c547cSRui Paulo {
4555b9c547cSRui Paulo 	xmlSchemaCleanupTypes();
4565b9c547cSRui Paulo 	xmlCleanupParser();
4575b9c547cSRui Paulo 	xmlMemoryDump();
4585b9c547cSRui Paulo 	os_free(ctx);
4595b9c547cSRui Paulo }
460