# HG changeset patch # User Olaf Wintermann # Date 1512302954 -3600 # Node ID c7f3fe4abdb23420dcf888880afab81758fb8449 # Parent d7bda914d1201d0554ae95120d73b50de716e77d dav get-property supports xml property output diff -r d7bda914d120 -r c7f3fe4abdb2 dav/main.c --- a/dav/main.c Sun Dec 03 10:17:15 2017 +0100 +++ b/dav/main.c Sun Dec 03 13:09:14 2017 +0100 @@ -163,8 +163,8 @@ "remove [-pc] [-L ] ", "copy [-pcO] [-L ] ", "move [-pcO] [-L ] ", - "get-property [-pc] [-n ] ", - "set-property [-pc] [-L ] [-n ] [value]", + "get-property [-pcx] [-n ] ", + "set-property [-pcx] [-L ] [-n ] [value]", "remove-property [-pc] [-n ] ", "lock [-pc] [-T timeout] ", "unlock [-pc] [-L ] ", @@ -222,6 +222,7 @@ fprintf(stderr, " -L specificy lock token\n"); fprintf(stderr, " -T timeout in seconds\n"); fprintf(stderr, " -n specify namespace uri\n"); + fprintf(stderr, " -x xml property content\n"); fprintf(stderr, " -N disable authentication prompt (all commands)\n"); fprintf(stderr, " -i disable cert verification (all commands)\n"); fprintf(stderr, " -v verbose output (all commands)\n"); @@ -1435,26 +1436,30 @@ } break; } + free(path); - // 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) { + DavXmlNode *x = dav_get_property_ns(res, propname.ns, propname.name); + if(!x) { fprintf(stderr, "Error: no property value.\n"); return -1; } - int ret = 0; - if(value) { - printf("%s\n", value); + if(cmd_getoption(a, "xml")) { + // print a real xml document on stdout + printxmldoc(stdout, propname.name, propname.ns, x); } else { - // TODO: correct error message - fprintf(stderr, "Error: property not found.\n"); - ret = -1; + // in this mode a simple string is printed on stdout + // or simplified and nicely formatted xml is printed on stderr + if(dav_xml_isstring(x)) { + printf("%s\n", dav_xml_getstring(x)); + } else { + char *str = xml2str(x); + fprintf(stderr, "%s", str); + free(str); + } } - free(path); - return ret; + return 0; } int cmd_set_property(CmdArgs *a) { @@ -1737,10 +1742,14 @@ printf("\nnamespace: %s\n", p.ns); last_ns = p.ns; } - - 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); + + DavXmlNode *xval = dav_get_property_ns(res, p.ns, p.name); + if(dav_xml_isstring(xval)) { + sstr_t value = sstr(dav_xml_getstring(xval)); + printf(" %s: %.*s\n", p.name, (int)value.length, value.ptr); + } else { + printf(" %s: $xml\n", p.name); + } } dav_session_free(sn, properties); @@ -1771,6 +1780,100 @@ } } +static void xml2str_i(DavXmlNode *node, UcxBuffer *buf, int indent) { + while(node) { + if(node->type == DAV_XML_ELEMENT) { + if(node->children) { + if(dav_xml_isstring(node->children)) { + sstr_t s = sstrtrim(sstr(dav_xml_getstring(node->children))); + ucx_bprintf( + buf, + "%*s<%s>%.*s\n", + indent, + "", + node->name, + (int)s.length, + s.ptr, + node->name); + } else { + ucx_bprintf(buf, "%*s<%s>\n", indent, "", node->name); + xml2str_i(node->children, buf, indent+2); + ucx_bprintf(buf, "%*s\n", indent, "", node->name); + } + } else { + ucx_bprintf(buf, "%*s<%s />", indent, "", node->name); + ucx_buffer_putc(buf, '\n'); + } + } else if(node->type == DAV_XML_TEXT) { + sstr_t val = sstrtrim(sstrn(node->content, node->contentlength)); + if(val.length > 0) { + ucx_bprintf(buf, "%*.*s", indent, (int)val.length, val.ptr); + } + } + + node = node->next; + } +} + +char* xml2str(DavXmlNode *node) { + char *str = malloc(256); + UcxBuffer *buf = ucx_buffer_new(str, 256, UCX_BUFFER_AUTOEXTEND); + xml2str_i(node, buf, 0); + char *space = buf->space; + ucx_buffer_free(buf); + return space; +} + +static void printnode(FILE *out, UcxMap *nsmap, DavXmlNode *node) { + while(node) { + if(node->type == DAV_XML_ELEMENT) { + char *prefix = ucx_map_cstr_get(nsmap, node->namespace); + char *freethis = NULL; + char *tagend = node->children ? ">" : " />"; + if(!prefix) { + sstr_t newpre = ucx_sprintf("x%d", (int)nsmap->count); + ucx_map_cstr_put(nsmap, node->namespace, newpre.ptr); + freethis = newpre.ptr; + prefix = newpre.ptr; + fprintf( + out, + "<%s:%s xmlns:%s=\"%s\"%s", + prefix, + node->name, + prefix, + node->namespace, + tagend); + } else { + fprintf(out, "<%s:%s%s", prefix, node->name, tagend); + } + + if(node->children) { + printnode(out, nsmap, node->children); + fprintf(out, "", prefix, node->name); + } + if(freethis) { + free(freethis); + } + } else if(node->type == DAV_XML_TEXT) { + fwrite(node->content, 1, node->contentlength, out); + } + + node = node->next; + } +} + +void printxmldoc(FILE *out, char *root, char *rootns, DavXmlNode *content) { + UcxMap *nsmap = ucx_map_new(16); + + ucx_map_cstr_put(nsmap, rootns, "x0"); + fprintf(out, "%s", "\n"); + fprintf(out, "", root, rootns); + + printnode(out, nsmap, content); + + fprintf(out, "\n", root); +} + /* ---------- config commands ---------- */ diff -r d7bda914d120 -r c7f3fe4abdb2 dav/main.h --- a/dav/main.h Sun Dec 03 10:17:15 2017 +0100 +++ b/dav/main.h Sun Dec 03 13:09:14 2017 +0100 @@ -81,6 +81,8 @@ int cmd_info(CmdArgs *args); char* stdin2str(); +char* xml2str(DavXmlNode *node); +void printxmldoc(FILE *out, char *root, char *rootns, DavXmlNode *content); int cmd_add_repository(CmdArgs *args); diff -r d7bda914d120 -r c7f3fe4abdb2 dav/optparser.c --- a/dav/optparser.c Sun Dec 03 10:17:15 2017 +0100 +++ b/dav/optparser.c Sun Dec 03 13:09:14 2017 +0100 @@ -123,6 +123,10 @@ ucx_map_cstr_put(a->options, "extended", NOARG); break; } + case 'x': { + ucx_map_cstr_put(a->options, "xml", NOARG); + break; + } case 'S': { // undocumented hidden feature ucx_map_cstr_put(a->options, "structure", NOARG); diff -r d7bda914d120 -r c7f3fe4abdb2 libidav/webdav.h --- a/libidav/webdav.h Sun Dec 03 10:17:15 2017 +0100 +++ b/libidav/webdav.h Sun Dec 03 13:09:14 2017 +0100 @@ -295,6 +295,7 @@ int dav_propfind(DavSession *sn, DavResource *root, UcxBuffer *rqbuf); char* dav_xml_getstring(DavXmlNode *node); +DavBool dav_xml_isstring(DavXmlNode *node); DavXmlNode* dav_text_node(DavSession *sn, char *text); #ifdef __cplusplus diff -r d7bda914d120 -r c7f3fe4abdb2 libidav/xml.c --- a/libidav/xml.c Sun Dec 03 10:17:15 2017 +0100 +++ b/libidav/xml.c Sun Dec 03 13:09:14 2017 +0100 @@ -145,6 +145,14 @@ } } +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));