1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include "config.h"
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/types.h>
35 #include <cx/hash_map.h>
36 #include <errno.h>
37 #include <libxml/tree.h>
38 #include "utils.h"
39
40 #define xstreq(a,b) xmlStrEqual(
BAD_CAST a,
BAD_CAST b)
41 #define xstrEQ(a,b) !xmlStrcasecmp(
BAD_CAST a,
BAD_CAST b)
42
43 #define print_error(lineno, ...) \
44 do {\
45 fprintf(stderr,
"Error (config.xml line %u): ", lineno); \
46 fprintf(stderr,
__VA_ARGS__); \
47 fprintf(stderr,
"Abort.\n"); \
48 }
while(
0);
49 #define print_warning(lineno, ...) \
50 do {\
51 fprintf(stderr,
"Warning (config.xml line %u): ", lineno); \
52 fprintf(stderr,
__VA_ARGS__); \
53 }
while(
0);
54
55 #ifdef _WIN32
56 #define ENV_HOME getenv(
"USERPROFILE")
57 #else
58 #define ENV_HOME getenv(
"HOME")
59 #endif
60
61
62 static int load_repository(
63 DavConfig *config,
64 DavCfgRepository **list_begin,
65 DavCfgRepository **list_end,
66 xmlNode *reponode);
67 static int load_key(
68 DavConfig *config,
69 DavCfgKey **list_begin,
70 DavCfgKey **list_end,
71 xmlNode *keynode);
72 static int load_proxy(
73 DavConfig *config, DavCfgProxy *proxy, xmlNode *proxynode,
int type);
74 static int load_namespace(
75 DavConfig *config,
76 DavCfgNamespace **list_begin,
77 DavCfgNamespace **list_end,
78 xmlNode *node);
79 static int load_secretstore(DavConfig *config, xmlNode *node);
80
81
82 int dav_cfg_string_set_value(DavConfig *config, CfgString *str, xmlNode *node) {
83 str->node = node;
84 char *value = util_xml_get_text(node);
85 if(value) {
86 str->value = cx_strdup_a(config->mp->allocator, cx_str(value));
87 return 0;
88 }
else {
89 str->value = (cxmutstr){
NULL,
0};
90 return 1;
91 }
92 }
93
94 void dav_cfg_bool_set_value(DavConfig *config, CfgBool *cbool, xmlNode *node) {
95 cbool->node = node;
96 char *value = util_xml_get_text(node);
97 cbool->value = util_getboolean(value);
98 }
99
100
101 DavConfig* dav_config_load(cxmutstr xmlfilecontent,
int *error) {
102 xmlDoc *doc = xmlReadMemory(xmlfilecontent.ptr, xmlfilecontent.length,
NULL,
NULL,
0);
103 if(!doc) {
104 if(error) {
105 *error =
DAV_CONFIG_ERROR_XML;
106 }
107 return NULL;
108 }
109
110 CxMempool *cfg_mp = cxMempoolCreate(
128,
NULL);
111 cxMempoolRegister(cfg_mp, doc, (cx_destructor_func)xmlFreeDoc);
112 DavConfig *config = cxMalloc(cfg_mp->allocator,
sizeof(DavConfig));
113 memset(config,
0,
sizeof(DavConfig));
114 config->mp = cfg_mp;
115 config->doc = doc;
116
117 DavCfgRepository *repos_begin =
NULL;
118 DavCfgRepository *repos_end =
NULL;
119 DavCfgKey *keys_begin =
NULL;
120 DavCfgKey *keys_end =
NULL;
121 DavCfgNamespace *namespaces_begin =
NULL;
122 DavCfgNamespace *namespaces_end =
NULL;
123
124 xmlNode *xml_root = xmlDocGetRootElement(doc);
125 xmlNode *node = xml_root->children;
126 int ret =
0;
127 while(node && !ret) {
128 if(node->type ==
XML_ELEMENT_NODE) {
129 (xstreq(node->name, "repository")) {
130 ret = load_repository(config, &repos_begin, &repos_end, node);
131 } else if(xstreq(node->name, "key")) {
132 ret = load_key(config, &keys_begin, &keys_end, node);
133 } else if (xstreq(node->name, "http-proxy")) {
134 config->http_proxy = cxCalloc(config->mp->allocator, 1, sizeof(DavCfgProxy));
135 ret = load_proxy(config, config->http_proxy, node, DAV_HTTP_PROXY);
136 } else if (xstreq(node->name, "https-proxy")) {
137 config->https_proxy = cxCalloc(config->mp->allocator, 1, sizeof(DavCfgProxy));
138 ret = load_proxy(config, config->https_proxy, node, DAV_HTTPS_PROXY);
139 } else if (xstreq(node->name, "namespace")) {
140 ret = load_namespace(config, &namespaces_begin, &namespaces_end, node);
141 } else if (xstreq(node->name, "secretstore")) {
142 ret = load_secretstore(config, node);
143 } else {
144 fprintf(stderr, "Unknown config element: %s\n", node->name);
145 ret = 1;
146 }
147 }
148 node = node->next;
149 }
150
151 config->repositories = repos_begin;
152 config->keys = keys_begin;
153 config->namespaces = namespaces_begin;
154
155 if(ret != 0 && error) {
156 *error = ret;
157 cxMempoolDestroy(cfg_mp);
158 }
159
160 return config;
161 }
162
163 void dav_config_free(DavConfig *config) {
164 cxMempoolDestroy(config->mp);
165 }
166
167 CxBuffer* dav_config2buf(DavConfig *config) {
168 xmlChar* xmlText = NULL;
169 int textLen = 0;
170 xmlDocDumpFormatMemory(config->doc, &xmlText, &textLen, 1);
171
172 if(!xmlText) {
173 return NULL;
174 }
175
176 CxBuffer *buf = cxBufferCreate(NULL, textLen, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
177 cxBufferWrite(xmlText, 1, textLen, buf);
178 xmlFree(xmlText);
179 return buf;
180 }
181
182
183 static int repo_add_config(
184 DavConfig *config,
185 DavCfgRepository *repo,
186 xmlNode* node)
187 {
188 unsigned short lineno = node->line;
189 char *key = (char*)node->name;
190 char *value = util_xml_get_text(node);
191
192
193 if(!value) {
194
195
196
197 print_error(lineno, "missing value for config element: %s\n", key);
198 return 1;
199 }
200
201 if(xstreq(key, "name")) {
202 dav_cfg_string_set_value(config, &repo->name, node);
203 } else if(xstreq(key, "url")) {
204 dav_cfg_string_set_value(config, &repo->url, node);
205 } else if(xstreq(key, "user")) {
206 dav_cfg_string_set_value(config, &repo->user, node);
207 } else if(xstreq(key, "password")) {
208 dav_cfg_string_set_value(config, &repo->password, node);
209 } else if(xstreq(key, "stored-user")) {
210 dav_cfg_string_set_value(config, &repo->stored_user, node);
211 } else if(xstreq(key, "default-key")) {
212 dav_cfg_string_set_value(config, &repo->default_key, node);
213 } else if(xstreq(key, "full-encryption")) {
214 dav_cfg_bool_set_value(config, &repo->full_encryption, node);
215 } else if(xstreq(key, "content-encryption")) {
216 dav_cfg_bool_set_value(config, &repo->content_encryption, node);
217 } else if(xstreq(key, "decrypt-content")) {
218 dav_cfg_bool_set_value(config, &repo->decrypt_content, node);
219 } else if(xstreq(key, "decrypt-name")) {
220 dav_cfg_bool_set_value(config, &repo->decrypt_name, node);
221 } else if(xstreq(key, "cert")) {
222 dav_cfg_string_set_value(config, &repo->cert, node);
223 } else if(xstreq(key, "verification")) {
224 dav_cfg_bool_set_value(config, &repo->verification, node);
225 } else if(xstreq(key, "ssl-version")) {
226 repo->ssl_version.node = node;
227 if(xstrEQ(value, "TLSv1")) {
228 repo->ssl_version.value = CURL_SSLVERSION_TLSv1;
229 } else if(xstrEQ(value, "SSLv2")) {
230 repo->ssl_version.value = CURL_SSLVERSION_SSLv2;
231 } else if(xstrEQ(value, "SSLv3")) {
232 repo->ssl_version.value = CURL_SSLVERSION_SSLv3;
233 }
234 #if LIBCURL_VERSION_MAJOR * 1000 + LIBCURL_VERSION_MINOR >= 7034
235 else if(xstrEQ(value, "TLSv1.0")) {
236 repo->ssl_version.value = CURL_SSLVERSION_TLSv1_0;
237 } else if(xstrEQ(value, "TLSv1.1")) {
238 repo->ssl_version.value = CURL_SSLVERSION_TLSv1_1;
239 } else if(xstrEQ(value, "TLSv1.2")) {
240 repo->ssl_version.value = CURL_SSLVERSION_TLSv1_2;
241 }
242 #endif
243 #if LIBCURL_VERSION_MAJOR * 1000 + LIBCURL_VERSION_MINOR >= 7052
244 else if(xstrEQ(value, "TLSv1.3")) {
245 repo->ssl_version.value = CURL_SSLVERSION_TLSv1_3;
246 }
247 #endif
248 else {
249 print_warning(lineno, "unknown ssl version: %s\n", value);
250 repo->ssl_version.value = CURL_SSLVERSION_DEFAULT;
251 }
252 } else if(xstreq(key, "authmethods")) {
253 repo->authmethods.node = node;
254 repo->authmethods.value = CURLAUTH_NONE;
255 const char *delims = " \t\r\n";
256 char *meths = strdup(value);
257 char *meth = strtok(meths, delims);
258 while (meth) {
259 if(xstrEQ(meth, "basic")) {
260 repo->authmethods.value |= CURLAUTH_BASIC;
261 } else if(xstrEQ(meth, "digest")) {
262 repo->authmethods.value |= CURLAUTH_DIGEST;
263 } else if(xstrEQ(meth, "negotiate")) {
264 repo->authmethods.value |= CURLAUTH_GSSNEGOTIATE;
265 } else if(xstrEQ(meth, "ntlm")) {
266 repo->authmethods.value |= CURLAUTH_NTLM;
267 } else if(xstrEQ(meth, "any")) {
268 repo->authmethods.value = CURLAUTH_ANY;
269 } else if(xstrEQ(meth, "none")) {
270
271 } else {
272 print_warning(lineno,
273 "unknown authentication method: %s\n", meth);
274 }
275 meth = strtok(NULL, delims);
276 }
277 free(meths);
278 } else {
279 print_error(lineno, "unkown repository config element: %s\n", key);
280 return 1;
281 }
282 return 0;
283 }
284
285 static int load_repository(
286 DavConfig *config,
287 DavCfgRepository **list_begin,
288 DavCfgRepository **list_end,
289 xmlNode *reponode)
290 {
291 DavCfgRepository *repo = dav_repository_new(config);
292 repo->node = reponode;
293
294
295 xmlNode *node = reponode->children;
296 int ret = 0;
297 while(node && !ret) {
298 if(node->type == XML_ELEMENT_NODE) {
299 ret = repo_add_config(config, repo, node);
300 }
301 node = node->next;
302 }
303
304
305 if(ret) {
306 return 1;
307 } else {
308 cx_linked_list_add(
309 (void**)list_begin,
310 (void**)list_end,
311 offsetof(DavCfgRepository, prev),
312 offsetof(DavCfgRepository, next),
313 repo);
314 }
315
316 return 0;
317 }
318
319 static xmlNode* addXmlNode(xmlNode *node, const char *name, cxmutstr content) {
320 xmlNode *text1 = xmlNewDocText(node->doc, BAD_CAST "\t\t");
321 xmlAddChild(node, text1);
322
323 cxmutstr ctn = cx_strdup(cx_strcast(content));
324 xmlNode *newNode = xmlNewChild(node, NULL, BAD_CAST name, BAD_CAST ctn.ptr);
325 free(ctn.ptr);
326
327 xmlNode *text2 = xmlNewDocText(node->doc, BAD_CAST "\n");
328 xmlAddChild(node, text2);
329
330 return newNode;
331 }
332
333 void dav_config_add_repository(DavConfig *config, DavCfgRepository *repo) {
334 if(repo->node) {
335 fprintf(stderr, "Error: dav_config_add_repository: node already exists\n");
336 return;
337 }
338
339 xmlNode *repoNode = xmlNewNode(NULL, BAD_CAST "repository");
340 xmlNode *rtext1 = xmlNewDocText(config->doc, BAD_CAST "\n");
341 xmlAddChild(repoNode, rtext1);
342
343 if(repo->name.value.ptr) {
344 repo->name.node = addXmlNode(repoNode, "name", repo->name.value);
345 }
346 if(repo->url.value.ptr) {
347 repo->url.node = addXmlNode(repoNode, "url", repo->url.value);
348 }
349 if(repo->user.value.ptr) {
350 repo->user.node = addXmlNode(repoNode, "user", repo->user.value);
351 }
352 if(repo->password.value.ptr) {
353 repo->password.node = addXmlNode(repoNode, "password", repo->password.value);
354 }
355
356 if(repo->stored_user.value.ptr) {
357 repo->stored_user.node = addXmlNode(repoNode, "stored-user", repo->stored_user.value);
358 }
359 if(repo->default_key.value.ptr) {
360 repo->default_key.node = addXmlNode(repoNode, "default-key", repo->default_key.value);
361 }
362 if(repo->cert.value.ptr) {
363 repo->cert.node = addXmlNode(repoNode, "cert", repo->cert.value);
364 }
365
366
367
368
369 xmlNode *rtext2 = xmlNewDocText(config->doc, BAD_CAST "\t");
370 xmlAddChild(repoNode, rtext2);
371
372
373 DavCfgRepository **list_begin = &config->repositories;
374 cx_linked_list_add(
375 (void**)list_begin,
376 NULL,
377 offsetof(DavCfgRepository, prev),
378 offsetof(DavCfgRepository, next),
379 repo);
380
381
382 xmlNode *xml_root = xmlDocGetRootElement(config->doc);
383
384 xmlNode *text1 = xmlNewDocText(config->doc, BAD_CAST
an> "\n\t");
385 xmlAddChild(xml_root, text1);
386
387 xmlAddChild(xml_root, repoNode);
388
389 xmlNode *text2 = xmlNewDocText(config->doc, BAD_CAST "\n");
390 xmlAddChild(xml_root, text2);
391 }
392
393 DavCfgRepository* dav_repository_new(DavConfig *config) {
394 DavCfgRepository *repo = cxMalloc(config->mp->allocator, sizeof(DavCfgRepository));
395 memset(repo, 0, sizeof(DavCfgRepository));
396 repo->decrypt_name.value = false;
397 repo->decrypt_content.value = true;
398 repo->decrypt_properties.value = false;
399 repo->verification.value = true;
400 repo->ssl_version.value = CURL_SSLVERSION_DEFAULT;
401 repo->authmethods.value = CURLAUTH_BASIC;
402 return repo;
403 }
404
405 void dav_repository_free(DavConfig *config, DavCfgRepository *repo) {
406
407 }
408
409 void dav_repository_remove_and_free(DavConfig *config, DavCfgRepository *repo) {
410 if(repo->prev) {
411 repo->prev->next = repo->next;
412 }
413 if(repo->next) {
414 repo->next->prev = repo->prev;
415 }
416
417 if(repo->node) {
418
419
420 xmlUnlinkNode(repo->node);
421 xmlFreeNode(repo->node);
422 }
423 }
424
425 int dav_repository_get_flags(DavCfgRepository *repo) {
426 int flags = 0;
427
428 DavBool encrypt_content = FALSE;
429 DavBool encrypt_name = FALSE;
430 DavBool encrypt_properties = FALSE;
431 DavBool decrypt_content = FALSE;
432 DavBool decrypt_name = FALSE;
433 DavBool decrypt_properties = FALSE;
434 if(repo->full_encryption.value) {
435 encrypt_content = TRUE;
436 encrypt_name = TRUE;
437 encrypt_properties = TRUE;
438 decrypt_content = TRUE;
439 decrypt_name = TRUE;
440 decrypt_properties = TRUE;
441 } else if(repo->content_encryption.value) {
442 encrypt_content = TRUE;
443 decrypt_content = TRUE;
444 }
445
446 if(decrypt_content) {
447 flags |= DAV_SESSION_DECRYPT_CONTENT;
448 }
449 if(decrypt_name) {
450 flags |= DAV_SESSION_DECRYPT_NAME;
451 }
452 if(decrypt_properties) {
453 flags |= DAV_SESSION_DECRYPT_PROPERTIES;
454 }
455 if(encrypt_content) {
456 flags |= DAV_SESSION_ENCRYPT_CONTENT;
457 }
458 if(encrypt_name) {
459 flags |= DAV_SESSION_ENCRYPT_NAME;
460 }
461 if(encrypt_properties) {
462 flags |= DAV_SESSION_ENCRYPT_PROPERTIES;
463 }
464 return flags;
465 }
466
467 void dav_repository_set_url(DavConfig *config, DavCfgRepository *repo, cxstring newurl) {
468 if(repo->url.value.ptr) {
469 cxFree(config->mp->allocator, repo->url.value.ptr);
470 }
471 repo->url.value = cx_strdup_a(config->mp->allocator, newurl);
472 }
473
474 void dav_repository_set_auth(DavConfig *config, DavCfgRepository *repo, cxstring user, cxstring password) {
475 const CxAllocator *a = config->mp->allocator;
476 repo->user.value = cx_strdup_a(a, user);
477 char *pwenc = util_base64encode(password.ptr, password.length);
478 repo->password.value = cx_strdup_a(a, cx_str(pwenc));
479 free(pwenc);
480 }
481
482 cxmutstr dav_repository_get_decodedpassword(DavCfgRepository *repo) {
483 cxmutstr pw = { NULL, 0 };
484 if(repo->password.value.ptr) {
485 pw = cx_mutstr(util_base64decode(repo->password.value.ptr));
486 }
487 return pw;
488 }
489
490
491 static int load_key(
492 DavConfig *config,
493 DavCfgKey **list_begin,
494 DavCfgKey **list_end,
495 xmlNode *keynode)
496 {
497 xmlNode *node = keynode->children;
498 DavCfgKey *key = cxMalloc(config->mp->allocator, sizeof(DavCfgKey));
499 memset(key, 0, sizeof(DavCfgKey));
500 key->type = DAV_KEY_TYPE_AES256;
501
502 int error = 0;
503 while(node) {
504 if(node->type == XML_ELEMENT_NODE) {
505 if(xstreq(node->name, "name")) {
506 dav_cfg_string_set_value(config, &key->name, node);
507 } else if(xstreq(node->name, "file")) {
508 dav_cfg_string_set_value(config, &key->file, node);
509 } else if(xstreq(node->name, "type")) {
510 const char *value = util_xml_get_text(node);
511 key->type_node = node;
512 if(!strcmp(value, "aes128")) {
513 key->type = DAV_KEY_TYPE_AES128;
514 } else if(!strcmp(value, "aes256")) {
515 key->type = DAV_KEY_TYPE_AES256;
516 } else {
517 print_error(node->line, "unknown key type %s\n", value);
518 error = 1;
519 }
520 } else {
521 key->unknown_elements++;
522 }
523
524 }
525 node = node->next;
526 }
527
528 if(!key->name.value.ptr) {
529 error = <
an class="c2html-macroconst">1;
530 }
531
532 if(!error) {
533 error = 0;
534 size_t expected_length = 0;
535 if(key->type == DAV_KEY_TYPE_AES128) {
536 expected_length = 16;
537 }
538 if(key->type == DAV_KEY_TYPE_AES256) {
539 expected_length = 32;
540 }
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556 }
557
558
559 if(error) {
560 return 1;
561 } else {
562
563 cx_linked_list_add(
564 (void**)list_begin,
565 (void**)list_end,
566 offsetof(DavCfgKey, prev),
567 offsetof(DavCfgKey, next),
568 key);
569
570 return 0;
571 }
572 }
573
574 static int load_proxy(
575 DavConfig *config, DavCfgProxy *proxy, xmlNode *proxynode, int type)
576 {
577 const char *stype;
578 if(type == DAV_HTTPS_PROXY) {
579 stype = "https";
580 } else if(type == DAV_HTTP_PROXY) {
581 stype = "http";
582 } else {
583 fprintf(stderr, "unknown proxy type\n");
584 return 1;
585 }
586
587 if(!proxy) {
588
589 fprintf(stderr, "no memory reserved for %s proxy.\n", stype);
590 return 1;
591 }
592
593 xmlNode *node = proxynode->children;
594 int ret = 0;
595 while(node && !ret) {
596 if(node->type == XML_ELEMENT_NODE) {
597 int reportmissingvalue = 0;
598 if(xstreq(node->name, "url")) {
599 reportmissingvalue = dav_cfg_string_set_value(config, &proxy->url, node);
600 } else if(xstreq(node->name, "user")) {
601 reportmissingvalue = dav_cfg_string_set_value(config, &proxy->user, node);
602 } else if(xstreq(node->name, "password")) {
603 reportmissingvalue = dav_cfg_string_set_value(config, &proxy->password, node);
604 } else if(xstreq(node->name, "no")) {
605 reportmissingvalue = dav_cfg_string_set_value(config, &proxy->noproxy, node);
606 } else {
607 proxy->unknown_elements++;
608 }
609
610 if (reportmissingvalue) {
611 print_error(node->line,
612 "missing value for proxy configuration element: %s\n",
613 node->name);
614 ret = 1;
615 break;
616 }
617 }
618 node = node->next;
619 }
620
621 if(!ret && !proxy->url.value.ptr) {
622 print_error(proxynode->line, "missing url for %s proxy.\n", stype);
623 return 1;
624 }
625
626 return ret;
627 }
628
629 static char* get_attr_content(xmlNode *node) {
630
631 while(node) {
632 if(node->type == XML_TEXT_NODE) {
633 return (char*)node->content;
634 }
635 node = node->next;
636 }
637 return NULL;
638 }
639
640 static int load_namespace(
641 DavConfig *config,
642 DavCfgNamespace **list_begin,
643 DavCfgNamespace **list_end,
644 xmlNode *node)
645 {
646 const char *prefix = NULL;
647 const char *uri = NULL;
648 xmlAttr *attr = node->properties;
649 while(attr) {
650 if(attr->type == XML_ATTRIBUTE_NODE) {
651 char *value = get_attr_content(attr->children);
652 if(!value) {
653 print_error(
654 node->line,
655 "missing value for attribute %s\n", (char*)attr->name);
656 return 1;
657 }
658 if(xstreq(attr->name, "prefix")) {
659 prefix = value;
660 } else if(xstreq(attr->name, "uri")) {
661 uri = value;
662 } else {
663 print_error(
664 node->line,
665 "unexpected attribute %s\n", (char*)attr->name);
666 return 1;
667 }
668 }
669 attr = attr->next;
670 }
671
672 if(!prefix) {
673 print_error(node->line, "missing prefix attribute\n");
674 return 1;
675 }
676 if(!uri) {
677 print_error(node->line, "missing uri attribute\n");
678 return 1;
679 }
680
681 DavCfgNamespace *ns = cxMalloc(config->mp->allocator, sizeof(DavCfgNamespace));
682 memset(ns, 0, sizeof(DavCfgNamespace));
683 ns->node = node;
684 ns->prefix = cx_strdup_a(config->mp->allocator, cx_str(prefix));
685 ns->uri = cx_strdup_a(config->mp->allocator, cx_str(uri));
686 cx_linked_list_add(
687 (void**)list_begin,
688 (void**)list_end,
689 offsetof(DavCfgNamespace, prev),
690 offsetof(DavCfgNamespace, next),
691 ns);
692
693 return 0;
694 }
695
696 static int load_secretstore(DavConfig *config, xmlNode *node) {
697
698
699 if(config->secretstore) {
700 return 1;
701 }
702
703 config->secretstore = cxCalloc(config->mp->allocator, 1, sizeof(DavCfgSecretStore));
704
705 node = node->children;
706 int error = 0;
707 while(node) {
708 if(node->type == XML_ELEMENT_NODE) {
709 if(xstreq(node->name, "unlock-command")) {
710 dav_cfg_string_set_value(config, &config->secretstore->unlock_cmd, node);
711 } else if(xstreq(node->name, "lock-command")) {
712 dav_cfg_string_set_value(config, &config->secretstore->lock_cmd, node);
713 }
714 }
715 node = node->next;
716 }
717
718 return error;
719 }
720
721
722
723
724
725 DavCfgRepository* dav_config_get_repository(DavConfig *config, cxstring name) {
726 DavCfgRepository *repo = config->repositories;
727 while(repo) {
728 if(!cx_strcmp(cx_strcast(repo->name.value), name)) {
729 return repo;
730 }
731 repo = repo->next;
732 }
733 return NULL;
734 }
735
736 DavCfgRepository* dav_config_url2repo(DavConfig *config, const char *url, char **path) {
737 cxmutstr p;
738 DavCfgRepository *repo = dav_config_url2repo_s(config, cx_str(url), &p);
739 *path = p.ptr;
740 return repo;
741 }
742
743 DavCfgRepository* dav_config_url2repo_s(DavConfig *config, cxstring url, cxmutstr *path) {
744 path->ptr = NULL;
745 path->length = 0;
746
747 int s;
748 if(cx_strprefix(url, CX_STR("http://"))) {
749 s = 7;
750 } else if(cx_strprefix(url, CX_STR("https://"))) {
751 s = 8;
752 } else {
753 s = 1;
754 }
755
756
757 cxstring r = cx_strsubs(url, s);
758 cxstring p = cx_strchr(r, '/');
759 r = cx_strsubsl(url, 0, url.length-p.length);
760 if(p.length == 0) {
761 p = cx_strn("/", 1);
762 }
763
764 DavCfgRepository *repo = dav_config_get_repository(config, r);
765 if(repo) {
766 *path = cx_strdup(p);
767 } else {
768
769
770 repo = dav_repository_new(config);
771 repo->name.value = cx_strdup_a(config->mp->allocator, CX_STR(""));
772 if(url.ptr[url.length-1] == '/') {
773 repo->url.value = cx_strdup_a(config->mp->allocator, url);
774 *path = cx_strdup(CX_STR("/"));
775 } else if (cx_strchr(url, '/').length > 0) {
776
777
778 cxstring repo_url = util_url_base_s(url);
779 repo->url.value = cx_strdup_a(config->mp->allocator, repo_url);
780 *path = cx_strdup(util_url_path_s(url));
781 } else {
782 repo->url.value = cx_strdup(url);
783 *path = cx_strdup(CX_STR("/"));
784 }
785 }
786
787 return repo;
788 }
789
790 int dav_config_keytype(DavCfgKeyType type) {
791 switch(type) {
792 default: break;
793 case DAV_KEY_TYPE_AES256: return DAV_KEY_AES256;
794 case DAV_KEY_TYPE_AES128: return DAV_KEY_AES128;
795 }
796 return 0;
797 }
798
799 int dav_config_register_keys(DavConfig *config, DavContext *ctx, dav_loadkeyfile_func loadkey) {
800 for(DavCfgKey *key=config->keys;key;key=key->next) {
801 char *file = cx_strdup_m(key->file.value).ptr;
802 cxmutstr keycontent = loadkey(file);
803 free(file);
804
805
806
807 if(!keycontent.ptr) {
808 return 1;
809 }
810
811 DavKey *davkey = calloc(1, sizeof(DavKey));
812 davkey->name = cx_strdup_m(key->name.value).ptr;
813 davkey->type = dav_config_keytype(key->type);
814 davkey->data = keycontent.ptr;
815 davkey->length = keycontent.length;
816
817 dav_context_add_key(ctx, davkey);
818 }
819 return 0;
820 }
821