libidav/xml.c

Thu, 14 Dec 2017 13:35:03 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Thu, 14 Dec 2017 13:35:03 +0100
changeset 346
3e20fd78e555
parent 338
c7f3fe4abdb2
child 361
b6f2462ee055
permissions
-rw-r--r--

fixes missing string terminator when printing simplified xml (dav get-property)

/*
 * 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 <stdio.h>
#include <stdlib.h>
#include <string.h>

#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("</%s>", 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;
    }
}

DavBool dav_xml_isstring(DavXmlNode *node) {
    if(node && node->type == DAV_XML_TEXT && !node->next) {
        return TRUE;
    } else {
        return FALSE;
    }
}

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;
}

mercurial