diff -r 29d544c3c2b8 -r 05647e862a17 dav/config.c --- a/dav/config.c Sun Sep 17 13:51:01 2023 +0200 +++ b/dav/config.c Sat Sep 30 16:33:47 2023 +0200 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -38,7 +39,10 @@ #include "config.h" #include "main.h" #include "pwd.h" +#include "system.h" + #include +#include #define xstreq(a,b) xmlStrEqual(BAD_CAST a, BAD_CAST b) #define xstrEQ(a,b) !xmlStrcasecmp(BAD_CAST a, BAD_CAST b) @@ -64,6 +68,7 @@ static CxMap *repos; static CxMap *keys; +static DavConfig *davconfig; static PwdStore *pstore; static char *secretstore_unlock_cmd; @@ -101,6 +106,20 @@ return path; } +cxmutstr config_load_file(const char *path) { + FILE *file = sys_fopen(path, "r"); + if(!file) { + return (cxmutstr){NULL,0}; + } + + CxBuffer buf; + cxBufferInit(&buf, NULL, 1024, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND); + cx_stream_copy(file, &buf, (cx_read_func)fread, (cx_write_func)cxBufferWrite); + fclose(file); + + return cx_mutstrn(buf.space, buf.size); +} + int load_config(DavContext *ctx) { context = ctx; // TODO: free the config somewhere @@ -127,6 +146,12 @@ } xmlDoc *doc = xmlReadFile(file, NULL, 0); + + cxmutstr config_content = config_load_file(file); + int config_error; + davconfig = dav_config_load(config_content, &config_error); + free(config_content.ptr); + free(file); if(!doc) { fprintf(stderr, "Cannot load config.xml\n"); @@ -162,6 +187,39 @@ return ret; } +DavConfig* get_config(void) { + return davconfig; +} + +int store_config(void) { + if(check_config_dir()) { + return 1; + } + + CxBuffer *buf = dav_config2buf(davconfig); + if(!buf) { + return 1; + } + + char *file = util_concat_path(ENV_HOME, ".dav/config.xml"); + FILE *cout = sys_fopen(file, "w"); + if(!cout) { + cxBufferFree(buf); + return 1; + } + + // should only fail if we run out of disk space or something like that + // in that case, the config file is only destroyed + // could only be prevented, if we write to a temp file first and than + // rename it + fwrite(buf->space, buf->size, 1, cout); + + cxBufferFree(buf); + fclose(cout); + + return 0; +} + void free_config(void) { if(repos) { CxIterator i = cxMapIteratorValues(repos); @@ -813,7 +871,7 @@ - +/* Repository* url2repo_s(cxstring url, char **path) { *path = NULL; @@ -867,6 +925,7 @@ Repository* url2repo(const char *url, char **path) { return url2repo_s(cx_str(url), path); } +*/ static int decrypt_secrets(CmdArgs *a, PwdStore *secrets) { if(cmd_getoption(a, "noinput")) { @@ -960,7 +1019,7 @@ } -static int get_location_credentials(CmdArgs *a, Repository *repo, char *path, char **user, char **password) { +static int get_location_credentials(CmdArgs *a, DavCfgRepository *repo, const char *path, char **user, char **password) { PwdStore *secrets = get_pwdstore(); if(!secrets) { return 0; @@ -976,19 +1035,20 @@ cx_foreach(PwdIndexEntry*, e, i) { CxIterator entry_iter = cxListIterator(e->locations); cx_foreach(char *, loc, entry_iter) { - char *path; - Repository *r = url2repo(loc, &path); + cxmutstr rpath; + DavCfgRepository *r = dav_config_url2repo_s(davconfig, cx_str(loc), &rpath); CredLocation *urlentry = calloc(1, sizeof(CredLocation)); urlentry->id = e->id; - urlentry->location = util_concat_path(r->url, path); + urlentry->location = util_concat_path_s(cx_strcast(r->url.value), cx_strcast(rpath)).ptr; cxListAdd(locations, urlentry); + free(rpath.ptr); } } // the list must be sorted cxListSort(locations); // create full request url string and remove protocol prefix - cxmutstr req_url_proto = cx_mutstr(util_concat_path(repo->url, path)); + cxmutstr req_url_proto = util_concat_path_s(cx_strcast(repo->url.value), cx_str(path)); cxstring req_url = cx_strcast(req_url_proto); if(cx_strprefix(req_url, CX_STR("http://"))) { req_url = cx_strsubs(req_url, 7); @@ -1034,25 +1094,31 @@ return ret; } -DavSession* connect_to_repo(DavContext *ctx, Repository *repo, char *path, dav_auth_func authfunc, CmdArgs *a) { - char *user = repo->user; - char *password = repo->password; +DavSession* connect_to_repo(DavContext *ctx, DavCfgRepository *repo, const char *path, dav_auth_func authfunc, CmdArgs *a) { + cxmutstr decodedpw = dav_repository_get_decodedpassword(repo); + + char *user = repo->user.value.ptr; + char *password = decodedpw.ptr; if(!user && !password) { - if(!get_stored_credentials(a, repo->stored_user, &user, &password)) { + if(!get_stored_credentials(a, repo->stored_user.value.ptr, &user, &password)) { get_location_credentials(a, repo, path, &user, &password); } } - DavSession *sn = dav_session_new_auth(ctx, repo->url, user, password); - sn->flags = get_repository_flags(repo); - sn->key = dav_context_get_key(ctx, repo->default_key); + DavSession *sn = dav_session_new_auth(ctx, repo->url.value.ptr, user, password); + if(password) { + free(password); + } + + sn->flags = dav_repository_get_flags(repo); + sn->key = dav_context_get_key(ctx, repo->default_key.value.ptr); curl_easy_setopt(sn->handle, CURLOPT_HTTPAUTH, repo->authmethods); curl_easy_setopt(sn->handle, CURLOPT_SSLVERSION, repo->ssl_version); - if(repo->cert) { - curl_easy_setopt(sn->handle, CURLOPT_CAINFO, repo->cert); + if(repo->cert.value.ptr) { + curl_easy_setopt(sn->handle, CURLOPT_CAINFO, repo->cert.value.ptr); } - if(!repo->verification || cmd_getoption(a, "insecure")) { + if(!repo->verification.value || cmd_getoption(a, "insecure")) { curl_easy_setopt(sn->handle, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(sn->handle, CURLOPT_SSL_VERIFYHOST, 0); }