remove old config loader

Sat, 30 Sep 2023 17:26:00 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 30 Sep 2023 17:26:00 +0200
changeset 796
81e0f67386a6
parent 795
05647e862a17
child 797
edbb20b1438d

remove old config loader

dav/config.c file | annotate | diff | comparison | revisions
dav/config.h file | annotate | diff | comparison | revisions
dav/main.c file | annotate | diff | comparison | revisions
libidav/config.c file | annotate | diff | comparison | revisions
libidav/config.h file | annotate | diff | comparison | revisions
libidav/session.c file | annotate | diff | comparison | revisions
libidav/webdav.h file | annotate | diff | comparison | revisions
--- a/dav/config.c	Sat Sep 30 16:33:47 2023 +0200
+++ b/dav/config.c	Sat Sep 30 17:26:00 2023 +0200
@@ -145,46 +145,18 @@
         return 1;
     }
     
-    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);
     
-    free(file);
-    if(!doc) {
+    if(!davconfig) {
         fprintf(stderr, "Cannot load config.xml\n");
         return 1;
     }
     
-    xmlNode *xml_root = xmlDocGetRootElement(doc);
-    xmlNode *node = xml_root->children;
-    int ret = 0;
-    while(node && !ret) {
-        if(node->type == XML_ELEMENT_NODE) {
-            if(xstreq(node->name, "repository")) {
-                ret = load_repository(node);
-            } else if(xstreq(node->name, "key")) {
-                ret = load_key(node);
-            } else if (xstreq(node->name, "http-proxy")) {
-                ret = load_proxy(ctx->http_proxy, node, HTTP_PROXY);
-            } else if (xstreq(node->name, "https-proxy")) {
-                ret = load_proxy(ctx->https_proxy, node, HTTPS_PROXY);
-            } else if (xstreq(node->name, "namespace")) {
-                ret = load_namespace(node);
-            } else if (xstreq(node->name, "secretstore")) {
-                ret = load_secretstore(node);
-            } else {
-                fprintf(stderr, "Unknown config element: %s\n", node->name);
-                ret = 1;
-            }
-        }
-        node = node->next;
-    }
-    
-    xmlFreeDoc(doc);
-    return ret;
+    return dav_config_register_keys(davconfig, ctx, load_key_file);
 }
 
 DavConfig* get_config(void) {
@@ -221,325 +193,8 @@
 }
 
 void free_config(void) {
-    if(repos) {
-        CxIterator i = cxMapIteratorValues(repos);
-        Repository *repo;
-        cx_foreach(Repository*, repo, i) {
-            if(repo->default_key) {
-                free(repo->default_key);
-            }
-            if(repo->name) {
-                free(repo->name);
-            }
-            if(repo->password) {
-                free(repo->password);
-            }
-            if(repo->url) {
-                free(repo->url);
-            }
-            if(repo->user) {
-                free(repo->user);
-            }
-            if(repo->cert) {
-                free(repo->cert);
-            }      
-            free(repo);
-        }
-        cxMapDestroy(repos);
-    }
-    if(keys) {
-        cxMapDestroy(keys);
-    }
-}
-
-Repository* repository_new(void) {
-    Repository *repo = calloc(1, sizeof(Repository));
-    repo->encrypt_name = false;
-    repo->encrypt_content = false;
-    repo->encrypt_properties = false;
-    repo->decrypt_name = false;
-    repo->decrypt_content = true;
-    repo->decrypt_properties = false;
-    repo->verification = true;
-    repo->ssl_version = CURL_SSLVERSION_DEFAULT;
-    repo->authmethods = CURLAUTH_BASIC;
-    return repo;
-}
-
-static int repo_add_config(Repository *repo, const xmlNode* node) {
-    unsigned short lineno = node->line;
-    char *key = (char*)node->name;
-    char *value = util_xml_get_text(node);
-
-    /* every key needs a value */
-    if(!value) {
-        /* TODO: maybe this should only be reported, if the key is valid
-         * But this makes the code very ugly.
-         */
-        print_error(lineno, "missing value for config element: %s\n", key);
-        return 1;
-    }
-    
-    if(xstreq(key, "name")) {
-        repo->name = strdup(value);
-    } else if(xstreq(key, "url")) {
-        repo->url = strdup(value);
-    } else if(xstreq(key, "user")) {
-        repo->user = strdup(value);
-    } else if(xstreq(key, "password")) {
-        repo->password = util_base64decode(value);
-    } else if(xstreq(key, "stored-user")) {
-        repo->stored_user = strdup(value);
-    } else if(xstreq(key, "default-key")) {
-        repo->default_key = strdup(value);
-    } else if(xstreq(key, "full-encryption")) {
-        if(util_getboolean(value)) {
-            repo->encrypt_name = true;
-            repo->encrypt_content = true;
-            repo->encrypt_properties = true;
-            repo->decrypt_name = true;
-            repo->decrypt_content = true;
-            repo->decrypt_properties = true;
-        }
-    } else if(xstreq(key, "content-encryption")) {
-        if(util_getboolean(value)) {
-            repo->encrypt_content = true;
-            repo->decrypt_content = true;
-        } else {
-            repo->encrypt_content = false;
-        }
-    } else if(xstreq(key, "decrypt-content")) {
-        repo->decrypt_content = util_getboolean(value);
-    } else if(xstreq(key, "decrypt-name")) {
-        repo->decrypt_name = util_getboolean(value);
-    } else if(xstreq(key, "cert")) {
-        char *configdir = util_concat_path(ENV_HOME, ".dav");
-        char *certfile = util_concat_path(configdir, value);
-        repo->cert = certfile;
-        free(configdir);
-    } else if(xstreq(key, "verification")) {
-        repo->verification = util_getboolean(value);
-    } else if(xstreq(key, "ssl-version")) {
-        if(xstrEQ(value, "TLSv1")) {
-            repo->ssl_version = CURL_SSLVERSION_TLSv1;
-        } else if(xstrEQ(value, "SSLv2")) {
-            repo->ssl_version = CURL_SSLVERSION_SSLv2;
-        } else if(xstrEQ(value, "SSLv3")) {
-            repo->ssl_version = CURL_SSLVERSION_SSLv3;
-        }
-#if LIBCURL_VERSION_MAJOR >= 7
-#if LIBCURL_VERSION_MINOR >= 34
-        else if(xstrEQ(value, "TLSv1.0")) {
-            repo->ssl_version = CURL_SSLVERSION_TLSv1_0;
-        } else if(xstrEQ(value, "TLSv1.1")) {
-            repo->ssl_version = CURL_SSLVERSION_TLSv1_1;
-        } else if(xstrEQ(value, "TLSv1.2")) {
-            repo->ssl_version = CURL_SSLVERSION_TLSv1_2;
-        }
-#endif
-#if LIBCURL_VERSION_MINOR >= 52
-        else if(xstrEQ(value, "TLSv1.3")) {
-            repo->ssl_version = CURL_SSLVERSION_TLSv1_3;
-        }
-#endif
-#endif
-        else {
-            print_warning(lineno, "unknown ssl version: %s\n", value);
-        }
-    } else if(xstreq(key, "authmethods")) {
-        repo->authmethods = CURLAUTH_NONE;
-        const char *delims = " \t\r\n";
-        char *meths = strdup(value);
-        char *meth = strtok(meths, delims);
-        while (meth) {
-            if(xstrEQ(meth, "basic")) {
-                repo->authmethods |= CURLAUTH_BASIC;
-            } else if(xstrEQ(meth, "digest")) {
-                repo->authmethods |= CURLAUTH_DIGEST;
-            } else if(xstrEQ(meth, "negotiate")) {
-                repo->authmethods |= CURLAUTH_GSSNEGOTIATE;
-            } else if(xstrEQ(meth, "ntlm")) {
-                repo->authmethods |= CURLAUTH_NTLM;
-            } else if(xstrEQ(meth, "any")) {
-                repo->authmethods = CURLAUTH_ANY;
-            } else if(xstrEQ(meth, "none")) {
-                /* skip */
-            } else {
-                print_warning(lineno,
-                        "unknown authentication method: %s\n", meth);
-            }
-            meth = strtok(NULL, delims);
-        }
-        free(meths);
-    } else {
-        print_error(lineno, "unkown repository config element: %s\n", key);
-        return 1;
-    }
-    return 0;
-}
-
-int load_repository(const xmlNode *reponode) {
-    Repository *repo = repository_new();
-    {
-        xmlNode *node = reponode->children;
-        int ret = 0;
-        while(node && !ret) {
-            if(node->type == XML_ELEMENT_NODE) {
-                ret = repo_add_config(repo, node);
-            }
-            node = node->next;
-        }
-        if(ret) {
-            free(repo);
-            return 1;
-        }
-    }
-    
-    if(!repo->name) {
-        print_error(reponode->line, "missing name for repository.\n");
-        return 1;
-    }
-    if(!repo->url) {
-        print_error(reponode->line,
-                "missing url for repository '%s'.\n", repo->name);
-        return 1;
-    }
-    
-    cxMapPut(repos, cx_hash_key_str(repo->name), repo);
-    return 0;
-}
-
-int load_proxy(DavProxy *proxy, const xmlNode *proxynode, int type) {
-    const char *stype;
-    if(type == HTTPS_PROXY) {
-        stype = "https";
-    } else if(type == HTTP_PROXY) {
-        stype = "http";
-    }
-    
-    if(!proxy) {
-        // no xml error - so report this directly via fprintf
-        fprintf(stderr, "no memory reserved for %s proxy.\n", stype);
-        return 1;
-    }
-    
-    xmlNode *node = proxynode->children;
-    int ret = 0;
-    while(node && !ret) {
-        if(node->type == XML_ELEMENT_NODE) {
-            char *value = util_xml_get_text(node);
-            int reportmissingvalue = 0;
-            if(xstreq(node->name, "url")) {
-                if(!(reportmissingvalue = !value)) {
-                    proxy->url = strdup(value);
-                }
-            } else if(xstreq(node->name, "user")) {
-                if(!(reportmissingvalue = !value)) {
-                    proxy->username = strdup(value);
-                }
-            } else if(xstreq(node->name, "password")) {
-                if(!(reportmissingvalue = !value)) {
-                    proxy->password = util_base64decode(value);
-                }
-            } else if(xstreq(node->name, "no")) {
-                if(!(reportmissingvalue = !value)) {
-                    proxy->no_proxy = strdup(value);
-                }
-            } else {
-                print_error(node->line,
-                        "invalid element for proxy config: %s\n", node->name);
-                ret = 1;
-            }
-            if (reportmissingvalue) {
-                print_error(node->line,
-                        "missing value for proxy configuration element: %s\n",
-                        node->name);
-                ret = 1;
-            }
-        }
-        node = node->next;
-    }
-    
-    if(!ret && !proxy->url) {
-        print_error(proxynode->line, "missing url for %s proxy.\n", stype);
-        return 1;
-    }
-    
-    return ret;
-}
-
-int load_key(const xmlNode *keynode) {
-    xmlNode *node = keynode->children;
-    Key *key = calloc(1, sizeof(Key));
-    key->type = KEY_AES256;
-    
-    int error = 0;
-    while(node) {
-        if(node->type == XML_ELEMENT_NODE) {
-            char *value = util_xml_get_text(node);
-            if(!value) {
-                // next
-            } else if(xstreq(node->name, "name")) {
-                key->name = strdup(value);
-            } else if(xstreq(node->name, "file")) {
-                // load key file
-                cxmutstr key_data = load_key_file(value);
-                if(key_data.length > 0) {
-                    key->data = key_data.ptr;
-                    key->length = key_data.length;
-                } else {
-                    print_error(node->line,
-                            "cannot get key from file: %s\n", value);
-                    error = 1;
-                }
-            } else if(xstreq(node->name, "type")) {
-                if(!strcmp(value, "aes128")) {
-                    key->type = KEY_AES128;
-                } else if(!strcmp(value, "aes256")) {
-                    key->type = KEY_AES256;
-                } else {
-                    print_error(node->line, "unknown key type %s\n", value);
-                    error = 1;
-                }
-            }
-                
-        }
-        node = node->next;
-    }
-    
-    if(!error && key->name) {
-        error = 0;
-        size_t expected_length = 0;
-        if(key->type == KEY_AES128) {
-            expected_length = 16;
-        }
-        if(key->type == KEY_AES256) {
-            expected_length = 32;
-        }
-        if(key->length < expected_length) {
-            print_error(keynode->line, "key %s is too small (%zu < %zu)\n",
-                    key->name,
-                    key->length,
-                    expected_length);
-            error = 1;
-        }
-        
-        // add key to context
-        if(!error) {
-            cxMapPut(keys, cx_hash_key_str(key->name), key);
-            dav_context_add_key(context, key);
-        }
-    }
-    
-    // cleanup
-    if(error) {
-        if(key->data) {
-            free(key->data);
-        }
-        free(key);
-        return 1;
-    } else {
-        return 0;
+    if(davconfig) {
+        dav_config_free(davconfig);
     }
 }
 
@@ -550,16 +205,17 @@
     
     FILE *file = NULL;
     if(filename[0] == '/') {
-        file = fopen(filename, "r");
+        file = sys_fopen(filename, "r");
     } else {
         char *path = util_concat_path(ENV_HOME, ".dav/");
         char *p2 = util_concat_path(path, filename);
-        file = fopen(p2, "r");
+        file = sys_fopen(p2, "r");
         free(path);
         free(p2);
     }
     
     if(!file) {
+        fprintf(stderr, "Error: cannot load keyfile %s\n", filename);
         return k;
     }
     
@@ -572,6 +228,16 @@
     return k;
 }
 
