xref: /freebsd-src/contrib/wpa/src/utils/xml-utils.c (revision 67350cb56a69468c118bd4ccf6e361b7ebfa9eb4)
15b9c547cSRui Paulo /*
25b9c547cSRui Paulo  * Generic XML helper functions
35b9c547cSRui Paulo  * Copyright (c) 2012-2013, Qualcomm Atheros, Inc.
45b9c547cSRui Paulo  *
55b9c547cSRui Paulo  * This software may be distributed under the terms of the BSD license.
65b9c547cSRui Paulo  * See README for more details.
75b9c547cSRui Paulo  */
85b9c547cSRui Paulo 
95b9c547cSRui Paulo #include "includes.h"
105b9c547cSRui Paulo 
115b9c547cSRui Paulo #include "common.h"
125b9c547cSRui Paulo #include "xml-utils.h"
135b9c547cSRui Paulo 
145b9c547cSRui Paulo 
get_node_uri_iter(struct xml_node_ctx * ctx,xml_node_t * root,char * uri)155b9c547cSRui Paulo static xml_node_t * get_node_uri_iter(struct xml_node_ctx *ctx,
165b9c547cSRui Paulo 				      xml_node_t *root, char *uri)
175b9c547cSRui Paulo {
185b9c547cSRui Paulo 	char *end;
195b9c547cSRui Paulo 	xml_node_t *node;
205b9c547cSRui Paulo 	const char *name;
215b9c547cSRui Paulo 
225b9c547cSRui Paulo 	end = strchr(uri, '/');
235b9c547cSRui Paulo 	if (end)
245b9c547cSRui Paulo 		*end++ = '\0';
255b9c547cSRui Paulo 
265b9c547cSRui Paulo 	node = root;
275b9c547cSRui Paulo 	xml_node_for_each_sibling(ctx, node) {
285b9c547cSRui Paulo 		xml_node_for_each_check(ctx, node);
295b9c547cSRui Paulo 		name = xml_node_get_localname(ctx, node);
305b9c547cSRui Paulo 		if (strcasecmp(name, uri) == 0)
315b9c547cSRui Paulo 			break;
325b9c547cSRui Paulo 	}
335b9c547cSRui Paulo 
345b9c547cSRui Paulo 	if (node == NULL)
355b9c547cSRui Paulo 		return NULL;
365b9c547cSRui Paulo 
375b9c547cSRui Paulo 	if (end) {
385b9c547cSRui Paulo 		return get_node_uri_iter(ctx, xml_node_first_child(ctx, node),
395b9c547cSRui Paulo 					 end);
405b9c547cSRui Paulo 	}
415b9c547cSRui Paulo 
425b9c547cSRui Paulo 	return node;
435b9c547cSRui Paulo }
445b9c547cSRui Paulo 
455b9c547cSRui Paulo 
get_node_uri(struct xml_node_ctx * ctx,xml_node_t * root,const char * uri)465b9c547cSRui Paulo xml_node_t * get_node_uri(struct xml_node_ctx *ctx, xml_node_t *root,
475b9c547cSRui Paulo 			  const char *uri)
485b9c547cSRui Paulo {
495b9c547cSRui Paulo 	char *search;
505b9c547cSRui Paulo 	xml_node_t *node;
515b9c547cSRui Paulo 
525b9c547cSRui Paulo 	search = os_strdup(uri);
535b9c547cSRui Paulo 	if (search == NULL)
545b9c547cSRui Paulo 		return NULL;
555b9c547cSRui Paulo 
565b9c547cSRui Paulo 	node = get_node_uri_iter(ctx, root, search);
575b9c547cSRui Paulo 
585b9c547cSRui Paulo 	os_free(search);
595b9c547cSRui Paulo 	return node;
605b9c547cSRui Paulo }
615b9c547cSRui Paulo 
625b9c547cSRui Paulo 
get_node_iter(struct xml_node_ctx * ctx,xml_node_t * root,const char * path)635b9c547cSRui Paulo static xml_node_t * get_node_iter(struct xml_node_ctx *ctx,
645b9c547cSRui Paulo 				  xml_node_t *root, const char *path)
655b9c547cSRui Paulo {
665b9c547cSRui Paulo 	char *end;
675b9c547cSRui Paulo 	xml_node_t *node;
685b9c547cSRui Paulo 	const char *name;
695b9c547cSRui Paulo 
705b9c547cSRui Paulo 	end = os_strchr(path, '/');
715b9c547cSRui Paulo 	if (end)
725b9c547cSRui Paulo 		*end++ = '\0';
735b9c547cSRui Paulo 
745b9c547cSRui Paulo 	xml_node_for_each_child(ctx, node, root) {
755b9c547cSRui Paulo 		xml_node_for_each_check(ctx, node);
765b9c547cSRui Paulo 		name = xml_node_get_localname(ctx, node);
775b9c547cSRui Paulo 		if (os_strcasecmp(name, path) == 0)
785b9c547cSRui Paulo 			break;
795b9c547cSRui Paulo 	}
805b9c547cSRui Paulo 
815b9c547cSRui Paulo 	if (node == NULL)
825b9c547cSRui Paulo 		return NULL;
835b9c547cSRui Paulo 	if (end)
845b9c547cSRui Paulo 		return get_node_iter(ctx, node, end);
855b9c547cSRui Paulo 	return node;
865b9c547cSRui Paulo }
875b9c547cSRui Paulo 
885b9c547cSRui Paulo 
get_node(struct xml_node_ctx * ctx,xml_node_t * root,const char * path)895b9c547cSRui Paulo xml_node_t * get_node(struct xml_node_ctx *ctx, xml_node_t *root,
905b9c547cSRui Paulo 		      const char *path)
915b9c547cSRui Paulo {
925b9c547cSRui Paulo 	char *search;
935b9c547cSRui Paulo 	xml_node_t *node;
945b9c547cSRui Paulo 
955b9c547cSRui Paulo 	search = os_strdup(path);
965b9c547cSRui Paulo 	if (search == NULL)
975b9c547cSRui Paulo 		return NULL;
985b9c547cSRui Paulo 
995b9c547cSRui Paulo 	node = get_node_iter(ctx, root, search);
1005b9c547cSRui Paulo 
1015b9c547cSRui Paulo 	os_free(search);
1025b9c547cSRui Paulo 	return node;
1035b9c547cSRui Paulo }
1045b9c547cSRui Paulo 
1055b9c547cSRui Paulo 
get_child_node(struct xml_node_ctx * ctx,xml_node_t * root,const char * path)1065b9c547cSRui Paulo xml_node_t * get_child_node(struct xml_node_ctx *ctx, xml_node_t *root,
1075b9c547cSRui Paulo 			    const char *path)
1085b9c547cSRui Paulo {
1095b9c547cSRui Paulo 	xml_node_t *node;
1105b9c547cSRui Paulo 	xml_node_t *match;
1115b9c547cSRui Paulo 
1125b9c547cSRui Paulo 	xml_node_for_each_child(ctx, node, root) {
1135b9c547cSRui Paulo 		xml_node_for_each_check(ctx, node);
1145b9c547cSRui Paulo 		match = get_node(ctx, node, path);
1155b9c547cSRui Paulo 		if (match)
1165b9c547cSRui Paulo 			return match;
1175b9c547cSRui Paulo 	}
1185b9c547cSRui Paulo 
1195b9c547cSRui Paulo 	return NULL;
1205b9c547cSRui Paulo }
1215b9c547cSRui Paulo 
1225b9c547cSRui Paulo 
node_from_file(struct xml_node_ctx * ctx,const char * name)1235b9c547cSRui Paulo xml_node_t * node_from_file(struct xml_node_ctx *ctx, const char *name)
1245b9c547cSRui Paulo {
1255b9c547cSRui Paulo 	xml_node_t *node;
1265b9c547cSRui Paulo 	char *buf, *buf2, *start;
1275b9c547cSRui Paulo 	size_t len;
1285b9c547cSRui Paulo 
1295b9c547cSRui Paulo 	buf = os_readfile(name, &len);
1305b9c547cSRui Paulo 	if (buf == NULL)
1315b9c547cSRui Paulo 		return NULL;
1325b9c547cSRui Paulo 	buf2 = os_realloc(buf, len + 1);
1335b9c547cSRui Paulo 	if (buf2 == NULL) {
1345b9c547cSRui Paulo 		os_free(buf);
1355b9c547cSRui Paulo 		return NULL;
1365b9c547cSRui Paulo 	}
1375b9c547cSRui Paulo 	buf = buf2;
1385b9c547cSRui Paulo 	buf[len] = '\0';
1395b9c547cSRui Paulo 
1405b9c547cSRui Paulo 	start = os_strstr(buf, "<!DOCTYPE ");
1415b9c547cSRui Paulo 	if (start) {
1425b9c547cSRui Paulo 		char *pos = start + 1;
1435b9c547cSRui Paulo 		int count = 1;
1445b9c547cSRui Paulo 		while (*pos) {
1455b9c547cSRui Paulo 			if (*pos == '<')
1465b9c547cSRui Paulo 				count++;
1475b9c547cSRui Paulo 			else if (*pos == '>') {
1485b9c547cSRui Paulo 				count--;
1495b9c547cSRui Paulo 				if (count == 0) {
1505b9c547cSRui Paulo 					pos++;
1515b9c547cSRui Paulo 					break;
1525b9c547cSRui Paulo 				}
1535b9c547cSRui Paulo 			}
1545b9c547cSRui Paulo 			pos++;
1555b9c547cSRui Paulo 		}
1565b9c547cSRui Paulo 		if (count == 0) {
1575b9c547cSRui Paulo 			/* Remove DOCTYPE to allow the file to be parsed */
1585b9c547cSRui Paulo 			os_memset(start, ' ', pos - start);
1595b9c547cSRui Paulo 		}
1605b9c547cSRui Paulo 	}
1615b9c547cSRui Paulo 
1625b9c547cSRui Paulo 	node = xml_node_from_buf(ctx, buf);
1635b9c547cSRui Paulo 	os_free(buf);
1645b9c547cSRui Paulo 
1655b9c547cSRui Paulo 	return node;
1665b9c547cSRui Paulo }
1675b9c547cSRui Paulo 
1685b9c547cSRui Paulo 
node_to_file(struct xml_node_ctx * ctx,const char * fname,xml_node_t * node)1695b9c547cSRui Paulo int node_to_file(struct xml_node_ctx *ctx, const char *fname, xml_node_t *node)
1705b9c547cSRui Paulo {
1715b9c547cSRui Paulo 	FILE *f;
1725b9c547cSRui Paulo 	char *str;
1735b9c547cSRui Paulo 
1745b9c547cSRui Paulo 	str = xml_node_to_str(ctx, node);
1755b9c547cSRui Paulo 	if (str == NULL)
1765b9c547cSRui Paulo 		return -1;
1775b9c547cSRui Paulo 
1785b9c547cSRui Paulo 	f = fopen(fname, "w");
1795b9c547cSRui Paulo 	if (!f) {
1805b9c547cSRui Paulo 		os_free(str);
1815b9c547cSRui Paulo 		return -1;
1825b9c547cSRui Paulo 	}
1835b9c547cSRui Paulo 
1845b9c547cSRui Paulo 	fprintf(f, "%s\n", str);
1855b9c547cSRui Paulo 	os_free(str);
1865b9c547cSRui Paulo 	fclose(f);
1875b9c547cSRui Paulo 
1885b9c547cSRui Paulo 	return 0;
1895b9c547cSRui Paulo }
1905b9c547cSRui Paulo 
1915b9c547cSRui Paulo 
get_val(struct xml_node_ctx * ctx,xml_node_t * node)1925b9c547cSRui Paulo static char * get_val(struct xml_node_ctx *ctx, xml_node_t *node)
1935b9c547cSRui Paulo {
1945b9c547cSRui Paulo 	char *val, *pos;
1955b9c547cSRui Paulo 
1965b9c547cSRui Paulo 	val = xml_node_get_text(ctx, node);
1975b9c547cSRui Paulo 	if (val == NULL)
1985b9c547cSRui Paulo 		return NULL;
1995b9c547cSRui Paulo 	pos = val;
2005b9c547cSRui Paulo 	while (*pos) {
2015b9c547cSRui Paulo 		if (*pos != ' ' && *pos != '\t' && *pos != '\r' && *pos != '\n')
2025b9c547cSRui Paulo 			return val;
2035b9c547cSRui Paulo 		pos++;
2045b9c547cSRui Paulo 	}
2055b9c547cSRui Paulo 
2065b9c547cSRui Paulo 	return NULL;
2075b9c547cSRui Paulo }
2085b9c547cSRui Paulo 
2095b9c547cSRui Paulo 
add_path(const char * prev,const char * leaf)2105b9c547cSRui Paulo static char * add_path(const char *prev, const char *leaf)
2115b9c547cSRui Paulo {
2125b9c547cSRui Paulo 	size_t len;
2135b9c547cSRui Paulo 	char *new_uri;
2145b9c547cSRui Paulo 
2155b9c547cSRui Paulo 	if (prev == NULL)
2165b9c547cSRui Paulo 		return NULL;
2175b9c547cSRui Paulo 
2185b9c547cSRui Paulo 	len = os_strlen(prev) + 1 + os_strlen(leaf) + 1;
2195b9c547cSRui Paulo 	new_uri = os_malloc(len);
2205b9c547cSRui Paulo 	if (new_uri)
2215b9c547cSRui Paulo 		os_snprintf(new_uri, len, "%s/%s", prev, leaf);
2225b9c547cSRui Paulo 
2235b9c547cSRui Paulo 	return new_uri;
2245b9c547cSRui Paulo }
2255b9c547cSRui Paulo 
2265b9c547cSRui Paulo 
node_to_tnds(struct xml_node_ctx * ctx,xml_node_t * out,xml_node_t * in,const char * uri)2275b9c547cSRui Paulo static void node_to_tnds(struct xml_node_ctx *ctx, xml_node_t *out,
2285b9c547cSRui Paulo 			 xml_node_t *in, const char *uri)
2295b9c547cSRui Paulo {
2305b9c547cSRui Paulo 	xml_node_t *node;
2315b9c547cSRui Paulo 	xml_node_t *tnds;
2325b9c547cSRui Paulo 	const char *name;
2335b9c547cSRui Paulo 	char *val;
2345b9c547cSRui Paulo 	char *new_uri;
2355b9c547cSRui Paulo 
2365b9c547cSRui Paulo 	xml_node_for_each_child(ctx, node, in) {
2375b9c547cSRui Paulo 		xml_node_for_each_check(ctx, node);
2385b9c547cSRui Paulo 		name = xml_node_get_localname(ctx, node);
2395b9c547cSRui Paulo 
2405b9c547cSRui Paulo 		tnds = xml_node_create(ctx, out, NULL, "Node");
2415b9c547cSRui Paulo 		if (tnds == NULL)
2425b9c547cSRui Paulo 			return;
2435b9c547cSRui Paulo 		xml_node_create_text(ctx, tnds, NULL, "NodeName", name);
2445b9c547cSRui Paulo 
2455b9c547cSRui Paulo 		if (uri)
2465b9c547cSRui Paulo 			xml_node_create_text(ctx, tnds, NULL, "Path", uri);
2475b9c547cSRui Paulo 
2485b9c547cSRui Paulo 		val = get_val(ctx, node);
249*85732ac8SCy Schubert 		if (val || !xml_node_first_child(ctx, node))
250*85732ac8SCy Schubert 			xml_node_create_text(ctx, tnds, NULL, "Value",
251*85732ac8SCy Schubert 					     val ? val : "");
2525b9c547cSRui Paulo 		xml_node_get_text_free(ctx, val);
2535b9c547cSRui Paulo 
2545b9c547cSRui Paulo 		new_uri = add_path(uri, name);
2555b9c547cSRui Paulo 		node_to_tnds(ctx, new_uri ? out : tnds, node, new_uri);
2565b9c547cSRui Paulo 		os_free(new_uri);
2575b9c547cSRui Paulo 	}
2585b9c547cSRui Paulo }
2595b9c547cSRui Paulo 
2605b9c547cSRui Paulo 
add_ddfname(struct xml_node_ctx * ctx,xml_node_t * parent,const char * urn)2615b9c547cSRui Paulo static int add_ddfname(struct xml_node_ctx *ctx, xml_node_t *parent,
2625b9c547cSRui Paulo 		       const char *urn)
2635b9c547cSRui Paulo {
2645b9c547cSRui Paulo 	xml_node_t *node;
2655b9c547cSRui Paulo 
2665b9c547cSRui Paulo 	node = xml_node_create(ctx, parent, NULL, "RTProperties");
2675b9c547cSRui Paulo 	if (node == NULL)
2685b9c547cSRui Paulo 		return -1;
2695b9c547cSRui Paulo 	node = xml_node_create(ctx, node, NULL, "Type");
2705b9c547cSRui Paulo 	if (node == NULL)
2715b9c547cSRui Paulo 		return -1;
2725b9c547cSRui Paulo 	xml_node_create_text(ctx, node, NULL, "DDFName", urn);
2735b9c547cSRui Paulo 	return 0;
2745b9c547cSRui Paulo }
2755b9c547cSRui Paulo 
2765b9c547cSRui Paulo 
mo_to_tnds(struct xml_node_ctx * ctx,xml_node_t * mo,int use_path,const char * urn,const char * ns_uri)2775b9c547cSRui Paulo xml_node_t * mo_to_tnds(struct xml_node_ctx *ctx, xml_node_t *mo,
2785b9c547cSRui Paulo 			int use_path, const char *urn, const char *ns_uri)
2795b9c547cSRui Paulo {
2805b9c547cSRui Paulo 	xml_node_t *root;
2815b9c547cSRui Paulo 	xml_node_t *node;
2825b9c547cSRui Paulo 	const char *name;
2835b9c547cSRui Paulo 
2845b9c547cSRui Paulo 	root = xml_node_create_root(ctx, ns_uri, NULL, NULL, "MgmtTree");
2855b9c547cSRui Paulo 	if (root == NULL)
2865b9c547cSRui Paulo 		return NULL;
2875b9c547cSRui Paulo 
2885b9c547cSRui Paulo 	xml_node_create_text(ctx, root, NULL, "VerDTD", "1.2");
2895b9c547cSRui Paulo 
2905b9c547cSRui Paulo 	name = xml_node_get_localname(ctx, mo);
2915b9c547cSRui Paulo 
2925b9c547cSRui Paulo 	node = xml_node_create(ctx, root, NULL, "Node");
2935b9c547cSRui Paulo 	if (node == NULL)
2945b9c547cSRui Paulo 		goto fail;
2955b9c547cSRui Paulo 	xml_node_create_text(ctx, node, NULL, "NodeName", name);
2965b9c547cSRui Paulo 	if (urn)
2975b9c547cSRui Paulo 		add_ddfname(ctx, node, urn);
2985b9c547cSRui Paulo 
2995b9c547cSRui Paulo 	node_to_tnds(ctx, use_path ? root : node, mo, use_path ? name : NULL);
3005b9c547cSRui Paulo 
3015b9c547cSRui Paulo 	return root;
3025b9c547cSRui Paulo 
3035b9c547cSRui Paulo fail:
3045b9c547cSRui Paulo 	xml_node_free(ctx, root);
3055b9c547cSRui Paulo 	return NULL;
3065b9c547cSRui Paulo }
3075b9c547cSRui Paulo 
3085b9c547cSRui Paulo 
get_first_child_node(struct xml_node_ctx * ctx,xml_node_t * node,const char * name)3095b9c547cSRui Paulo static xml_node_t * get_first_child_node(struct xml_node_ctx *ctx,
3105b9c547cSRui Paulo 					 xml_node_t *node,
3115b9c547cSRui Paulo 					 const char *name)
3125b9c547cSRui Paulo {
3135b9c547cSRui Paulo 	const char *lname;
3145b9c547cSRui Paulo 	xml_node_t *child;
3155b9c547cSRui Paulo 
3165b9c547cSRui Paulo 	xml_node_for_each_child(ctx, child, node) {
3175b9c547cSRui Paulo 		xml_node_for_each_check(ctx, child);
3185b9c547cSRui Paulo 		lname = xml_node_get_localname(ctx, child);
3195b9c547cSRui Paulo 		if (os_strcasecmp(lname, name) == 0)
3205b9c547cSRui Paulo 			return child;
3215b9c547cSRui Paulo 	}
3225b9c547cSRui Paulo 
3235b9c547cSRui Paulo 	return NULL;
3245b9c547cSRui Paulo }
3255b9c547cSRui Paulo 
3265b9c547cSRui Paulo 
get_node_text(struct xml_node_ctx * ctx,xml_node_t * node,const char * node_name)3275b9c547cSRui Paulo static char * get_node_text(struct xml_node_ctx *ctx, xml_node_t *node,
3285b9c547cSRui Paulo 			    const char *node_name)
3295b9c547cSRui Paulo {
3305b9c547cSRui Paulo 	node = get_first_child_node(ctx, node, node_name);
3315b9c547cSRui Paulo 	if (node == NULL)
3325b9c547cSRui Paulo 		return NULL;
3335b9c547cSRui Paulo 	return xml_node_get_text(ctx, node);
3345b9c547cSRui Paulo }
3355b9c547cSRui Paulo 
3365b9c547cSRui Paulo 
add_mo_node(struct xml_node_ctx * ctx,xml_node_t * root,xml_node_t * node,const char * uri)3375b9c547cSRui Paulo static xml_node_t * add_mo_node(struct xml_node_ctx *ctx, xml_node_t *root,
3385b9c547cSRui Paulo 				xml_node_t *node, const char *uri)
3395b9c547cSRui Paulo {
3405b9c547cSRui Paulo 	char *nodename, *value, *path;
3415b9c547cSRui Paulo 	xml_node_t *parent;
3425b9c547cSRui Paulo 
3435b9c547cSRui Paulo 	nodename = get_node_text(ctx, node, "NodeName");
3445b9c547cSRui Paulo 	if (nodename == NULL)
3455b9c547cSRui Paulo 		return NULL;
3465b9c547cSRui Paulo 	value = get_node_text(ctx, node, "Value");
3475b9c547cSRui Paulo 
3485b9c547cSRui Paulo 	if (root == NULL) {
3495b9c547cSRui Paulo 		root = xml_node_create_root(ctx, NULL, NULL, NULL,
3505b9c547cSRui Paulo 					    nodename);
3515b9c547cSRui Paulo 		if (root && value)
3525b9c547cSRui Paulo 			xml_node_set_text(ctx, root, value);
3535b9c547cSRui Paulo 	} else {
3545b9c547cSRui Paulo 		if (uri == NULL) {
3555b9c547cSRui Paulo 			xml_node_get_text_free(ctx, nodename);
3565b9c547cSRui Paulo 			xml_node_get_text_free(ctx, value);
3575b9c547cSRui Paulo 			return NULL;
3585b9c547cSRui Paulo 		}
3595b9c547cSRui Paulo 		path = get_node_text(ctx, node, "Path");
3605b9c547cSRui Paulo 		if (path)
3615b9c547cSRui Paulo 			uri = path;
3625b9c547cSRui Paulo 		parent = get_node_uri(ctx, root, uri);
3635b9c547cSRui Paulo 		xml_node_get_text_free(ctx, path);
3645b9c547cSRui Paulo 		if (parent == NULL) {
3655b9c547cSRui Paulo 			printf("Could not find URI '%s'\n", uri);
3665b9c547cSRui Paulo 			xml_node_get_text_free(ctx, nodename);
3675b9c547cSRui Paulo 			xml_node_get_text_free(ctx, value);
3685b9c547cSRui Paulo 			return NULL;
3695b9c547cSRui Paulo 		}
3705b9c547cSRui Paulo 		if (value)
3715b9c547cSRui Paulo 			xml_node_create_text(ctx, parent, NULL, nodename,
3725b9c547cSRui Paulo 					     value);
3735b9c547cSRui Paulo 		else
3745b9c547cSRui Paulo 			xml_node_create(ctx, parent, NULL, nodename);
3755b9c547cSRui Paulo 	}
3765b9c547cSRui Paulo 
3775b9c547cSRui Paulo 	xml_node_get_text_free(ctx, nodename);
3785b9c547cSRui Paulo 	xml_node_get_text_free(ctx, value);
3795b9c547cSRui Paulo 
3805b9c547cSRui Paulo 	return root;
3815b9c547cSRui Paulo }
3825b9c547cSRui Paulo 
3835b9c547cSRui Paulo 
tnds_to_mo_iter(struct xml_node_ctx * ctx,xml_node_t * root,xml_node_t * node,const char * uri)3845b9c547cSRui Paulo static xml_node_t * tnds_to_mo_iter(struct xml_node_ctx *ctx, xml_node_t *root,
3855b9c547cSRui Paulo 				    xml_node_t *node, const char *uri)
3865b9c547cSRui Paulo {
3875b9c547cSRui Paulo 	xml_node_t *child;
3885b9c547cSRui Paulo 	const char *name;
3895b9c547cSRui Paulo 	char *nodename;
3905b9c547cSRui Paulo 
3915b9c547cSRui Paulo 	xml_node_for_each_sibling(ctx, node) {
3925b9c547cSRui Paulo 		xml_node_for_each_check(ctx, node);
3935b9c547cSRui Paulo 
3945b9c547cSRui Paulo 		nodename = get_node_text(ctx, node, "NodeName");
3955b9c547cSRui Paulo 		if (nodename == NULL)
3965b9c547cSRui Paulo 			return NULL;
3975b9c547cSRui Paulo 
3985b9c547cSRui Paulo 		name = xml_node_get_localname(ctx, node);
3995b9c547cSRui Paulo 		if (strcmp(name, "Node") == 0) {
4005b9c547cSRui Paulo 			if (root && !uri) {
4015b9c547cSRui Paulo 				printf("Invalid TNDS tree structure - "
4025b9c547cSRui Paulo 				       "multiple top level nodes\n");
4035b9c547cSRui Paulo 				xml_node_get_text_free(ctx, nodename);
4045b9c547cSRui Paulo 				return NULL;
4055b9c547cSRui Paulo 			}
4065b9c547cSRui Paulo 			root = add_mo_node(ctx, root, node, uri);
4075b9c547cSRui Paulo 		}
4085b9c547cSRui Paulo 
4095b9c547cSRui Paulo 		child = get_first_child_node(ctx, node, "Node");
4105b9c547cSRui Paulo 		if (child) {
4115b9c547cSRui Paulo 			if (uri == NULL)
4125b9c547cSRui Paulo 				tnds_to_mo_iter(ctx, root, child, nodename);
4135b9c547cSRui Paulo 			else {
4145b9c547cSRui Paulo 				char *new_uri;
4155b9c547cSRui Paulo 				new_uri = add_path(uri, nodename);
4165b9c547cSRui Paulo 				tnds_to_mo_iter(ctx, root, child, new_uri);
4175b9c547cSRui Paulo 				os_free(new_uri);
4185b9c547cSRui Paulo 			}
4195b9c547cSRui Paulo 		}
4205b9c547cSRui Paulo 		xml_node_get_text_free(ctx, nodename);
4215b9c547cSRui Paulo 	}
4225b9c547cSRui Paulo 
4235b9c547cSRui Paulo 	return root;
4245b9c547cSRui Paulo }
4255b9c547cSRui Paulo 
4265b9c547cSRui Paulo 
tnds_to_mo(struct xml_node_ctx * ctx,xml_node_t * tnds)4275b9c547cSRui Paulo xml_node_t * tnds_to_mo(struct xml_node_ctx *ctx, xml_node_t *tnds)
4285b9c547cSRui Paulo {
4295b9c547cSRui Paulo 	const char *name;
4305b9c547cSRui Paulo 	xml_node_t *node;
4315b9c547cSRui Paulo 
4325b9c547cSRui Paulo 	name = xml_node_get_localname(ctx, tnds);
4335b9c547cSRui Paulo 	if (name == NULL || os_strcmp(name, "MgmtTree") != 0)
4345b9c547cSRui Paulo 		return NULL;
4355b9c547cSRui Paulo 
4365b9c547cSRui Paulo 	node = get_first_child_node(ctx, tnds, "Node");
4375b9c547cSRui Paulo 	if (!node)
4385b9c547cSRui Paulo 		return NULL;
4395b9c547cSRui Paulo 	return tnds_to_mo_iter(ctx, NULL, node, NULL);
4405b9c547cSRui Paulo }
4415b9c547cSRui Paulo 
4425b9c547cSRui Paulo 
soap_build_envelope(struct xml_node_ctx * ctx,xml_node_t * node)4435b9c547cSRui Paulo xml_node_t * soap_build_envelope(struct xml_node_ctx *ctx, xml_node_t *node)
4445b9c547cSRui Paulo {
4455b9c547cSRui Paulo 	xml_node_t *envelope, *body;
4465b9c547cSRui Paulo 	xml_namespace_t *ns;
4475b9c547cSRui Paulo 
4485b9c547cSRui Paulo 	envelope = xml_node_create_root(
4495b9c547cSRui Paulo 		ctx, "http://www.w3.org/2003/05/soap-envelope", "soap12", &ns,
4505b9c547cSRui Paulo 		"Envelope");
4515b9c547cSRui Paulo 	if (envelope == NULL)
4525b9c547cSRui Paulo 		return NULL;
4535b9c547cSRui Paulo 	body = xml_node_create(ctx, envelope, ns, "Body");
4545b9c547cSRui Paulo 	xml_node_add_child(ctx, body, node);
4555b9c547cSRui Paulo 	return envelope;
4565b9c547cSRui Paulo }
4575b9c547cSRui Paulo 
4585b9c547cSRui Paulo 
soap_get_body(struct xml_node_ctx * ctx,xml_node_t * soap)4595b9c547cSRui Paulo xml_node_t * soap_get_body(struct xml_node_ctx *ctx, xml_node_t *soap)
4605b9c547cSRui Paulo {
4615b9c547cSRui Paulo 	xml_node_t *body, *child;
4625b9c547cSRui Paulo 
4635b9c547cSRui Paulo 	body = get_node_uri(ctx, soap, "Envelope/Body");
4645b9c547cSRui Paulo 	if (body == NULL)
4655b9c547cSRui Paulo 		return NULL;
4665b9c547cSRui Paulo 	xml_node_for_each_child(ctx, child, body) {
4675b9c547cSRui Paulo 		xml_node_for_each_check(ctx, child);
4685b9c547cSRui Paulo 		return child;
4695b9c547cSRui Paulo 	}
4705b9c547cSRui Paulo 	return NULL;
4715b9c547cSRui Paulo }
472