libidav/methods.c

changeset 128
649eb328674a
parent 104
6fb4d24d9df9
child 135
664aeaec8d25
--- a/libidav/methods.c	Tue Jun 02 10:07:20 2015 +0200
+++ b/libidav/methods.c	Tue Jun 02 20:57:23 2015 +0200
@@ -225,6 +225,156 @@
     return buf;
 }
 
+PropfindParser* create_propfind_parser(UcxBuffer *response, char *url) {
+    PropfindParser *parser = malloc(sizeof(PropfindParser));
+    if(!parser) {
+        return NULL;
+    }
+    parser->document = xmlReadMemory(response->space, response->size, url, NULL, 0);
+    parser->current = NULL;
+    if(parser->document) {
+        xmlNode *xml_root = xmlDocGetRootElement(parser->document);
+        if(xml_root) {
+            xmlNode *node = xml_root->children;
+            while(node) {
+                // find first response tag
+                if(node->type == XML_ELEMENT_NODE) {
+                    if(xstreq(node->name, "response")) {
+                        parser->current = node;
+                        break;
+                    }
+                }
+                node = node->next;
+            }
+            return parser;
+        } else {
+            xmlFreeDoc(parser->document);
+        }
+    }
+    free(parser);
+    return NULL;
+}
+
+int get_propfind_response(PropfindParser *parser, ResponseTag *result) {
+    if(parser->current == NULL) {
+        return 0;
+    }
+    
+    char *href = NULL;
+    int iscollection = 0;
+    UcxList *properties = NULL; // xmlNode list
+    char *crypto_name = NULL; // name set by crypto-name property
+    char *crypto_key = NULL;
+    
+    xmlNode *node = parser->current->children;
+    while(node) {
+        if(node->type == XML_ELEMENT_NODE) {
+            if(xstreq(node->name, "href")) {
+                xmlNode *href_node = node->children;
+                if(href_node->type != XML_TEXT_NODE) {
+                    // error
+                    return -1;
+                }
+                href = (char*)href_node->content;
+            } else if(xstreq(node->name, "propstat")) {
+                xmlNode *n = node->children;
+                xmlNode *prop_node = NULL;
+                int ok = 0;
+                // get the status code
+                while(n) {
+                    if(n->type == XML_ELEMENT_NODE) {
+                        if(xstreq(n->name, "prop")) {
+                            prop_node = n;
+                        } else if(xstreq(n->name, "status")) {
+                            xmlNode *status_node = n->children;
+                            if(status_node->type != XML_TEXT_NODE) {
+                                // error
+                                return -1;
+                            }
+                            sstr_t status_str = sstr((char*)status_node->content);
+                            if(status_str.length < 13) {
+                                // error
+                                return -1;
+                            }
+                            status_str = sstrsubsl(status_str, 9, 3);
+                            if(!sstrcmp(status_str, S("200"))) {
+                                ok = 1;
+                            }
+                        }
+                    }    
+                    n = n->next;
+                }
+                // if status is ok, get all properties
+                if(ok) {
+                    n = prop_node->children;
+                    while(n) {
+                        if(n->type == XML_ELEMENT_NODE) {
+                            properties = ucx_list_append(properties, n);
+                            if(xstreq(n->name, "resourcetype")) {
+                                xmlNode *rsnode = n->children;
+                                if(rsnode && rsnode->type == XML_ELEMENT_NODE) {
+                                    // TODO: check content
+                                    iscollection = 1;
+                                }
+                            } else if(xstreq(n->ns->href, DAV_NS)) {
+                                if(xstreq(n->name, "crypto-name")) {
+                                    crypto_name = util_xml_get_text(n);
+                                } else if(xstreq(n->name, "crypto-key")) {
+                                    crypto_key = util_xml_get_text(n);
+                                }
+                            }
+                        }
+                        n = n->next;
+                    }
+                }
+            }
+        }
+        node = node->next;
+    }
+    
+    result->href = href;
+    result->iscollection = iscollection;
+    result->properties = properties;
+    result->crypto_name = crypto_name;
+    result->crypto_key = crypto_key;
+    
+    // find next response tag
+    xmlNode *next = parser->current->next;
+    while(next) {
+        if(next->type == XML_ELEMENT_NODE) {
+            if(xstreq(next->name, "response")) {
+                break;
+            }
+        }
+        next = next->next;
+    }
+    parser->current = next;
+    
+    return 1;
+}
+
+int hrefeq(DavSession *sn, char *href1, char *href2) {
+    sstr_t href_s = sstr(util_url_decode(sn, href1));
+    sstr_t href_r = sstr(util_url_decode(sn, href2));
+    int ret = 0;
+    if(!sstrcmp(href_s, href_r)) {
+        ret = 1;
+    } else if(href_s.length == href_r.length + 1) {
+        if(href_s.ptr[href_s.length-1] == '/') {
+            href_s.length--;
+            if(!sstrcmp(href_s, href_r)) {
+                ret = 1;
+            }
+        }
+    }
+
+    free(href_s.ptr);
+    free(href_r.ptr);
+    
+    return ret;
+}
+
+
 DavResource* parse_propfind_response(DavSession *sn, DavResource *root, UcxBuffer *response, DavQOp *cond, size_t len) {
     char *url = NULL;
     curl_easy_getinfo(sn->handle, CURLINFO_EFFECTIVE_URL, &url);
@@ -256,6 +406,63 @@
     return root;
 }
 
+DavResource* response2resource(DavSession *sn, ResponseTag *response, char *parent_path) {
+    // create resource
+    char *name = NULL;
+    if(DAV_DECRYPT_NAME(sn) && response->crypto_name) {
+        if(!response->crypto_key) {
+            // TODO: error
+            fprintf(stderr, "encrypted resource without key\n");
+            return NULL;
+        }
+        name = util_decrypt_str(sn, response->crypto_name, response->crypto_key);
+        if(!name) {
+            // TODO: error
+            fprintf(stderr, "decrypted name is null\n");
+            return NULL;
+        }
+    } else {
+        sstr_t resname = sstr(util_resource_name(response->href));
+        int nlen = 0;
+        char *uname = curl_easy_unescape(
+                sn->handle,
+                resname.ptr,
+                resname.length,
+                &nlen);
+        name = dav_session_strdup(sn, uname);
+        curl_free(uname);
+    }
+
+    char *href = dav_session_strdup(sn, href);
+    DavResource *res = NULL;
+    if(parent_path) {
+        res = dav_resource_new_full(sn, parent_path, name, href);
+    } else {
+        res = dav_resource_new_href(sn, href);
+    }
+    dav_session_free(sn, name);
+    
+    add_properties(res, response); 
+    return res;
+}
+
+void add_properties(DavResource *res, ResponseTag *response) {
+    res->iscollection = response->iscollection;
+    
+    // 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);
+        }
+    }
+    
+    set_davprops(res);
+}
+
 int parse_response_tag(DavResource *resource, xmlNode *node, DavQOp *cond, size_t clen) {
     DavSession *sn = resource->session;
     

mercurial