dav get-property supports xml property output

Sun, 03 Dec 2017 13:09:14 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 03 Dec 2017 13:09:14 +0100
changeset 338
c7f3fe4abdb2
parent 337
d7bda914d120
child 344
72791e299d64

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

mercurial