1 /* Copyright (c) 2013, Vsevolod Stakhov 2 * All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above copyright 9 * notice, this list of conditions and the following disclaimer in the 10 * documentation and/or other materials provided with the distribution. 11 * 12 * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY 13 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY 16 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 */ 23 24 #include "ucl.h" 25 #include "ucl_internal.h" 26 #include "ucl_chartable.h" 27 28 #include <libgen.h> /* For dirname */ 29 30 #ifdef HAVE_OPENSSL 31 #include <openssl/err.h> 32 #include <openssl/sha.h> 33 #include <openssl/rsa.h> 34 #include <openssl/ssl.h> 35 #include <openssl/evp.h> 36 #endif 37 38 /** 39 * @file rcl_util.c 40 * Utilities for rcl parsing 41 */ 42 43 44 static void 45 ucl_object_free_internal (ucl_object_t *obj, bool allow_rec) 46 { 47 ucl_object_t *sub, *tmp; 48 49 while (obj != NULL) { 50 if (obj->trash_stack[UCL_TRASH_KEY] != NULL) { 51 UCL_FREE (obj->hh.keylen, obj->trash_stack[UCL_TRASH_KEY]); 52 } 53 if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) { 54 UCL_FREE (obj->len, obj->trash_stack[UCL_TRASH_VALUE]); 55 } 56 57 if (obj->type == UCL_ARRAY) { 58 sub = obj->value.av; 59 while (sub != NULL) { 60 tmp = sub->next; 61 ucl_object_free_internal (sub, false); 62 sub = tmp; 63 } 64 } 65 else if (obj->type == UCL_OBJECT) { 66 if (obj->value.ov != NULL) { 67 ucl_hash_destroy (obj->value.ov, (ucl_hash_free_func *)ucl_object_unref); 68 } 69 } 70 tmp = obj->next; 71 UCL_FREE (sizeof (ucl_object_t), obj); 72 obj = tmp; 73 74 if (!allow_rec) { 75 break; 76 } 77 } 78 } 79 80 void 81 ucl_object_free (ucl_object_t *obj) 82 { 83 ucl_object_free_internal (obj, true); 84 } 85 86 size_t 87 ucl_unescape_json_string (char *str, size_t len) 88 { 89 char *t = str, *h = str; 90 int i, uval; 91 92 /* t is target (tortoise), h is source (hare) */ 93 94 while (len) { 95 if (*h == '\\') { 96 h ++; 97 switch (*h) { 98 case 'n': 99 *t++ = '\n'; 100 break; 101 case 'r': 102 *t++ = '\r'; 103 break; 104 case 'b': 105 *t++ = '\b'; 106 break; 107 case 't': 108 *t++ = '\t'; 109 break; 110 case 'f': 111 *t++ = '\f'; 112 break; 113 case '\\': 114 *t++ = '\\'; 115 break; 116 case '"': 117 *t++ = '"'; 118 break; 119 case 'u': 120 /* Unicode escape */ 121 uval = 0; 122 for (i = 0; i < 4; i++) { 123 uval <<= 4; 124 if (isdigit (h[i])) { 125 uval += h[i] - '0'; 126 } 127 else if (h[i] >= 'a' && h[i] <= 'f') { 128 uval += h[i] - 'a' + 10; 129 } 130 else if (h[i] >= 'A' && h[i] <= 'F') { 131 uval += h[i] - 'A' + 10; 132 } 133 } 134 h += 3; 135 len -= 3; 136 /* Encode */ 137 if(uval < 0x80) { 138 t[0] = (char)uval; 139 t ++; 140 } 141 else if(uval < 0x800) { 142 t[0] = 0xC0 + ((uval & 0x7C0) >> 6); 143 t[1] = 0x80 + ((uval & 0x03F)); 144 t += 2; 145 } 146 else if(uval < 0x10000) { 147 t[0] = 0xE0 + ((uval & 0xF000) >> 12); 148 t[1] = 0x80 + ((uval & 0x0FC0) >> 6); 149 t[2] = 0x80 + ((uval & 0x003F)); 150 t += 3; 151 } 152 else if(uval <= 0x10FFFF) { 153 t[0] = 0xF0 + ((uval & 0x1C0000) >> 18); 154 t[1] = 0x80 + ((uval & 0x03F000) >> 12); 155 t[2] = 0x80 + ((uval & 0x000FC0) >> 6); 156 t[3] = 0x80 + ((uval & 0x00003F)); 157 t += 4; 158 } 159 else { 160 *t++ = '?'; 161 } 162 break; 163 default: 164 *t++ = *h; 165 break; 166 } 167 h ++; 168 len --; 169 } 170 else { 171 *t++ = *h++; 172 } 173 len --; 174 } 175 *t = '\0'; 176 177 return (t - str); 178 } 179 180 char * 181 ucl_copy_key_trash (ucl_object_t *obj) 182 { 183 if (obj->trash_stack[UCL_TRASH_KEY] == NULL && obj->key != NULL) { 184 obj->trash_stack[UCL_TRASH_KEY] = malloc (obj->keylen + 1); 185 if (obj->trash_stack[UCL_TRASH_KEY] != NULL) { 186 memcpy (obj->trash_stack[UCL_TRASH_KEY], obj->key, obj->keylen); 187 obj->trash_stack[UCL_TRASH_KEY][obj->keylen] = '\0'; 188 } 189 obj->key = obj->trash_stack[UCL_TRASH_KEY]; 190 obj->flags |= UCL_OBJECT_ALLOCATED_KEY; 191 } 192 193 return obj->trash_stack[UCL_TRASH_KEY]; 194 } 195 196 char * 197 ucl_copy_value_trash (ucl_object_t *obj) 198 { 199 if (obj->trash_stack[UCL_TRASH_VALUE] == NULL) { 200 if (obj->type == UCL_STRING) { 201 /* Special case for strings */ 202 obj->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len + 1); 203 if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) { 204 memcpy (obj->trash_stack[UCL_TRASH_VALUE], obj->value.sv, obj->len); 205 obj->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0'; 206 obj->value.sv = obj->trash_stack[UCL_TRASH_VALUE]; 207 } 208 } 209 else { 210 /* Just emit value in json notation */ 211 obj->trash_stack[UCL_TRASH_VALUE] = ucl_object_emit_single_json (obj); 212 obj->len = strlen (obj->trash_stack[UCL_TRASH_VALUE]); 213 } 214 obj->flags |= UCL_OBJECT_ALLOCATED_VALUE; 215 } 216 return obj->trash_stack[UCL_TRASH_VALUE]; 217 } 218 219 ucl_object_t* 220 ucl_parser_get_object (struct ucl_parser *parser) 221 { 222 if (parser->state != UCL_STATE_ERROR && parser->top_obj != NULL) { 223 return ucl_object_ref (parser->top_obj); 224 } 225 226 return NULL; 227 } 228 229 void 230 ucl_parser_free (struct ucl_parser *parser) 231 { 232 struct ucl_stack *stack, *stmp; 233 struct ucl_macro *macro, *mtmp; 234 struct ucl_chunk *chunk, *ctmp; 235 struct ucl_pubkey *key, *ktmp; 236 struct ucl_variable *var, *vtmp; 237 238 if (parser->top_obj != NULL) { 239 ucl_object_unref (parser->top_obj); 240 } 241 242 LL_FOREACH_SAFE (parser->stack, stack, stmp) { 243 free (stack); 244 } 245 HASH_ITER (hh, parser->macroes, macro, mtmp) { 246 free (macro->name); 247 HASH_DEL (parser->macroes, macro); 248 UCL_FREE (sizeof (struct ucl_macro), macro); 249 } 250 LL_FOREACH_SAFE (parser->chunks, chunk, ctmp) { 251 UCL_FREE (sizeof (struct ucl_chunk), chunk); 252 } 253 LL_FOREACH_SAFE (parser->keys, key, ktmp) { 254 UCL_FREE (sizeof (struct ucl_pubkey), key); 255 } 256 LL_FOREACH_SAFE (parser->variables, var, vtmp) { 257 free (var->value); 258 free (var->var); 259 UCL_FREE (sizeof (struct ucl_variable), var); 260 } 261 262 if (parser->err != NULL) { 263 utstring_free(parser->err); 264 } 265 266 UCL_FREE (sizeof (struct ucl_parser), parser); 267 } 268 269 const char * 270 ucl_parser_get_error(struct ucl_parser *parser) 271 { 272 if (parser->err == NULL) 273 return NULL; 274 275 return utstring_body(parser->err); 276 } 277 278 bool 279 ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len) 280 { 281 #ifndef HAVE_OPENSSL 282 ucl_create_err (&parser->err, "cannot check signatures without openssl"); 283 return false; 284 #else 285 # if (OPENSSL_VERSION_NUMBER < 0x10000000L) 286 ucl_create_err (&parser->err, "cannot check signatures, openssl version is unsupported"); 287 return EXIT_FAILURE; 288 # else 289 struct ucl_pubkey *nkey; 290 BIO *mem; 291 292 mem = BIO_new_mem_buf ((void *)key, len); 293 nkey = UCL_ALLOC (sizeof (struct ucl_pubkey)); 294 nkey->key = PEM_read_bio_PUBKEY (mem, &nkey->key, NULL, NULL); 295 BIO_free (mem); 296 if (nkey->key == NULL) { 297 UCL_FREE (sizeof (struct ucl_pubkey), nkey); 298 ucl_create_err (&parser->err, "%s", 299 ERR_error_string (ERR_get_error (), NULL)); 300 return false; 301 } 302 LL_PREPEND (parser->keys, nkey); 303 # endif 304 #endif 305 return true; 306 } 307 308 #ifdef CURL_FOUND 309 struct ucl_curl_cbdata { 310 unsigned char *buf; 311 size_t buflen; 312 }; 313 314 static size_t 315 ucl_curl_write_callback (void* contents, size_t size, size_t nmemb, void* ud) 316 { 317 struct ucl_curl_cbdata *cbdata = ud; 318 size_t realsize = size * nmemb; 319 320 cbdata->buf = realloc (cbdata->buf, cbdata->buflen + realsize + 1); 321 if (cbdata->buf == NULL) { 322 return 0; 323 } 324 325 memcpy (&(cbdata->buf[cbdata->buflen]), contents, realsize); 326 cbdata->buflen += realsize; 327 cbdata->buf[cbdata->buflen] = 0; 328 329 return realsize; 330 } 331 #endif 332 333 /** 334 * Fetch a url and save results to the memory buffer 335 * @param url url to fetch 336 * @param len length of url 337 * @param buf target buffer 338 * @param buflen target length 339 * @return 340 */ 341 static bool 342 ucl_fetch_url (const unsigned char *url, unsigned char **buf, size_t *buflen, 343 UT_string **err, bool must_exist) 344 { 345 346 #ifdef HAVE_FETCH_H 347 struct url *fetch_url; 348 struct url_stat us; 349 FILE *in; 350 351 fetch_url = fetchParseURL (url); 352 if (fetch_url == NULL) { 353 ucl_create_err (err, "invalid URL %s: %s", 354 url, strerror (errno)); 355 return false; 356 } 357 if ((in = fetchXGet (fetch_url, &us, "")) == NULL) { 358 if (!must_exist) { 359 ucl_create_err (err, "cannot fetch URL %s: %s", 360 url, strerror (errno)); 361 } 362 fetchFreeURL (fetch_url); 363 return false; 364 } 365 366 *buflen = us.size; 367 *buf = malloc (*buflen); 368 if (*buf == NULL) { 369 ucl_create_err (err, "cannot allocate buffer for URL %s: %s", 370 url, strerror (errno)); 371 fclose (in); 372 fetchFreeURL (fetch_url); 373 return false; 374 } 375 376 if (fread (*buf, *buflen, 1, in) != 1) { 377 ucl_create_err (err, "cannot read URL %s: %s", 378 url, strerror (errno)); 379 fclose (in); 380 fetchFreeURL (fetch_url); 381 return false; 382 } 383 384 fetchFreeURL (fetch_url); 385 return true; 386 #elif defined(CURL_FOUND) 387 CURL *curl; 388 int r; 389 struct ucl_curl_cbdata cbdata; 390 391 curl = curl_easy_init (); 392 if (curl == NULL) { 393 ucl_create_err (err, "CURL interface is broken"); 394 return false; 395 } 396 if ((r = curl_easy_setopt (curl, CURLOPT_URL, url)) != CURLE_OK) { 397 ucl_create_err (err, "invalid URL %s: %s", 398 url, curl_easy_strerror (r)); 399 curl_easy_cleanup (curl); 400 return false; 401 } 402 curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, ucl_curl_write_callback); 403 cbdata.buf = *buf; 404 cbdata.buflen = *buflen; 405 curl_easy_setopt (curl, CURLOPT_WRITEDATA, &cbdata); 406 407 if ((r = curl_easy_perform (curl)) != CURLE_OK) { 408 if (!must_exist) { 409 ucl_create_err (err, "error fetching URL %s: %s", 410 url, curl_easy_strerror (r)); 411 } 412 curl_easy_cleanup (curl); 413 if (cbdata.buf) { 414 free (cbdata.buf); 415 } 416 return false; 417 } 418 *buf = cbdata.buf; 419 *buflen = cbdata.buflen; 420 421 return true; 422 #else 423 ucl_create_err (err, "URL support is disabled"); 424 return false; 425 #endif 426 } 427 428 /** 429 * Fetch a file and save results to the memory buffer 430 * @param filename filename to fetch 431 * @param len length of filename 432 * @param buf target buffer 433 * @param buflen target length 434 * @return 435 */ 436 static bool 437 ucl_fetch_file (const unsigned char *filename, unsigned char **buf, size_t *buflen, 438 UT_string **err, bool must_exist) 439 { 440 int fd; 441 struct stat st; 442 443 if (stat (filename, &st) == -1 || !S_ISREG (st.st_mode)) { 444 if (must_exist) { 445 ucl_create_err (err, "cannot stat file %s: %s", 446 filename, strerror (errno)); 447 } 448 return false; 449 } 450 if (st.st_size == 0) { 451 /* Do not map empty files */ 452 *buf = ""; 453 *buflen = 0; 454 } 455 else { 456 if ((fd = open (filename, O_RDONLY)) == -1) { 457 ucl_create_err (err, "cannot open file %s: %s", 458 filename, strerror (errno)); 459 return false; 460 } 461 if ((*buf = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { 462 close (fd); 463 ucl_create_err (err, "cannot mmap file %s: %s", 464 filename, strerror (errno)); 465 return false; 466 } 467 *buflen = st.st_size; 468 close (fd); 469 } 470 471 return true; 472 } 473 474 475 #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L) 476 static inline bool 477 ucl_sig_check (const unsigned char *data, size_t datalen, 478 const unsigned char *sig, size_t siglen, struct ucl_parser *parser) 479 { 480 struct ucl_pubkey *key; 481 char dig[EVP_MAX_MD_SIZE]; 482 unsigned int diglen; 483 EVP_PKEY_CTX *key_ctx; 484 EVP_MD_CTX *sign_ctx = NULL; 485 486 sign_ctx = EVP_MD_CTX_create (); 487 488 LL_FOREACH (parser->keys, key) { 489 key_ctx = EVP_PKEY_CTX_new (key->key, NULL); 490 if (key_ctx != NULL) { 491 if (EVP_PKEY_verify_init (key_ctx) <= 0) { 492 EVP_PKEY_CTX_free (key_ctx); 493 continue; 494 } 495 if (EVP_PKEY_CTX_set_rsa_padding (key_ctx, RSA_PKCS1_PADDING) <= 0) { 496 EVP_PKEY_CTX_free (key_ctx); 497 continue; 498 } 499 if (EVP_PKEY_CTX_set_signature_md (key_ctx, EVP_sha256 ()) <= 0) { 500 EVP_PKEY_CTX_free (key_ctx); 501 continue; 502 } 503 EVP_DigestInit (sign_ctx, EVP_sha256 ()); 504 EVP_DigestUpdate (sign_ctx, data, datalen); 505 EVP_DigestFinal (sign_ctx, dig, &diglen); 506 507 if (EVP_PKEY_verify (key_ctx, sig, siglen, dig, diglen) == 1) { 508 EVP_MD_CTX_destroy (sign_ctx); 509 EVP_PKEY_CTX_free (key_ctx); 510 return true; 511 } 512 513 EVP_PKEY_CTX_free (key_ctx); 514 } 515 } 516 517 EVP_MD_CTX_destroy (sign_ctx); 518 519 return false; 520 } 521 #endif 522 523 /** 524 * Include an url to configuration 525 * @param data 526 * @param len 527 * @param parser 528 * @param err 529 * @return 530 */ 531 static bool 532 ucl_include_url (const unsigned char *data, size_t len, 533 struct ucl_parser *parser, bool check_signature, bool must_exist) 534 { 535 536 bool res; 537 unsigned char *buf = NULL; 538 size_t buflen = 0; 539 struct ucl_chunk *chunk; 540 char urlbuf[PATH_MAX]; 541 int prev_state; 542 543 snprintf (urlbuf, sizeof (urlbuf), "%.*s", (int)len, data); 544 545 if (!ucl_fetch_url (urlbuf, &buf, &buflen, &parser->err, must_exist)) { 546 return (!must_exist || false); 547 } 548 549 if (check_signature) { 550 #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L) 551 unsigned char *sigbuf = NULL; 552 size_t siglen = 0; 553 /* We need to check signature first */ 554 snprintf (urlbuf, sizeof (urlbuf), "%.*s.sig", (int)len, data); 555 if (!ucl_fetch_url (urlbuf, &sigbuf, &siglen, &parser->err, true)) { 556 return false; 557 } 558 if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) { 559 ucl_create_err (&parser->err, "cannot verify url %s: %s", 560 urlbuf, 561 ERR_error_string (ERR_get_error (), NULL)); 562 if (siglen > 0) { 563 munmap (sigbuf, siglen); 564 } 565 return false; 566 } 567 if (siglen > 0) { 568 munmap (sigbuf, siglen); 569 } 570 #endif 571 } 572 573 prev_state = parser->state; 574 parser->state = UCL_STATE_INIT; 575 576 res = ucl_parser_add_chunk (parser, buf, buflen); 577 if (res == true) { 578 /* Remove chunk from the stack */ 579 chunk = parser->chunks; 580 if (chunk != NULL) { 581 parser->chunks = chunk->next; 582 UCL_FREE (sizeof (struct ucl_chunk), chunk); 583 } 584 } 585 586 parser->state = prev_state; 587 free (buf); 588 589 return res; 590 } 591 592 /** 593 * Include a file to configuration 594 * @param data 595 * @param len 596 * @param parser 597 * @param err 598 * @return 599 */ 600 static bool 601 ucl_include_file (const unsigned char *data, size_t len, 602 struct ucl_parser *parser, bool check_signature, bool must_exist) 603 { 604 bool res; 605 struct ucl_chunk *chunk; 606 unsigned char *buf = NULL; 607 size_t buflen; 608 char filebuf[PATH_MAX], realbuf[PATH_MAX]; 609 int prev_state; 610 611 snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data); 612 if (realpath (filebuf, realbuf) == NULL) { 613 if (!must_exist) { 614 return true; 615 } 616 ucl_create_err (&parser->err, "cannot open file %s: %s", 617 filebuf, 618 strerror (errno)); 619 return false; 620 } 621 622 if (!ucl_fetch_file (realbuf, &buf, &buflen, &parser->err, must_exist)) { 623 return (!must_exist || false); 624 } 625 626 if (check_signature) { 627 #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L) 628 unsigned char *sigbuf = NULL; 629 size_t siglen = 0; 630 /* We need to check signature first */ 631 snprintf (filebuf, sizeof (filebuf), "%s.sig", realbuf); 632 if (!ucl_fetch_file (filebuf, &sigbuf, &siglen, &parser->err, true)) { 633 return false; 634 } 635 if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) { 636 ucl_create_err (&parser->err, "cannot verify file %s: %s", 637 filebuf, 638 ERR_error_string (ERR_get_error (), NULL)); 639 if (siglen > 0) { 640 munmap (sigbuf, siglen); 641 } 642 return false; 643 } 644 if (siglen > 0) { 645 munmap (sigbuf, siglen); 646 } 647 #endif 648 } 649 650 ucl_parser_set_filevars (parser, realbuf, false); 651 652 prev_state = parser->state; 653 parser->state = UCL_STATE_INIT; 654 655 res = ucl_parser_add_chunk (parser, buf, buflen); 656 if (res == true) { 657 /* Remove chunk from the stack */ 658 chunk = parser->chunks; 659 if (chunk != NULL) { 660 parser->chunks = chunk->next; 661 UCL_FREE (sizeof (struct ucl_chunk), chunk); 662 } 663 } 664 665 parser->state = prev_state; 666 667 if (buflen > 0) { 668 munmap (buf, buflen); 669 } 670 671 return res; 672 } 673 674 /** 675 * Handle include macro 676 * @param data include data 677 * @param len length of data 678 * @param ud user data 679 * @param err error ptr 680 * @return 681 */ 682 bool 683 ucl_include_handler (const unsigned char *data, size_t len, void* ud) 684 { 685 struct ucl_parser *parser = ud; 686 687 if (*data == '/' || *data == '.') { 688 /* Try to load a file */ 689 return ucl_include_file (data, len, parser, false, true); 690 } 691 692 return ucl_include_url (data, len, parser, false, true); 693 } 694 695 /** 696 * Handle includes macro 697 * @param data include data 698 * @param len length of data 699 * @param ud user data 700 * @param err error ptr 701 * @return 702 */ 703 bool 704 ucl_includes_handler (const unsigned char *data, size_t len, void* ud) 705 { 706 struct ucl_parser *parser = ud; 707 708 if (*data == '/' || *data == '.') { 709 /* Try to load a file */ 710 return ucl_include_file (data, len, parser, true, true); 711 } 712 713 return ucl_include_url (data, len, parser, true, true); 714 } 715 716 717 bool 718 ucl_try_include_handler (const unsigned char *data, size_t len, void* ud) 719 { 720 struct ucl_parser *parser = ud; 721 722 if (*data == '/' || *data == '.') { 723 /* Try to load a file */ 724 return ucl_include_file (data, len, parser, false, false); 725 } 726 727 return ucl_include_url (data, len, parser, false, false); 728 } 729 730 bool 731 ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand) 732 { 733 char realbuf[PATH_MAX], *curdir; 734 735 if (filename != NULL) { 736 if (need_expand) { 737 if (realpath (filename, realbuf) == NULL) { 738 return false; 739 } 740 } 741 else { 742 ucl_strlcpy (realbuf, filename, sizeof (realbuf)); 743 } 744 745 /* Define variables */ 746 ucl_parser_register_variable (parser, "FILENAME", realbuf); 747 curdir = dirname (realbuf); 748 ucl_parser_register_variable (parser, "CURDIR", curdir); 749 } 750 else { 751 /* Set everything from the current dir */ 752 curdir = getcwd (realbuf, sizeof (realbuf)); 753 ucl_parser_register_variable (parser, "FILENAME", "undef"); 754 ucl_parser_register_variable (parser, "CURDIR", curdir); 755 } 756 757 return true; 758 } 759 760 bool 761 ucl_parser_add_file (struct ucl_parser *parser, const char *filename) 762 { 763 unsigned char *buf; 764 size_t len; 765 bool ret; 766 char realbuf[PATH_MAX]; 767 768 if (realpath (filename, realbuf) == NULL) { 769 ucl_create_err (&parser->err, "cannot open file %s: %s", 770 filename, 771 strerror (errno)); 772 return false; 773 } 774 775 if (!ucl_fetch_file (realbuf, &buf, &len, &parser->err, true)) { 776 return false; 777 } 778 779 ucl_parser_set_filevars (parser, realbuf, false); 780 ret = ucl_parser_add_chunk (parser, buf, len); 781 782 if (len > 0) { 783 munmap (buf, len); 784 } 785 786 return ret; 787 } 788 789 size_t 790 ucl_strlcpy (char *dst, const char *src, size_t siz) 791 { 792 char *d = dst; 793 const char *s = src; 794 size_t n = siz; 795 796 /* Copy as many bytes as will fit */ 797 if (n != 0) { 798 while (--n != 0) { 799 if ((*d++ = *s++) == '\0') { 800 break; 801 } 802 } 803 } 804 805 if (n == 0 && siz != 0) { 806 *d = '\0'; 807 } 808 809 return (s - src - 1); /* count does not include NUL */ 810 } 811 812 size_t 813 ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz) 814 { 815 memcpy (dst, src, siz - 1); 816 dst[siz - 1] = '\0'; 817 818 return siz - 1; 819 } 820 821 size_t 822 ucl_strlcpy_tolower (char *dst, const char *src, size_t siz) 823 { 824 char *d = dst; 825 const char *s = src; 826 size_t n = siz; 827 828 /* Copy as many bytes as will fit */ 829 if (n != 0) { 830 while (--n != 0) { 831 if ((*d++ = tolower (*s++)) == '\0') { 832 break; 833 } 834 } 835 } 836 837 if (n == 0 && siz != 0) { 838 *d = '\0'; 839 } 840 841 return (s - src); /* count does not include NUL */ 842 } 843 844 ucl_object_t * 845 ucl_object_fromstring_common (const char *str, size_t len, enum ucl_string_flags flags) 846 { 847 ucl_object_t *obj; 848 const char *start, *end, *p, *pos; 849 char *dst, *d; 850 size_t escaped_len; 851 852 if (str == NULL) { 853 return NULL; 854 } 855 856 obj = ucl_object_new (); 857 if (obj) { 858 if (len == 0) { 859 len = strlen (str); 860 } 861 if (flags & UCL_STRING_TRIM) { 862 /* Skip leading spaces */ 863 for (start = str; (size_t)(start - str) < len; start ++) { 864 if (!ucl_test_character (*start, UCL_CHARACTER_WHITESPACE_UNSAFE)) { 865 break; 866 } 867 } 868 /* Skip trailing spaces */ 869 for (end = str + len - 1; end > start; end --) { 870 if (!ucl_test_character (*end, UCL_CHARACTER_WHITESPACE_UNSAFE)) { 871 break; 872 } 873 } 874 end ++; 875 } 876 else { 877 start = str; 878 end = str + len; 879 } 880 881 obj->type = UCL_STRING; 882 if (flags & UCL_STRING_ESCAPE) { 883 for (p = start, escaped_len = 0; p < end; p ++, escaped_len ++) { 884 if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) { 885 escaped_len ++; 886 } 887 } 888 dst = malloc (escaped_len + 1); 889 if (dst != NULL) { 890 for (p = start, d = dst; p < end; p ++, d ++) { 891 if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) { 892 switch (*p) { 893 case '\n': 894 *d++ = '\\'; 895 *d = 'n'; 896 break; 897 case '\r': 898 *d++ = '\\'; 899 *d = 'r'; 900 break; 901 case '\b': 902 *d++ = '\\'; 903 *d = 'b'; 904 break; 905 case '\t': 906 *d++ = '\\'; 907 *d = 't'; 908 break; 909 case '\f': 910 *d++ = '\\'; 911 *d = 'f'; 912 break; 913 case '\\': 914 *d++ = '\\'; 915 *d = '\\'; 916 break; 917 case '"': 918 *d++ = '\\'; 919 *d = '"'; 920 break; 921 } 922 } 923 else { 924 *d = *p; 925 } 926 } 927 *d = '\0'; 928 obj->value.sv = dst; 929 obj->trash_stack[UCL_TRASH_VALUE] = dst; 930 obj->len = escaped_len; 931 } 932 } 933 else { 934 dst = malloc (end - start + 1); 935 if (dst != NULL) { 936 ucl_strlcpy_unsafe (dst, start, end - start + 1); 937 obj->value.sv = dst; 938 obj->trash_stack[UCL_TRASH_VALUE] = dst; 939 obj->len = end - start; 940 } 941 } 942 if ((flags & UCL_STRING_PARSE) && dst != NULL) { 943 /* Parse what we have */ 944 if (flags & UCL_STRING_PARSE_BOOLEAN) { 945 if (!ucl_maybe_parse_boolean (obj, dst, obj->len) && (flags & UCL_STRING_PARSE_NUMBER)) { 946 ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos, 947 flags & UCL_STRING_PARSE_DOUBLE, 948 flags & UCL_STRING_PARSE_BYTES); 949 } 950 } 951 else { 952 ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos, 953 flags & UCL_STRING_PARSE_DOUBLE, 954 flags & UCL_STRING_PARSE_BYTES); 955 } 956 } 957 } 958 959 return obj; 960 } 961 962 static ucl_object_t * 963 ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt, 964 const char *key, size_t keylen, bool copy_key, bool merge, bool replace) 965 { 966 ucl_object_t *found, *cur; 967 ucl_object_iter_t it = NULL; 968 const char *p; 969 970 if (elt == NULL || key == NULL) { 971 return NULL; 972 } 973 974 if (top == NULL) { 975 top = ucl_object_new (); 976 top->type = UCL_OBJECT; 977 } 978 979 if (top->type != UCL_OBJECT) { 980 /* It is possible to convert NULL type to an object */ 981 if (top->type == UCL_NULL) { 982 top->type = UCL_OBJECT; 983 } 984 else { 985 /* Refuse converting of other object types */ 986 return top; 987 } 988 } 989 990 if (top->value.ov == NULL) { 991 top->value.ov = ucl_hash_create (); 992 } 993 994 if (keylen == 0) { 995 keylen = strlen (key); 996 } 997 998 for (p = key; p < key + keylen; p ++) { 999 if (ucl_test_character (*p, UCL_CHARACTER_UCL_UNSAFE)) { 1000 elt->flags |= UCL_OBJECT_NEED_KEY_ESCAPE; 1001 break; 1002 } 1003 } 1004 1005 elt->key = key; 1006 elt->keylen = keylen; 1007 1008 if (copy_key) { 1009 ucl_copy_key_trash (elt); 1010 } 1011 1012 found = ucl_hash_search_obj (top->value.ov, elt); 1013 1014 if (!found) { 1015 top->value.ov = ucl_hash_insert_object (top->value.ov, elt); 1016 DL_APPEND (found, elt); 1017 } 1018 else { 1019 if (replace) { 1020 ucl_hash_delete (top->value.ov, found); 1021 ucl_object_unref (found); 1022 top->value.ov = ucl_hash_insert_object (top->value.ov, elt); 1023 found = NULL; 1024 DL_APPEND (found, elt); 1025 } 1026 else if (merge) { 1027 if (found->type != UCL_OBJECT && elt->type == UCL_OBJECT) { 1028 /* Insert old elt to new one */ 1029 elt = ucl_object_insert_key_common (elt, found, found->key, found->keylen, copy_key, false, false); 1030 ucl_hash_delete (top->value.ov, found); 1031 top->value.ov = ucl_hash_insert_object (top->value.ov, elt); 1032 } 1033 else if (found->type == UCL_OBJECT && elt->type != UCL_OBJECT) { 1034 /* Insert new to old */ 1035 found = ucl_object_insert_key_common (found, elt, elt->key, elt->keylen, copy_key, false, false); 1036 } 1037 else if (found->type == UCL_OBJECT && elt->type == UCL_OBJECT) { 1038 /* Mix two hashes */ 1039 while ((cur = ucl_iterate_object (elt, &it, true)) != NULL) { 1040 ucl_object_ref (cur); 1041 found = ucl_object_insert_key_common (found, cur, cur->key, cur->keylen, copy_key, false, false); 1042 } 1043 ucl_object_unref (elt); 1044 } 1045 else { 1046 /* Just make a list of scalars */ 1047 DL_APPEND (found, elt); 1048 } 1049 } 1050 else { 1051 DL_APPEND (found, elt); 1052 } 1053 } 1054 1055 return top; 1056 } 1057 1058 ucl_object_t * 1059 ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, 1060 const char *key, size_t keylen, bool copy_key) 1061 { 1062 return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, false); 1063 } 1064 1065 ucl_object_t * 1066 ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt, 1067 const char *key, size_t keylen, bool copy_key) 1068 { 1069 return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, true, false); 1070 } 1071 1072 ucl_object_t * 1073 ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt, 1074 const char *key, size_t keylen, bool copy_key) 1075 { 1076 return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, true); 1077 } 1078 1079 ucl_object_t * 1080 ucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen) 1081 { 1082 ucl_object_t *ret, srch; 1083 1084 if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) { 1085 return NULL; 1086 } 1087 1088 srch.key = key; 1089 srch.keylen = klen; 1090 ret = ucl_hash_search_obj (obj->value.ov, &srch); 1091 1092 return ret; 1093 } 1094 1095 ucl_object_t * 1096 ucl_object_find_key (ucl_object_t *obj, const char *key) 1097 { 1098 size_t klen; 1099 ucl_object_t *ret, srch; 1100 1101 if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) { 1102 return NULL; 1103 } 1104 1105 klen = strlen (key); 1106 srch.key = key; 1107 srch.keylen = klen; 1108 ret = ucl_hash_search_obj (obj->value.ov, &srch); 1109 1110 return ret; 1111 } 1112 1113 ucl_object_t* 1114 ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values) 1115 { 1116 ucl_object_t *elt; 1117 1118 if (expand_values) { 1119 switch (obj->type) { 1120 case UCL_OBJECT: 1121 return (ucl_object_t*)ucl_hash_iterate (obj->value.ov, iter); 1122 break; 1123 case UCL_ARRAY: 1124 elt = *iter; 1125 if (elt == NULL) { 1126 elt = obj->value.av; 1127 if (elt == NULL) { 1128 return NULL; 1129 } 1130 } 1131 else if (elt == obj->value.av) { 1132 return NULL; 1133 } 1134 *iter = elt->next ? elt->next : obj->value.av; 1135 return elt; 1136 default: 1137 /* Go to linear iteration */ 1138 break; 1139 } 1140 } 1141 /* Treat everything as a linear list */ 1142 elt = *iter; 1143 if (elt == NULL) { 1144 elt = obj; 1145 if (elt == NULL) { 1146 return NULL; 1147 } 1148 } 1149 else if (elt == obj) { 1150 return NULL; 1151 } 1152 *iter = elt->next ? elt->next : obj; 1153 return elt; 1154 1155 /* Not reached */ 1156 return NULL; 1157 } 1158