diff -r 0f94d369bb02 -r 1bcaac272cdf dav/propfind.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dav/propfind.c Fri Nov 30 21:18:13 2012 +0100 @@ -0,0 +1,226 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 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 "utils.h" +#include "propfind.h" + +Propfind* dav_propfind(CURL *handle) { + Propfind *response = malloc(sizeof(Propfind)); + response->resource = NULL; + response->children = NULL; + + curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "PROPFIND"); + + struct curl_slist *headers = NULL; + headers = curl_slist_append(headers, "Content-Type: text/xml"); + curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers); + + UcxBuffer *rqbuf = create_propfind_request_body(); + UcxBuffer *rpbuf = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND); + //printf("request\n%s\n", body->space); + + curl_easy_setopt(handle, CURLOPT_UPLOAD, 1); + curl_easy_setopt(handle, CURLOPT_READFUNCTION, ucx_buffer_read); + curl_easy_setopt(handle, CURLOPT_READDATA, rqbuf); + curl_easy_setopt(handle, CURLOPT_INFILESIZE, rqbuf->size); + + curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, ucx_buffer_write); + curl_easy_setopt(handle, CURLOPT_WRITEDATA, rpbuf); + + ucx_buffer_seek(rqbuf, 0, SEEK_SET); + CURLcode res = curl_easy_perform(handle); + if(res == CURLE_OK) { + //printf("response\n%s\n", rpbuf->space); + + char *url = NULL; + curl_easy_getinfo(handle, CURLINFO_EFFECTIVE_URL, &url); + response->url = util_url_path(url); + + parse_propfind(response, rpbuf); + + response->url = strdup(url); + } + curl_easy_reset(handle); + + return response; +} + +UcxBuffer* create_propfind_request_body() { + UcxBuffer *buf = ucx_buffer_new(NULL, 512, 0); + sstr_t s; + + s = ST("\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + + s = ST("\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + + s = ST("\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + + s = ST("\n\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + + s = ST("\n\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + + s = ST("\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + + s = ST("\n\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + + return buf; +} + +int parse_propfind(Propfind *propfind, UcxBuffer *response) { + xmlTextReaderPtr reader = xmlReaderForMemory( + response->space, + response->size, + propfind->url, + NULL, + 0); + + int ret = 0; + if(reader != NULL) { + int r; + while((r = xmlTextReaderRead(reader)) == 1) { + int nodetype = xmlTextReaderNodeType(reader); + if(nodetype == XML_READER_TYPE_ELEMENT) { + const xmlChar *name = xmlTextReaderConstLocalName(reader); + if(!xmlStrcmp(name, BAD_CAST "response")) { + r = parse_response(reader, propfind); + if(r != 0) { + ret = -1; + break; + } + } + } + } + xmlFreeTextReader(reader); + } + + return ret; +} + +int parse_response(xmlTextReaderPtr reader, Propfind *propfind) { + DavResource *res = calloc(sizeof(DavResource), 1); + if(res == NULL) { + return -1; + } + + /* + * 0: href + * 1: creationdate + * 2: getlastmodified + * 3: getcontentlength + * 4: getcontenttype + * 5: resourcetype + */ + int valuetype = -1; + + int r; + while((r = xmlTextReaderRead(reader)) == 1) { + int nodetype = xmlTextReaderNodeType(reader); + + if(nodetype == XML_READER_TYPE_END_ELEMENT) { + const xmlChar *name = xmlTextReaderConstLocalName(reader); + if(!xmlStrcmp(name, BAD_CAST "response")) { + break; + } + } + + switch(nodetype) { + case XML_READER_TYPE_ELEMENT: { + const xmlChar *name = xmlTextReaderConstLocalName(reader); + if(!xmlStrcmp(name, BAD_CAST "href")) { + valuetype = 0; + } else if(!xmlStrcmp(name, BAD_CAST "creationdate")) { + valuetype = 1; + } else if(!xmlStrcmp(name, BAD_CAST "getlastmodified")) { + valuetype = 2; + } else if(!xmlStrcmp(name, BAD_CAST "getcontentlength")) { + valuetype = 3; + } else if(!xmlStrcmp(name, BAD_CAST "getcontenttype")) { + valuetype = 4; + } else if(!xmlStrcmp(name, BAD_CAST "resourcetype")) { + valuetype = 5; + } else if(!xmlStrcmp(name, BAD_CAST "collection") + && valuetype == 5) { + res->collection = 1; + } else { + valuetype = -1; + } + break; + } + case XML_READER_TYPE_TEXT: { + const xmlChar *cvalue = xmlTextReaderConstValue(reader); + if(cvalue == NULL) { + break; + } + char *value = strdup((char*)cvalue); + switch(valuetype) { + case 0: { + res->href = value; + res->name = util_resource_name(value); + break; + } + case 1: { + res->creationdate = 0; // TODO + break; + } + case 2: { + res->lastmodified = 0; // TODO + break; + } + case 3: { + res->contentlength = atoi(value); + break; + } + case 4: { + res->contenttype = value; + //break; + } + } + //break; + } + } + } + + if(!strcmp(res->href, propfind->url)) { + propfind->resource = res; + } else { + propfind->children = ucx_dlist_append(propfind->children, res); + } + + return 0; +}