--- a/dav/config.c Mon Nov 07 19:32:17 2016 +0100 +++ b/dav/config.c Fri Nov 11 15:03:19 2016 +0100 @@ -35,11 +35,20 @@ #include <libxml/tree.h> #include "config.h" +#include "main.h" #include <libidav/utils.h> #define xstreq(a,b) xmlStrEqual(BAD_CAST a, BAD_CAST b) #define xstrEQ(a,b) !xmlStrcasecmp(BAD_CAST a, BAD_CAST b) +#define print_error(...) \ + do {\ + fprintf(stderr, "Error (config.xml): " __VA_ARGS__); \ + fprintf(stderr, "Abort.\n"); \ + } while(0); +#define print_warning(...) \ + fprintf(stderr, "Warning (config.xml): " __VA_ARGS__); + #ifdef _WIN32 #define ENV_HOME getenv("USERPROFILE") #else @@ -48,8 +57,6 @@ static UcxMap *repos; static UcxMap *keys; -static Proxy *http_proxy; -static Proxy *https_proxy; int check_config_dir(void) { char *file = util_concat_path(ENV_HOME, ".dav"); @@ -73,15 +80,13 @@ xmlFreeDoc(doc); } -void load_config(DavContext *ctx) { +int load_config(DavContext *ctx) { context = ctx; // TODO: free the config somewhere repos = ucx_map_new(16); keys = ucx_map_new(16); - http_proxy = calloc(1, sizeof(Proxy)); - https_proxy = calloc(1, sizeof(Proxy)); if(check_config_dir()) { - return; + return 1; } char *file = util_concat_path(ENV_HOME, ".dav/config.xml"); @@ -97,64 +102,72 @@ perror("Cannot load config.xml"); } } - return; + return 1; } xmlDoc *doc = xmlReadFile(file, NULL, 0); free(file); if(!doc) { fprintf(stderr, "Cannot load config.xml\n"); - return; + return 1; } xmlNode *xml_root = xmlDocGetRootElement(doc); xmlNode *node = xml_root->children; - while(node) { + int ret = 0; + while(node && !ret) { if(node->type == XML_ELEMENT_NODE) { if(xstreq(node->name, "repository")) { - load_repository(node); + ret = load_repository(node); } else if(xstreq(node->name, "key")) { - load_key(node); + ret = load_key(node); } else if (xstreq(node->name, "http-proxy")) { - load_proxy(node, HTTP_PROXY); + ret = load_proxy(ctx->http_proxy, node, HTTP_PROXY); } else if (xstreq(node->name, "https-proxy")) { - load_proxy(node, HTTPS_PROXY); + ret = load_proxy(ctx->https_proxy, node, HTTPS_PROXY); + } else { + fprintf(stderr, "Unknown config element: %s\n", node->name); + ret = 1; } } node = node->next; } xmlFreeDoc(doc); + return ret; } void free_config(void) { - UcxMapIterator i = ucx_map_iterator(repos); - UcxKey k; - Repository *repo; - UCX_MAP_FOREACH(k, repo, i) { - if(repo->default_key) { - free(repo->default_key); - } - if(repo->name) { - free(repo->name); - } - if(repo->password) { - free(repo->password); + if(repos) { + UcxMapIterator i = ucx_map_iterator(repos); + UcxKey k; + Repository *repo; + UCX_MAP_FOREACH(k, 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); } - if(repo->url) { - free(repo->url); - } - if(repo->user) { - free(repo->user); - } - if(repo->cert) { - free(repo->cert); - } - free(repo); + ucx_map_free(repos); } - ucx_map_free(repos); - - ucx_map_free(keys); + if(keys) { + ucx_map_free(keys); + } } Repository* repository_new(void) { @@ -169,45 +182,48 @@ return repo; } -void load_repository(xmlNode *reponode) { - xmlNode *node = reponode->children; +int load_repository(xmlNode *reponode) { Repository *repo = repository_new(); - while(node) { - if(node->type == XML_ELEMENT_NODE) { - char *name = (char*)node->name; - char *value = util_xml_get_text(node); - if(value) { - if(repo_add_config(repo, name, value)) { - fprintf( - stderr, - "Unkown repository config element: %s\n", - name); - } + { + xmlNode *node = reponode->children; + int ret = 0; + while(node && !ret) { + if(node->type == XML_ELEMENT_NODE) { + char *name = (char*)node->name; + char *value = util_xml_get_text(node); + ret = repo_add_config(repo, name, value); } + node = node->next; } - node = node->next; + if(ret) { + free(repo); + return 1; + } } if(!repo->name) { - fprintf( - stderr, - "Cannot load config.xml: missing name for repository.\n"); - fprintf(stderr, "Abort.\n"); - exit(-1); + print_error("missing name for repository.\n"); + return 1; } if(!repo->url) { - fprintf( - stderr, - "Cannot load config.xml: " - "missing url for repository '%s'.\n", repo->name); - fprintf(stderr, "Abort.\n"); - exit(-1); + print_error("missing url for repository '%s'.\n", repo->name); + return 1; } ucx_map_cstr_put(repos, repo->name, repo); + return 0; } -int repo_add_config(Repository *repo, char *key, char *value) { +int repo_add_config(Repository *repo, char *key, char *value) { + /* 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("missing value for config element: %s\n", key); + return 1; + } + if(xstreq(key, "name")) { repo->name = strdup(value); } else if(xstreq(key, "url")) { @@ -263,7 +279,7 @@ #endif #endif else { - fprintf(stderr, "Unknown ssl version: %s\n", value); + print_warning("unknown ssl version: %s\n", value); } } else if(xstreq(key, "authmethods")) { repo->authmethods = CURLAUTH_NONE; @@ -284,56 +300,76 @@ } else if(xstrEQ(value, "none")) { /* skip */ } else { - fprintf(stderr, "Unknown authentication method: %s\n", value); + print_warning("unknown authentication method: %s\n", value); } meth = strtok(NULL, delims); } free(meths); } else { - return -1; + print_error("unkown repository config element: %s\n", key); + return 1; } return 0; } -void load_proxy(xmlNode *proxynode, int type) { - Proxy *proxy; +int load_proxy(DavProxy *proxy, xmlNode *proxynode, int type) { const char *stype; - if (type == HTTPS_PROXY) { - proxy = https_proxy; + if(type == HTTPS_PROXY) { stype = "https"; - } else if (type == HTTP_PROXY) { - proxy = http_proxy; + } else if(type == HTTP_PROXY) { stype = "http"; } + if(!proxy) { + print_error("no memory reserved for %s proxy.\n", stype); + return 1; + } + xmlNode *node = proxynode->children; - while(node) { + int ret = 0; + while(node && !ret) { if(node->type == XML_ELEMENT_NODE) { char *value = util_xml_get_text(node); - if(!value) { - // next - } else if(xstreq(node->name, "url")) { - proxy->url = strdup(value); + int reportmissingvalue = 0; + if(xstreq(node->name, "url")) { + if(!(reportmissingvalue = !value)) { + proxy->url = strdup(value); + } } else if(xstreq(node->name, "user")) { - proxy->user = strdup(value); + if(!(reportmissingvalue = !value)) { + proxy->username = strdup(value); + } } else if(xstreq(node->name, "password")) { - proxy->password = util_base64decode(value); + if(!(reportmissingvalue = !value)) { + proxy->password = util_base64decode(value); + } } else if(xstreq(node->name, "no")) { - proxy->no = strdup(value); + if(!(reportmissingvalue = !value)) { + proxy->no_proxy = strdup(value); + } + } else { + print_error("invalid element for proxy config: %s\n", + node->name); + ret = 1; + } + if (reportmissingvalue) { + print_error("missing value for proxy configuration " + "element '%s'.\n", node->name); + ret = 1; } } node = node->next; } - if(!proxy->url) { - fprintf(stderr, - "Cannot load config.xml: missing url for %s proxy.\n", stype); - fprintf(stderr, "Abort.\n"); - exit(-1); + if(!ret && !proxy->url) { + print_error("missing url for %s proxy.\n", stype); + return 1; } + + return ret; } -void load_key(xmlNode *keynode) { +int load_key(xmlNode *keynode) { xmlNode *node = keynode->children; Key *key = calloc(1, sizeof(Key)); key->type = KEY_AES256; @@ -353,7 +389,7 @@ key->data = key_data.ptr; key->length = key_data.length; } else { - fprintf(stderr, "Error: Cannot key from file: %s\n", value); + print_error("cannot get key from file: %s\n", value); error = 1; } } else if(xstreq(node->name, "type")) { @@ -362,7 +398,7 @@ } else if(!strcmp(value, "aes256")) { key->type = KEY_AES256; } else { - fprintf(stderr, "Error: unknown key type %s\n", value); + print_error("unknown key type %s\n", value); error = 1; } } @@ -373,27 +409,19 @@ if(!error && key->name) { error = 0; + size_t expected_length = 0; if(key->type == KEY_AES128) { - if(key->length < 16) { - fprintf( - stderr, - "Error: Key %s is too small (%zu < 16)\n", - key->name, - key->length); - error = 1; - } - key->length = 16; + expected_length = 16; } if(key->type == KEY_AES256) { - if(key->length < 32) { - fprintf( - stderr, - "Error: Key %s is too small (%zu < 32)\n", - key->name, - key->length); - error = 1; - } - key->length = 32; + expected_length = 32; + } + if(key->length < expected_length) { + print_error("key %s is too small (%zu < %zu)\n", + key->name, + key->length, + expected_length); + error = 1; } // add key to context @@ -409,6 +437,9 @@ free(key->data); } free(key); + return 1; + } else { + return 0; } } @@ -473,15 +504,6 @@ return ucx_map_cstr_get(keys, name); } -Proxy* get_http_proxy(void) { - return http_proxy; -} - -Proxy* get_https_proxy(void) { - return https_proxy; -} - - int add_repository(Repository *repo) { char *file = util_concat_path(ENV_HOME, ".dav/config.xml"); xmlDoc *doc = xmlReadFile(file, NULL, 0);