# HG changeset patch # User Olaf Wintermann # Date 1508669887 -7200 # Node ID 9ca1e4706acca16e131be16c6cb1f7def508cb24 # Parent 54819e984a19629fe1077e4b9f6e57d52e4b8d52 adds initial support for xml properties in libidav diff -r 54819e984a19 -r 9ca1e4706acc dav/main.c --- a/dav/main.c Thu Oct 12 20:37:46 2017 +0200 +++ b/dav/main.c Sun Oct 22 12:58:07 2017 +0200 @@ -550,7 +550,7 @@ flags[0] = 'd'; type = ""; } - char *keyprop = dav_get_property_ns( + char *keyprop = dav_get_string_property_ns( res, DAV_NS, "crypto-key"); @@ -560,10 +560,10 @@ if(cmd_getoption(a, "extended")) { flags[6] = '\0'; - if(dav_get_property(res, "D:lockdiscovery")) { + if(dav_get_string_property(res, "D:lockdiscovery")) { flags[2] = 'l'; } - char *executable = dav_get_property_ns( + char *executable = dav_get_string_property_ns( res, "http://apache.org/dav/props/", "executable"); @@ -1216,7 +1216,9 @@ break; } - char *value = dav_get_property_ns(res, propname.ns, propname.name); + // TODO: show xml + //DavXmlNode *x = dav_get_property_ns(res, propname.ns, propname.name); + char *value = dav_get_string_property_ns(res, propname.ns, propname.name); if(!value) { fprintf(stderr, "Error: no property value.\n"); return -1; @@ -1511,7 +1513,7 @@ last_ns = p.ns; } - sstr_t value = sstr(dav_get_property_ns(res, p.ns, p.name)); + sstr_t value = sstr(dav_get_string_property_ns(res, p.ns, p.name)); value = sstrtrim(value); printf(" %s: %.*s\n", p.name, (int)value.length, value.ptr); } diff -r 54819e984a19 -r 9ca1e4706acc dav/sync.c --- a/dav/sync.c Thu Oct 12 20:37:46 2017 +0200 +++ b/dav/sync.c Sun Oct 22 12:58:07 2017 +0200 @@ -376,7 +376,7 @@ continue; } - char *status = dav_get_property(res, "idav:status"); + char *status = dav_get_string_property(res, "idav:status"); if(status && !strcmp(status, "broken")) { res = res->next; continue; @@ -498,7 +498,7 @@ LocalResource *local = ucx_map_cstr_get(db->resources, res->path); char *local_path = util_concat_path(dir->path, res->path); - char *etag = dav_get_property(res, "D:getetag"); + char *etag = dav_get_string_property(res, "D:getetag"); struct stat s; memset(&s, 0, sizeof(struct stat)); if(local && !res->iscollection) { @@ -1180,7 +1180,7 @@ DavResource *remote = dav_get(sn, res->path, "D:getetag"); int ret = 0; if(remote) { - char *etag = dav_get_property(remote, "D:getetag"); + char *etag = dav_get_string_property(remote, "D:getetag"); if(!res->etag) { // the resource is on the server and the client has no etag ret = 1; @@ -1274,7 +1274,7 @@ sync_set_status(res, "broken"); } else { // everything seems fine, we can update the local resource - char *etag = dav_get_property(up_res, "D:getetag"); + char *etag = dav_get_string_property(up_res, "D:getetag"); if(etag) { if(strlen(etag) > 2 && etag[0] == 'W' && etag[1] == '/') { etag = etag + 2; @@ -1291,7 +1291,7 @@ local->etag = NULL; } - if(dav_get_property(up_res, "idav:status")) { + if(dav_get_string_property(up_res, "idav:status")) { sync_remove_status(up_res); } @@ -1340,7 +1340,7 @@ fprintf(stderr, "Cannot delete resource %s\n", res->path); } } else { - char *etag = dav_get_property(res, "D:getetag"); + char *etag = dav_get_string_property(res, "D:getetag"); if(etag) { if(strlen(etag) > 2 && etag[0] == 'W' && etag[1] == '/') { etag = etag + 2; diff -r 54819e984a19 -r 9ca1e4706acc docs/src/index.html --- a/docs/src/index.html Thu Oct 12 20:37:46 2017 +0200 +++ b/docs/src/index.html Sun Oct 22 12:58:07 2017 +0200 @@ -28,6 +28,7 @@
  • move
  • get-property
  • set-property
  • +
  • remove-property
  • lock
  • unlock
  • info
  • diff -r 54819e984a19 -r 9ca1e4706acc libidav/Makefile --- a/libidav/Makefile Thu Oct 12 20:37:46 2017 +0200 +++ b/libidav/Makefile Sun Oct 22 12:58:07 2017 +0200 @@ -39,6 +39,7 @@ SRC += davqlparser.c SRC += davqlexec.c SRC += crypto.c +SRC += xml.c OBJ = $(SRC:%.c=../build/libidav/%$(OBJ_EXT)) diff -r 54819e984a19 -r 9ca1e4706acc libidav/davqlexec.c --- a/libidav/davqlexec.c Thu Oct 12 20:37:46 2017 +0200 +++ b/libidav/davqlexec.c Sun Oct 22 12:58:07 2017 +0200 @@ -1056,7 +1056,7 @@ } case DAVQL_CMD_PROP_IDENTIFIER: { //printf("property %s:%s\n", cmd.data.property.ns, cmd.data.property.name); - char *value = dav_get_property_ns(res, cmd.data.property.ns, cmd.data.property.name); + char *value = dav_get_string_property_ns(res, cmd.data.property.ns, cmd.data.property.name); obj.type = 1; obj.length = value ? strlen(value) : 0; obj.data.string = value; diff -r 54819e984a19 -r 9ca1e4706acc libidav/methods.c --- a/libidav/methods.c Thu Oct 12 20:37:46 2017 +0200 +++ b/libidav/methods.c Sun Oct 22 12:58:07 2017 +0200 @@ -34,6 +34,7 @@ #include "methods.h" #include "crypto.h" #include "session.h" +#include "xml.h" #include @@ -107,7 +108,7 @@ util_capture_header(handle, NULL); ucx_map_free_content(respheaders, free); ucx_map_free(respheaders); - + return ret; } @@ -530,12 +531,7 @@ // add properties UCX_FOREACH(elm, response->properties) { xmlNode *prop = elm->data; - - // TODO: add xml data instead of a string - char *text = util_xml_get_text(prop); - if(text) { - resource_add_property(res, (char*)prop->ns->href, (char*)prop->name, text); - } + resource_add_property(res, (char*)prop->ns->href, (char*)prop->name, prop->children); } set_davprops(res); @@ -667,12 +663,7 @@ // add properties UCX_FOREACH(elm, properties) { xmlNode *prop = elm->data; - - // TODO: add xml data instead of a string - char *text = util_xml_get_text(prop); - if(text) { - resource_add_property(res, (char*)prop->ns->href, (char*)prop->name, text); - } + resource_add_property(res, (char*)prop->ns->href, (char*)prop->name, prop->children); } ucx_list_free(properties); @@ -685,10 +676,10 @@ } void set_davprops(DavResource *res) { - char *cl = dav_get_property_ns(res, "DAV:", "getcontentlength"); - char *ct = dav_get_property_ns(res, "DAV:", "getcontenttype"); - char *cd = dav_get_property_ns(res, "DAV:", "creationdate"); - char *lm = dav_get_property_ns(res, "DAV:", "getlastmodified"); + char *cl = dav_get_string_property_ns(res, "DAV:", "getcontentlength"); + char *ct = dav_get_string_property_ns(res, "DAV:", "getcontenttype"); + char *cd = dav_get_string_property_ns(res, "DAV:", "creationdate"); + char *lm = dav_get_string_property_ns(res, "DAV:", "getlastmodified"); res->contenttype = ct; if(cl) { @@ -807,6 +798,7 @@ prefix = "D"; } + // begin tag s = S("<"); ucx_buffer_write(s.ptr, 1, s.length, buf); s = sstr(prefix); @@ -817,8 +809,16 @@ ucx_buffer_write(s.ptr, 1, s.length, buf); s = S(">"); ucx_buffer_write(s.ptr, 1, s.length, buf); - s = sstr(property->value); - ucx_buffer_write(s.ptr, 1, s.length, buf); + + // content + DavXmlNode *content = property->value; + if(content->type == DAV_XML_TEXT) { + ucx_buffer_write(content->content, 1, content->contentlength, buf); + } else { + // TODO: implement + } + + // end tag s = S("href; } -void resource_add_property(DavResource *res, char *ns, char *name, char *val) { +void resource_add_property(DavResource *res, char *ns, char *name, xmlNode *val) { if(!val) { return; } UcxKey key = dav_property_key(ns, name); - sstr_t v = sstrdup_a(res->session->mp->allocator, sstr(val)); - ucx_map_put(((DavResourceData*)res->data)->properties, key, v.ptr); + DavXmlNode *v = dav_convert_xml(res->session, val); + ucx_map_put(((DavResourceData*)res->data)->properties, key, v); free(key.data); } -char* resource_get_property(DavResource *res, char *ns, char *name) { +void resource_add_string_property(DavResource *res, char *ns, char *name, char *val) { + if(!val) { + return; + } + UcxKey key = dav_property_key(ns, name); - char *property = resource_get_property_k(res, key); + DavXmlNode *v = dav_text_node(res->session, val); + ucx_map_put(((DavResourceData*)res->data)->properties, key, v); + free(key.data); +} + +DavXmlNode* resource_get_property(DavResource *res, char *ns, char *name) { + UcxKey key = dav_property_key(ns, name); + DavXmlNode *property = resource_get_property_k(res, key); free(key.data); return property; } -char* resource_get_property_k(DavResource *res, UcxKey key) { +DavXmlNode* resource_get_property_k(DavResource *res, UcxKey key) { DavResourceData *data = (DavResourceData*)res->data; return ucx_map_get(data->properties, key); } @@ -339,8 +351,10 @@ default: ret = 0; } } else if(cr->type == 1) { - char *value1 = resource_get_property_k(res1, cr->column.property); - char *value2 = resource_get_property_k(res2, cr->column.property); + DavXmlNode *xvalue1 = resource_get_property_k(res1, cr->column.property); + DavXmlNode *xvalue2 = resource_get_property_k(res2, cr->column.property); + char *value1 = dav_xml_getstring(xvalue1); + char *value2 = dav_xml_getstring(xvalue2); if(!value1) { ret = value2 ? -1 : 0; } else if(!value2) { @@ -403,7 +417,25 @@ } } -char* dav_get_property(DavResource *res, char *name) { +char* dav_get_string_property(DavResource *res, char *name) { + char *pns; + char *pname; + dav_get_property_namespace_str(res->session->context, name, &pns, &pname); + if(!pns || !pname) { + return NULL; + } + return dav_get_string_property_ns(res, pns, pname); +} + +char* dav_get_string_property_ns(DavResource *res, char *ns, char *name) { + DavXmlNode *prop = dav_get_property_ns(res, ns, name); + if(!prop) { + return NULL; + } + return dav_xml_getstring(prop); +} + +DavXmlNode* dav_get_property(DavResource *res, char *name) { char *pns; char *pname; dav_get_property_namespace_str(res->session->context, name, &pns, &pname); @@ -413,11 +445,11 @@ return dav_get_property_ns(res, pns, pname); } -char* dav_get_property_ns(DavResource *res, char *ns, char *name) { +DavXmlNode* dav_get_property_ns(DavResource *res, char *ns, char *name) { if(!ns || !name) { return NULL; } - char *property = resource_get_property(res, ns, name); + DavXmlNode *property = resource_get_property(res, ns, name); DavResourceData *data = res->data; // resource_get_property only returns persistent properties // check the remove and set list @@ -435,7 +467,7 @@ UCX_FOREACH(elm, data->set) { DavProperty *p = elm->data; if(!strcmp(p->name, name) && !strcmp(p->ns->name, ns)) { - return p->value; + return p->value; // TODO: fix } } // no property update @@ -457,7 +489,7 @@ res->session, sizeof(DavProperty)); property->name = dav_session_strdup(res->session, name); - property->value = dav_session_strdup(res->session, value); + property->value = dav_text_node(res->session, value); DavNamespace *namespace = dav_session_malloc( res->session, @@ -646,7 +678,7 @@ free(enc_hash); return 1; } - resource_add_property(res, DAV_NS, "crypto-hash", enc_hash); + resource_add_string_property(res, DAV_NS, "crypto-hash", enc_hash); free(enc_hash); } else { ret = do_put_request( @@ -713,7 +745,7 @@ AESDecrypter *dec = NULL; DavKey *key = NULL; if(DAV_DECRYPT_CONTENT(sn)) { - char *keyname = dav_get_property_ns(res, DAV_NS, "crypto-key"); + char *keyname = dav_get_string_property_ns(res, DAV_NS, "crypto-key"); if(keyname) { key = dav_context_get_key(sn->context, keyname); if(key) { @@ -752,7 +784,7 @@ int verify_failed = 0; if(DAV_DECRYPT_CONTENT(sn) && key) { // try to verify the content - char *res_hash = dav_get_property_ns(res, DAV_NS, "crypto-hash"); + char *res_hash = dav_get_string_property_ns(res, DAV_NS, "crypto-hash"); if(res_hash) { size_t len = 0; diff -r 54819e984a19 -r 9ca1e4706acc libidav/resource.h --- a/libidav/resource.h Thu Oct 12 20:37:46 2017 +0200 +++ b/libidav/resource.h Sun Oct 22 12:58:07 2017 +0200 @@ -70,9 +70,9 @@ void resource_set_info(DavResource *res, char *href_str); DavResourceData* resource_data_new(DavSession *sn); -void resource_add_property(DavResource *res, char *ns, char *name, char *val); -char* resource_get_property(DavResource *res, char *ns, char *name); -char* resource_get_property_k(DavResource *res, UcxKey key); +void resource_add_property(DavResource *res, char *ns, char *name, xmlNode *val); +DavXmlNode* resource_get_property(DavResource *res, char *ns, char *name); +DavXmlNode* resource_get_property_k(DavResource *res, UcxKey key); void resource_add_child(DavResource *parent, DavResource *child); void resource_add_ordered_child(DavResource *parent, DavResource *child, UcxList *ordercr); int resource_add_crypto_info(DavSession *sn, char *href, char *name, char *hash); diff -r 54819e984a19 -r 9ca1e4706acc libidav/webdav.h --- a/libidav/webdav.h Thu Oct 12 20:37:46 2017 +0200 +++ b/libidav/webdav.h Sun Oct 22 12:58:07 2017 +0200 @@ -53,11 +53,12 @@ typedef struct DavProxy DavProxy; typedef struct DavSession DavSession; typedef struct DavResource DavResource; -typedef struct DavResult DavResult; +typedef struct DavResult DavResult; typedef struct DavNamespace DavNamespace; typedef struct DavProperty DavProperty; typedef struct DavPropName DavPropName; typedef struct DavKey DavKey; +typedef struct DavXmlNode DavXmlNode; typedef size_t(*dav_read_func)(void*, size_t, size_t, void*); typedef size_t(*dav_write_func)(const void*, size_t, size_t, void*); @@ -87,6 +88,14 @@ typedef enum DavError DavError; +enum DavXmlNodeType { + DAV_XML_NONE = 0, + DAV_XML_ELEMENT, + DAV_XML_TEXT +}; + +typedef enum DavXmlNodeType DavXmlNodeType; + #define DAV_SESSION_ENCRYPT_CONTENT 0x0001 #define DAV_SESSION_ENCRYPT_NAME 0x0002 #define DAV_SESSION_DECRYPT_CONTENT 0x0004 @@ -151,7 +160,7 @@ struct DavProperty { DavNamespace *ns; char *name; - char *value; + DavXmlNode *value; }; struct DavPropName { @@ -174,6 +183,23 @@ size_t length; }; +struct DavXmlNode { + DavXmlNodeType type; + + char *namespace; + char *name; + + DavXmlNode *prev; + DavXmlNode *next; + DavXmlNode *children; + DavXmlNode *parent; + + // TODO: attributes + + char *content; + size_t contentlength; +}; + DavContext* dav_context_new(); void dav_context_destroy(DavContext *ctx); @@ -245,8 +271,10 @@ int dav_lock_t(DavResource *res, time_t timeout); int dav_unlock(DavResource *res); -char* dav_get_property(DavResource *res, char *name); -char* dav_get_property_ns(DavResource *res, char *ns, char *name); +DavXmlNode* dav_get_property(DavResource *res, char *name); +DavXmlNode* dav_get_property_ns(DavResource *res, char *ns, char *name); +char* dav_get_string_property(DavResource *res, char *name); +char* dav_get_string_property_ns(DavResource *res, char *ns, char *name); void dav_set_property(DavResource *res, char *name, char *value); void dav_set_property_ns(DavResource *res, char *ns, char *name, char *value); void dav_remove_property(DavResource *res, char *name); @@ -266,6 +294,9 @@ // private int dav_propfind(DavSession *sn, DavResource *root, UcxBuffer *rqbuf); +char* dav_xml_getstring(DavXmlNode *node); +DavXmlNode* dav_text_node(DavSession *sn, char *text); + #ifdef __cplusplus } #endif 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; +} + diff -r 54819e984a19 -r 9ca1e4706acc libidav/xml.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libidav/xml.h Sun Oct 22 12:58:07 2017 +0200 @@ -0,0 +1,47 @@ +/* + * 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. + */ +#ifndef DAV_XML_H +#define DAV_XML_H + +#include "webdav.h" + +#ifdef __cplusplus +extern "C" { +#endif + +DavXmlNode* dav_convert_xml(DavSession *sn, xmlNode *node); + +void dav_print_xml(DavXmlNode *node); + + +#ifdef __cplusplus +} +#endif + +#endif /* DAV_XML_H */ +