libidav/utils.c

changeset 747
efbd59642577
parent 741
e9a5dd08258d
child 757
7ced4052e8ca
equal deleted inserted replaced
746:a569148841ff 747:efbd59642577
30 #include <stdio.h> 30 #include <stdio.h>
31 #include <stdlib.h> 31 #include <stdlib.h>
32 #include <string.h> 32 #include <string.h>
33 #include <errno.h> 33 #include <errno.h>
34 #include <ctype.h> 34 #include <ctype.h>
35 #include <ucx/string.h> 35 #include <cx/string.h>
36 #include <ucx/buffer.h> 36 #include <cx/buffer.h>
37 #include <ucx/utils.h> 37 #include <cx/utils.h>
38 #include <cx/printf.h>
38 #include <libxml/tree.h> 39 #include <libxml/tree.h>
39 #include <curl/curl.h> 40 #include <curl/curl.h>
40 41
41 #ifdef _WIN32 42 #ifdef _WIN32
42 #include <conio.h> 43 #include <conio.h>
64 #include <openssl/bio.h> 65 #include <openssl/bio.h>
65 #include <openssl/buffer.h> 66 #include <openssl/buffer.h>
66 #include <openssl/rand.h> 67 #include <openssl/rand.h>
67 */ 68 */
68 69
69 static size_t extractval(sstr_t str, char *result, char delim) { 70 static size_t extractval(cxstring str, char *result, char delim) {
70 size_t n = 0; 71 size_t n = 0;
71 for(size_t i = 0; i < str.length ; i++) { 72 for(size_t i = 0; i < str.length ; i++) {
72 if(isdigit(str.ptr[i])) { 73 if(isdigit(str.ptr[i])) {
73 result[n++] = str.ptr[i]; 74 result[n++] = str.ptr[i];
74 } else if(str.ptr[i] != delim) { 75 } else if(str.ptr[i] != delim) {
91 memset(&tparts, 0, sizeof(struct tm)); 92 memset(&tparts, 0, sizeof(struct tm));
92 long val; 93 long val;
93 char conv[16]; 94 char conv[16];
94 95
95 // work on the trimmed string 96 // work on the trimmed string
96 sstr_t date = sstrtrim(sstr(iso8601str)); 97 cxstring date = cx_strtrim(cx_str(iso8601str));
97 98
98 sstr_t time = sstrchr(date, 'T'); 99 cxstring time = cx_strchr(date, 'T');
99 if(time.length == 0) { 100 if(time.length == 0) {
100 return 0; 101 return 0;
101 } 102 }
102 date.length = time.ptr - date.ptr; 103 date.length = time.ptr - date.ptr;
103 time.ptr++; time.length--; 104 time.ptr++; time.length--;
104 105
105 sstr_t tzinfo; 106 cxstring tzinfo;
106 if((tzinfo = sstrchr(time, 'Z')).length > 0 || 107 if((tzinfo = cx_strchr(time, 'Z')).length > 0 ||
107 (tzinfo = sstrchr(time, '+')).length > 0 || 108 (tzinfo = cx_strchr(time, '+')).length > 0 ||
108 (tzinfo = sstrchr(time, '-')).length > 0) { 109 (tzinfo = cx_strchr(time, '-')).length > 0) {
109 110
110 time.length = tzinfo.ptr - time.ptr; 111 time.length = tzinfo.ptr - time.ptr;
111 } 112 }
112 113
113 // parse date 114 // parse date
122 tparts.tm_mday = val % 100; 123 tparts.tm_mday = val % 100;
123 tparts.tm_mon = (val % 10000) / 100 - 1; 124 tparts.tm_mon = (val % 10000) / 100 - 1;
124 tparts.tm_year = val / 10000 - 1900; 125 tparts.tm_year = val / 10000 - 1900;
125 126
126 // parse time and skip possible fractional seconds 127 // parse time and skip possible fractional seconds
127 sstr_t frac; 128 cxstring frac;
128 if((frac = sstrchr(time, '.')).length > 0 || 129 if((frac = cx_strchr(time, '.')).length > 0 ||
129 (frac = sstrchr(time, ',')).length > 0) { 130 (frac = cx_strchr(time, ',')).length > 0) {
130 time.length = frac.ptr - time.ptr; 131 time.length = frac.ptr - time.ptr;
131 } 132 }
132 if((time.length != 6 && time.length != 8) 133 if((time.length != 6 && time.length != 8)
133 || extractval(time, conv , ':') != 6) { 134 || extractval(time, conv , ':') != 6) {
134 return 0; 135 return 0;
142 // parse time zone (if any) 143 // parse time zone (if any)
143 if(tzinfo.length == 0) { 144 if(tzinfo.length == 0) {
144 // local time 145 // local time
145 tparts.tm_isdst = -1; 146 tparts.tm_isdst = -1;
146 return mktime(&tparts); 147 return mktime(&tparts);
147 } else if(!sstrcmp(tzinfo, S("Z"))) { 148 } else if(!cx_strcmp(tzinfo, cx_str("Z"))) {
148 #ifdef __FreeBSD__ 149 #ifdef __FreeBSD__
149 return timegm(&tparts); 150 return timegm(&tparts);
150 #else 151 #else
151 return mktime(&tparts) - timezone; 152 return mktime(&tparts) - timezone;
152 #endif 153 #endif
274 *result = 0; 275 *result = 0;
275 return 1; 276 return 1;
276 } 277 }
277 } 278 }
278 279
279 char* util_url_base_s(sstr_t url) { 280 char* util_url_base_s(cxstring url) {
280 size_t i = 0; 281 size_t i = 0;
281 if(url.length > 0) { 282 if(url.length > 0) {
282 int slmax; 283 int slmax;
283 if(sstrprefix(url, SC("http://"))) { 284 if(cx_strprefix(url, cx_str("http://"))) {
284 slmax = 3; 285 slmax = 3;
285 } else if(sstrprefix(url, SC("https://"))) { 286 } else if(cx_strprefix(url, cx_str("https://"))) {
286 slmax = 3; 287 slmax = 3;
287 } else { 288 } else {
288 slmax = 1; 289 slmax = 1;
289 } 290 }
290 int slashcount = 0; 291 int slashcount = 0;
296 break; 297 break;
297 } 298 }
298 } 299 }
299 } 300 }
300 } 301 }
301 sstr_t server = sstrsubsl(url, 0, i); 302 cxstring server = cx_strsubsl(url, 0, i);
302 return sstrdup(server).ptr; 303 return cx_strdup(server).ptr;
303 } 304 }
304 305
305 char* util_url_base(char *url) { 306 char* util_url_base(char *url) {
306 return util_url_base_s(sstr(url)); 307 return util_url_base_s(cx_str(url));
307 } 308 }
308 309
309 char* util_url_path(char *url) { 310 const char* util_url_path(const char *url) {
310 char *path = NULL; 311 const char *path = NULL;
311 size_t len = strlen(url); 312 size_t len = strlen(url);
312 int slashcount = 0; 313 int slashcount = 0;
313 int slmax; 314 int slmax;
314 if(len > 7 && !strncasecmp(url, "http://", 7)) { 315 if(len > 7 && !strncasecmp(url, "http://", 7)) {
315 slmax = 3; 316 slmax = 3;
333 path = url + len; // empty string 334 path = url + len; // empty string
334 } 335 }
335 return path; 336 return path;
336 } 337 }
337 338
338 char* util_url_decode(DavSession *sn, char *url) { 339 char* util_url_decode(DavSession *sn, const char *url) {
339 char *unesc = curl_easy_unescape(sn->handle, url, strlen(url), NULL); 340 char *unesc = curl_easy_unescape(sn->handle, url, strlen(url), NULL);
340 char *ret = strdup(unesc); 341 char *ret = strdup(unesc);
341 curl_free(unesc); 342 curl_free(unesc);
342 return ret; 343 return ret;
343 } 344 }
344 345
345 static size_t util_header_callback(char *buffer, size_t size, 346 static size_t util_header_callback(char *buffer, size_t size,
346 size_t nitems, void *data) { 347 size_t nitems, void *data) {
347 348
348 sstr_t sbuffer = sstrn(buffer, size*nitems); 349 cxstring sbuffer = cx_strn(buffer, size*nitems);
349 350
350 UcxMap *map = (UcxMap*) data; 351 CxMap *map = (CxMap*) data;
351 352
352 // if we get a status line, clear the map and exit 353 // if we get a status line, clear the map and exit
353 if(sstrprefix(sbuffer, S("HTTP/"))) { 354 if(cx_strprefix(sbuffer, cx_str("HTTP/"))) {
354 ucx_map_free_content(map, free); 355 // TODO: use new map destructor ucx_map_free_content(map, free);
355 ucx_map_clear(map); 356 cxMapClear(map);
356 return size*nitems; 357 return size*nitems;
357 } 358 }
358 359
359 // if we get the terminating CRLF, just exit 360 // if we get the terminating CRLF, just exit
360 if(!sstrcmp(sbuffer, S("\r\n"))) { 361 if(!cx_strcmp(sbuffer, cx_str("\r\n"))) {
361 return 2; 362 return 2;
362 } 363 }
363 364
364 sstr_t key = sbuffer; 365 cxstring key = sbuffer;
365 sstr_t value = sstrchr(sbuffer, ':'); 366 cxstring value = cx_strchr(sbuffer, ':');
366 367
367 if(value.length == 0) { 368 if(value.length == 0) {
368 return 0; // invalid header line 369 return 0; // invalid header line
369 } 370 }
370 371
371 key.length = value.ptr - key.ptr; 372 key.length = value.ptr - key.ptr;
372 value.ptr++; value.length--; 373 value.ptr++; value.length--;
373 374
374 key = sstrlower(sstrtrim(key)); 375 cxmutstr key_cp = cx_strdup(cx_strtrim(key));
375 value = sstrdup(sstrtrim(value)); 376 cx_strlower(key_cp);
377 cxmutstr value_cp = cx_strdup(cx_strtrim(value));
376 378
377 ucx_map_sstr_put(map, key, value.ptr); 379 cxMapPut(map, cx_hash_key(key_cp.ptr, key_cp.length), value_cp.ptr);
378 380
379 free(key.ptr); 381 free(key_cp.ptr);
380 382
381 return sbuffer.length; 383 return sbuffer.length;
382 } 384 }
383 385
384 int util_path_isrelated(const char *path1, const char *path2) { 386 int util_path_isrelated(const char *path1, const char *path2) {
385 scstr_t p1 = scstr(path1); 387 cxstring p1 = cx_str(path1);
386 scstr_t p2 = scstr(path2); 388 cxstring p2 = cx_str(path2);
387 389
388 if(IS_PATH_SEPARATOR(p1.ptr[p1.length-1])) { 390 if(IS_PATH_SEPARATOR(p1.ptr[p1.length-1])) {
389 p1.length--; 391 p1.length--;
390 } 392 }
391 if(IS_PATH_SEPARATOR(p2.ptr[p2.length-1])) { 393 if(IS_PATH_SEPARATOR(p2.ptr[p2.length-1])) {
394 396
395 if(p2.length < p1.length) { 397 if(p2.length < p1.length) {
396 return 0; 398 return 0;
397 } 399 }
398 400
399 if(!sstrcmp(p1, p2)) { 401 if(!cx_strcmp(p1, p2)) {
400 return 1; 402 return 1;
401 } 403 }
402 404
403 if(sstrprefix(p2, p1)) { 405 if(cx_strprefix(p2, p1)) {
404 if(IS_PATH_SEPARATOR(p2.ptr[p1.length])) { 406 if(IS_PATH_SEPARATOR(p2.ptr[p1.length])) {
405 return 1; 407 return 1;
406 } 408 }
407 } 409 }
408 410
432 } 434 }
433 #endif 435 #endif
434 436
435 char* util_path_normalize(const char *path) { 437 char* util_path_normalize(const char *path) {
436 size_t len = strlen(path); 438 size_t len = strlen(path);
437 UcxBuffer *buf = ucx_buffer_new(NULL, len+1, UCX_BUFFER_AUTOEXTEND); 439 CxBuffer buf;
440 cxBufferInit(&buf, NULL, len+1, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND);
438 441
439 if(path[0] == '/') { 442 if(path[0] == '/') {
440 ucx_buffer_putc(buf, '/'); 443 cxBufferPut(&buf, '/');
441 } 444 }
442 445
443 int add_separator = 0; 446 int add_separator = 0;
444 int seg_start = 0; 447 int seg_start = 0;
445 for(int i=0;i<=len;i++) { 448 for(int i=0;i<=len;i++) {
451 seg_ptr++; 454 seg_ptr++;
452 seg_len--; 455 seg_len--;
453 } 456 }
454 457
455 if(seg_len > 0) { 458 if(seg_len > 0) {
456 scstr_t seg = scstrn(seg_ptr, seg_len); 459 cxstring seg = cx_strn(seg_ptr, seg_len);
457 if(!sstrcmp(seg, SC(".."))) { 460 if(!cx_strcmp(seg, CX_STR(".."))) {
458 for(int j=buf->pos;j>=0;j--) { 461 for(int j=buf.pos;j>=0;j--) {
459 char t = buf->space[j]; 462 char t = buf.space[j];
460 if(IS_PATH_SEPARATOR(t) || j == 0) { 463 if(IS_PATH_SEPARATOR(t) || j == 0) {
461 buf->pos = j; 464 buf.pos = j;
462 buf->size = j; 465 buf.size = j;
463 buf->space[j] = 0; 466 buf.space[j] = 0;
464 add_separator = IS_PATH_SEPARATOR(t) ? 1 : 0; 467 add_separator = IS_PATH_SEPARATOR(t) ? 1 : 0;
465 break; 468 break;
466 } 469 }
467 } 470 }
468 } else if(!sstrcmp(seg, SC("."))) { 471 } else if(!cx_strcmp(seg, CX_STR("."))) {
469 // ignore 472 // ignore
470 } else { 473 } else {
471 if(add_separator) { 474 if(add_separator) {
472 ucx_buffer_putc(buf, PATH_SEPARATOR); 475 cxBufferPut(&buf, PATH_SEPARATOR);
473 } 476 }
474 ucx_buffer_write(seg_ptr, 1, seg_len, buf); 477 cxBufferWrite(seg_ptr, 1, seg_len, &buf);
475 add_separator = 1; 478 add_separator = 1;
476 } 479 }
477 } 480 }
478 481
479 seg_start = i; 482 seg_start = i;
480 } 483 }
481 } 484 }
482 485
483 ucx_buffer_putc(buf, 0); 486 cxBufferPut(&buf, 0);
484 487
485 488 return buf.space;
486 char *space = buf->space;
487 buf->flags = 0; // disable autofree
488 ucx_buffer_free(buf);
489 return space;
490 } 489 }
491 490
492 static char* create_relative_path(const char *abspath, const char *base) { 491 static char* create_relative_path(const char *abspath, const char *base) {
493 size_t path_len = strlen(abspath); 492 size_t path_len = strlen(abspath);
494 size_t base_len = strlen(base); 493 size_t base_len = strlen(base);
521 last_dir = i; 520 last_dir = i;
522 } 521 }
523 } 522 }
524 523
525 char *ret = NULL; 524 char *ret = NULL;
526 UcxBuffer *out = NULL; 525 CxBuffer out;
527 if(last_dir+1 < base_len) { 526 if(last_dir+1 < base_len) {
528 // base is deeper than the link root, we have to go backwards 527 // base is deeper than the link root, we have to go backwards
529 int dircount = 0; 528 int dircount = 0;
530 for(int i=last_dir+1;i<base_len;i++) { 529 for(int i=last_dir+1;i<base_len;i++) {
531 if(IS_PATH_SEPARATOR(base[i])) { 530 if(IS_PATH_SEPARATOR(base[i])) {
532 dircount++; 531 dircount++;
533 } 532 }
534 } 533 }
535 534
536 out = ucx_buffer_new(NULL, dircount*3+path_len-last_dir, UCX_BUFFER_AUTOEXTEND); 535 cxBufferInit(&out, NULL, dircount*3+path_len-last_dir, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND);
537 536
538 for(int i=0;i<dircount;i++) { 537 for(int i=0;i<dircount;i++) {
539 ucx_buffer_puts(out, "../"); 538 cxBufferPutString(&out, "../");
540 } 539 }
541 } else { 540 } else {
542 out = ucx_buffer_new(NULL, 1024, path_len - last_dir); 541 cxBufferInit(&out, NULL, path_len - last_dir, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND);
543 } 542 }
544 543
545 ucx_buffer_puts(out, abspath + last_dir + 1); 544 cxBufferPutString(&out, abspath + last_dir + 1);
546 ucx_buffer_putc(out, 0); 545 cxBufferPut(&out, 0);
547 out->flags = 0; 546
548 ret = out->space; 547 return out.space;
549 ucx_buffer_free(out);
550
551 return ret;
552 } 548 }
553 549
554 #ifdef _WIN32 550 #ifdef _WIN32
555 char* util_create_relative_path(const char *abspath, const char *base) { 551 char* util_create_relative_path(const char *abspath, const char *base) {
556 char *abspath_converted = strdup(abspath); 552 char *abspath_converted = strdup(abspath);
579 return create_relative_path(abspath, base); 575 return create_relative_path(abspath, base);
580 } 576 }
581 #endif 577 #endif
582 578
583 579
584 void util_capture_header(CURL *handle, UcxMap* map) { 580 void util_capture_header(CURL *handle, CxMap* map) {
585 if(map) { 581 if(map) {
586 curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, util_header_callback); 582 curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, util_header_callback);
587 curl_easy_setopt(handle, CURLOPT_HEADERDATA, map); 583 curl_easy_setopt(handle, CURLOPT_HEADERDATA, map);
588 } else { 584 } else {
589 curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, NULL); 585 curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, NULL);
590 curl_easy_setopt(handle, CURLOPT_HEADERDATA, NULL); 586 curl_easy_setopt(handle, CURLOPT_HEADERDATA, NULL);
591 } 587 }
592 } 588 }
593 589
594 char* util_resource_name(char *url) { 590 const char* util_resource_name(const char *url) {
595 sstr_t urlstr = sstr(url); 591 cxstring urlstr = cx_str(url);
596 if(urlstr.ptr[urlstr.length-1] == '/') { 592 if(urlstr.ptr[urlstr.length-1] == '/') {
597 urlstr.length--; 593 urlstr.length--;
598 } 594 }
599 sstr_t resname = sstrrchr(urlstr, '/'); 595 cxstring resname = cx_strrchr(urlstr, '/');
600 if(resname.length > 1) { 596 if(resname.length > 1) {
601 return resname.ptr+1; 597 return resname.ptr+1;
602 } else { 598 } else {
603 return url; 599 return url;
604 } 600 }
611 return mkdir(path, mode); 607 return mkdir(path, mode);
612 #endif 608 #endif
613 } 609 }
614 610
615 char* util_concat_path(const char *url_base, const char *p) { 611 char* util_concat_path(const char *url_base, const char *p) {
616 sstr_t base = sstr((char*)url_base); 612 cxstring base = cx_str((char*)url_base);
617 sstr_t path; 613 cxstring path;
618 if(p) { 614 if(p) {
619 path = sstr((char*)p); 615 path = cx_str((char*)p);
620 } else { 616 } else {
621 path = sstrn("", 0); 617 path = CX_STR("");
622 } 618 }
623 619
624 int add_separator = 0; 620 int add_separator = 0;
625 if(base.length != 0 && base.ptr[base.length-1] == '/') { 621 if(base.length != 0 && base.ptr[base.length-1] == '/') {
626 if(path.ptr[0] == '/') { 622 if(path.ptr[0] == '/') {
630 if(path.length == 0 || path.ptr[0] != '/') { 626 if(path.length == 0 || path.ptr[0] != '/') {
631 add_separator = 1; 627 add_separator = 1;
632 } 628 }
633 } 629 }
634 630
635 sstr_t url; 631 cxmutstr url;
636 if(add_separator) { 632 if(add_separator) {
637 url = sstrcat(3, base, sstr("/"), path); 633 url = cx_strcat(3, base, CX_STR("/"), path);
638 } else { 634 } else {
639 url = sstrcat(2, base, path); 635 url = cx_strcat(2, base, path);
640 } 636 }
641 637
642 return url.ptr; 638 return url.ptr;
643 } 639 }
644 640
645 char* util_get_url(DavSession *sn, const char *href) { 641 char* util_get_url(DavSession *sn, const char *href) {
646 scstr_t base = scstr(sn->base_url); 642 cxstring base = cx_str(sn->base_url);
647 scstr_t href_str = scstr(href); 643 cxstring href_str = cx_str(href);
648 644
649 char *base_path = util_url_path(sn->base_url); 645 const char *base_path = util_url_path(sn->base_url);
650 base.length -= strlen(base_path); 646 base.length -= strlen(base_path);
651 647
652 sstr_t url = sstrcat(2, base, href_str); 648 cxmutstr url = cx_strcat(2, base, href_str);
653 return url.ptr; 649 return url.ptr;
654 } 650 }
655 651
656 void util_set_url(DavSession *sn, const char *href) { 652 void util_set_url(DavSession *sn, const char *href) {
657 char *url = util_get_url(sn, href); 653 char *url = util_get_url(sn, href);
658 curl_easy_setopt(sn->handle, CURLOPT_URL, url); 654 curl_easy_setopt(sn->handle, CURLOPT_URL, url);
659 free(url); 655 free(url);
660 } 656 }
661 657
662 char* util_path_to_url(DavSession *sn, char *path) { 658 char* util_path_to_url(DavSession *sn, const char *path) {
663 char *space = malloc(256); 659 CxBuffer url;
664 UcxBuffer *url = ucx_buffer_new(space, 256, UCX_BUFFER_AUTOEXTEND); 660 cxBufferInit(&url, NULL, 256, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND);
665 661
666 // add base url 662 // add base url
667 ucx_buffer_write(sn->base_url, 1, strlen(sn->base_url), url); 663 cxBufferWrite(sn->base_url, 1, strlen(sn->base_url), &url);
668 // remove trailing slash 664 // remove trailing slash
669 ucx_buffer_seek(url, -1, SEEK_CUR); 665 cxBufferSeek(&url, -1, SEEK_CUR);
670 666
671 sstr_t p = sstr(path); 667 cxstring p = cx_str(path);
672 ssize_t ntk = 0; 668
673 sstr_t *tks = sstrsplit(p, S("/"), &ntk); 669 CxStrtokCtx tkctx = cx_strtok(p, CX_STR("/"), INT_MAX);
674 670 cxstring node;
675 for(int i=0;i<ntk;i++) { 671 while(cx_strtok_next(&tkctx, &node)) {
676 sstr_t node = tks[i];
677 if(node.length > 0) { 672 if(node.length > 0) {
678 char *esc = curl_easy_escape(sn->handle, node.ptr, node.length); 673 char *esc = curl_easy_escape(sn->handle, node.ptr, node.length);
679 ucx_buffer_putc(url, '/'); 674 cxBufferPut(&url, '/');
680 ucx_buffer_write(esc, 1, strlen(esc), url); 675 cxBufferWrite(esc, 1, strlen(esc), &url);
681 curl_free(esc); 676 curl_free(esc);
682 } 677 }
683 free(node.ptr); 678 }
684 } 679
685 free(tks);
686 if(path[p.length-1] == '/') { 680 if(path[p.length-1] == '/') {
687 ucx_buffer_putc(url, '/'); 681 cxBufferPut(&url, '/');
688 } 682 }
689 ucx_buffer_putc(url, 0); 683 cxBufferPut(&url, 0);
690 684
691 space = url->space; 685 return url.space;
692 ucx_buffer_free(url);
693
694 return space;
695 } 686 }
696 687
697 char* util_parent_path(const char *path) { 688 char* util_parent_path(const char *path) {
698 char *name = util_resource_name((char*)path); 689 const char *name = util_resource_name(path);
699 size_t namelen = strlen(name); 690 size_t namelen = strlen(name);
700 size_t pathlen = strlen(path); 691 size_t pathlen = strlen(path);
701 size_t parentlen = pathlen - namelen; 692 size_t parentlen = pathlen - namelen;
702 char *parent = malloc(parentlen + 1); 693 char *parent = malloc(parentlen + 1);
703 memcpy(parent, path, parentlen); 694 memcpy(parent, path, parentlen);
950 } 941 }
951 942
952 return out; 943 return out;
953 } 944 }
954 945
955 char* util_encrypt_str(DavSession *sn, char *str, char *key) { 946 char* util_encrypt_str(DavSession *sn, const char *str, const char *key) {
956 DavKey *k = dav_context_get_key(sn->context, key); 947 DavKey *k = dav_context_get_key(sn->context, key);
957 if(!k) { 948 if(!k) {
958 sn->error = DAV_ERROR; 949 sn->error = DAV_ERROR;
959 sstr_t err = ucx_sprintf("Key %s not found", key); 950 cxmutstr err = cx_asprintf("Key %s not found", key);
960 dav_session_set_errstr(sn, err.ptr); 951 dav_session_set_errstr(sn, err.ptr);
961 free(err.ptr); 952 free(err.ptr);
962 return NULL; 953 return NULL;
963 } 954 }
964 955
965 return util_encrypt_str_k(sn, str, k); 956 return util_encrypt_str_k(sn, str, k);
966 } 957 }
967 958
968 char* util_encrypt_str_k(DavSession *sn, char *str, DavKey *key) { 959 char* util_encrypt_str_k(DavSession *sn, const char *str, DavKey *key) {
969 char *enc_str = aes_encrypt(str, strlen(str), key); 960 char *enc_str = aes_encrypt(str, strlen(str), key);
970 char *ret_str = dav_session_strdup(sn, enc_str); 961 char *ret_str = dav_session_strdup(sn, enc_str);
971 free(enc_str); 962 free(enc_str);
972 return ret_str; 963 return ret_str;
973 } 964 }
974 965
975 char* util_decrypt_str(DavSession *sn, char *str, char *key) { 966 char* util_decrypt_str(DavSession *sn, const char *str, const char *key) {
976 DavKey *k = dav_context_get_key(sn->context, key); 967 DavKey *k = dav_context_get_key(sn->context, key);
977 if(!k) { 968 if(!k) {
978 sn->error = DAV_ERROR; 969 sn->error = DAV_ERROR;
979 sstr_t err = ucx_sprintf("Key %s not found", key); 970 cxmutstr err = cx_asprintf("Key %s not found", key);
980 dav_session_set_errstr(sn, err.ptr); 971 dav_session_set_errstr(sn, err.ptr);
981 free(err.ptr); 972 free(err.ptr);
982 return NULL; 973 return NULL;
983 } 974 }
984 975
985 return util_decrypt_str_k(sn, str, k); 976 return util_decrypt_str_k(sn, str, k);
986 } 977 }
987 978
988 char* util_decrypt_str_k(DavSession *sn, char *str, DavKey *key) { 979 char* util_decrypt_str_k(DavSession *sn, const char *str, DavKey *key) {
989 size_t len = 0; 980 size_t len = 0;
990 char *dec_str = aes_decrypt(str, &len, key); 981 char *dec_str = aes_decrypt(str, &len, key);
991 char *ret_str = dav_session_strdup(sn, dec_str); 982 char *ret_str = dav_session_strdup(sn, dec_str);
992 free(dec_str); 983 free(dec_str);
993 return ret_str; 984 return ret_str;
995 986
996 char* util_random_str() { 987 char* util_random_str() {
997 unsigned char *str = malloc(25); 988 unsigned char *str = malloc(25);
998 str[24] = '\0'; 989 str[24] = '\0';
999 990
1000 sstr_t t = S( 991 cxstring t = CX_STR(
1001 "01234567890" 992 "01234567890"
1002 "abcdefghijklmnopqrstuvwxyz" 993 "abcdefghijklmnopqrstuvwxyz"
1003 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 994 "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
1004 const unsigned char *table = (const unsigned char*)t.ptr; 995 const unsigned char *table = (const unsigned char*)t.ptr;
1005 996
1019 /* 1010 /*
1020 * gets a substring from 0 to the appearance of the token 1011 * gets a substring from 0 to the appearance of the token
1021 * tokens are separated by space 1012 * tokens are separated by space
1022 * sets sub to the substring and returns the remaining string 1013 * sets sub to the substring and returns the remaining string
1023 */ 1014 */
1015 // TODO: remove if it isn't used
1016 /*
1024 sstr_t util_getsubstr_until_token(sstr_t str, sstr_t token, sstr_t *sub) { 1017 sstr_t util_getsubstr_until_token(sstr_t str, sstr_t token, sstr_t *sub) {
1025 int i; 1018 int i;
1026 int token_start = -1; 1019 int token_start = -1;
1027 int token_end = -1; 1020 int token_end = -1;
1028 for(i=0;i<=str.length;i++) { 1021 for(i=0;i<=str.length;i++) {
1058 str.ptr = NULL; 1051 str.ptr = NULL;
1059 str.length = 0; 1052 str.length = 0;
1060 return str; 1053 return str;
1061 } 1054 }
1062 } 1055 }
1063 1056 */
1064 sstr_t util_readline(FILE *stream) { 1057
1065 UcxBuffer *buf = ucx_buffer_new(NULL, 128, UCX_BUFFER_AUTOEXTEND); 1058 cxmutstr util_readline(FILE *stream) {
1059 CxBuffer buf;
1060 cxBufferInit(&buf, NULL, 128, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND);
1066 1061
1067 int c; 1062 int c;
1068 while((c = fgetc(stream)) != EOF) { 1063 while((c = fgetc(stream)) != EOF) {
1069 if(c == '\n') { 1064 if(c == '\n') {
1070 break; 1065 break;
1071 } 1066 }
1072 ucx_buffer_putc(buf, c); 1067 cxBufferPut(&buf, c);
1073 } 1068 }
1074 1069
1075 sstr_t str = sstrdup(sstrtrim(sstrn(buf->space, buf->size))); 1070 cxmutstr str = cx_strdup(cx_strtrim(cx_strn(buf.space, buf.size)));
1076 ucx_buffer_free(buf); 1071 cxBufferDestroy(&buf);
1077 return str; 1072 return str;
1078 } 1073 }
1079 1074
1080 char* util_password_input(char *prompt) { 1075 char* util_password_input(char *prompt) {
1081 fprintf(stderr, "%s", prompt); 1076 fprintf(stderr, "%s", prompt);
1095 } 1090 }
1096 1091
1097 #endif 1092 #endif
1098 1093
1099 // read password input 1094 // read password input
1100 UcxBuffer *buf = ucx_buffer_new(NULL, 128, UCX_BUFFER_AUTOEXTEND); 1095 CxBuffer buf;
1096 cxBufferInit(&buf, NULL, 128, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND);
1101 int c = 0; 1097 int c = 0;
1102 while((c = getpasswordchar()) != EOF) { 1098 while((c = getpasswordchar()) != EOF) {
1103 if(c == '\n' || c == '\r') { 1099 if(c == '\n' || c == '\r') {
1104 break; 1100 break;
1105 } 1101 }
1106 ucx_buffer_putc(buf, c); 1102 cxBufferPut(&buf, c);
1107 } 1103 }
1108 ucx_buffer_putc(buf, 0); 1104 cxBufferPut(&buf, 0);
1109 fflush(stdin); 1105 fflush(stdin);
1110 1106
1111 #ifndef _WIN32 1107 #ifndef _WIN32
1112 // restore terminal settings 1108 // restore terminal settings
1113 if (isatty(fileno(stdin)) && tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) { 1109 if (isatty(fileno(stdin)) && tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) {
1114 perror("tcsetattr"); 1110 perror("tcsetattr");
1115 } 1111 }
1116 #endif 1112 #endif
1117 1113
1118 char *str = buf->space; 1114 return buf.space;
1119 free(buf); // only free the UcxBuffer struct 1115 }
1120 return str; 1116
1121 } 1117 int util_exec_command(char *command, CxBuffer *outbuf) {
1122
1123 int util_exec_command(char *command, UcxBuffer *outbuf) {
1124 #ifdef _WIN32 1118 #ifdef _WIN32
1125 fprintf(stderr, "util_exec_command unsupported\n"); 1119 fprintf(stderr, "util_exec_command unsupported\n");
1126 return 1; 1120 return 1;
1127 #else 1121 #else
1128 1122
1154 1148
1155 if(!ret) { 1149 if(!ret) {
1156 ssize_t r; 1150 ssize_t r;
1157 char buf[1024]; 1151 char buf[1024];
1158 while((r = read(pout[0], buf, 1024)) > 0) { 1152 while((r = read(pout[0], buf, 1024)) > 0) {
1159 ucx_buffer_write(buf, 1, r, outbuf); 1153 cxBufferWrite(buf, 1, r, outbuf);
1160 } 1154 }
1161 } 1155 }
1162 1156
1163 // wait for child process 1157 // wait for child process
1164 ret = 1; 1158 ret = 1;
1171 #endif 1165 #endif
1172 } 1166 }
1173 1167
1174 char* util_hexstr(const unsigned char *data, size_t len) { 1168 char* util_hexstr(const unsigned char *data, size_t len) {
1175 size_t buflen = 2*len + 4; 1169 size_t buflen = 2*len + 4;
1176 UcxBuffer *buf = ucx_buffer_new(malloc(buflen), buflen + 1, 0); 1170 CxBuffer buf;
1171 cxBufferInit(&buf, NULL, buflen + 1, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND);
1177 for(int i=0;i<len;i++) { 1172 for(int i=0;i<len;i++) {
1178 ucx_bprintf(buf, "%02x", data[i]); 1173 cx_bprintf(&buf, "%02x", data[i]);
1179 } 1174 }
1180 ucx_buffer_putc(buf, 0); 1175 cxBufferPut(&buf, 0);
1181 char *str = buf->space; 1176 return buf.space;
1182 ucx_buffer_free(buf);
1183 return str;
1184 } 1177 }
1185 1178
1186 void util_remove_trailing_pathseparator(char *path) { 1179 void util_remove_trailing_pathseparator(char *path) {
1187 size_t len = strlen(path); 1180 size_t len = strlen(path);
1188 if(len < 2) { 1181 if(len < 2) {
1213 free(buf); 1206 free(buf);
1214 fclose(in); 1207 fclose(in);
1215 1208
1216 return util_hexstr(hash, DAV_SHA256_DIGEST_LENGTH); 1209 return util_hexstr(hash, DAV_SHA256_DIGEST_LENGTH);
1217 } 1210 }
1211
1212 struct regdestructor {
1213 cx_destructor_func destructor;
1214 void *data;
1215 };
1216
1217 static void call_destructor(struct regdestructor *d) {
1218 d->destructor(d->data);
1219 }
1220
1221 int util_regdestr(CxMempool *mp, void *data, cx_destructor_func destructor) {
1222 // the ucx maintainer doesn't like me anymore and forces me to
1223 // implement basic stuff by myself
1224 struct regdestructor *reg = cxMalloc(mp->allocator, sizeof(struct regdestructor));
1225 if(!reg) {
1226 return 1;
1227 }
1228 reg->destructor = destructor;
1229 reg->data = data;
1230 cxMempoolSetDestructor(mp, reg, (cx_destructor_func)call_destructor);
1231 return 0;
1232 }

mercurial