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