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