libidav/webdav.c

changeset 747
efbd59642577
parent 645
ad61c1654dce
child 786
f9d6e4cbcb62
equal deleted inserted replaced
746:a569148841ff 747:efbd59642577
33 33
34 #include "utils.h" 34 #include "utils.h"
35 #include "webdav.h" 35 #include "webdav.h"
36 #include "session.h" 36 #include "session.h"
37 #include "methods.h" 37 #include "methods.h"
38 #include "ucx/buffer.h" 38 #include <cx/buffer.h>
39 #include "ucx/utils.h" 39 #include <cx/utils.h>
40 #include <cx/linked_list.h>
41 #include <cx/hash_map.h>
42 #include <cx/compare.h>
40 #include "davqlparser.h" 43 #include "davqlparser.h"
41 #include "davqlexec.h" 44 #include "davqlexec.h"
42 45
43 46
44 DavContext* dav_context_new(void) { 47 DavContext* dav_context_new(void) {
45 // initialize 48 // initialize
46 DavContext *context = calloc(1, sizeof(DavContext)); 49 DavContext *context = calloc(1, sizeof(DavContext));
47 if(!context) { 50 if(!context) {
48 return NULL; 51 return NULL;
49 } 52 }
50 context->sessions = NULL; 53 context->sessions = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_intptr, CX_STORE_POINTERS);
51 context->http_proxy = calloc(1, sizeof(DavProxy)); 54 context->http_proxy = calloc(1, sizeof(DavProxy));
52 if(!context->http_proxy) { 55 if(!context->http_proxy) {
53 dav_context_destroy(context); 56 dav_context_destroy(context);
54 return NULL; 57 return NULL;
55 } 58 }
56 context->https_proxy = calloc(1, sizeof(DavProxy)); 59 context->https_proxy = calloc(1, sizeof(DavProxy));
57 if(!context->https_proxy) { 60 if(!context->https_proxy) {
58 dav_context_destroy(context); 61 dav_context_destroy(context);
59 return NULL; 62 return NULL;
60 } 63 }
61 context->namespaces = ucx_map_new(16); 64 context->namespaces = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, 16);
62 if(!context->namespaces) { 65 if(!context->namespaces) {
63 dav_context_destroy(context); 66 dav_context_destroy(context);
64 return NULL; 67 return NULL;
65 } 68 }
66 context->namespaceinfo = ucx_map_new(16); 69 context->namespaceinfo = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, 16);
67 if(!context->namespaceinfo) { 70 if(!context->namespaceinfo) {
68 dav_context_destroy(context); 71 dav_context_destroy(context);
69 } 72 }
70 context->keys = ucx_map_new(16); 73 context->keys = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, 16);
71 if(!context->keys) { 74 if(!context->keys) {
72 dav_context_destroy(context); 75 dav_context_destroy(context);
73 return NULL; 76 return NULL;
74 } 77 }
75 78
95 return context; 98 return context;
96 } 99 }
97 100
98 void dav_context_destroy(DavContext *ctx) { 101 void dav_context_destroy(DavContext *ctx) {
99 // destroy all sessions assoziated with this context 102 // destroy all sessions assoziated with this context
100 UcxList *elm = ctx->sessions; 103 CxIterator i = cxListIterator(ctx->sessions);
101 while(elm) { 104 cx_foreach(DavSession*, sn, i) {
102 DavSession *sn = elm->data;
103 elm = elm->next;
104 dav_session_destroy(sn); 105 dav_session_destroy(sn);
105 } 106 }
107 cxListDestroy(ctx->sessions);
106 if(ctx->http_proxy) { 108 if(ctx->http_proxy) {
107 free(ctx->http_proxy); 109 free(ctx->http_proxy);
108 } 110 }
109 if(ctx->https_proxy) { 111 if(ctx->https_proxy) {
110 free(ctx->https_proxy); 112 free(ctx->https_proxy);
111 } 113 }
112 114
113 if(ctx->namespaces) { 115 if(ctx->namespaces) {
114 UcxMapIterator i = ucx_map_iterator(ctx->namespaces); 116 i = cxMapIteratorValues(ctx->namespaces);
115 UcxKey k; 117 cx_foreach(DavNamespace*, ns, i) {
116 DavNamespace *ns;
117 UCX_MAP_FOREACH(k, ns, i) {
118 if(!ns) continue; 118 if(!ns) continue;
119 if(ns->prefix) { 119 if(ns->prefix) {
120 free(ns->prefix); 120 free(ns->prefix);
121 } 121 }
122 if(ns->name) { 122 if(ns->name) {
123 free(ns->name); 123 free(ns->name);
124 } 124 }
125 free(ns); 125 free(ns);
126 } 126 }
127 ucx_map_free(ctx->namespaces); 127 cxMapDestroy(ctx->namespaces);
128 } 128 }
129 if(ctx->namespaceinfo) { 129 if(ctx->namespaceinfo) {
130 // TODO: implement 130 // TODO: implement
131 } 131 }
132 if(ctx->keys) { 132 if(ctx->keys) {
133 UcxMapIterator i = ucx_map_iterator(ctx->keys); 133 i = cxMapIteratorValues(ctx->keys);
134 UcxKey k; 134 cx_foreach(DavKey*, key, i) {
135 DavKey *key;
136 UCX_MAP_FOREACH(k, key, i) {
137 if(!key) continue; 135 if(!key) continue;
138 if(key->name) { 136 if(key->name) {
139 free(key->name); 137 free(key->name);
140 } 138 }
141 if(key->data) { 139 if(key->data) {
142 free(key->data); 140 free(key->data);
143 } 141 }
144 free(key); 142 free(key);
145 } 143 }
146 ucx_map_free(ctx->keys); 144 cxMapDestroy(ctx->keys);
147 } 145 }
148 146
149 free(ctx); 147 free(ctx);
150 } 148 }
151 149
152 void dav_context_add_key(DavContext *context, DavKey *key) { 150 void dav_context_add_key(DavContext *context, DavKey *key) {
153 ucx_map_cstr_put(context->keys, key->name, key); 151 cxMapPut(context->keys, cx_hash_key_str(key->name), key);
154 } 152 }
155 153
156 DavKey* dav_context_get_key(DavContext *context, char *name) { 154 DavKey* dav_context_get_key(DavContext *context, const char *name) {
157 if(name) { 155 if(name) {
158 return ucx_map_cstr_get(context->keys, name); 156 return cxMapGet(context->keys, cx_hash_key_str(name));
159 } 157 }
160 return NULL; 158 return NULL;
161 } 159 }
162 160
163 int dav_add_namespace(DavContext *context, const char *prefix, const char *name) { 161 int dav_add_namespace(DavContext *context, const char *prefix, const char *name) {
171 169
172 int err = 0; 170 int err = 0;
173 if(p && n) { 171 if(p && n) {
174 namespace->prefix = p; 172 namespace->prefix = p;
175 namespace->name = n; 173 namespace->name = n;
176 err = ucx_map_cstr_put(context->namespaces, prefix, namespace); 174 err = cxMapPut(context->namespaces, cx_hash_key_str(prefix), namespace);
177 } 175 }
178 176
179 if(err) { 177 if(err) {
180 free(namespace); 178 free(namespace);
181 if(p) free(p); 179 if(p) free(p);
184 182
185 return err; 183 return err;
186 } 184 }
187 185
188 DavNamespace* dav_get_namespace(DavContext *context, const char *prefix) { 186 DavNamespace* dav_get_namespace(DavContext *context, const char *prefix) {
189 return ucx_map_cstr_get(context->namespaces, prefix); 187 return cxMapGet(context->namespaces, cx_hash_key_str(prefix));
190 } 188 }
191 189
192 DavNamespace* dav_get_namespace_s(DavContext *context, sstr_t prefix) { 190 DavNamespace* dav_get_namespace_s(DavContext *context, cxstring prefix) {
193 return ucx_map_sstr_get(context->namespaces, prefix); 191 return cxMapGet(context->namespaces, cx_hash_key(prefix.ptr, prefix.length));
194 } 192 }
195 193
196 int dav_enable_namespace_encryption(DavContext *context, const char *ns, DavBool encrypt) { 194 int dav_enable_namespace_encryption(DavContext *context, const char *ns, DavBool encrypt) {
197 DavNSInfo *info = ucx_map_cstr_get(context->namespaceinfo, ns); 195 CxHashKey hkey = cx_hash_key_str(ns);
196 DavNSInfo *info = cxMapGet(context->namespaceinfo, hkey);
198 if(!info) { 197 if(!info) {
199 info = calloc(1, sizeof(DavNSInfo)); 198 info = calloc(1, sizeof(DavNSInfo));
200 info->encrypt = encrypt; 199 info->encrypt = encrypt;
201 ucx_map_cstr_put(context->namespaceinfo, ns, info); 200 cxMapPut(context->namespaceinfo, hkey, info);
202 } else { 201 } else {
203 info->encrypt = encrypt; 202 info->encrypt = encrypt;
204 } 203 }
205 return 0; 204 return 0;
206 } 205 }
207 206
208 int dav_namespace_is_encrypted(DavContext *context, const char *ns) { 207 int dav_namespace_is_encrypted(DavContext *context, const char *ns) {
209 DavNSInfo *info = ucx_map_cstr_get(context->namespaceinfo, ns); 208 DavNSInfo *info = cxMapGet(context->namespaceinfo, cx_hash_key_str(ns));
210 if(info) { 209 if(info) {
211 return info->encrypt; 210 return info->encrypt;
212 } 211 }
213 return 0; 212 return 0;
214 } 213 }
224 char *pname = strchr(prefixed_name, ':'); 223 char *pname = strchr(prefixed_name, ':');
225 char *pns = "DAV:"; 224 char *pns = "DAV:";
226 if(pname) { 225 if(pname) {
227 DavNamespace *ns = dav_get_namespace_s( 226 DavNamespace *ns = dav_get_namespace_s(
228 ctx, 227 ctx,
229 sstrn(prefixed_name, pname-prefixed_name)); 228 cx_strn(prefixed_name, pname-prefixed_name));
230 if(ns) { 229 if(ns) {
231 pns = ns->name; 230 pns = ns->name;
232 pname++; 231 pname++;
233 } else { 232 } else {
234 pns = NULL; 233 pns = NULL;
248 { 247 {
249 char *pname = strchr(prefixed_name, ':'); 248 char *pname = strchr(prefixed_name, ':');
250 if(pname) { 249 if(pname) {
251 DavNamespace *ns = dav_get_namespace_s( 250 DavNamespace *ns = dav_get_namespace_s(
252 ctx, 251 ctx,
253 sstrn(prefixed_name, pname-prefixed_name)); 252 cx_strn(prefixed_name, pname-prefixed_name));
254 if(ns) { 253 if(ns) {
255 *name = pname +1; 254 *name = pname +1;
256 return ns; 255 return ns;
257 } else { 256 } else {
258 *name = NULL; 257 *name = NULL;
259 return NULL; 258 return NULL;
260 } 259 }
261 } else { 260 } else {
262 *name = prefixed_name; 261 *name = prefixed_name;
263 return dav_get_namespace_s(ctx, S("D")); 262 return dav_get_namespace_s(ctx, cx_str("D"));
264 } 263 }
265 } 264 }
266 265
267 // TODO: add sstr_t version of dav_get_property_ns 266 // TODO: add sstr_t version of dav_get_property_ns
268 267
269 void dav_set_effective_href(DavSession *sn, DavResource *resource) { 268 void dav_set_effective_href(DavSession *sn, DavResource *resource) {
270 char *eff_url; 269 char *eff_url;
271 curl_easy_getinfo(sn->handle, CURLINFO_EFFECTIVE_URL, &eff_url); 270 curl_easy_getinfo(sn->handle, CURLINFO_EFFECTIVE_URL, &eff_url);
272 if(eff_url) { 271 if(eff_url) {
273 char *href = util_url_path(eff_url); 272 const char *href = util_url_path(eff_url);
274 if(strcmp(href, resource->href)) { 273 if(strcmp(href, resource->href)) {
275 dav_session_free(sn, resource->href); 274 dav_session_free(sn, resource->href);
276 resource->href = dav_session_strdup(sn, href); 275 resource->href = dav_session_strdup(sn, href);
277 } 276 }
278 } 277 }
279 } 278 }
280 279
281 DavResource* dav_get(DavSession *sn, char *path, char *properties) { 280 DavResource* dav_get(DavSession *sn, char *path, const char *properties) {
282 CURL *handle = sn->handle; 281 CURL *handle = sn->handle;
283 DavResource *resource = dav_resource_new(sn, path); 282 DavResource *resource = dav_resource_new(sn, path);
284 util_set_url(sn, dav_resource_get_href(resource)); 283 util_set_url(sn, dav_resource_get_href(resource));
285 284
286 UcxList *proplist = NULL; 285 CxList *proplist = NULL;
287 if(properties) { 286 if(properties) {
288 proplist = parse_properties_string(sn->context, sstr(properties)); 287 proplist = parse_properties_string(sn->context, cx_str(properties));
289 } 288 }
290 UcxBuffer *rqbuf = create_propfind_request(sn, proplist, "propfind", 0); 289 CxBuffer *rqbuf = create_propfind_request(sn, proplist, "propfind", 0);
291 UcxBuffer *rpbuf = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND); 290 CxBuffer *rpbuf = cxBufferCreate(NULL, 4096, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND);
292 291
293 //fwrite(rqbuf->space, 1, rqbuf->size, stdout); 292 //fwrite(rqbuf->space, 1, rqbuf->size, stdout);
294 //printf("\n"); 293 //printf("\n");
295 294
296 CURLcode ret = do_propfind_request(sn, rqbuf, rpbuf); 295 CURLcode ret = do_propfind_request(sn, rqbuf, rpbuf);
308 dav_session_set_error(sn, ret, status); 307 dav_session_set_error(sn, ret, status);
309 dav_resource_free(resource); 308 dav_resource_free(resource);
310 resource = NULL; 309 resource = NULL;
311 } 310 }
312 311
313 ucx_buffer_free(rqbuf); 312 cxBufferFree(rqbuf);
314 ucx_buffer_free(rpbuf); 313 cxBufferFree(rpbuf);
315 while(proplist) { 314
316 DavProperty *p = proplist->data; 315 if(proplist) {
317 free(p->name); 316 CxIterator i = cxListIterator(proplist);
318 free(p); 317 cx_foreach(DavProperty*, p, i) {
319 UcxList *next = proplist->next; 318 free(p->name);
320 free(proplist); 319 }
321 proplist = next; 320 cxListDestroy(proplist);
322 } 321 }
323 322
324 return resource; 323 return resource;
325 } 324 }
326 325
327 326
328 int dav_propfind(DavSession *sn, DavResource *root, UcxBuffer *rqbuf) { 327 int dav_propfind(DavSession *sn, DavResource *root, CxBuffer *rqbuf) {
329 // clean resource properties 328 // clean resource properties
330 DavResourceData *data = root->data; 329 DavResourceData *data = root->data;
331 ucx_map_clear(data->properties); // TODO: free existing content 330 cxMapClear(data->properties); // TODO: free existing content
332 331
333 CURL *handle = sn->handle; 332 CURL *handle = sn->handle;
334 util_set_url(sn, dav_resource_get_href(root)); 333 util_set_url(sn, dav_resource_get_href(root));
335 334
336 UcxBuffer *rpbuf = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND); 335 CxBuffer *rpbuf = cxBufferCreate(NULL, 4096, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND);
337 DavResource *resource = root; 336 DavResource *resource = root;
338 CURLcode ret = do_propfind_request(sn, rqbuf, rpbuf); 337 CURLcode ret = do_propfind_request(sn, rqbuf, rpbuf);
339 long status = 0; 338 long status = 0;
340 long error = 0; 339 long error = 0;
341 curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status); 340 curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status);
348 root->exists = 1; 347 root->exists = 1;
349 } else { 348 } else {
350 dav_session_set_error(sn, ret, status); 349 dav_session_set_error(sn, ret, status);
351 error = 1; 350 error = 1;
352 } 351 }
353 ucx_buffer_free(rpbuf); 352 cxBufferFree(rpbuf);
354 return error; 353 return error;
355 } 354 }
356 355
357 UcxList* parse_properties_string(DavContext *context, sstr_t str) { 356 CxList* parse_properties_string(DavContext *context, cxstring str) {
358 UcxList *proplist = NULL; 357 CxList *proplist = cxLinkedListCreateSimple(sizeof(DavProperty));
359 ssize_t nprops = 0; 358
360 sstr_t *props = sstrsplit(str, S(","), &nprops); 359 CxStrtokCtx tok = cx_strtok(str, cx_str(","), INT_MAX);
361 for(int i=0;i<nprops;i++) { 360 cxstring s;
362 sstr_t s = props[i]; 361 while(cx_strtok_next(&tok, &s)) {
363 sstr_t nsname = sstrchr(s, ':'); 362 cxstring nsname = cx_strchr(s, ':');
364 if(nsname.length > 0) { 363 if(nsname.length > 0) {
365 sstr_t nspre = sstrsubsl(s, 0, nsname.ptr - s.ptr); 364 cxstring nspre = cx_strsubsl(s, 0, nsname.ptr - s.ptr);
366 nsname.ptr++; 365 nsname.ptr++;
367 nsname.length--; 366 nsname.length--;
368 367
369 DavProperty *dp = malloc(sizeof(DavProperty)); 368 DavProperty dp;
370 sstr_t pre = sstrtrim(nspre); 369 cxstring pre = cx_strtrim(nspre);
371 dp->ns = dav_get_namespace_s(context, pre); 370 dp.ns = dav_get_namespace_s(context, pre);
372 dp->name = sstrdup(nsname).ptr; 371 dp.name = cx_strdup(nsname).ptr;
373 if(dp->ns && dp->name) { 372 dp.value = NULL;
374 proplist = ucx_list_append(proplist, dp); 373 if(dp.ns && dp.name) {
374 cxListAdd(proplist, &dp);
375 } else { 375 } else {
376 free(dp->name); 376 free(dp.name);
377 free(dp);
378 } 377 }
379 } 378 }
380 free(s.ptr); 379 }
381 } 380
382 free(props);
383 return proplist; 381 return proplist;
384 } 382 }
385 383
386 DavResource* dav_query(DavSession *sn, char *query, ...) { 384 DavResource* dav_query(DavSession *sn, char *query, ...) {
387 DavQLStatement *stmt = dav_parse_statement(sstr(query)); 385 DavQLStatement *stmt = dav_parse_statement(cx_str(query));
388 if(!stmt) { 386 if(!stmt) {
389 sn->error = DAV_ERROR; 387 sn->error = DAV_ERROR;
390 return NULL; 388 return NULL;
391 } 389 }
392 if(stmt->errorcode != 0) { 390 if(stmt->errorcode != 0) {

mercurial