xref: /freebsd-src/contrib/wpa/src/utils/xml_libxml2.c (revision 5b9c547c072b84410b50897cc53710c75b2f6b74)
1*5b9c547cSRui Paulo /*
2*5b9c547cSRui Paulo  * XML wrapper for libxml2
3*5b9c547cSRui Paulo  * Copyright (c) 2012-2013, Qualcomm Atheros, Inc.
4*5b9c547cSRui Paulo  *
5*5b9c547cSRui Paulo  * This software may be distributed under the terms of the BSD license.
6*5b9c547cSRui Paulo  * See README for more details.
7*5b9c547cSRui Paulo  */
8*5b9c547cSRui Paulo 
9*5b9c547cSRui Paulo #include "includes.h"
10*5b9c547cSRui Paulo #define LIBXML_VALID_ENABLED
11*5b9c547cSRui Paulo #include <libxml/tree.h>
12*5b9c547cSRui Paulo #include <libxml/xmlschemastypes.h>
13*5b9c547cSRui Paulo 
14*5b9c547cSRui Paulo #include "common.h"
15*5b9c547cSRui Paulo #include "base64.h"
16*5b9c547cSRui Paulo #include "xml-utils.h"
17*5b9c547cSRui Paulo 
18*5b9c547cSRui Paulo 
19*5b9c547cSRui Paulo struct xml_node_ctx {
20*5b9c547cSRui Paulo 	void *ctx;
21*5b9c547cSRui Paulo };
22*5b9c547cSRui Paulo 
23*5b9c547cSRui Paulo 
24*5b9c547cSRui Paulo struct str_buf {
25*5b9c547cSRui Paulo 	char *buf;
26*5b9c547cSRui Paulo 	size_t len;
27*5b9c547cSRui Paulo };
28*5b9c547cSRui Paulo 
29*5b9c547cSRui Paulo #define MAX_STR 1000
30*5b9c547cSRui Paulo 
31*5b9c547cSRui Paulo static void add_str(void *ctx_ptr, const char *fmt, ...)
32*5b9c547cSRui Paulo {
33*5b9c547cSRui Paulo 	struct str_buf *str = ctx_ptr;
34*5b9c547cSRui Paulo 	va_list ap;
35*5b9c547cSRui Paulo 	char *n;
36*5b9c547cSRui Paulo 	int len;
37*5b9c547cSRui Paulo 
38*5b9c547cSRui Paulo 	n = os_realloc(str->buf, str->len + MAX_STR + 2);
39*5b9c547cSRui Paulo 	if (n == NULL)
40*5b9c547cSRui Paulo 		return;
41*5b9c547cSRui Paulo 	str->buf = n;
42*5b9c547cSRui Paulo 
43*5b9c547cSRui Paulo 	va_start(ap, fmt);
44*5b9c547cSRui Paulo 	len = vsnprintf(str->buf + str->len, MAX_STR, fmt, ap);
45*5b9c547cSRui Paulo 	va_end(ap);
46*5b9c547cSRui Paulo 	if (len >= MAX_STR)
47*5b9c547cSRui Paulo 		len = MAX_STR - 1;
48*5b9c547cSRui Paulo 	str->len += len;
49*5b9c547cSRui Paulo 	str->buf[str->len] = '\0';
50*5b9c547cSRui Paulo }
51*5b9c547cSRui Paulo 
52*5b9c547cSRui Paulo 
53*5b9c547cSRui Paulo int xml_validate(struct xml_node_ctx *ctx, xml_node_t *node,
54*5b9c547cSRui Paulo 		 const char *xml_schema_fname, char **ret_err)
55*5b9c547cSRui Paulo {
56*5b9c547cSRui Paulo 	xmlDocPtr doc;
57*5b9c547cSRui Paulo 	xmlNodePtr n;
58*5b9c547cSRui Paulo 	xmlSchemaParserCtxtPtr pctx;
59*5b9c547cSRui Paulo 	xmlSchemaValidCtxtPtr vctx;
60*5b9c547cSRui Paulo 	xmlSchemaPtr schema;
61*5b9c547cSRui Paulo 	int ret;
62*5b9c547cSRui Paulo 	struct str_buf errors;
63*5b9c547cSRui Paulo 
64*5b9c547cSRui Paulo 	if (ret_err)
65*5b9c547cSRui Paulo 		*ret_err = NULL;
66*5b9c547cSRui Paulo 
67*5b9c547cSRui Paulo 	doc = xmlNewDoc((xmlChar *) "1.0");
68*5b9c547cSRui Paulo 	if (doc == NULL)
69*5b9c547cSRui Paulo 		return -1;
70*5b9c547cSRui Paulo 	n = xmlDocCopyNode((xmlNodePtr) node, doc, 1);
71*5b9c547cSRui Paulo 	if (n == NULL) {
72*5b9c547cSRui Paulo 		xmlFreeDoc(doc);
73*5b9c547cSRui Paulo 		return -1;
74*5b9c547cSRui Paulo 	}
75*5b9c547cSRui Paulo 	xmlDocSetRootElement(doc, n);
76*5b9c547cSRui Paulo 
77*5b9c547cSRui Paulo 	os_memset(&errors, 0, sizeof(errors));
78*5b9c547cSRui Paulo 
79*5b9c547cSRui Paulo 	pctx = xmlSchemaNewParserCtxt(xml_schema_fname);
80*5b9c547cSRui Paulo 	xmlSchemaSetParserErrors(pctx, (xmlSchemaValidityErrorFunc) add_str,
81*5b9c547cSRui Paulo 				 (xmlSchemaValidityWarningFunc) add_str,
82*5b9c547cSRui Paulo 				 &errors);
83*5b9c547cSRui Paulo 	schema = xmlSchemaParse(pctx);
84*5b9c547cSRui Paulo 	xmlSchemaFreeParserCtxt(pctx);
85*5b9c547cSRui Paulo 
86*5b9c547cSRui Paulo 	vctx = xmlSchemaNewValidCtxt(schema);
87*5b9c547cSRui Paulo 	xmlSchemaSetValidErrors(vctx, (xmlSchemaValidityErrorFunc) add_str,
88*5b9c547cSRui Paulo 				(xmlSchemaValidityWarningFunc) add_str,
89*5b9c547cSRui Paulo 				&errors);
90*5b9c547cSRui Paulo 
91*5b9c547cSRui Paulo 	ret = xmlSchemaValidateDoc(vctx, doc);
92*5b9c547cSRui Paulo 	xmlSchemaFreeValidCtxt(vctx);
93*5b9c547cSRui Paulo 	xmlFreeDoc(doc);
94*5b9c547cSRui Paulo 	xmlSchemaFree(schema);
95*5b9c547cSRui Paulo 
96*5b9c547cSRui Paulo 	if (ret == 0) {
97*5b9c547cSRui Paulo 		os_free(errors.buf);
98*5b9c547cSRui Paulo 		return 0;
99*5b9c547cSRui Paulo 	} else if (ret > 0) {
100*5b9c547cSRui Paulo 		if (ret_err)
101*5b9c547cSRui Paulo 			*ret_err = errors.buf;
102*5b9c547cSRui Paulo 		else
103*5b9c547cSRui Paulo 			os_free(errors.buf);
104*5b9c547cSRui Paulo 		return -1;
105*5b9c547cSRui Paulo 	} else {
106*5b9c547cSRui Paulo 		if (ret_err)
107*5b9c547cSRui Paulo 			*ret_err = errors.buf;
108*5b9c547cSRui Paulo 		else
109*5b9c547cSRui Paulo 			os_free(errors.buf);
110*5b9c547cSRui Paulo 		return -1;
111*5b9c547cSRui Paulo 	}
112*5b9c547cSRui Paulo }
113*5b9c547cSRui Paulo 
114*5b9c547cSRui Paulo 
115*5b9c547cSRui Paulo int xml_validate_dtd(struct xml_node_ctx *ctx, xml_node_t *node,
116*5b9c547cSRui Paulo 		     const char *dtd_fname, char **ret_err)
117*5b9c547cSRui Paulo {
118*5b9c547cSRui Paulo 	xmlDocPtr doc;
119*5b9c547cSRui Paulo 	xmlNodePtr n;
120*5b9c547cSRui Paulo 	xmlValidCtxt vctx;
121*5b9c547cSRui Paulo 	xmlDtdPtr dtd;
122*5b9c547cSRui Paulo 	int ret;
123*5b9c547cSRui Paulo 	struct str_buf errors;
124*5b9c547cSRui Paulo 
125*5b9c547cSRui Paulo 	if (ret_err)
126*5b9c547cSRui Paulo 		*ret_err = NULL;
127*5b9c547cSRui Paulo 
128*5b9c547cSRui Paulo 	doc = xmlNewDoc((xmlChar *) "1.0");
129*5b9c547cSRui Paulo 	if (doc == NULL)
130*5b9c547cSRui Paulo 		return -1;
131*5b9c547cSRui Paulo 	n = xmlDocCopyNode((xmlNodePtr) node, doc, 1);
132*5b9c547cSRui Paulo 	if (n == NULL) {
133*5b9c547cSRui Paulo 		xmlFreeDoc(doc);
134*5b9c547cSRui Paulo 		return -1;
135*5b9c547cSRui Paulo 	}
136*5b9c547cSRui Paulo 	xmlDocSetRootElement(doc, n);
137*5b9c547cSRui Paulo 
138*5b9c547cSRui Paulo 	os_memset(&errors, 0, sizeof(errors));
139*5b9c547cSRui Paulo 
140*5b9c547cSRui Paulo 	dtd = xmlParseDTD(NULL, (const xmlChar *) dtd_fname);
141*5b9c547cSRui Paulo 	if (dtd == NULL) {
142*5b9c547cSRui Paulo 		xmlFreeDoc(doc);
143*5b9c547cSRui Paulo 		return -1;
144*5b9c547cSRui Paulo 	}
145*5b9c547cSRui Paulo 
146*5b9c547cSRui Paulo 	os_memset(&vctx, 0, sizeof(vctx));
147*5b9c547cSRui Paulo 	vctx.userData = &errors;
148*5b9c547cSRui Paulo 	vctx.error = add_str;
149*5b9c547cSRui Paulo 	vctx.warning = add_str;
150*5b9c547cSRui Paulo 	ret = xmlValidateDtd(&vctx, doc, dtd);
151*5b9c547cSRui Paulo 	xmlFreeDoc(doc);
152*5b9c547cSRui Paulo 	xmlFreeDtd(dtd);
153*5b9c547cSRui Paulo 
154*5b9c547cSRui Paulo 	if (ret == 1) {
155*5b9c547cSRui Paulo 		os_free(errors.buf);
156*5b9c547cSRui Paulo 		return 0;
157*5b9c547cSRui Paulo 	} else {
158*5b9c547cSRui Paulo 		if (ret_err)
159*5b9c547cSRui Paulo 			*ret_err = errors.buf;
160*5b9c547cSRui Paulo 		else
161*5b9c547cSRui Paulo 			os_free(errors.buf);
162*5b9c547cSRui Paulo 		return -1;
163*5b9c547cSRui Paulo 	}
164*5b9c547cSRui Paulo }
165*5b9c547cSRui Paulo 
166*5b9c547cSRui Paulo 
167*5b9c547cSRui Paulo void xml_node_free(struct xml_node_ctx *ctx, xml_node_t *node)
168*5b9c547cSRui Paulo {
169*5b9c547cSRui Paulo 	xmlFreeNode((xmlNodePtr) node);
170*5b9c547cSRui Paulo }
171*5b9c547cSRui Paulo 
172*5b9c547cSRui Paulo 
173*5b9c547cSRui Paulo xml_node_t * xml_node_get_parent(struct xml_node_ctx *ctx, xml_node_t *node)
174*5b9c547cSRui Paulo {
175*5b9c547cSRui Paulo 	return (xml_node_t *) ((xmlNodePtr) node)->parent;
176*5b9c547cSRui Paulo }
177*5b9c547cSRui Paulo 
178*5b9c547cSRui Paulo 
179*5b9c547cSRui Paulo xml_node_t * xml_node_from_buf(struct xml_node_ctx *ctx, const char *buf)
180*5b9c547cSRui Paulo {
181*5b9c547cSRui Paulo 	xmlDocPtr doc;
182*5b9c547cSRui Paulo 	xmlNodePtr node;
183*5b9c547cSRui Paulo 
184*5b9c547cSRui Paulo 	doc = xmlParseMemory(buf, strlen(buf));
185*5b9c547cSRui Paulo 	if (doc == NULL)
186*5b9c547cSRui Paulo 		return NULL;
187*5b9c547cSRui Paulo 	node = xmlDocGetRootElement(doc);
188*5b9c547cSRui Paulo 	node = xmlCopyNode(node, 1);
189*5b9c547cSRui Paulo 	xmlFreeDoc(doc);
190*5b9c547cSRui Paulo 
191*5b9c547cSRui Paulo 	return (xml_node_t *) node;
192*5b9c547cSRui Paulo }
193*5b9c547cSRui Paulo 
194*5b9c547cSRui Paulo 
195*5b9c547cSRui Paulo const char * xml_node_get_localname(struct xml_node_ctx *ctx,
196*5b9c547cSRui Paulo 				    xml_node_t *node)
197*5b9c547cSRui Paulo {
198*5b9c547cSRui Paulo 	return (const char *) ((xmlNodePtr) node)->name;
199*5b9c547cSRui Paulo }
200*5b9c547cSRui Paulo 
201*5b9c547cSRui Paulo 
202*5b9c547cSRui Paulo char * xml_node_to_str(struct xml_node_ctx *ctx, xml_node_t *node)
203*5b9c547cSRui Paulo {
204*5b9c547cSRui Paulo 	xmlChar *buf;
205*5b9c547cSRui Paulo 	int bufsiz;
206*5b9c547cSRui Paulo 	char *ret, *pos;
207*5b9c547cSRui Paulo 	xmlNodePtr n = (xmlNodePtr) node;
208*5b9c547cSRui Paulo 	xmlDocPtr doc;
209*5b9c547cSRui Paulo 
210*5b9c547cSRui Paulo 	doc = xmlNewDoc((xmlChar *) "1.0");
211*5b9c547cSRui Paulo 	n = xmlDocCopyNode(n, doc, 1);
212*5b9c547cSRui Paulo 	xmlDocSetRootElement(doc, n);
213*5b9c547cSRui Paulo 	xmlDocDumpFormatMemory(doc, &buf, &bufsiz, 0);
214*5b9c547cSRui Paulo 	xmlFreeDoc(doc);
215*5b9c547cSRui Paulo 	pos = (char *) buf;
216*5b9c547cSRui Paulo 	if (strncmp(pos, "<?xml", 5) == 0) {
217*5b9c547cSRui Paulo 		pos = strchr(pos, '>');
218*5b9c547cSRui Paulo 		if (pos)
219*5b9c547cSRui Paulo 			pos++;
220*5b9c547cSRui Paulo 		while (pos && (*pos == '\r' || *pos == '\n'))
221*5b9c547cSRui Paulo 			pos++;
222*5b9c547cSRui Paulo 	}
223*5b9c547cSRui Paulo 	if (pos)
224*5b9c547cSRui Paulo 		ret = os_strdup(pos);
225*5b9c547cSRui Paulo 	else
226*5b9c547cSRui Paulo 		ret = NULL;
227*5b9c547cSRui Paulo 	xmlFree(buf);
228*5b9c547cSRui Paulo 
229*5b9c547cSRui Paulo 	if (ret) {
230*5b9c547cSRui Paulo 		pos = ret;
231*5b9c547cSRui Paulo 		if (pos[0]) {
232*5b9c547cSRui Paulo 			while (pos[1])
233*5b9c547cSRui Paulo 				pos++;
234*5b9c547cSRui Paulo 		}
235*5b9c547cSRui Paulo 		while (pos >= ret && *pos == '\n')
236*5b9c547cSRui Paulo 			*pos-- = '\0';
237*5b9c547cSRui Paulo 	}
238*5b9c547cSRui Paulo 
239*5b9c547cSRui Paulo 	return ret;
240*5b9c547cSRui Paulo }
241*5b9c547cSRui Paulo 
242*5b9c547cSRui Paulo 
243*5b9c547cSRui Paulo void xml_node_detach(struct xml_node_ctx *ctx, xml_node_t *node)
244*5b9c547cSRui Paulo {
245*5b9c547cSRui Paulo 	xmlUnlinkNode((xmlNodePtr) node);
246*5b9c547cSRui Paulo }
247*5b9c547cSRui Paulo 
248*5b9c547cSRui Paulo 
249*5b9c547cSRui Paulo void xml_node_add_child(struct xml_node_ctx *ctx, xml_node_t *parent,
250*5b9c547cSRui Paulo 			xml_node_t *child)
251*5b9c547cSRui Paulo {
252*5b9c547cSRui Paulo 	xmlAddChild((xmlNodePtr) parent, (xmlNodePtr) child);
253*5b9c547cSRui Paulo }
254*5b9c547cSRui Paulo 
255*5b9c547cSRui Paulo 
256*5b9c547cSRui Paulo xml_node_t * xml_node_create_root(struct xml_node_ctx *ctx, const char *ns_uri,
257*5b9c547cSRui Paulo 				  const char *ns_prefix,
258*5b9c547cSRui Paulo 				  xml_namespace_t **ret_ns, const char *name)
259*5b9c547cSRui Paulo {
260*5b9c547cSRui Paulo 	xmlNodePtr node;
261*5b9c547cSRui Paulo 	xmlNsPtr ns = NULL;
262*5b9c547cSRui Paulo 
263*5b9c547cSRui Paulo 	node = xmlNewNode(NULL, (const xmlChar *) name);
264*5b9c547cSRui Paulo 	if (node == NULL)
265*5b9c547cSRui Paulo 		return NULL;
266*5b9c547cSRui Paulo 	if (ns_uri) {
267*5b9c547cSRui Paulo 		ns = xmlNewNs(node, (const xmlChar *) ns_uri,
268*5b9c547cSRui Paulo 			      (const xmlChar *) ns_prefix);
269*5b9c547cSRui Paulo 		xmlSetNs(node, ns);
270*5b9c547cSRui Paulo 	}
271*5b9c547cSRui Paulo 
272*5b9c547cSRui Paulo 	if (ret_ns)
273*5b9c547cSRui Paulo 		*ret_ns = (xml_namespace_t *) ns;
274*5b9c547cSRui Paulo 
275*5b9c547cSRui Paulo 	return (xml_node_t *) node;
276*5b9c547cSRui Paulo }
277*5b9c547cSRui Paulo 
278*5b9c547cSRui Paulo 
279*5b9c547cSRui Paulo xml_node_t * xml_node_create(struct xml_node_ctx *ctx, xml_node_t *parent,
280*5b9c547cSRui Paulo 			     xml_namespace_t *ns, const char *name)
281*5b9c547cSRui Paulo {
282*5b9c547cSRui Paulo 	xmlNodePtr node;
283*5b9c547cSRui Paulo 	node = xmlNewChild((xmlNodePtr) parent, (xmlNsPtr) ns,
284*5b9c547cSRui Paulo 			   (const xmlChar *) name, NULL);
285*5b9c547cSRui Paulo 	return (xml_node_t *) node;
286*5b9c547cSRui Paulo }
287*5b9c547cSRui Paulo 
288*5b9c547cSRui Paulo 
289*5b9c547cSRui Paulo xml_node_t * xml_node_create_text(struct xml_node_ctx *ctx,
290*5b9c547cSRui Paulo 				  xml_node_t *parent, xml_namespace_t *ns,
291*5b9c547cSRui Paulo 				  const char *name, const char *value)
292*5b9c547cSRui Paulo {
293*5b9c547cSRui Paulo 	xmlNodePtr node;
294*5b9c547cSRui Paulo 	node = xmlNewTextChild((xmlNodePtr) parent, (xmlNsPtr) ns,
295*5b9c547cSRui Paulo 			       (const xmlChar *) name, (const xmlChar *) value);
296*5b9c547cSRui Paulo 	return (xml_node_t *) node;
297*5b9c547cSRui Paulo }
298*5b9c547cSRui Paulo 
299*5b9c547cSRui Paulo 
300*5b9c547cSRui Paulo xml_node_t * xml_node_create_text_ns(struct xml_node_ctx *ctx,
301*5b9c547cSRui Paulo 				     xml_node_t *parent, const char *ns_uri,
302*5b9c547cSRui Paulo 				     const char *name, const char *value)
303*5b9c547cSRui Paulo {
304*5b9c547cSRui Paulo 	xmlNodePtr node;
305*5b9c547cSRui Paulo 	xmlNsPtr ns;
306*5b9c547cSRui Paulo 
307*5b9c547cSRui Paulo 	node = xmlNewTextChild((xmlNodePtr) parent, NULL,
308*5b9c547cSRui Paulo 			       (const xmlChar *) name, (const xmlChar *) value);
309*5b9c547cSRui Paulo 	ns = xmlNewNs(node, (const xmlChar *) ns_uri, NULL);
310*5b9c547cSRui Paulo 	xmlSetNs(node, ns);
311*5b9c547cSRui Paulo 	return (xml_node_t *) node;
312*5b9c547cSRui Paulo }
313*5b9c547cSRui Paulo 
314*5b9c547cSRui Paulo 
315*5b9c547cSRui Paulo void xml_node_set_text(struct xml_node_ctx *ctx, xml_node_t *node,
316*5b9c547cSRui Paulo 		       const char *value)
317*5b9c547cSRui Paulo {
318*5b9c547cSRui Paulo 	/* TODO: escape XML special chars in value */
319*5b9c547cSRui Paulo 	xmlNodeSetContent((xmlNodePtr) node, (xmlChar *) value);
320*5b9c547cSRui Paulo }
321*5b9c547cSRui Paulo 
322*5b9c547cSRui Paulo 
323*5b9c547cSRui Paulo int xml_node_add_attr(struct xml_node_ctx *ctx, xml_node_t *node,
324*5b9c547cSRui Paulo 		      xml_namespace_t *ns, const char *name, const char *value)
325*5b9c547cSRui Paulo {
326*5b9c547cSRui Paulo 	xmlAttrPtr attr;
327*5b9c547cSRui Paulo 
328*5b9c547cSRui Paulo 	if (ns) {
329*5b9c547cSRui Paulo 		attr = xmlNewNsProp((xmlNodePtr) node, (xmlNsPtr) ns,
330*5b9c547cSRui Paulo 				    (const xmlChar *) name,
331*5b9c547cSRui Paulo 				    (const xmlChar *) value);
332*5b9c547cSRui Paulo 	} else {
333*5b9c547cSRui Paulo 		attr = xmlNewProp((xmlNodePtr) node, (const xmlChar *) name,
334*5b9c547cSRui Paulo 				  (const xmlChar *) value);
335*5b9c547cSRui Paulo 	}
336*5b9c547cSRui Paulo 
337*5b9c547cSRui Paulo 	return attr ? 0 : -1;
338*5b9c547cSRui Paulo }
339*5b9c547cSRui Paulo 
340*5b9c547cSRui Paulo 
341*5b9c547cSRui Paulo char * xml_node_get_attr_value(struct xml_node_ctx *ctx, xml_node_t *node,
342*5b9c547cSRui Paulo 			       char *name)
343*5b9c547cSRui Paulo {
344*5b9c547cSRui Paulo 	return (char *) xmlGetNoNsProp((xmlNodePtr) node,
345*5b9c547cSRui Paulo 				       (const xmlChar *) name);
346*5b9c547cSRui Paulo }
347*5b9c547cSRui Paulo 
348*5b9c547cSRui Paulo 
349*5b9c547cSRui Paulo char * xml_node_get_attr_value_ns(struct xml_node_ctx *ctx, xml_node_t *node,
350*5b9c547cSRui Paulo 				  const char *ns_uri, char *name)
351*5b9c547cSRui Paulo {
352*5b9c547cSRui Paulo 	return (char *) xmlGetNsProp((xmlNodePtr) node, (const xmlChar *) name,
353*5b9c547cSRui Paulo 				     (const xmlChar *) ns_uri);
354*5b9c547cSRui Paulo }
355*5b9c547cSRui Paulo 
356*5b9c547cSRui Paulo 
357*5b9c547cSRui Paulo void xml_node_get_attr_value_free(struct xml_node_ctx *ctx, char *val)
358*5b9c547cSRui Paulo {
359*5b9c547cSRui Paulo 	if (val)
360*5b9c547cSRui Paulo 		xmlFree((xmlChar *) val);
361*5b9c547cSRui Paulo }
362*5b9c547cSRui Paulo 
363*5b9c547cSRui Paulo 
364*5b9c547cSRui Paulo xml_node_t * xml_node_first_child(struct xml_node_ctx *ctx,
365*5b9c547cSRui Paulo 				  xml_node_t *parent)
366*5b9c547cSRui Paulo {
367*5b9c547cSRui Paulo 	return (xml_node_t *) ((xmlNodePtr) parent)->children;
368*5b9c547cSRui Paulo }
369*5b9c547cSRui Paulo 
370*5b9c547cSRui Paulo 
371*5b9c547cSRui Paulo xml_node_t * xml_node_next_sibling(struct xml_node_ctx *ctx,
372*5b9c547cSRui Paulo 				   xml_node_t *node)
373*5b9c547cSRui Paulo {
374*5b9c547cSRui Paulo 	return (xml_node_t *) ((xmlNodePtr) node)->next;
375*5b9c547cSRui Paulo }
376*5b9c547cSRui Paulo 
377*5b9c547cSRui Paulo 
378*5b9c547cSRui Paulo int xml_node_is_element(struct xml_node_ctx *ctx, xml_node_t *node)
379*5b9c547cSRui Paulo {
380*5b9c547cSRui Paulo 	return ((xmlNodePtr) node)->type == XML_ELEMENT_NODE;
381*5b9c547cSRui Paulo }
382*5b9c547cSRui Paulo 
383*5b9c547cSRui Paulo 
384*5b9c547cSRui Paulo char * xml_node_get_text(struct xml_node_ctx *ctx, xml_node_t *node)
385*5b9c547cSRui Paulo {
386*5b9c547cSRui Paulo 	if (xmlChildElementCount((xmlNodePtr) node) > 0)
387*5b9c547cSRui Paulo 		return NULL;
388*5b9c547cSRui Paulo 	return (char *) xmlNodeGetContent((xmlNodePtr) node);
389*5b9c547cSRui Paulo }
390*5b9c547cSRui Paulo 
391*5b9c547cSRui Paulo 
392*5b9c547cSRui Paulo void xml_node_get_text_free(struct xml_node_ctx *ctx, char *val)
393*5b9c547cSRui Paulo {
394*5b9c547cSRui Paulo 	if (val)
395*5b9c547cSRui Paulo 		xmlFree((xmlChar *) val);
396*5b9c547cSRui Paulo }
397*5b9c547cSRui Paulo 
398*5b9c547cSRui Paulo 
399*5b9c547cSRui Paulo char * xml_node_get_base64_text(struct xml_node_ctx *ctx, xml_node_t *node,
400*5b9c547cSRui Paulo 				int *ret_len)
401*5b9c547cSRui Paulo {
402*5b9c547cSRui Paulo 	char *txt;
403*5b9c547cSRui Paulo 	unsigned char *ret;
404*5b9c547cSRui Paulo 	size_t len;
405*5b9c547cSRui Paulo 
406*5b9c547cSRui Paulo 	txt = xml_node_get_text(ctx, node);
407*5b9c547cSRui Paulo 	if (txt == NULL)
408*5b9c547cSRui Paulo 		return NULL;
409*5b9c547cSRui Paulo 
410*5b9c547cSRui Paulo 	ret = base64_decode((unsigned char *) txt, strlen(txt), &len);
411*5b9c547cSRui Paulo 	if (ret_len)
412*5b9c547cSRui Paulo 		*ret_len = len;
413*5b9c547cSRui Paulo 	xml_node_get_text_free(ctx, txt);
414*5b9c547cSRui Paulo 	if (ret == NULL)
415*5b9c547cSRui Paulo 		return NULL;
416*5b9c547cSRui Paulo 	txt = os_malloc(len + 1);
417*5b9c547cSRui Paulo 	if (txt == NULL) {
418*5b9c547cSRui Paulo 		os_free(ret);
419*5b9c547cSRui Paulo 		return NULL;
420*5b9c547cSRui Paulo 	}
421*5b9c547cSRui Paulo 	os_memcpy(txt, ret, len);
422*5b9c547cSRui Paulo 	txt[len] = '\0';
423*5b9c547cSRui Paulo 	return txt;
424*5b9c547cSRui Paulo }
425*5b9c547cSRui Paulo 
426*5b9c547cSRui Paulo 
427*5b9c547cSRui Paulo xml_node_t * xml_node_copy(struct xml_node_ctx *ctx, xml_node_t *node)
428*5b9c547cSRui Paulo {
429*5b9c547cSRui Paulo 	if (node == NULL)
430*5b9c547cSRui Paulo 		return NULL;
431*5b9c547cSRui Paulo 	return (xml_node_t *) xmlCopyNode((xmlNodePtr) node, 1);
432*5b9c547cSRui Paulo }
433*5b9c547cSRui Paulo 
434*5b9c547cSRui Paulo 
435*5b9c547cSRui Paulo struct xml_node_ctx * xml_node_init_ctx(void *upper_ctx,
436*5b9c547cSRui Paulo 					const void *env)
437*5b9c547cSRui Paulo {
438*5b9c547cSRui Paulo 	struct xml_node_ctx *xctx;
439*5b9c547cSRui Paulo 
440*5b9c547cSRui Paulo 	xctx = os_zalloc(sizeof(*xctx));
441*5b9c547cSRui Paulo 	if (xctx == NULL)
442*5b9c547cSRui Paulo 		return NULL;
443*5b9c547cSRui Paulo 	xctx->ctx = upper_ctx;
444*5b9c547cSRui Paulo 
445*5b9c547cSRui Paulo 	LIBXML_TEST_VERSION
446*5b9c547cSRui Paulo 
447*5b9c547cSRui Paulo 	return xctx;
448*5b9c547cSRui Paulo }
449*5b9c547cSRui Paulo 
450*5b9c547cSRui Paulo 
451*5b9c547cSRui Paulo void xml_node_deinit_ctx(struct xml_node_ctx *ctx)
452*5b9c547cSRui Paulo {
453*5b9c547cSRui Paulo 	xmlSchemaCleanupTypes();
454*5b9c547cSRui Paulo 	xmlCleanupParser();
455*5b9c547cSRui Paulo 	xmlMemoryDump();
456*5b9c547cSRui Paulo 	os_free(ctx);
457*5b9c547cSRui Paulo }
458