Sun, 03 Dec 2017 13:09:14 +0100
dav get-property supports xml property output
dav/main.c | file | annotate | diff | comparison | revisions | |
dav/main.h | file | annotate | diff | comparison | revisions | |
dav/optparser.c | file | annotate | diff | comparison | revisions | |
libidav/webdav.h | file | annotate | diff | comparison | revisions | |
libidav/xml.c | file | annotate | diff | comparison | revisions |
--- 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 <lock>] <url>", "copy [-pcO] [-L <lock>] <url> <url>", "move [-pcO] [-L <lock>] <url> <url>", - "get-property [-pc] [-n <uri>] <url> <property>", - "set-property [-pc] [-L <lock>] [-n <uri>] <url> <property> [value]", + "get-property [-pcx] [-n <uri>] <url> <property>", + "set-property [-pcx] [-L <lock>] [-n <uri>] <url> <property> [value]", "remove-property [-pc] [-n <uri>] <url> <property>", "lock [-pc] [-T timeout] <url>", "unlock [-pc] [-L <lock>] <url>", @@ -222,6 +222,7 @@ fprintf(stderr, " -L <lock> specificy lock token\n"); fprintf(stderr, " -T <sec> timeout in seconds\n"); fprintf(stderr, " -n <uri> 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</%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</%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, "</%s:%s>", 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", "<?xml version=\"1.0\"?>\n"); + fprintf(out, "<x0:%s xmlns:x0=\"%s\">", root, rootns); + + printnode(out, nsmap, content); + + fprintf(out, "</x0:%s>\n", root); +} + /* ---------- config commands ---------- */
--- 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);
--- 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);
--- 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
--- 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));