Fri, 30 Nov 2012 21:18:13 +0100
added existing source code
/* * 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 <stdio.h> #include <stdlib.h> #include <string.h> #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("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"); ucx_buffer_write(s.ptr, 1, s.length, buf); s = ST("<D:propfind xmlns:D=\"DAV:\">\n"); ucx_buffer_write(s.ptr, 1, s.length, buf); s = ST("<D:prop>\n"); ucx_buffer_write(s.ptr, 1, s.length, buf); s = ST("<D:creationdate />\n<D:getlastmodified />\n"); ucx_buffer_write(s.ptr, 1, s.length, buf); s = ST("<D:getcontentlength />\n<D:getcontenttype />\n"); ucx_buffer_write(s.ptr, 1, s.length, buf); s = ST("<D:resourcetype />\n"); ucx_buffer_write(s.ptr, 1, s.length, buf); s = ST("</D:prop>\n</D:propfind>\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; }