--- a/libidav/utils.c Tue Apr 16 11:46:53 2019 +0200 +++ b/libidav/utils.c Sat Apr 20 12:31:08 2019 +0200 @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2018 Olaf Wintermann. All rights reserved. + * Copyright 2019 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: @@ -455,6 +455,68 @@ return space; } +char* util_create_relative_path(const char *abspath, const char *base) { + size_t path_len = strlen(abspath); + size_t base_len = strlen(base); + + if(abspath[path_len-1] == '/') { + path_len--; + } + if(base[base_len-1] == '/') { + base_len--; + } + // get base parent + for(int i=base_len-1;i>=0;i--) { + if(base[i] == '/') { + base_len = i+1; + break; + } + } + + size_t max = path_len > base_len ? base_len : path_len; + + // get prefix of abspath and base + // this dir is the root of the link + size_t i; + size_t last_dir = 0; + for(i=0;i<max;i++) { + char c = abspath[i]; + if(c != base[i]) { + break; + } else if(c == '/') { + last_dir = i; + } + } + + char *ret = NULL; + UcxBuffer *out = NULL; + if(last_dir+1 < base_len) { + // base is deeper than the link root, we have to go backwards + int dircount = 0; + for(int i=last_dir+1;i<base_len;i++) { + if(base[i] == '/') { + dircount++; + } + } + + out = ucx_buffer_new(NULL, dircount*3+path_len-last_dir, UCX_BUFFER_AUTOEXTEND); + + for(int i=0;i<dircount;i++) { + ucx_buffer_puts(out, "../"); + } + } else { + out = ucx_buffer_new(NULL, 1024, path_len - last_dir); + } + + ucx_buffer_puts(out, abspath + last_dir + 1); + ucx_buffer_putc(out, 0); + out->flags = 0; + ret = out->space; + ucx_buffer_free(out); + + return ret; +} + void util_capture_header(CURL *handle, UcxMap* map) { if(map) {