1  /*
2   * XML wrapper for libxml2
3   * Copyright (c) 2012-2013, Qualcomm Atheros, Inc.
4   *
5   * This software may be distributed under the terms of the BSD license.
6   * See README for more details.
7   */
8  
9  #include "includes.h"
10  #define LIBXML_VALID_ENABLED
11  #include <libxml/tree.h>
12  #include <libxml/xmlschemastypes.h>
13  
14  #include "common.h"
15  #include "base64.h"
16  #include "xml-utils.h"
17  
18  
19  struct xml_node_ctx {
20  	void *ctx;
21  };
22  
23  
xml_node_free(struct xml_node_ctx * ctx,xml_node_t * node)24  void xml_node_free(struct xml_node_ctx *ctx, xml_node_t *node)
25  {
26  	xmlFreeNode((xmlNodePtr) node);
27  }
28  
29  
xml_node_from_buf(struct xml_node_ctx * ctx,const char * buf)30  xml_node_t * xml_node_from_buf(struct xml_node_ctx *ctx, const char *buf)
31  {
32  	xmlDocPtr doc;
33  	xmlNodePtr node;
34  
35  	doc = xmlParseMemory(buf, strlen(buf));
36  	if (doc == NULL)
37  		return NULL;
38  	node = xmlDocGetRootElement(doc);
39  	node = xmlCopyNode(node, 1);
40  	xmlFreeDoc(doc);
41  
42  	return (xml_node_t *) node;
43  }
44  
45  
xml_node_get_localname(struct xml_node_ctx * ctx,xml_node_t * node)46  const char * xml_node_get_localname(struct xml_node_ctx *ctx,
47  				    xml_node_t *node)
48  {
49  	return (const char *) ((xmlNodePtr) node)->name;
50  }
51  
52  
xml_node_to_str(struct xml_node_ctx * ctx,xml_node_t * node)53  char * xml_node_to_str(struct xml_node_ctx *ctx, xml_node_t *node)
54  {
55  	xmlChar *buf;
56  	int bufsiz;
57  	char *ret, *pos;
58  	xmlNodePtr n = (xmlNodePtr) node;
59  	xmlDocPtr doc;
60  
61  	doc = xmlNewDoc((xmlChar *) "1.0");
62  	n = xmlDocCopyNode(n, doc, 1);
63  	xmlDocSetRootElement(doc, n);
64  	xmlDocDumpFormatMemory(doc, &buf, &bufsiz, 0);
65  	xmlFreeDoc(doc);
66  	if (!buf)
67  		return NULL;
68  	pos = (char *) buf;
69  	if (strncmp(pos, "<?xml", 5) == 0) {
70  		pos = strchr(pos, '>');
71  		if (pos)
72  			pos++;
73  		while (pos && (*pos == '\r' || *pos == '\n'))
74  			pos++;
75  	}
76  	if (pos)
77  		ret = os_strdup(pos);
78  	else
79  		ret = NULL;
80  	xmlFree(buf);
81  
82  	if (ret) {
83  		pos = ret;
84  		if (pos[0]) {
85  			while (pos[1])
86  				pos++;
87  		}
88  		while (pos >= ret && *pos == '\n')
89  			*pos-- = '\0';
90  	}
91  
92  	return ret;
93  }
94  
95  
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)96  xml_node_t * xml_node_create_root(struct xml_node_ctx *ctx, const char *ns_uri,
97  				  const char *ns_prefix,
98  				  xml_namespace_t **ret_ns, const char *name)
99  {
100  	xmlNodePtr node;
101  	xmlNsPtr ns = NULL;
102  
103  	node = xmlNewNode(NULL, (const xmlChar *) name);
104  	if (node == NULL)
105  		return NULL;
106  	if (ns_uri) {
107  		ns = xmlNewNs(node, (const xmlChar *) ns_uri,
108  			      (const xmlChar *) ns_prefix);
109  		xmlSetNs(node, ns);
110  	}
111  
112  	if (ret_ns)
113  		*ret_ns = (xml_namespace_t *) ns;
114  
115  	return (xml_node_t *) node;
116  }
117  
118  
xml_node_create(struct xml_node_ctx * ctx,xml_node_t * parent,xml_namespace_t * ns,const char * name)119  xml_node_t * xml_node_create(struct xml_node_ctx *ctx, xml_node_t *parent,
120  			     xml_namespace_t *ns, const char *name)
121  {
122  	xmlNodePtr node;
123  	node = xmlNewChild((xmlNodePtr) parent, (xmlNsPtr) ns,
124  			   (const xmlChar *) name, NULL);
125  	return (xml_node_t *) node;
126  }
127  
128  
xml_node_create_text(struct xml_node_ctx * ctx,xml_node_t * parent,xml_namespace_t * ns,const char * name,const char * value)129  xml_node_t * xml_node_create_text(struct xml_node_ctx *ctx,
130  				  xml_node_t *parent, xml_namespace_t *ns,
131  				  const char *name, const char *value)
132  {
133  	xmlNodePtr node;
134  	node = xmlNewTextChild((xmlNodePtr) parent, (xmlNsPtr) ns,
135  			       (const xmlChar *) name, (const xmlChar *) value);
136  	return (xml_node_t *) node;
137  }
138  
139  
xml_node_create_text_ns(struct xml_node_ctx * ctx,xml_node_t * parent,const char * ns_uri,const char * name,const char * value)140  xml_node_t * xml_node_create_text_ns(struct xml_node_ctx *ctx,
141  				     xml_node_t *parent, const char *ns_uri,
142  				     const char *name, const char *value)
143  {
144  	xmlNodePtr node;
145  	xmlNsPtr ns;
146  
147  	node = xmlNewTextChild((xmlNodePtr) parent, NULL,
148  			       (const xmlChar *) name, (const xmlChar *) value);
149  	ns = xmlNewNs(node, (const xmlChar *) ns_uri, NULL);
150  	xmlSetNs(node, ns);
151  	return (xml_node_t *) node;
152  }
153  
154  
xml_node_set_text(struct xml_node_ctx * ctx,xml_node_t * node,const char * value)155  void xml_node_set_text(struct xml_node_ctx *ctx, xml_node_t *node,
156  		       const char *value)
157  {
158  	/* TODO: escape XML special chars in value */
159  	xmlNodeSetContent((xmlNodePtr) node, (xmlChar *) value);
160  }
161  
162  
xml_node_first_child(struct xml_node_ctx * ctx,xml_node_t * parent)163  xml_node_t * xml_node_first_child(struct xml_node_ctx *ctx,
164  				  xml_node_t *parent)
165  {
166  	return (xml_node_t *) ((xmlNodePtr) parent)->children;
167  }
168  
169  
xml_node_next_sibling(struct xml_node_ctx * ctx,xml_node_t * node)170  xml_node_t * xml_node_next_sibling(struct xml_node_ctx *ctx,
171  				   xml_node_t *node)
172  {
173  	return (xml_node_t *) ((xmlNodePtr) node)->next;
174  }
175  
176  
xml_node_is_element(struct xml_node_ctx * ctx,xml_node_t * node)177  int xml_node_is_element(struct xml_node_ctx *ctx, xml_node_t *node)
178  {
179  	return ((xmlNodePtr) node)->type == XML_ELEMENT_NODE;
180  }
181  
182  
xml_node_get_text(struct xml_node_ctx * ctx,xml_node_t * node)183  char * xml_node_get_text(struct xml_node_ctx *ctx, xml_node_t *node)
184  {
185  	if (xmlChildElementCount((xmlNodePtr) node) > 0)
186  		return NULL;
187  	return (char *) xmlNodeGetContent((xmlNodePtr) node);
188  }
189  
190  
xml_node_get_text_free(struct xml_node_ctx * ctx,char * val)191  void xml_node_get_text_free(struct xml_node_ctx *ctx, char *val)
192  {
193  	if (val)
194  		xmlFree((xmlChar *) val);
195  }
196  
197  
xml_node_get_base64_text(struct xml_node_ctx * ctx,xml_node_t * node,int * ret_len)198  char * xml_node_get_base64_text(struct xml_node_ctx *ctx, xml_node_t *node,
199  				int *ret_len)
200  {
201  	char *txt;
202  	unsigned char *ret;
203  	size_t len;
204  
205  	txt = xml_node_get_text(ctx, node);
206  	if (txt == NULL)
207  		return NULL;
208  
209  	ret = base64_decode(txt, strlen(txt), &len);
210  	if (ret_len)
211  		*ret_len = len;
212  	xml_node_get_text_free(ctx, txt);
213  	if (ret == NULL)
214  		return NULL;
215  	txt = os_malloc(len + 1);
216  	if (txt == NULL) {
217  		os_free(ret);
218  		return NULL;
219  	}
220  	os_memcpy(txt, ret, len);
221  	txt[len] = '\0';
222  	return txt;
223  }
224  
225  
xml_node_init_ctx(void * upper_ctx,const void * env)226  struct xml_node_ctx * xml_node_init_ctx(void *upper_ctx,
227  					const void *env)
228  {
229  	struct xml_node_ctx *xctx;
230  
231  	xctx = os_zalloc(sizeof(*xctx));
232  	if (xctx == NULL)
233  		return NULL;
234  	xctx->ctx = upper_ctx;
235  
236  	LIBXML_TEST_VERSION
237  
238  	return xctx;
239  }
240  
241  
xml_node_deinit_ctx(struct xml_node_ctx * ctx)242  void xml_node_deinit_ctx(struct xml_node_ctx *ctx)
243  {
244  	xmlSchemaCleanupTypes();
245  	xmlCleanupParser();
246  	xmlMemoryDump();
247  	os_free(ctx);
248  }
249