--- a/libidav/utils.c Sun Apr 16 14:12:24 2023 +0200 +++ b/libidav/utils.c Fri Apr 21 21:25:32 2023 +0200 @@ -32,9 +32,10 @@ #include <string.h> #include <errno.h> #include <ctype.h> -#include <ucx/string.h> -#include <ucx/buffer.h> -#include <ucx/utils.h> +#include <cx/string.h> +#include <cx/buffer.h> +#include <cx/utils.h> +#include <cx/printf.h> #include <libxml/tree.h> #include <curl/curl.h> @@ -66,7 +67,7 @@ #include <openssl/rand.h> */ -static size_t extractval(sstr_t str, char *result, char delim) { +static size_t extractval(cxstring str, char *result, char delim) { size_t n = 0; for(size_t i = 0; i < str.length ; i++) { if(isdigit(str.ptr[i])) { @@ -93,19 +94,19 @@ char conv[16]; // work on the trimmed string - sstr_t date = sstrtrim(sstr(iso8601str)); + cxstring date = cx_strtrim(cx_str(iso8601str)); - sstr_t time = sstrchr(date, 'T'); + cxstring time = cx_strchr(date, 'T'); if(time.length == 0) { return 0; } date.length = time.ptr - date.ptr; time.ptr++; time.length--; - sstr_t tzinfo; - if((tzinfo = sstrchr(time, 'Z')).length > 0 || - (tzinfo = sstrchr(time, '+')).length > 0 || - (tzinfo = sstrchr(time, '-')).length > 0) { + cxstring tzinfo; + if((tzinfo = cx_strchr(time, 'Z')).length > 0 || + (tzinfo = cx_strchr(time, '+')).length > 0 || + (tzinfo = cx_strchr(time, '-')).length > 0) { time.length = tzinfo.ptr - time.ptr; } @@ -124,9 +125,9 @@ tparts.tm_year = val / 10000 - 1900; // parse time and skip possible fractional seconds - sstr_t frac; - if((frac = sstrchr(time, '.')).length > 0 || - (frac = sstrchr(time, ',')).length > 0) { + cxstring frac; + if((frac = cx_strchr(time, '.')).length > 0 || + (frac = cx_strchr(time, ',')).length > 0) { time.length = frac.ptr - time.ptr; } if((time.length != 6 && time.length != 8) @@ -144,7 +145,7 @@ // local time tparts.tm_isdst = -1; return mktime(&tparts); - } else if(!sstrcmp(tzinfo, S("Z"))) { + } else if(!cx_strcmp(tzinfo, cx_str("Z"))) { #ifdef __FreeBSD__ return timegm(&tparts); #else @@ -276,13 +277,13 @@ } } -char* util_url_base_s(sstr_t url) { +char* util_url_base_s(cxstring url) { size_t i = 0; if(url.length > 0) { int slmax; - if(sstrprefix(url, SC("http://"))) { + if(cx_strprefix(url, cx_str("http://"))) { slmax = 3; - } else if(sstrprefix(url, SC("https://"))) { + } else if(cx_strprefix(url, cx_str("https://"))) { slmax = 3; } else { slmax = 1; @@ -298,16 +299,16 @@ } } } - sstr_t server = sstrsubsl(url, 0, i); - return sstrdup(server).ptr; + cxstring server = cx_strsubsl(url, 0, i); + return cx_strdup(server).ptr; } char* util_url_base(char *url) { - return util_url_base_s(sstr(url)); + return util_url_base_s(cx_str(url)); } -char* util_url_path(char *url) { - char *path = NULL; +const char* util_url_path(const char *url) { + const char *path = NULL; size_t len = strlen(url); int slashcount = 0; int slmax; @@ -335,7 +336,7 @@ return path; } -char* util_url_decode(DavSession *sn, char *url) { +char* util_url_decode(DavSession *sn, const char *url) { char *unesc = curl_easy_unescape(sn->handle, url, strlen(url), NULL); char *ret = strdup(unesc); curl_free(unesc); @@ -345,24 +346,24 @@ static size_t util_header_callback(char *buffer, size_t size, size_t nitems, void *data) { - sstr_t sbuffer = sstrn(buffer, size*nitems); + cxstring sbuffer = cx_strn(buffer, size*nitems); - UcxMap *map = (UcxMap*) data; + CxMap *map = (CxMap*) data; // if we get a status line, clear the map and exit - if(sstrprefix(sbuffer, S("HTTP/"))) { - ucx_map_free_content(map, free); - ucx_map_clear(map); + if(cx_strprefix(sbuffer, cx_str("HTTP/"))) { + // TODO: use new map destructor ucx_map_free_content(map, free); + cxMapClear(map); return size*nitems; } // if we get the terminating CRLF, just exit - if(!sstrcmp(sbuffer, S("\r\n"))) { + if(!cx_strcmp(sbuffer, cx_str("\r\n"))) { return 2; } - sstr_t key = sbuffer; - sstr_t value = sstrchr(sbuffer, ':'); + cxstring key = sbuffer; + cxstring value = cx_strchr(sbuffer, ':'); if(value.length == 0) { return 0; // invalid header line @@ -371,19 +372,20 @@ key.length = value.ptr - key.ptr; value.ptr++; value.length--; - key = sstrlower(sstrtrim(key)); - value = sstrdup(sstrtrim(value)); + cxmutstr key_cp = cx_strdup(cx_strtrim(key)); + cx_strlower(key_cp); + cxmutstr value_cp = cx_strdup(cx_strtrim(value)); - ucx_map_sstr_put(map, key, value.ptr); + cxMapPut(map, cx_hash_key(key_cp.ptr, key_cp.length), value_cp.ptr); - free(key.ptr); + free(key_cp.ptr); return sbuffer.length; } int util_path_isrelated(const char *path1, const char *path2) { - scstr_t p1 = scstr(path1); - scstr_t p2 = scstr(path2); + cxstring p1 = cx_str(path1); + cxstring p2 = cx_str(path2); if(IS_PATH_SEPARATOR(p1.ptr[p1.length-1])) { p1.length--; @@ -396,11 +398,11 @@ return 0; } - if(!sstrcmp(p1, p2)) { + if(!cx_strcmp(p1, p2)) { return 1; } - if(sstrprefix(p2, p1)) { + if(cx_strprefix(p2, p1)) { if(IS_PATH_SEPARATOR(p2.ptr[p1.length])) { return 1; } @@ -434,10 +436,11 @@ char* util_path_normalize(const char *path) { size_t len = strlen(path); - UcxBuffer *buf = ucx_buffer_new(NULL, len+1, UCX_BUFFER_AUTOEXTEND); + CxBuffer buf; + cxBufferInit(&buf, NULL, len+1, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND); if(path[0] == '/') { - ucx_buffer_putc(buf, '/'); + cxBufferPut(&buf, '/'); } int add_separator = 0; @@ -453,25 +456,25 @@ } if(seg_len > 0) { - scstr_t seg = scstrn(seg_ptr, seg_len); - if(!sstrcmp(seg, SC(".."))) { - for(int j=buf->pos;j>=0;j--) { - char t = buf->space[j]; + cxstring seg = cx_strn(seg_ptr, seg_len); + if(!cx_strcmp(seg, CX_STR(".."))) { + for(int j=buf.pos;j>=0;j--) { + char t = buf.space[j]; if(IS_PATH_SEPARATOR(t) || j == 0) { - buf->pos = j; - buf->size = j; - buf->space[j] = 0; + buf.pos = j; + buf.size = j; + buf.space[j] = 0; add_separator = IS_PATH_SEPARATOR(t) ? 1 : 0; break; } } - } else if(!sstrcmp(seg, SC("."))) { + } else if(!cx_strcmp(seg, CX_STR("."))) { // ignore } else { if(add_separator) { - ucx_buffer_putc(buf, PATH_SEPARATOR); + cxBufferPut(&buf, PATH_SEPARATOR); } - ucx_buffer_write(seg_ptr, 1, seg_len, buf); + cxBufferWrite(seg_ptr, 1, seg_len, &buf); add_separator = 1; } } @@ -480,13 +483,9 @@ } } - ucx_buffer_putc(buf, 0); - + cxBufferPut(&buf, 0); - char *space = buf->space; - buf->flags = 0; // disable autofree - ucx_buffer_free(buf); - return space; + return buf.space; } static char* create_relative_path(const char *abspath, const char *base) { @@ -523,7 +522,7 @@ } char *ret = NULL; - UcxBuffer *out = NULL; + CxBuffer out; if(last_dir+1 < base_len) { // base is deeper than the link root, we have to go backwards int dircount = 0; @@ -533,22 +532,19 @@ } } - out = ucx_buffer_new(NULL, dircount*3+path_len-last_dir, UCX_BUFFER_AUTOEXTEND); + cxBufferInit(&out, NULL, dircount*3+path_len-last_dir, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND); for(int i=0;i<dircount;i++) { - ucx_buffer_puts(out, "../"); + cxBufferPutString(&out, "../"); } } else { - out = ucx_buffer_new(NULL, 1024, path_len - last_dir); + cxBufferInit(&out, NULL, path_len - last_dir, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND); } - ucx_buffer_puts(out, abspath + last_dir + 1); - ucx_buffer_putc(out, 0); - out->flags = 0; - ret = out->space; - ucx_buffer_free(out); + cxBufferPutString(&out, abspath + last_dir + 1); + cxBufferPut(&out, 0); - return ret; + return out.space; } #ifdef _WIN32 @@ -581,7 +577,7 @@ #endif -void util_capture_header(CURL *handle, UcxMap* map) { +void util_capture_header(CURL *handle, CxMap* map) { if(map) { curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, util_header_callback); curl_easy_setopt(handle, CURLOPT_HEADERDATA, map); @@ -591,12 +587,12 @@ } } -char* util_resource_name(char *url) { - sstr_t urlstr = sstr(url); +const char* util_resource_name(const char *url) { + cxstring urlstr = cx_str(url); if(urlstr.ptr[urlstr.length-1] == '/') { urlstr.length--; } - sstr_t resname = sstrrchr(urlstr, '/'); + cxstring resname = cx_strrchr(urlstr, '/'); if(resname.length > 1) { return resname.ptr+1; } else { @@ -613,12 +609,12 @@ } char* util_concat_path(const char *url_base, const char *p) { - sstr_t base = sstr((char*)url_base); - sstr_t path; + cxstring base = cx_str((char*)url_base); + cxstring path; if(p) { - path = sstr((char*)p); + path = cx_str((char*)p); } else { - path = sstrn("", 0); + path = CX_STR(""); } int add_separator = 0; @@ -632,24 +628,24 @@ } } - sstr_t url; + cxmutstr url; if(add_separator) { - url = sstrcat(3, base, sstr("/"), path); + url = cx_strcat(3, base, CX_STR("/"), path); } else { - url = sstrcat(2, base, path); + url = cx_strcat(2, base, path); } return url.ptr; } char* util_get_url(DavSession *sn, const char *href) { - scstr_t base = scstr(sn->base_url); - scstr_t href_str = scstr(href); + cxstring base = cx_str(sn->base_url); + cxstring href_str = cx_str(href); - char *base_path = util_url_path(sn->base_url); + const char *base_path = util_url_path(sn->base_url); base.length -= strlen(base_path); - sstr_t url = sstrcat(2, base, href_str); + cxmutstr url = cx_strcat(2, base, href_str); return url.ptr; } @@ -659,43 +655,38 @@ free(url); } -char* util_path_to_url(DavSession *sn, char *path) { - char *space = malloc(256); - UcxBuffer *url = ucx_buffer_new(space, 256, UCX_BUFFER_AUTOEXTEND); +char* util_path_to_url(DavSession *sn, const char *path) { + CxBuffer url; + cxBufferInit(&url, NULL, 256, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND); // add base url - ucx_buffer_write(sn->base_url, 1, strlen(sn->base_url), url); + cxBufferWrite(sn->base_url, 1, strlen(sn->base_url), &url); // remove trailing slash - ucx_buffer_seek(url, -1, SEEK_CUR); + cxBufferSeek(&url, -1, SEEK_CUR); - sstr_t p = sstr(path); - ssize_t ntk = 0; - sstr_t *tks = sstrsplit(p, S("/"), &ntk); + cxstring p = cx_str(path); - for(int i=0;i<ntk;i++) { - sstr_t node = tks[i]; + CxStrtokCtx tkctx = cx_strtok(p, CX_STR("/"), INT_MAX); + cxstring node; + while(cx_strtok_next(&tkctx, &node)) { if(node.length > 0) { char *esc = curl_easy_escape(sn->handle, node.ptr, node.length); - ucx_buffer_putc(url, '/'); - ucx_buffer_write(esc, 1, strlen(esc), url); + cxBufferPut(&url, '/'); + cxBufferWrite(esc, 1, strlen(esc), &url); curl_free(esc); } - free(node.ptr); - } - free(tks); - if(path[p.length-1] == '/') { - ucx_buffer_putc(url, '/'); } - ucx_buffer_putc(url, 0); - space = url->space; - ucx_buffer_free(url); + if(path[p.length-1] == '/') { + cxBufferPut(&url, '/'); + } + cxBufferPut(&url, 0); - return space; + return url.space; } char* util_parent_path(const char *path) { - char *name = util_resource_name((char*)path); + const char *name = util_resource_name(path); size_t namelen = strlen(name); size_t pathlen = strlen(path); size_t parentlen = pathlen - namelen; @@ -952,11 +943,11 @@ return out; } -char* util_encrypt_str(DavSession *sn, char *str, char *key) { +char* util_encrypt_str(DavSession *sn, const char *str, const char *key) { DavKey *k = dav_context_get_key(sn->context, key); if(!k) { sn->error = DAV_ERROR; - sstr_t err = ucx_sprintf("Key %s not found", key); + cxmutstr err = cx_asprintf("Key %s not found", key); dav_session_set_errstr(sn, err.ptr); free(err.ptr); return NULL; @@ -965,18 +956,18 @@ return util_encrypt_str_k(sn, str, k); } -char* util_encrypt_str_k(DavSession *sn, char *str, DavKey *key) { +char* util_encrypt_str_k(DavSession *sn, const char *str, DavKey *key) { char *enc_str = aes_encrypt(str, strlen(str), key); char *ret_str = dav_session_strdup(sn, enc_str); free(enc_str); return ret_str; } -char* util_decrypt_str(DavSession *sn, char *str, char *key) { +char* util_decrypt_str(DavSession *sn, const char *str, const char *key) { DavKey *k = dav_context_get_key(sn->context, key); if(!k) { sn->error = DAV_ERROR; - sstr_t err = ucx_sprintf("Key %s not found", key); + cxmutstr err = cx_asprintf("Key %s not found", key); dav_session_set_errstr(sn, err.ptr); free(err.ptr); return NULL; @@ -985,7 +976,7 @@ return util_decrypt_str_k(sn, str, k); } -char* util_decrypt_str_k(DavSession *sn, char *str, DavKey *key) { +char* util_decrypt_str_k(DavSession *sn, const char *str, DavKey *key) { size_t len = 0; char *dec_str = aes_decrypt(str, &len, key); char *ret_str = dav_session_strdup(sn, dec_str); @@ -997,7 +988,7 @@ unsigned char *str = malloc(25); str[24] = '\0'; - sstr_t t = S( + cxstring t = CX_STR( "01234567890" "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); @@ -1021,6 +1012,8 @@ * tokens are separated by space * sets sub to the substring and returns the remaining string */ +// TODO: remove if it isn't used +/* sstr_t util_getsubstr_until_token(sstr_t str, sstr_t token, sstr_t *sub) { int i; int token_start = -1; @@ -1060,20 +1053,22 @@ return str; } } +*/ -sstr_t util_readline(FILE *stream) { - UcxBuffer *buf = ucx_buffer_new(NULL, 128, UCX_BUFFER_AUTOEXTEND); +cxmutstr util_readline(FILE *stream) { + CxBuffer buf; + cxBufferInit(&buf, NULL, 128, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND); int c; while((c = fgetc(stream)) != EOF) { if(c == '\n') { break; } - ucx_buffer_putc(buf, c); + cxBufferPut(&buf, c); } - sstr_t str = sstrdup(sstrtrim(sstrn(buf->space, buf->size))); - ucx_buffer_free(buf); + cxmutstr str = cx_strdup(cx_strtrim(cx_strn(buf.space, buf.size))); + cxBufferDestroy(&buf); return str; } @@ -1097,15 +1092,16 @@ #endif // read password input - UcxBuffer *buf = ucx_buffer_new(NULL, 128, UCX_BUFFER_AUTOEXTEND); + CxBuffer buf; + cxBufferInit(&buf, NULL, 128, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND); int c = 0; while((c = getpasswordchar()) != EOF) { if(c == '\n' || c == '\r') { break; } - ucx_buffer_putc(buf, c); + cxBufferPut(&buf, c); } - ucx_buffer_putc(buf, 0); + cxBufferPut(&buf, 0); fflush(stdin); #ifndef _WIN32 @@ -1115,12 +1111,10 @@ } #endif - char *str = buf->space; - free(buf); // only free the UcxBuffer struct - return str; + return buf.space; } -int util_exec_command(char *command, UcxBuffer *outbuf) { +int util_exec_command(char *command, CxBuffer *outbuf) { #ifdef _WIN32 fprintf(stderr, "util_exec_command unsupported\n"); return 1; @@ -1156,7 +1150,7 @@ ssize_t r; char buf[1024]; while((r = read(pout[0], buf, 1024)) > 0) { - ucx_buffer_write(buf, 1, r, outbuf); + cxBufferWrite(buf, 1, r, outbuf); } } @@ -1173,14 +1167,13 @@ char* util_hexstr(const unsigned char *data, size_t len) { size_t buflen = 2*len + 4; - UcxBuffer *buf = ucx_buffer_new(malloc(buflen), buflen + 1, 0); + CxBuffer buf; + cxBufferInit(&buf, NULL, buflen + 1, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND); for(int i=0;i<len;i++) { - ucx_bprintf(buf, "%02x", data[i]); + cx_bprintf(&buf, "%02x", data[i]); } - ucx_buffer_putc(buf, 0); - char *str = buf->space; - ucx_buffer_free(buf); - return str; + cxBufferPut(&buf, 0); + return buf.space; } void util_remove_trailing_pathseparator(char *path) { @@ -1215,3 +1208,25 @@ return util_hexstr(hash, DAV_SHA256_DIGEST_LENGTH); } + +struct regdestructor { + cx_destructor_func destructor; + void *data; +}; + +static void call_destructor(struct regdestructor *d) { + d->destructor(d->data); +} + +int util_regdestr(CxMempool *mp, void *data, cx_destructor_func destructor) { + // the ucx maintainer doesn't like me anymore and forces me to + // implement basic stuff by myself + struct regdestructor *reg = cxMalloc(mp->allocator, sizeof(struct regdestructor)); + if(!reg) { + return 1; + } + reg->destructor = destructor; + reg->data = data; + cxMempoolSetDestructor(mp, reg, (cx_destructor_func)call_destructor); + return 0; +}