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