223 ucx_buffer_write(s.ptr, 1, s.length, buf); |
223 ucx_buffer_write(s.ptr, 1, s.length, buf); |
224 |
224 |
225 return buf; |
225 return buf; |
226 } |
226 } |
227 |
227 |
|
228 PropfindParser* create_propfind_parser(UcxBuffer *response, char *url) { |
|
229 PropfindParser *parser = malloc(sizeof(PropfindParser)); |
|
230 if(!parser) { |
|
231 return NULL; |
|
232 } |
|
233 parser->document = xmlReadMemory(response->space, response->size, url, NULL, 0); |
|
234 parser->current = NULL; |
|
235 if(parser->document) { |
|
236 xmlNode *xml_root = xmlDocGetRootElement(parser->document); |
|
237 if(xml_root) { |
|
238 xmlNode *node = xml_root->children; |
|
239 while(node) { |
|
240 // find first response tag |
|
241 if(node->type == XML_ELEMENT_NODE) { |
|
242 if(xstreq(node->name, "response")) { |
|
243 parser->current = node; |
|
244 break; |
|
245 } |
|
246 } |
|
247 node = node->next; |
|
248 } |
|
249 return parser; |
|
250 } else { |
|
251 xmlFreeDoc(parser->document); |
|
252 } |
|
253 } |
|
254 free(parser); |
|
255 return NULL; |
|
256 } |
|
257 |
|
258 int get_propfind_response(PropfindParser *parser, ResponseTag *result) { |
|
259 if(parser->current == NULL) { |
|
260 return 0; |
|
261 } |
|
262 |
|
263 char *href = NULL; |
|
264 int iscollection = 0; |
|
265 UcxList *properties = NULL; // xmlNode list |
|
266 char *crypto_name = NULL; // name set by crypto-name property |
|
267 char *crypto_key = NULL; |
|
268 |
|
269 xmlNode *node = parser->current->children; |
|
270 while(node) { |
|
271 if(node->type == XML_ELEMENT_NODE) { |
|
272 if(xstreq(node->name, "href")) { |
|
273 xmlNode *href_node = node->children; |
|
274 if(href_node->type != XML_TEXT_NODE) { |
|
275 // error |
|
276 return -1; |
|
277 } |
|
278 href = (char*)href_node->content; |
|
279 } else if(xstreq(node->name, "propstat")) { |
|
280 xmlNode *n = node->children; |
|
281 xmlNode *prop_node = NULL; |
|
282 int ok = 0; |
|
283 // get the status code |
|
284 while(n) { |
|
285 if(n->type == XML_ELEMENT_NODE) { |
|
286 if(xstreq(n->name, "prop")) { |
|
287 prop_node = n; |
|
288 } else if(xstreq(n->name, "status")) { |
|
289 xmlNode *status_node = n->children; |
|
290 if(status_node->type != XML_TEXT_NODE) { |
|
291 // error |
|
292 return -1; |
|
293 } |
|
294 sstr_t status_str = sstr((char*)status_node->content); |
|
295 if(status_str.length < 13) { |
|
296 // error |
|
297 return -1; |
|
298 } |
|
299 status_str = sstrsubsl(status_str, 9, 3); |
|
300 if(!sstrcmp(status_str, S("200"))) { |
|
301 ok = 1; |
|
302 } |
|
303 } |
|
304 } |
|
305 n = n->next; |
|
306 } |
|
307 // if status is ok, get all properties |
|
308 if(ok) { |
|
309 n = prop_node->children; |
|
310 while(n) { |
|
311 if(n->type == XML_ELEMENT_NODE) { |
|
312 properties = ucx_list_append(properties, n); |
|
313 if(xstreq(n->name, "resourcetype")) { |
|
314 xmlNode *rsnode = n->children; |
|
315 if(rsnode && rsnode->type == XML_ELEMENT_NODE) { |
|
316 // TODO: check content |
|
317 iscollection = 1; |
|
318 } |
|
319 } else if(xstreq(n->ns->href, DAV_NS)) { |
|
320 if(xstreq(n->name, "crypto-name")) { |
|
321 crypto_name = util_xml_get_text(n); |
|
322 } else if(xstreq(n->name, "crypto-key")) { |
|
323 crypto_key = util_xml_get_text(n); |
|
324 } |
|
325 } |
|
326 } |
|
327 n = n->next; |
|
328 } |
|
329 } |
|
330 } |
|
331 } |
|
332 node = node->next; |
|
333 } |
|
334 |
|
335 result->href = href; |
|
336 result->iscollection = iscollection; |
|
337 result->properties = properties; |
|
338 result->crypto_name = crypto_name; |
|
339 result->crypto_key = crypto_key; |
|
340 |
|
341 // find next response tag |
|
342 xmlNode *next = parser->current->next; |
|
343 while(next) { |
|
344 if(next->type == XML_ELEMENT_NODE) { |
|
345 if(xstreq(next->name, "response")) { |
|
346 break; |
|
347 } |
|
348 } |
|
349 next = next->next; |
|
350 } |
|
351 parser->current = next; |
|
352 |
|
353 return 1; |
|
354 } |
|
355 |
|
356 int hrefeq(DavSession *sn, char *href1, char *href2) { |
|
357 sstr_t href_s = sstr(util_url_decode(sn, href1)); |
|
358 sstr_t href_r = sstr(util_url_decode(sn, href2)); |
|
359 int ret = 0; |
|
360 if(!sstrcmp(href_s, href_r)) { |
|
361 ret = 1; |
|
362 } else if(href_s.length == href_r.length + 1) { |
|
363 if(href_s.ptr[href_s.length-1] == '/') { |
|
364 href_s.length--; |
|
365 if(!sstrcmp(href_s, href_r)) { |
|
366 ret = 1; |
|
367 } |
|
368 } |
|
369 } |
|
370 |
|
371 free(href_s.ptr); |
|
372 free(href_r.ptr); |
|
373 |
|
374 return ret; |
|
375 } |
|
376 |
|
377 |
228 DavResource* parse_propfind_response(DavSession *sn, DavResource *root, UcxBuffer *response, DavQOp *cond, size_t len) { |
378 DavResource* parse_propfind_response(DavSession *sn, DavResource *root, UcxBuffer *response, DavQOp *cond, size_t len) { |
229 char *url = NULL; |
379 char *url = NULL; |
230 curl_easy_getinfo(sn->handle, CURLINFO_EFFECTIVE_URL, &url); |
380 curl_easy_getinfo(sn->handle, CURLINFO_EFFECTIVE_URL, &url); |
231 if(!root) { |
381 if(!root) { |
232 printf("method.c: TODO: remove\n"); |
382 printf("method.c: TODO: remove\n"); |
252 node = node->next; |
402 node = node->next; |
253 } |
403 } |
254 xmlFreeDoc(doc); |
404 xmlFreeDoc(doc); |
255 |
405 |
256 return root; |
406 return root; |
|
407 } |
|
408 |
|
409 DavResource* response2resource(DavSession *sn, ResponseTag *response, char *parent_path) { |
|
410 // create resource |
|
411 char *name = NULL; |
|
412 if(DAV_DECRYPT_NAME(sn) && response->crypto_name) { |
|
413 if(!response->crypto_key) { |
|
414 // TODO: error |
|
415 fprintf(stderr, "encrypted resource without key\n"); |
|
416 return NULL; |
|
417 } |
|
418 name = util_decrypt_str(sn, response->crypto_name, response->crypto_key); |
|
419 if(!name) { |
|
420 // TODO: error |
|
421 fprintf(stderr, "decrypted name is null\n"); |
|
422 return NULL; |
|
423 } |
|
424 } else { |
|
425 sstr_t resname = sstr(util_resource_name(response->href)); |
|
426 int nlen = 0; |
|
427 char *uname = curl_easy_unescape( |
|
428 sn->handle, |
|
429 resname.ptr, |
|
430 resname.length, |
|
431 &nlen); |
|
432 name = dav_session_strdup(sn, uname); |
|
433 curl_free(uname); |
|
434 } |
|
435 |
|
436 char *href = dav_session_strdup(sn, href); |
|
437 DavResource *res = NULL; |
|
438 if(parent_path) { |
|
439 res = dav_resource_new_full(sn, parent_path, name, href); |
|
440 } else { |
|
441 res = dav_resource_new_href(sn, href); |
|
442 } |
|
443 dav_session_free(sn, name); |
|
444 |
|
445 add_properties(res, response); |
|
446 return res; |
|
447 } |
|
448 |
|
449 void add_properties(DavResource *res, ResponseTag *response) { |
|
450 res->iscollection = response->iscollection; |
|
451 |
|
452 // add properties |
|
453 UCX_FOREACH(elm, response->properties) { |
|
454 xmlNode *prop = elm->data; |
|
455 |
|
456 // TODO: add xml data instead of a string |
|
457 char *text = util_xml_get_text(prop); |
|
458 if(text) { |
|
459 resource_add_property(res, (char*)prop->ns->href, (char*)prop->name, text); |
|
460 } |
|
461 } |
|
462 |
|
463 set_davprops(res); |
257 } |
464 } |
258 |
465 |
259 int parse_response_tag(DavResource *resource, xmlNode *node, DavQOp *cond, size_t clen) { |
466 int parse_response_tag(DavResource *resource, xmlNode *node, DavQOp *cond, size_t clen) { |
260 DavSession *sn = resource->session; |
467 DavSession *sn = resource->session; |
261 |
468 |