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 24 void xml_node_free(struct xml_node_ctx *ctx, xml_node_t *node) 25 { 26 xmlFreeNode((xmlNodePtr) node); 27 } 28 29 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 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 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 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 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 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 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 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 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 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 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 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 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 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 os_free(ret); 223 return txt; 224 } 225 226 227 struct xml_node_ctx * xml_node_init_ctx(void *upper_ctx, 228 const void *env) 229 { 230 struct xml_node_ctx *xctx; 231 232 xctx = os_zalloc(sizeof(*xctx)); 233 if (xctx == NULL) 234 return NULL; 235 xctx->ctx = upper_ctx; 236 237 LIBXML_TEST_VERSION 238 239 return xctx; 240 } 241 242 243 void xml_node_deinit_ctx(struct xml_node_ctx *ctx) 244 { 245 xmlSchemaCleanupTypes(); 246 xmlCleanupParser(); 247 xmlMemoryDump(); 248 os_free(ctx); 249 } 250