X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=libeap%2Fsrc%2Futils%2Fxml-utils.c;fp=libeap%2Fsrc%2Futils%2Fxml-utils.c;h=4916d29765f913594b721607bfc611ef53398793;hb=88e34eecb5769da6526361b35df00fdbe823eac5;hp=0000000000000000000000000000000000000000;hpb=2394142e4bf89e0a9e2a0091ac16bd6442e3d4c7;p=mech_eap.git diff --git a/libeap/src/utils/xml-utils.c b/libeap/src/utils/xml-utils.c new file mode 100644 index 0000000..4916d29 --- /dev/null +++ b/libeap/src/utils/xml-utils.c @@ -0,0 +1,471 @@ +/* + * Generic XML helper functions + * Copyright (c) 2012-2013, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "xml-utils.h" + + +static xml_node_t * get_node_uri_iter(struct xml_node_ctx *ctx, + xml_node_t *root, char *uri) +{ + char *end; + xml_node_t *node; + const char *name; + + end = strchr(uri, '/'); + if (end) + *end++ = '\0'; + + node = root; + xml_node_for_each_sibling(ctx, node) { + xml_node_for_each_check(ctx, node); + name = xml_node_get_localname(ctx, node); + if (strcasecmp(name, uri) == 0) + break; + } + + if (node == NULL) + return NULL; + + if (end) { + return get_node_uri_iter(ctx, xml_node_first_child(ctx, node), + end); + } + + return node; +} + + +xml_node_t * get_node_uri(struct xml_node_ctx *ctx, xml_node_t *root, + const char *uri) +{ + char *search; + xml_node_t *node; + + search = os_strdup(uri); + if (search == NULL) + return NULL; + + node = get_node_uri_iter(ctx, root, search); + + os_free(search); + return node; +} + + +static xml_node_t * get_node_iter(struct xml_node_ctx *ctx, + xml_node_t *root, const char *path) +{ + char *end; + xml_node_t *node; + const char *name; + + end = os_strchr(path, '/'); + if (end) + *end++ = '\0'; + + xml_node_for_each_child(ctx, node, root) { + xml_node_for_each_check(ctx, node); + name = xml_node_get_localname(ctx, node); + if (os_strcasecmp(name, path) == 0) + break; + } + + if (node == NULL) + return NULL; + if (end) + return get_node_iter(ctx, node, end); + return node; +} + + +xml_node_t * get_node(struct xml_node_ctx *ctx, xml_node_t *root, + const char *path) +{ + char *search; + xml_node_t *node; + + search = os_strdup(path); + if (search == NULL) + return NULL; + + node = get_node_iter(ctx, root, search); + + os_free(search); + return node; +} + + +xml_node_t * get_child_node(struct xml_node_ctx *ctx, xml_node_t *root, + const char *path) +{ + xml_node_t *node; + xml_node_t *match; + + xml_node_for_each_child(ctx, node, root) { + xml_node_for_each_check(ctx, node); + match = get_node(ctx, node, path); + if (match) + return match; + } + + return NULL; +} + + +xml_node_t * node_from_file(struct xml_node_ctx *ctx, const char *name) +{ + xml_node_t *node; + char *buf, *buf2, *start; + size_t len; + + buf = os_readfile(name, &len); + if (buf == NULL) + return NULL; + buf2 = os_realloc(buf, len + 1); + if (buf2 == NULL) { + os_free(buf); + return NULL; + } + buf = buf2; + buf[len] = '\0'; + + start = os_strstr(buf, "') { + count--; + if (count == 0) { + pos++; + break; + } + } + pos++; + } + if (count == 0) { + /* Remove DOCTYPE to allow the file to be parsed */ + os_memset(start, ' ', pos - start); + } + } + + node = xml_node_from_buf(ctx, buf); + os_free(buf); + + return node; +} + + +int node_to_file(struct xml_node_ctx *ctx, const char *fname, xml_node_t *node) +{ + FILE *f; + char *str; + + str = xml_node_to_str(ctx, node); + if (str == NULL) + return -1; + + f = fopen(fname, "w"); + if (!f) { + os_free(str); + return -1; + } + + fprintf(f, "%s\n", str); + os_free(str); + fclose(f); + + return 0; +} + + +static char * get_val(struct xml_node_ctx *ctx, xml_node_t *node) +{ + char *val, *pos; + + val = xml_node_get_text(ctx, node); + if (val == NULL) + return NULL; + pos = val; + while (*pos) { + if (*pos != ' ' && *pos != '\t' && *pos != '\r' && *pos != '\n') + return val; + pos++; + } + + return NULL; +} + + +static char * add_path(const char *prev, const char *leaf) +{ + size_t len; + char *new_uri; + + if (prev == NULL) + return NULL; + + len = os_strlen(prev) + 1 + os_strlen(leaf) + 1; + new_uri = os_malloc(len); + if (new_uri) + os_snprintf(new_uri, len, "%s/%s", prev, leaf); + + return new_uri; +} + + +static void node_to_tnds(struct xml_node_ctx *ctx, xml_node_t *out, + xml_node_t *in, const char *uri) +{ + xml_node_t *node; + xml_node_t *tnds; + const char *name; + char *val; + char *new_uri; + + xml_node_for_each_child(ctx, node, in) { + xml_node_for_each_check(ctx, node); + name = xml_node_get_localname(ctx, node); + + tnds = xml_node_create(ctx, out, NULL, "Node"); + if (tnds == NULL) + return; + xml_node_create_text(ctx, tnds, NULL, "NodeName", name); + + if (uri) + xml_node_create_text(ctx, tnds, NULL, "Path", uri); + + val = get_val(ctx, node); + if (val) { + xml_node_create_text(ctx, tnds, NULL, "Value", val); + xml_node_get_text_free(ctx, val); + } + + new_uri = add_path(uri, name); + node_to_tnds(ctx, new_uri ? out : tnds, node, new_uri); + os_free(new_uri); + } +} + + +static int add_ddfname(struct xml_node_ctx *ctx, xml_node_t *parent, + const char *urn) +{ + xml_node_t *node; + + node = xml_node_create(ctx, parent, NULL, "RTProperties"); + if (node == NULL) + return -1; + node = xml_node_create(ctx, node, NULL, "Type"); + if (node == NULL) + return -1; + xml_node_create_text(ctx, node, NULL, "DDFName", urn); + return 0; +} + + +xml_node_t * mo_to_tnds(struct xml_node_ctx *ctx, xml_node_t *mo, + int use_path, const char *urn, const char *ns_uri) +{ + xml_node_t *root; + xml_node_t *node; + const char *name; + + root = xml_node_create_root(ctx, ns_uri, NULL, NULL, "MgmtTree"); + if (root == NULL) + return NULL; + + xml_node_create_text(ctx, root, NULL, "VerDTD", "1.2"); + + name = xml_node_get_localname(ctx, mo); + + node = xml_node_create(ctx, root, NULL, "Node"); + if (node == NULL) + goto fail; + xml_node_create_text(ctx, node, NULL, "NodeName", name); + if (urn) + add_ddfname(ctx, node, urn); + + node_to_tnds(ctx, use_path ? root : node, mo, use_path ? name : NULL); + + return root; + +fail: + xml_node_free(ctx, root); + return NULL; +} + + +static xml_node_t * get_first_child_node(struct xml_node_ctx *ctx, + xml_node_t *node, + const char *name) +{ + const char *lname; + xml_node_t *child; + + xml_node_for_each_child(ctx, child, node) { + xml_node_for_each_check(ctx, child); + lname = xml_node_get_localname(ctx, child); + if (os_strcasecmp(lname, name) == 0) + return child; + } + + return NULL; +} + + +static char * get_node_text(struct xml_node_ctx *ctx, xml_node_t *node, + const char *node_name) +{ + node = get_first_child_node(ctx, node, node_name); + if (node == NULL) + return NULL; + return xml_node_get_text(ctx, node); +} + + +static xml_node_t * add_mo_node(struct xml_node_ctx *ctx, xml_node_t *root, + xml_node_t *node, const char *uri) +{ + char *nodename, *value, *path; + xml_node_t *parent; + + nodename = get_node_text(ctx, node, "NodeName"); + if (nodename == NULL) + return NULL; + value = get_node_text(ctx, node, "Value"); + + if (root == NULL) { + root = xml_node_create_root(ctx, NULL, NULL, NULL, + nodename); + if (root && value) + xml_node_set_text(ctx, root, value); + } else { + if (uri == NULL) { + xml_node_get_text_free(ctx, nodename); + xml_node_get_text_free(ctx, value); + return NULL; + } + path = get_node_text(ctx, node, "Path"); + if (path) + uri = path; + parent = get_node_uri(ctx, root, uri); + xml_node_get_text_free(ctx, path); + if (parent == NULL) { + printf("Could not find URI '%s'\n", uri); + xml_node_get_text_free(ctx, nodename); + xml_node_get_text_free(ctx, value); + return NULL; + } + if (value) + xml_node_create_text(ctx, parent, NULL, nodename, + value); + else + xml_node_create(ctx, parent, NULL, nodename); + } + + xml_node_get_text_free(ctx, nodename); + xml_node_get_text_free(ctx, value); + + return root; +} + + +static xml_node_t * tnds_to_mo_iter(struct xml_node_ctx *ctx, xml_node_t *root, + xml_node_t *node, const char *uri) +{ + xml_node_t *child; + const char *name; + char *nodename; + + xml_node_for_each_sibling(ctx, node) { + xml_node_for_each_check(ctx, node); + + nodename = get_node_text(ctx, node, "NodeName"); + if (nodename == NULL) + return NULL; + + name = xml_node_get_localname(ctx, node); + if (strcmp(name, "Node") == 0) { + if (root && !uri) { + printf("Invalid TNDS tree structure - " + "multiple top level nodes\n"); + xml_node_get_text_free(ctx, nodename); + return NULL; + } + root = add_mo_node(ctx, root, node, uri); + } + + child = get_first_child_node(ctx, node, "Node"); + if (child) { + if (uri == NULL) + tnds_to_mo_iter(ctx, root, child, nodename); + else { + char *new_uri; + new_uri = add_path(uri, nodename); + tnds_to_mo_iter(ctx, root, child, new_uri); + os_free(new_uri); + } + } + xml_node_get_text_free(ctx, nodename); + } + + return root; +} + + +xml_node_t * tnds_to_mo(struct xml_node_ctx *ctx, xml_node_t *tnds) +{ + const char *name; + xml_node_t *node; + + name = xml_node_get_localname(ctx, tnds); + if (name == NULL || os_strcmp(name, "MgmtTree") != 0) + return NULL; + + node = get_first_child_node(ctx, tnds, "Node"); + if (!node) + return NULL; + return tnds_to_mo_iter(ctx, NULL, node, NULL); +} + + +xml_node_t * soap_build_envelope(struct xml_node_ctx *ctx, xml_node_t *node) +{ + xml_node_t *envelope, *body; + xml_namespace_t *ns; + + envelope = xml_node_create_root( + ctx, "http://www.w3.org/2003/05/soap-envelope", "soap12", &ns, + "Envelope"); + if (envelope == NULL) + return NULL; + body = xml_node_create(ctx, envelope, ns, "Body"); + xml_node_add_child(ctx, body, node); + return envelope; +} + + +xml_node_t * soap_get_body(struct xml_node_ctx *ctx, xml_node_t *soap) +{ + xml_node_t *body, *child; + + body = get_node_uri(ctx, soap, "Envelope/Body"); + if (body == NULL) + return NULL; + xml_node_for_each_child(ctx, child, body) { + xml_node_for_each_check(ctx, child); + return child; + } + return NULL; +}