diff -r 54819e984a19 -r 9ca1e4706acc libidav/xml.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libidav/xml.c Sun Oct 22 12:58:07 2017 +0200 @@ -0,0 +1,157 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2017 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include "xml.h" + +static DavXmlNodeType convert_type(xmlElementType type) { + DavXmlNodeType ct; + switch(type) { + default: ct = DAV_XML_NONE; break; + case XML_ELEMENT_NODE: ct = DAV_XML_ELEMENT; break; + case XML_TEXT_NODE: ct = DAV_XML_TEXT; + } + return ct; +} + +typedef struct { + xmlNode *node; + DavXmlNode *parent; +} ConvXmlElm; + +DavXmlNode* dav_convert_xml(DavSession *sn, xmlNode *node) { + if(!node) { + return NULL; + } + DavXmlNodeType newnt = convert_type(node->type); + if(newnt == DAV_XML_NONE) { + return NULL; + } + + UcxMempool *mp = sn->mp; + + ConvXmlElm *ce = malloc(sizeof(ConvXmlElm)); + ce->node = node; + ce->parent = NULL; + UcxList *stack = ucx_list_prepend(NULL, ce); + + DavXmlNode *ret = NULL; + + while(stack) { + ConvXmlElm *c = stack->data; + stack = ucx_list_remove(stack, stack); + + xmlNode *n = c->node; + DavXmlNode *prev = NULL; + while(n) { + DavXmlNode *newxn = ucx_mempool_calloc(mp, 1, sizeof(DavXmlNode)); + if(!ret) { + ret = newxn; + } + newxn->type = convert_type(n->type); + newxn->parent = c->parent; + if(c->parent && !c->parent->children) { + c->parent->children = newxn; + } + newxn->prev = prev; + if(prev) { + prev->next = newxn; + } + + if(newxn->type == DAV_XML_ELEMENT) { + newxn->name = dav_session_strdup(sn, (char*)n->name); + if(n->ns && n->ns->href) { + newxn->namespace = dav_session_strdup(sn, (char*)n->ns->href); + } + + // TODO: copy attributes + + if(n->children) { + ConvXmlElm *convc = malloc(sizeof(ConvXmlElm)); + convc->node = n->children; + convc->parent = newxn; + stack = ucx_list_prepend(stack, convc); + } + } else if(newxn->type == DAV_XML_TEXT) { + sstr_t content = sstrdup_a(mp->allocator, sstr((char*)n->content)); + newxn->content = content.ptr; + newxn->contentlength = content.length; + } + + prev = newxn; + n = n->next; + } + + free(c); + } + + return ret; +} + +void dav_print_xml(DavXmlNode *node) { + if(node->type == DAV_XML_ELEMENT) { + printf("<%s>", node->name); + + DavXmlNode *child = node->children; + if(child) { + dav_print_xml(child); + } + + printf("", node->name); + } else { + fwrite(node->content, 1, node->contentlength, stdout); + fflush(stdout); + } + if(node->next) { + dav_print_xml(node->next); + } +} + +/* ------------------------- public API ------------------------- */ + +char* dav_xml_getstring(DavXmlNode *node) { + if(node && node->type == DAV_XML_TEXT) { + return node->content; + } else { + return NULL; + } +} + +DavXmlNode* dav_text_node(DavSession *sn, char *text) { + UcxMempool *mp = sn->mp; + DavXmlNode *newxn = ucx_mempool_calloc(mp, 1, sizeof(DavXmlNode)); + newxn->type = DAV_XML_TEXT; + sstr_t content = sstrdup_a(mp->allocator, sstr(text)); + newxn->content = content.ptr; + newxn->contentlength = content.length; + return newxn; +} +