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