395 } |
395 } |
396 } |
396 } |
397 |
397 |
398 return 0; |
398 return 0; |
399 } |
399 } |
|
400 |
|
401 char* util_path_normalize(const char *path) { |
|
402 size_t len = strlen(path); |
|
403 UcxBuffer *buf = ucx_buffer_new(NULL, len+1, UCX_BUFFER_AUTOEXTEND); |
|
404 |
|
405 if(path[0] == '/') { |
|
406 ucx_buffer_putc(buf, '/'); |
|
407 } |
|
408 |
|
409 int add_separator = 0; |
|
410 int seg_start = 0; |
|
411 for(int i=0;i<=len;i++) { |
|
412 char c = path[i]; |
|
413 if(c == '/' || c == '\0') { |
|
414 const char *seg_ptr = path+seg_start; |
|
415 int seg_len = i - seg_start; |
|
416 if(seg_ptr[0] == '/') { |
|
417 seg_ptr++; |
|
418 seg_len--; |
|
419 } |
|
420 |
|
421 if(seg_len > 0) { |
|
422 scstr_t seg = scstrn(seg_ptr, seg_len); |
|
423 if(!sstrcmp(seg, SC(".."))) { |
|
424 for(int j=buf->pos;j>=0;j--) { |
|
425 char t = buf->space[j]; |
|
426 if(t == '/' || j == 0) { |
|
427 buf->pos = j; |
|
428 buf->size = j; |
|
429 buf->space[j] = 0; |
|
430 add_separator = t == '/' ? 1 : 0; |
|
431 break; |
|
432 } |
|
433 } |
|
434 } else if(!sstrcmp(seg, SC("."))) { |
|
435 // ignore |
|
436 } else { |
|
437 if(add_separator) { |
|
438 ucx_buffer_putc(buf, '/'); |
|
439 } |
|
440 ucx_buffer_write(seg_ptr, 1, seg_len, buf); |
|
441 add_separator = 1; |
|
442 } |
|
443 } |
|
444 |
|
445 seg_start = i; |
|
446 } |
|
447 } |
|
448 |
|
449 ucx_buffer_putc(buf, 0); |
|
450 |
|
451 |
|
452 char *space = buf->space; |
|
453 buf->flags = 0; // disable autofree |
|
454 ucx_buffer_free(buf); |
|
455 return space; |
|
456 } |
|
457 |
400 |
458 |
401 void util_capture_header(CURL *handle, UcxMap* map) { |
459 void util_capture_header(CURL *handle, UcxMap* map) { |
402 if(map) { |
460 if(map) { |
403 curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, util_header_callback); |
461 curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, util_header_callback); |
404 curl_easy_setopt(handle, CURLOPT_HEADERDATA, map); |
462 curl_easy_setopt(handle, CURLOPT_HEADERDATA, map); |