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