+int list_repositories(void) {
+    if(!davconfig) {
+        return 1;
+    }
+    for(DavCfgRepository *repo=davconfig->repositories;repo;repo=repo->next) {
+        printf("%.*s\n", (int)repo->name.value.length, repo->name.value.ptr);
+    }
+    return 0;
+}
+
 static char* get_attr_content(xmlNode *node) {
     // TODO: remove code duplication (util_xml_get_text)
     while(node) {
@@ -654,206 +320,6 @@
     return error;
 }
 
-Repository* get_repository(cxstring name) {
-    if(!name.ptr) {
-        return NULL;
-    }
-    return cxMapGet(repos, cx_hash_key(name.ptr, name.length));
-}
-
-int get_repository_flags(Repository *repo) {
-    int flags = 0;
-    if(repo->decrypt_content) {
-        flags |= DAV_SESSION_DECRYPT_CONTENT;
-    }
-    if(repo->decrypt_name) {
-        flags |= DAV_SESSION_DECRYPT_NAME;
-    }
-    if(repo->decrypt_properties) {
-        flags |= DAV_SESSION_DECRYPT_PROPERTIES;
-    }
-    if(repo->encrypt_content) {
-        flags |= DAV_SESSION_ENCRYPT_CONTENT;
-    }
-    if(repo->encrypt_name) {
-        flags |= DAV_SESSION_ENCRYPT_NAME;
-    }
-    if(repo->encrypt_properties) {
-        flags |= DAV_SESSION_ENCRYPT_PROPERTIES;
-    }
-    return flags;
-}
-
-
-Key* get_key(const char *name) {
-    if(!name) {
-        return NULL;
-    }
-    return cxMapGet(keys, cx_hash_key_str(name));
-}
-
-int add_repository(Repository *repo) {
-    if(check_config_dir()) {
-        fprintf(stderr, "Cannot create .dav directory\n");
-        return 1;
-    }
-    
-    char *file = util_concat_path(ENV_HOME, ".dav/config.xml");
-    struct stat s;
-    if(stat(file, &s)) {
-        switch(errno) {
-            case ENOENT: {
-                create_default_config(file);
-                break;
-            }
-            default: {
-                perror("Cannot load config.xml");
-                free(file);
-                return 1;
-            }
-        }
-    }
-    
-    xmlDoc *doc = xmlReadFile(file, NULL, 0);
-    if(!doc) {
-        free(file);
-        fprintf(stderr, "Cannot load config.xml\n");
-        return 1;
-    }
-    
-    xmlNode *root = xmlDocGetRootElement(doc);
-    if(!root) {
-        fprintf(stderr, "Missing root node in config.xml\n");
-        xmlFreeDoc(doc);
-        free(file);
-        return 1;
-    }
-    
-    xmlNode *repoNode = xmlNewNode(NULL, BAD_CAST "repository");
-    xmlNodeAddContent(repoNode, BAD_CAST "\n\t\t");
-    xmlNewTextChild(repoNode, NULL, BAD_CAST "name", BAD_CAST repo->name);
-    xmlNodeAddContent(repoNode, BAD_CAST "\n\t\t");
-    xmlNewTextChild(repoNode, NULL, BAD_CAST "url", BAD_CAST repo->url);
-    xmlNodeAddContent(repoNode, BAD_CAST "\n");
-    if(repo->user) {
-        xmlNodeAddContent(repoNode, BAD_CAST "\t\t");
-        xmlNewChild(repoNode, NULL, BAD_CAST "user", BAD_CAST repo->user);
-        xmlNodeAddContent(repoNode, BAD_CAST "\n");
-        if(repo->password) {
-            char *pwenc = util_base64encode(
-                    repo->password,
-                    strlen(repo->password));
-            xmlNodeAddContent(repoNode, BAD_CAST "\t\t");
-            xmlNewTextChild(repoNode, NULL, BAD_CAST "password", BAD_CAST pwenc);
-            free(pwenc);
-            xmlNodeAddContent(repoNode, BAD_CAST "\n");
-        }
-    }
-    xmlNodeAddContent(repoNode, BAD_CAST "\t");
-    
-    xmlNodeAddContent(root, BAD_CAST "\n\t");
-    xmlAddChild(root, repoNode);
-    xmlNodeAddContent(root, BAD_CAST "\n");
-    
-    int ret = (xmlSaveFormatFileEnc(file, doc, "UTF-8", 1) == -1) ? 1 : 0;
-    xmlFreeDoc(doc);
-    free(file);
-    
-    return ret;
-}
-
-int remove_repository(Repository *repo) {
-    char *file = util_concat_path(ENV_HOME, ".dav/config.xml");
-    struct stat s;
-    if(stat(file, &s)) {
-        perror("Cannot access config.xml");
-        free(file);
-        return 1;
-    }
-    
-    xmlDoc *doc = xmlReadFile(file, NULL, 0);
-    if(!doc) {
-        free(file);
-        fprintf(stderr, "Cannot load config.xml\n");
-        return 1;
-    }
-    
-    xmlNodePtr root = xmlDocGetRootElement(doc);
-    if(!root) {
-        fprintf(stderr, "Missing root node in config.xml\n");
-        xmlFreeDoc(doc);
-        free(file);
-        return 1;
-    }
-    
-    xmlNodePtr repoNode = root->children;
-    xmlNodePtr matchedRepoNode = NULL;
-    while(!matchedRepoNode && repoNode) {
-        if(repoNode->type == XML_ELEMENT_NODE
-                && xstreq(repoNode->name, "repository")) {
-            xmlNodePtr nameNode = repoNode->children;
-            while(!matchedRepoNode && nameNode) {
-                if (nameNode->type == XML_ELEMENT_NODE
-                        && xstreq(nameNode->name, "name")) {
-                    char *reponame = util_xml_get_text(nameNode);
-                    if(!strcmp(repo->name, reponame)) {
-                        matchedRepoNode = repoNode;
-                    }
-                }
-                nameNode = nameNode->next;
-            }
-        }
-        repoNode = repoNode->next;
-    }
-    
-    if(matchedRepoNode) {
-        xmlNodePtr prev = matchedRepoNode->prev;
-        xmlNodePtr next = matchedRepoNode->next;
-        if(prev && prev->type == XML_TEXT_NODE) {
-            cxstring content = cx_str((char*)prev->content);
-            cxstring lf = cx_strrchr(content, '\n');
-            if(lf.length > 0) {
-                content.length = lf.ptr - content.ptr;
-                char* newcontent = cx_strdup(content).ptr;
-                xmlNodeSetContent(prev, (xmlChar*)newcontent);
-                free(newcontent);
-            }
-        }
-        if(next && next->type == XML_TEXT_NODE) {
-            cxstring lf = cx_strchr(cx_str((char*)next->content), '\n');
-            if(lf.length > 0) {
-                char* newcontent = malloc(lf.length);
-                memcpy(newcontent, lf.ptr+1, lf.length-1);
-                newcontent[lf.length-1] = '\0';
-                xmlNodeSetContent(next, (xmlChar*)newcontent);
-                free(newcontent);
-            }
-        }
-        
-        xmlUnlinkNode(matchedRepoNode);
-        xmlFreeNode(matchedRepoNode);
-    }
-    
-    int ret = (xmlSaveFormatFileEnc(file, doc, "UTF-8", 1) == -1) ? 1 : 0;
-    xmlFreeDoc(doc);
-    free(file);
-    
-    return ret;
-}
-
-int list_repositories(void) {
-    CxIterator i = cxMapIteratorValues(repos);
-    Repository *repo;
-    cx_foreach(Repository *, repo, i) {
-        printf("%s\n", repo->name);
-    }
-    return 0;
-}
-
-CxIterator get_repositories(void) {
-    return cxMapIteratorValues(repos);
-}
-
 PwdStore* get_pwdstore(void) {
     return pstore;
 }
@@ -1129,18 +595,18 @@
 }
 
 int request_auth(DavSession *sn, void *userdata) {
-    Repository *repo = userdata;
+    DavCfgRepository *repo = userdata;
     
-    char *user = NULL;
+    cxstring user = {NULL, 0};
     char ubuf[256];
-    if(repo->user) {
-       user = repo->user; 
+    if(repo->user.value.ptr) {
+       user = cx_strcast(repo->user.value);
     } else {
         fprintf(stderr, "User: ");
         fflush(stderr);
-        user = fgets(ubuf, 256, stdin);
+        user = cx_str(fgets(ubuf, 256, stdin));
     }
-    if(!user) {
+    if(!user.ptr) {
         return 0;
     }
     
@@ -1149,12 +615,7 @@
         return 0;
     }
     
-    size_t ulen = strlen(user);
-    if(user[ulen-1] == '\n') {
-        user[ulen-1] = '\0';
-    }
-    
-    dav_session_set_auth(sn, user, password);
+    dav_session_set_auth_s(sn, user, cx_str(password));
     free(password);
     
     return 0;
--- a/dav/config.h	Sat Sep 30 16:33:47 2023 +0200
+++ b/dav/config.h	Sat Sep 30 17:26:00 2023 +0200
@@ -41,38 +41,10 @@
 extern "C" {
 #endif
 
-typedef struct Repository Repository;
-typedef struct DavKey     Key;
-typedef struct Proxy      Proxy;
 
 #define HTTP_PROXY 1
 #define HTTPS_PROXY 2
 
-enum key_type {
-    KEY_AES128 = 0,
-    KEY_AES256,
-};
-
-typedef enum key_type KeyType;
-
-struct Repository {
-    char *name;
-    char *url;
-    char *user;
-    char *password;
-    char *stored_user;
-    char *default_key;
-    char *cert;
-    bool verification;
-    bool encrypt_content;
-    bool encrypt_name;
-    bool encrypt_properties;
-    bool decrypt_content;
-    bool decrypt_name;
-    bool decrypt_properties;
-    int ssl_version;
-    unsigned long authmethods;
-};
 
 int check_config_dir(void);
 
@@ -83,26 +55,11 @@
 int load_config(DavContext *ctx);
 DavConfig* get_config(void);
 int store_config(void);
-
 void free_config(void);
-int load_repository(const xmlNode *reponode);
-int load_key(const xmlNode *keynode);
-int load_proxy(DavProxy*, const xmlNode *proxynode, int type);
-cxmutstr load_key_file(const char *filename);
-int load_namespace(const xmlNode *node);
-int load_secretstore(const xmlNode *node);
 
-Repository* repository_new(void);
+cxmutstr load_key_file(const char *filename);
 
-Repository* get_repository(cxstring name);
-int get_repository_flags(Repository *repo);
-DavSession *repository_session(Repository *repo);
-Key* get_key(const char *name);
-
-int add_repository(Repository *repo);
-int remove_repository(Repository *repo);
 int list_repositories(void);
-CxIterator get_repositories(void);
 
 PwdStore* get_pwdstore(void);
 int pwdstore_save(PwdStore *pwdstore);
--- a/dav/main.c	Sat Sep 30 16:33:47 2023 +0200
+++ b/dav/main.c	Sat Sep 30 17:26:00 2023 +0200
@@ -2421,7 +2421,7 @@
         fprintf(stderr, "Abort\n");
         return -1;
     }
-    if(get_repository(cx_str(name))) {
+    if(dav_config_get_repository(get_config(), cx_str(name))) {
         fprintf(stderr, "Repository %s already exists.\nAbort\n", name);
         return -1;
     }
@@ -3117,13 +3117,13 @@
         }
     }
     if(repocomp) {
-        CxIterator i = get_repositories();
-        cx_foreach(Repository*, repo, i) {
-            if(cx_strprefix(cx_str(repo->name), url)) {
+        DavConfig *config = get_config();
+        for(DavCfgRepository *repo=config->repositories; repo; repo=repo->next) {
+            if(cx_strprefix(cx_strcast(repo->name.value), url)) {
                 if(quote == '\0') {
-                    printf("%s/\n", repo->name);
+                    printf("%s/\n", repo->name.value.ptr);
                 } else {
-                    printf("%c%s/%c\n", quote, repo->name, quote);
+                    printf("%c%s/%c\n", quote, repo->name.value.ptr, quote);
                 }
             }
             
--- a/libidav/config.c	Sat Sep 30 16:33:47 2023 +0200
+++ b/libidav/config.c	Sat Sep 30 17:26:00 2023 +0200
@@ -160,6 +160,10 @@
     return config;
 }
 
+void dav_config_free(DavConfig *config) {
+    cxMempoolDestroy(config->mp);
+}
+
 CxBuffer* dav_config2buf(DavConfig *config) {
     xmlChar* xmlText = NULL;
     int textLen = 0;
@@ -778,3 +782,35 @@
     
     return repo;
 }
+
+int dav_config_keytype(DavCfgKeyType type) {
+    switch(type) {
+        default: break;
+        case DAV_KEY_TYPE_AES256: return DAV_KEY_AES256;
+        case DAV_KEY_TYPE_AES128: return DAV_KEY_AES128;
+    }
+    return 0;
+}
+
+int dav_config_register_keys(DavConfig *config, DavContext *ctx, dav_loadkeyfile_func loadkey) {
+    for(DavCfgKey *key=config->keys;key;key=key->next) {
+        char *file = cx_strdup_m(key->file.value).ptr;
+        cxmutstr keycontent = loadkey(file);
+        free(file);
+        
+        // TODO: check key length
+        
+        if(!keycontent.ptr) {
+            return 1;
+        }
+        
+        DavKey *davkey = calloc(1, sizeof(DavKey));
+        davkey->name = cx_strdup_m(key->name.value).ptr;
+        davkey->type = dav_config_keytype(key->type);
+        davkey->data = keycontent.ptr;
+        davkey->length = keycontent.length;
+        
+        dav_context_add_key(ctx, davkey);
+    }
+    return 0;
+}
--- a/libidav/config.h	Sat Sep 30 16:33:47 2023 +0200
+++ b/libidav/config.h	Sat Sep 30 17:26:00 2023 +0200
@@ -49,6 +49,8 @@
 
 typedef enum dav_cfg_key_type DavCfgKeyType;
 
+typedef cxmutstr (*dav_loadkeyfile_func)(const char *filename);
+
 #define DAV_HTTP_PROXY 1
 #define DAV_HTTPS_PROXY 2
     
@@ -160,6 +162,8 @@
 
 DavConfig* dav_config_load(cxmutstr xmlfilecontent, int *error);
 
+void dav_config_free(DavConfig *config);
+
 CxBuffer* dav_config2buf(DavConfig *config);
 
 void dav_config_add_repository(DavConfig *config, DavCfgRepository *repo);
@@ -179,6 +183,8 @@
 DavCfgRepository* dav_config_url2repo(DavConfig *config, const char *url, char **path);
 DavCfgRepository* dav_config_url2repo_s(DavConfig *config, cxstring url, cxmutstr *path);
 
+int dav_config_keytype(DavCfgKeyType type);
+int dav_config_register_keys(DavConfig *config, DavContext *ctx, dav_loadkeyfile_func loadkey);
 
 #ifdef __cplusplus
 }
--- a/libidav/session.c	Sat Sep 30 16:33:47 2023 +0200
+++ b/libidav/session.c	Sat Sep 30 17:26:00 2023 +0200
@@ -114,13 +114,17 @@
     return sn;
 }
 
-void dav_session_set_auth(DavSession *sn, char *user, char *password) {
+void dav_session_set_auth(DavSession *sn, const char *user, const char *password) {
     if(user && password) {
-        size_t ulen = strlen(user);
-        size_t plen = strlen(password);
-        size_t upwdlen = ulen + plen + 2;
+        dav_session_set_auth_s(sn, cx_str(user), cx_str(password));
+    }
+}
+
+void dav_session_set_auth_s(DavSession *sn, cxstring user, cxstring password) {
+    if(user.length > 0 && password.length > 0) {
+        size_t upwdlen = user.length + password.length + 2;
         char *upwdbuf = malloc(upwdlen);
-        snprintf(upwdbuf, upwdlen, "%s:%s", user, password);
+        snprintf(upwdbuf, upwdlen, "%.*s:%.*s", (int)user.length, user.ptr, (int)password.length, password.ptr);
         curl_easy_setopt(sn->handle, CURLOPT_USERPWD, upwdbuf);
         free(upwdbuf);
     }
--- a/libidav/webdav.h	Sat Sep 30 16:33:47 2023 +0200
+++ b/libidav/webdav.h	Sat Sep 30 17:26:00 2023 +0200
@@ -268,7 +268,8 @@
         char *base_url,
         char *user,
         char *password);
-void dav_session_set_auth(DavSession *sn, char *user, char *password);
+void dav_session_set_auth(DavSession *sn, const char *user, const char *password);
+void dav_session_set_auth_s(DavSession *sn, cxstring user, cxstring password);
 void dav_session_set_baseurl(DavSession *sn, char *base_url);
 void dav_session_enable_encryption(DavSession *sn, DavKey *key, int flags);
 

mercurial