2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright 2018 Olaf Wintermann. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
33 #include <ucx/utils.h>
37 static DavXmlNodeType convert_type(xmlElementType type) {
40 default: ct = DAV_XML_NONE; break;
41 case XML_ELEMENT_NODE: ct = DAV_XML_ELEMENT; break;
42 case XML_TEXT_NODE: ct = DAV_XML_TEXT;
52 DavXmlNode* dav_convert_xml(DavSession *sn, xmlNode *node) {
56 DavXmlNodeType newnt = convert_type(node->type);
57 if(newnt == DAV_XML_NONE) {
61 UcxMempool *mp = sn->mp;
63 ConvXmlElm *ce = malloc(sizeof(ConvXmlElm));
66 UcxList *stack = ucx_list_prepend(NULL, ce);
68 DavXmlNode *ret = NULL;
71 ConvXmlElm *c = stack->data;
72 stack = ucx_list_remove(stack, stack);
75 DavXmlNode *prev = NULL;
77 DavXmlNode *newxn = ucx_mempool_calloc(mp, 1, sizeof(DavXmlNode));
81 newxn->type = convert_type(n->type);
82 newxn->parent = c->parent;
83 if(c->parent && !c->parent->children) {
84 c->parent->children = newxn;
91 if(newxn->type == DAV_XML_ELEMENT) {
92 newxn->name = dav_session_strdup(sn, (char*)n->name);
93 if(n->ns && n->ns->href) {
94 newxn->namespace = dav_session_strdup(sn, (char*)n->ns->href);
97 xmlAttr *attr = n->properties;
98 DavXmlAttr *newattr = NULL;
99 DavXmlAttr *newattr_last = NULL;
101 DavXmlAttr *na = ucx_mempool_calloc(mp, 1, sizeof(DavXmlAttr));
102 na->name = dav_session_strdup(sn, (char*)attr->name);
103 if(attr->children && attr->children->type == XML_TEXT_NODE) {
104 na->value = dav_session_strdup(sn, (char*)attr->children->content);
109 newattr_last->next = na;
115 newxn->attributes = newattr;
118 ConvXmlElm *convc = malloc(sizeof(ConvXmlElm));
119 convc->node = n->children;
120 convc->parent = newxn;
121 stack = ucx_list_prepend(stack, convc);
123 } else if(newxn->type == DAV_XML_TEXT) {
124 sstr_t content = sstrdup_a(mp->allocator, sstr((char*)n->content));
125 newxn->content = content.ptr;
126 newxn->contentlength = content.length;
139 void dav_print_xml(DavXmlNode *node) {
140 if(node->type == DAV_XML_ELEMENT) {
141 printf("<%s", node->name);
142 DavXmlAttr *attr = node->attributes;
144 printf(" %s=\"%s\"", attr->name, attr->value);
149 DavXmlNode *child = node->children;
151 dav_print_xml(child);
154 printf("</%s>", node->name);
156 fwrite(node->content, 1, node->contentlength, stdout);
160 dav_print_xml(node->next);
164 void dav_print_node(void *stream, write_func writef, UcxMap *nsmap, DavXmlNode *node) {
166 if(node->type == DAV_XML_ELEMENT) {
167 char *tagend = node->children ? ">" : " />";
169 if(node->namespace) {
170 prefix = ucx_map_cstr_get(nsmap, node->namespace);
172 sstr_t newpre = ucx_sprintf("x%d", (int)nsmap->count+1);
173 // TODO: fix namespace declaration
174 //ucx_map_cstr_put(nsmap, node->namespace, newpre.ptr);
179 "<%s:%s xmlns:%s=\"%s\"",
185 ucx_fprintf(stream, writef, "<%s:%s", prefix, node->name);
188 ucx_fprintf(stream, writef, "<%s", node->name);
191 DavXmlAttr *attr = node->attributes;
193 ucx_fprintf(stream, writef, " %s=\"%s\"", attr->name, attr->value);
196 writef(tagend, 1, strlen(tagend), stream); // end xml tag
199 dav_print_node(stream, writef, nsmap, node->children);
201 ucx_fprintf(stream, writef, "</%s:%s>", prefix, node->name);
203 ucx_fprintf(stream, writef, "</%s>", node->name);
206 } else if(node->type == DAV_XML_TEXT) {
207 writef(node->content, 1, node->contentlength, stream);
214 /* ------------------------- public API ------------------------- */
216 char* dav_xml_getstring(DavXmlNode *node) {
217 if(node && node->type == DAV_XML_TEXT) {
218 return node->content;
224 DavBool dav_xml_isstring(DavXmlNode *node) {
225 if(node && node->type == DAV_XML_TEXT && !node->next) {
232 DavXmlNode* dav_xml_nextelm(DavXmlNode *node) {
235 if(node->type == DAV_XML_ELEMENT) {
243 DavXmlNode* dav_text_node(DavSession *sn, char *text) {
244 UcxMempool *mp = sn->mp;
245 DavXmlNode *newxn = ucx_mempool_calloc(mp, 1, sizeof(DavXmlNode));
246 newxn->type = DAV_XML_TEXT;
247 sstr_t content = sstrdup_a(mp->allocator, sstr(text));
248 newxn->content = content.ptr;
249 newxn->contentlength = content.length;
254 DavXmlAttr* dav_copy_xml_attr(DavXmlAttr *attr) {
258 DavXmlAttr *newattr = NULL;
259 DavXmlAttr *prev = NULL;
261 DavXmlAttr *n = calloc(1, sizeof(DavXmlAttr));
262 n->name = strdup(attr->name);
263 n->value = strdup(attr->value);
275 DavXmlNode* dav_copy_node(DavXmlNode *node) {
276 DavXmlNode *ret = NULL;
277 DavXmlNode *prev = NULL;
279 DavXmlNode *copy = calloc(1, sizeof(DavXmlNode));
280 copy->type = node->type;
281 if(node->type == DAV_XML_ELEMENT) {
282 copy->namespace = strdup(node->namespace);
283 copy->name = strdup(node->name);
284 copy->children = dav_copy_node(node->children);
285 copy->attributes = dav_copy_xml_attr(node->attributes);
287 copy->contentlength = node->contentlength;
288 copy->content = malloc(node->contentlength+1);
289 memcpy(copy->content, node->content, node->contentlength);
290 copy->content[copy->contentlength] = 0;
306 DavXmlNode* dav_xml_createnode(const char *ns, const char *name) {
307 DavXmlNode *node = calloc(1, sizeof(DavXmlNode));
308 node->type = DAV_XML_ELEMENT;
309 node->namespace = strdup(ns);
310 node->name = strdup(name);
314 DavXmlNode* dav_xml_createnode_with_text(const char *ns, const char *name, const char *text) {
315 DavXmlNode *node = calloc(1, sizeof(DavXmlNode));
316 node->type = DAV_XML_ELEMENT;
317 node->namespace = strdup(ns);
318 node->name = strdup(name);
320 DavXmlNode *textnode = dav_xml_createtextnode(text);
321 node->children = textnode;
326 DavXmlNode* dav_xml_createtextnode(const char *text) {
327 DavXmlNode *node = calloc(1, sizeof(DavXmlNode));
328 node->type = DAV_XML_TEXT;
329 sstr_t content = sstrdup(sstr((char*)text));
330 node->content = content.ptr;
331 node->contentlength = content.length;
335 void dav_xml_add_child(DavXmlNode *node, DavXmlNode *child) {
336 DavXmlNode *last_child = NULL;
337 DavXmlNode *c = node->children;
343 last_child->next = child;
344 child->prev = last_child;
346 node->children = child;
350 void dav_xml_add_attr(DavXmlNode *node, const char *name, const char *value) {
351 DavXmlAttr *attr = calloc(1, sizeof(DavXmlAttr));
352 attr->name = strdup(name);
353 attr->value = strdup(value);
355 if(node->attributes) {
357 DavXmlAttr *end = node->attributes;
364 node->attributes = attr;
368 char* dav_xml_get_attr(DavXmlNode *node, const char *name) {
369 DavXmlAttr *attr = node->attributes;
371 if(!strcmp(attr->name, name)) {
380 DavXmlNode* dav_parse_xml(DavSession *sn, const char *str, size_t len) {
381 xmlDoc *doc = xmlReadMemory(str, len, NULL, NULL, 0);
385 xmlNode *xml_root = xmlDocGetRootElement(doc);
390 DavXmlNode *x = dav_convert_xml(sn, xml_root);