Rapid spam filtering system https://rspamd.com/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4014 lines
84 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. /* Copyright (c) 2013, Vsevolod Stakhov
  2. * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
  14. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  15. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  16. * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
  17. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  18. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  19. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  20. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  21. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  22. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. */
  24. #include "ucl.h"
  25. #include "ucl_internal.h"
  26. #include "ucl_chartable.h"
  27. #include "kvec.h"
  28. #include <limits.h>
  29. #include <stdarg.h>
  30. #include <stdio.h> /* for snprintf */
  31. #ifndef _WIN32
  32. #include <glob.h>
  33. #include <sys/param.h>
  34. #else
  35. #ifndef NBBY
  36. #define NBBY 8
  37. #endif
  38. #endif
  39. #ifdef HAVE_LIBGEN_H
  40. #ifndef _WIN32
  41. # include <libgen.h> /* For dirname */
  42. #endif
  43. #endif
  44. typedef kvec_t(ucl_object_t *) ucl_array_t;
  45. #define UCL_ARRAY_GET(ar, obj) ucl_array_t *ar = \
  46. (ucl_array_t *)((obj) != NULL ? (obj)->value.av : NULL)
  47. #ifdef HAVE_OPENSSL
  48. #include <openssl/err.h>
  49. #include <openssl/sha.h>
  50. #include <openssl/rsa.h>
  51. #include <openssl/ssl.h>
  52. #include <openssl/evp.h>
  53. #endif
  54. #ifdef CURL_FOUND
  55. /* Seems to be broken */
  56. #define CURL_DISABLE_TYPECHECK 1
  57. #include <curl/curl.h>
  58. #endif
  59. #ifdef HAVE_FETCH_H
  60. #include <fetch.h>
  61. #endif
  62. #if defined(_WIN32)
  63. #include <windows.h>
  64. #include <io.h>
  65. #include <direct.h>
  66. #ifndef PROT_READ
  67. #define PROT_READ 1
  68. #endif
  69. #ifndef PROT_WRITE
  70. #define PROT_WRITE 2
  71. #endif
  72. #ifndef PROT_READWRITE
  73. #define PROT_READWRITE 3
  74. #endif
  75. #ifndef MAP_SHARED
  76. #define MAP_SHARED 1
  77. #endif
  78. #ifndef MAP_PRIVATE
  79. #define MAP_PRIVATE 2
  80. #endif
  81. #ifndef MAP_FAILED
  82. #define MAP_FAILED ((void *) -1)
  83. #endif
  84. #define getcwd _getcwd
  85. #define open _open
  86. #define close _close
  87. static void *ucl_mmap(char *addr, size_t length, int prot, int access, int fd, off_t offset)
  88. {
  89. void *map = NULL;
  90. HANDLE handle = INVALID_HANDLE_VALUE;
  91. switch (prot) {
  92. default:
  93. case PROT_READ:
  94. {
  95. handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READONLY, 0, length, 0);
  96. if (!handle) break;
  97. map = (void *) MapViewOfFile(handle, FILE_MAP_READ, 0, 0, length);
  98. CloseHandle(handle);
  99. break;
  100. }
  101. case PROT_WRITE:
  102. {
  103. handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READWRITE, 0, length, 0);
  104. if (!handle) break;
  105. map = (void *) MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, length);
  106. CloseHandle(handle);
  107. break;
  108. }
  109. case PROT_READWRITE:
  110. {
  111. handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READWRITE, 0, length, 0);
  112. if (!handle) break;
  113. map = (void *) MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, length);
  114. CloseHandle(handle);
  115. break;
  116. }
  117. }
  118. if (map == (void *) NULL) {
  119. return (void *) MAP_FAILED;
  120. }
  121. return (void *) ((char *) map + offset);
  122. }
  123. static int ucl_munmap(void *map,size_t length)
  124. {
  125. if (!UnmapViewOfFile(map)) {
  126. return(-1);
  127. }
  128. return(0);
  129. }
  130. static char* ucl_realpath(const char *path, char *resolved_path)
  131. {
  132. char *p;
  133. char tmp[MAX_PATH + 1];
  134. strncpy(tmp, path, sizeof(tmp)-1);
  135. p = tmp;
  136. while(*p) {
  137. if (*p == '/') *p = '\\';
  138. p++;
  139. }
  140. return _fullpath(resolved_path, tmp, MAX_PATH);
  141. }
  142. char *dirname(char *path)
  143. {
  144. static char path_buffer[_MAX_PATH];
  145. char drive[_MAX_DRIVE];
  146. char dir[_MAX_DIR];
  147. char fname[_MAX_FNAME];
  148. char ext[_MAX_EXT];
  149. _splitpath (path, drive, dir, fname, ext);
  150. _makepath(path_buffer, drive, dir, NULL, NULL);
  151. return path_buffer;
  152. }
  153. char *basename(char *path)
  154. {
  155. static char path_buffer[_MAX_PATH];
  156. char drive[_MAX_DRIVE];
  157. char dir[_MAX_DIR];
  158. char fname[_MAX_FNAME];
  159. char ext[_MAX_EXT];
  160. _splitpath(path, drive, dir, fname, ext);
  161. _makepath(path_buffer, NULL, NULL, fname, ext);
  162. return path_buffer;
  163. }
  164. #else
  165. #define ucl_mmap mmap
  166. #define ucl_munmap munmap
  167. #define ucl_realpath realpath
  168. #endif
  169. typedef void (*ucl_object_dtor) (ucl_object_t *obj);
  170. static void ucl_object_free_internal (ucl_object_t *obj, bool allow_rec,
  171. ucl_object_dtor dtor);
  172. static void ucl_object_dtor_unref (ucl_object_t *obj);
  173. static void
  174. ucl_object_dtor_free (ucl_object_t *obj)
  175. {
  176. if (obj->trash_stack[UCL_TRASH_KEY] != NULL) {
  177. UCL_FREE (obj->hh.keylen, obj->trash_stack[UCL_TRASH_KEY]);
  178. }
  179. if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
  180. UCL_FREE (obj->len, obj->trash_stack[UCL_TRASH_VALUE]);
  181. }
  182. /* Do not free ephemeral objects */
  183. if ((obj->flags & UCL_OBJECT_EPHEMERAL) == 0) {
  184. if (obj->type != UCL_USERDATA) {
  185. UCL_FREE (sizeof (ucl_object_t), obj);
  186. }
  187. else {
  188. struct ucl_object_userdata *ud = (struct ucl_object_userdata *)obj;
  189. if (ud->dtor) {
  190. ud->dtor (obj->value.ud);
  191. }
  192. UCL_FREE (sizeof (*ud), obj);
  193. }
  194. }
  195. }
  196. /*
  197. * This is a helper function that performs exactly the same as
  198. * `ucl_object_unref` but it doesn't iterate over elements allowing
  199. * to use it for individual elements of arrays and multiple values
  200. */
  201. static void
  202. ucl_object_dtor_unref_single (ucl_object_t *obj)
  203. {
  204. if (obj != NULL) {
  205. #ifdef HAVE_ATOMIC_BUILTINS
  206. unsigned int rc = __sync_sub_and_fetch (&obj->ref, 1);
  207. if (rc == 0) {
  208. #else
  209. if (--obj->ref == 0) {
  210. #endif
  211. ucl_object_free_internal (obj, false, ucl_object_dtor_unref);
  212. }
  213. }
  214. }
  215. static void
  216. ucl_object_dtor_unref (ucl_object_t *obj)
  217. {
  218. if (obj->ref == 0) {
  219. ucl_object_dtor_free (obj);
  220. }
  221. else {
  222. /* This may cause dtor unref being called one more time */
  223. ucl_object_dtor_unref_single (obj);
  224. }
  225. }
  226. static void
  227. ucl_object_free_internal (ucl_object_t *obj, bool allow_rec, ucl_object_dtor dtor)
  228. {
  229. ucl_object_t *tmp, *sub;
  230. while (obj != NULL) {
  231. if (obj->type == UCL_ARRAY) {
  232. UCL_ARRAY_GET (vec, obj);
  233. unsigned int i;
  234. if (vec != NULL) {
  235. for (i = 0; i < vec->n; i ++) {
  236. sub = kv_A (*vec, i);
  237. if (sub != NULL) {
  238. tmp = sub;
  239. while (sub) {
  240. tmp = sub->next;
  241. dtor (sub);
  242. sub = tmp;
  243. }
  244. }
  245. }
  246. kv_destroy (*vec);
  247. UCL_FREE (sizeof (*vec), vec);
  248. }
  249. obj->value.av = NULL;
  250. }
  251. else if (obj->type == UCL_OBJECT) {
  252. if (obj->value.ov != NULL) {
  253. ucl_hash_destroy (obj->value.ov, (ucl_hash_free_func)dtor);
  254. }
  255. obj->value.ov = NULL;
  256. }
  257. tmp = obj->next;
  258. dtor (obj);
  259. obj = tmp;
  260. if (!allow_rec) {
  261. break;
  262. }
  263. }
  264. }
  265. void
  266. ucl_object_free (ucl_object_t *obj)
  267. {
  268. ucl_object_free_internal (obj, true, ucl_object_dtor_free);
  269. }
  270. size_t
  271. ucl_unescape_json_string (char *str, size_t len)
  272. {
  273. char *t = str, *h = str;
  274. int i, uval;
  275. if (len <= 1) {
  276. return len;
  277. }
  278. /* t is target (tortoise), h is source (hare) */
  279. while (len) {
  280. if (*h == '\\') {
  281. h ++;
  282. if (len == 1) {
  283. /*
  284. * If \ is last, then do not try to go further
  285. * Issue: #74
  286. */
  287. len --;
  288. *t++ = '\\';
  289. continue;
  290. }
  291. switch (*h) {
  292. case 'n':
  293. *t++ = '\n';
  294. break;
  295. case 'r':
  296. *t++ = '\r';
  297. break;
  298. case 'b':
  299. *t++ = '\b';
  300. break;
  301. case 't':
  302. *t++ = '\t';
  303. break;
  304. case 'f':
  305. *t++ = '\f';
  306. break;
  307. case '\\':
  308. *t++ = '\\';
  309. break;
  310. case '"':
  311. *t++ = '"';
  312. break;
  313. case 'u':
  314. /* Unicode escape */
  315. uval = 0;
  316. h ++; /* u character */
  317. len --;
  318. if (len > 3) {
  319. for (i = 0; i < 4; i++) {
  320. uval <<= 4;
  321. if (isdigit (h[i])) {
  322. uval += h[i] - '0';
  323. }
  324. else if (h[i] >= 'a' && h[i] <= 'f') {
  325. uval += h[i] - 'a' + 10;
  326. }
  327. else if (h[i] >= 'A' && h[i] <= 'F') {
  328. uval += h[i] - 'A' + 10;
  329. }
  330. else {
  331. break;
  332. }
  333. }
  334. /* Encode */
  335. if(uval < 0x80) {
  336. t[0] = (char)uval;
  337. t ++;
  338. }
  339. else if(uval < 0x800) {
  340. t[0] = 0xC0 + ((uval & 0x7C0) >> 6);
  341. t[1] = 0x80 + ((uval & 0x03F));
  342. t += 2;
  343. }
  344. else if(uval < 0x10000) {
  345. t[0] = 0xE0 + ((uval & 0xF000) >> 12);
  346. t[1] = 0x80 + ((uval & 0x0FC0) >> 6);
  347. t[2] = 0x80 + ((uval & 0x003F));
  348. t += 3;
  349. }
  350. #if 0
  351. /* It's not actually supported now */
  352. else if(uval <= 0x10FFFF) {
  353. t[0] = 0xF0 + ((uval & 0x1C0000) >> 18);
  354. t[1] = 0x80 + ((uval & 0x03F000) >> 12);
  355. t[2] = 0x80 + ((uval & 0x000FC0) >> 6);
  356. t[3] = 0x80 + ((uval & 0x00003F));
  357. t += 4;
  358. }
  359. #endif
  360. else {
  361. *t++ = '?';
  362. }
  363. /* Consume 4 characters of source */
  364. h += 4;
  365. len -= 4;
  366. if (len > 0) {
  367. len --; /* for '\' character */
  368. }
  369. continue;
  370. }
  371. else {
  372. *t++ = 'u';
  373. }
  374. break;
  375. default:
  376. *t++ = *h;
  377. break;
  378. }
  379. h ++;
  380. len --;
  381. }
  382. else {
  383. *t++ = *h++;
  384. }
  385. if (len > 0) {
  386. len --;
  387. }
  388. }
  389. *t = '\0';
  390. return (t - str);
  391. }
  392. size_t
  393. ucl_unescape_squoted_string (char *str, size_t len)
  394. {
  395. char *t = str, *h = str;
  396. if (len <= 1) {
  397. return len;
  398. }
  399. /* t is target (tortoise), h is source (hare) */
  400. while (len) {
  401. if (*h == '\\') {
  402. h ++;
  403. if (len == 1) {
  404. /*
  405. * If \ is last, then do not try to go further
  406. * Issue: #74
  407. */
  408. len --;
  409. *t++ = '\\';
  410. continue;
  411. }
  412. switch (*h) {
  413. case '\'':
  414. *t++ = '\'';
  415. break;
  416. case '\n':
  417. /* Ignore \<newline> style stuff */
  418. break;
  419. case '\r':
  420. /* Ignore \r and the following \n if needed */
  421. if (len > 1 && h[1] == '\n') {
  422. h ++;
  423. len --;
  424. }
  425. break;
  426. default:
  427. /* Ignore \ */
  428. *t++ = '\\';
  429. *t++ = *h;
  430. break;
  431. }
  432. h ++;
  433. len --;
  434. }
  435. else {
  436. *t++ = *h++;
  437. }
  438. if (len > 0) {
  439. len --;
  440. }
  441. }
  442. *t = '\0';
  443. return (t - str);
  444. }
  445. char *
  446. ucl_copy_key_trash (const ucl_object_t *obj)
  447. {
  448. ucl_object_t *deconst;
  449. if (obj == NULL) {
  450. return NULL;
  451. }
  452. if (obj->trash_stack[UCL_TRASH_KEY] == NULL && obj->key != NULL) {
  453. deconst = __DECONST (ucl_object_t *, obj);
  454. deconst->trash_stack[UCL_TRASH_KEY] = malloc (obj->keylen + 1);
  455. if (deconst->trash_stack[UCL_TRASH_KEY] != NULL) {
  456. memcpy (deconst->trash_stack[UCL_TRASH_KEY], obj->key, obj->keylen);
  457. deconst->trash_stack[UCL_TRASH_KEY][obj->keylen] = '\0';
  458. }
  459. deconst->key = obj->trash_stack[UCL_TRASH_KEY];
  460. deconst->flags |= UCL_OBJECT_ALLOCATED_KEY;
  461. }
  462. return obj->trash_stack[UCL_TRASH_KEY];
  463. }
  464. void
  465. ucl_chunk_free (struct ucl_chunk *chunk)
  466. {
  467. if (chunk) {
  468. struct ucl_parser_special_handler_chain *chain, *tmp;
  469. LL_FOREACH_SAFE (chunk->special_handlers, chain, tmp) {
  470. if (chain->special_handler->free_function) {
  471. chain->special_handler->free_function (
  472. chain->begin,
  473. chain->len,
  474. chain->special_handler->user_data);
  475. } else {
  476. UCL_FREE (chain->len, chain->begin);
  477. }
  478. UCL_FREE (sizeof (*chain), chain);
  479. }
  480. chunk->special_handlers = NULL;
  481. if (chunk->fname) {
  482. free (chunk->fname);
  483. }
  484. UCL_FREE (sizeof (*chunk), chunk);
  485. }
  486. }
  487. char *
  488. ucl_copy_value_trash (const ucl_object_t *obj)
  489. {
  490. ucl_object_t *deconst;
  491. if (obj == NULL) {
  492. return NULL;
  493. }
  494. if (obj->trash_stack[UCL_TRASH_VALUE] == NULL) {
  495. deconst = __DECONST (ucl_object_t *, obj);
  496. if (obj->type == UCL_STRING) {
  497. /* Special case for strings */
  498. if (obj->flags & UCL_OBJECT_BINARY) {
  499. deconst->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len);
  500. if (deconst->trash_stack[UCL_TRASH_VALUE] != NULL) {
  501. memcpy (deconst->trash_stack[UCL_TRASH_VALUE],
  502. obj->value.sv,
  503. obj->len);
  504. deconst->value.sv = obj->trash_stack[UCL_TRASH_VALUE];
  505. }
  506. }
  507. else {
  508. deconst->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len + 1);
  509. if (deconst->trash_stack[UCL_TRASH_VALUE] != NULL) {
  510. memcpy (deconst->trash_stack[UCL_TRASH_VALUE],
  511. obj->value.sv,
  512. obj->len);
  513. deconst->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0';
  514. deconst->value.sv = obj->trash_stack[UCL_TRASH_VALUE];
  515. }
  516. }
  517. }
  518. else {
  519. /* Just emit value in json notation */
  520. deconst->trash_stack[UCL_TRASH_VALUE] = ucl_object_emit_single_json (obj);
  521. deconst->len = strlen (obj->trash_stack[UCL_TRASH_VALUE]);
  522. }
  523. deconst->flags |= UCL_OBJECT_ALLOCATED_VALUE;
  524. }
  525. return obj->trash_stack[UCL_TRASH_VALUE];
  526. }
  527. ucl_object_t*
  528. ucl_parser_get_object (struct ucl_parser *parser)
  529. {
  530. if (parser->state != UCL_STATE_ERROR && parser->top_obj != NULL) {
  531. return ucl_object_ref (parser->top_obj);
  532. }
  533. return NULL;
  534. }
  535. void
  536. ucl_parser_free (struct ucl_parser *parser)
  537. {
  538. struct ucl_stack *stack, *stmp;
  539. struct ucl_macro *macro, *mtmp;
  540. struct ucl_chunk *chunk, *ctmp;
  541. struct ucl_pubkey *key, *ktmp;
  542. struct ucl_variable *var, *vtmp;
  543. ucl_object_t *tr, *trtmp;
  544. if (parser == NULL) {
  545. return;
  546. }
  547. if (parser->top_obj != NULL) {
  548. ucl_object_unref (parser->top_obj);
  549. }
  550. if (parser->includepaths != NULL) {
  551. ucl_object_unref (parser->includepaths);
  552. }
  553. LL_FOREACH_SAFE (parser->stack, stack, stmp) {
  554. free (stack);
  555. }
  556. HASH_ITER (hh, parser->macroes, macro, mtmp) {
  557. free (macro->name);
  558. HASH_DEL (parser->macroes, macro);
  559. UCL_FREE (sizeof (struct ucl_macro), macro);
  560. }
  561. LL_FOREACH_SAFE (parser->chunks, chunk, ctmp) {
  562. ucl_chunk_free (chunk);
  563. }
  564. LL_FOREACH_SAFE (parser->keys, key, ktmp) {
  565. UCL_FREE (sizeof (struct ucl_pubkey), key);
  566. }
  567. LL_FOREACH_SAFE (parser->variables, var, vtmp) {
  568. free (var->value);
  569. free (var->var);
  570. UCL_FREE (sizeof (struct ucl_variable), var);
  571. }
  572. LL_FOREACH_SAFE (parser->trash_objs, tr, trtmp) {
  573. ucl_object_free_internal (tr, false, ucl_object_dtor_free);
  574. }
  575. if (parser->err != NULL) {
  576. utstring_free (parser->err);
  577. }
  578. if (parser->cur_file) {
  579. free (parser->cur_file);
  580. }
  581. if (parser->comments) {
  582. ucl_object_unref (parser->comments);
  583. }
  584. UCL_FREE (sizeof (struct ucl_parser), parser);
  585. }
  586. const char *
  587. ucl_parser_get_error(struct ucl_parser *parser)
  588. {
  589. if (parser == NULL) {
  590. return NULL;
  591. }
  592. if (parser->err == NULL) {
  593. return NULL;
  594. }
  595. return utstring_body (parser->err);
  596. }
  597. int
  598. ucl_parser_get_error_code(struct ucl_parser *parser)
  599. {
  600. if (parser == NULL) {
  601. return 0;
  602. }
  603. return parser->err_code;
  604. }
  605. unsigned
  606. ucl_parser_get_column(struct ucl_parser *parser)
  607. {
  608. if (parser == NULL || parser->chunks == NULL) {
  609. return 0;
  610. }
  611. return parser->chunks->column;
  612. }
  613. unsigned
  614. ucl_parser_get_linenum(struct ucl_parser *parser)
  615. {
  616. if (parser == NULL || parser->chunks == NULL) {
  617. return 0;
  618. }
  619. return parser->chunks->line;
  620. }
  621. void
  622. ucl_parser_clear_error(struct ucl_parser *parser)
  623. {
  624. if (parser != NULL && parser->err != NULL) {
  625. utstring_free(parser->err);
  626. parser->err = NULL;
  627. parser->err_code = 0;
  628. }
  629. }
  630. bool
  631. ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len)
  632. {
  633. #ifndef HAVE_OPENSSL
  634. ucl_create_err (&parser->err, "cannot check signatures without openssl");
  635. return false;
  636. #else
  637. # if (OPENSSL_VERSION_NUMBER < 0x10000000L)
  638. ucl_create_err (&parser->err, "cannot check signatures, openssl version is unsupported");
  639. return EXIT_FAILURE;
  640. # else
  641. struct ucl_pubkey *nkey;
  642. BIO *mem;
  643. mem = BIO_new_mem_buf ((void *)key, len);
  644. nkey = UCL_ALLOC (sizeof (struct ucl_pubkey));
  645. if (nkey == NULL) {
  646. ucl_create_err (&parser->err, "cannot allocate memory for key");
  647. return false;
  648. }
  649. nkey->key = PEM_read_bio_PUBKEY (mem, &nkey->key, NULL, NULL);
  650. BIO_free (mem);
  651. if (nkey->key == NULL) {
  652. UCL_FREE (sizeof (struct ucl_pubkey), nkey);
  653. ucl_create_err (&parser->err, "%s",
  654. ERR_error_string (ERR_get_error (), NULL));
  655. return false;
  656. }
  657. LL_PREPEND (parser->keys, nkey);
  658. # endif
  659. #endif
  660. return true;
  661. }
  662. void ucl_parser_add_special_handler (struct ucl_parser *parser,
  663. struct ucl_parser_special_handler *handler)
  664. {
  665. LL_APPEND (parser->special_handlers, handler);
  666. }
  667. #ifdef CURL_FOUND
  668. struct ucl_curl_cbdata {
  669. unsigned char *buf;
  670. size_t buflen;
  671. };
  672. static size_t
  673. ucl_curl_write_callback (void* contents, size_t size, size_t nmemb, void* ud)
  674. {
  675. struct ucl_curl_cbdata *cbdata = ud;
  676. size_t realsize = size * nmemb;
  677. cbdata->buf = realloc (cbdata->buf, cbdata->buflen + realsize + 1);
  678. if (cbdata->buf == NULL) {
  679. return 0;
  680. }
  681. memcpy (&(cbdata->buf[cbdata->buflen]), contents, realsize);
  682. cbdata->buflen += realsize;
  683. cbdata->buf[cbdata->buflen] = 0;
  684. return realsize;
  685. }
  686. #endif
  687. /**
  688. * Fetch a url and save results to the memory buffer
  689. * @param url url to fetch
  690. * @param len length of url
  691. * @param buf target buffer
  692. * @param buflen target length
  693. * @return
  694. */
  695. bool
  696. ucl_fetch_url (const unsigned char *url, unsigned char **buf, size_t *buflen,
  697. UT_string **err, bool must_exist)
  698. {
  699. #ifdef HAVE_FETCH_H
  700. struct url *fetch_url;
  701. struct url_stat us;
  702. FILE *in;
  703. fetch_url = fetchParseURL (url);
  704. if (fetch_url == NULL) {
  705. ucl_create_err (err, "invalid URL %s: %s",
  706. url, strerror (errno));
  707. return false;
  708. }
  709. if ((in = fetchXGet (fetch_url, &us, "")) == NULL) {
  710. if (!must_exist) {
  711. ucl_create_err (err, "cannot fetch URL %s: %s",
  712. url, strerror (errno));
  713. }
  714. fetchFreeURL (fetch_url);
  715. return false;
  716. }
  717. *buflen = us.size;
  718. *buf = malloc (*buflen);
  719. if (*buf == NULL) {
  720. ucl_create_err (err, "cannot allocate buffer for URL %s: %s",
  721. url, strerror (errno));
  722. fclose (in);
  723. fetchFreeURL (fetch_url);
  724. return false;
  725. }
  726. if (fread (*buf, *buflen, 1, in) != 1) {
  727. ucl_create_err (err, "cannot read URL %s: %s",
  728. url, strerror (errno));
  729. fclose (in);
  730. fetchFreeURL (fetch_url);
  731. return false;
  732. }
  733. fetchFreeURL (fetch_url);
  734. return true;
  735. #elif defined(CURL_FOUND)
  736. CURL *curl;
  737. int r;
  738. struct ucl_curl_cbdata cbdata;
  739. curl = curl_easy_init ();
  740. if (curl == NULL) {
  741. ucl_create_err (err, "CURL interface is broken");
  742. return false;
  743. }
  744. if ((r = curl_easy_setopt (curl, CURLOPT_URL, url)) != CURLE_OK) {
  745. ucl_create_err (err, "invalid URL %s: %s",
  746. url, curl_easy_strerror (r));
  747. curl_easy_cleanup (curl);
  748. return false;
  749. }
  750. curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, ucl_curl_write_callback);
  751. cbdata.buf = NULL;
  752. cbdata.buflen = 0;
  753. curl_easy_setopt (curl, CURLOPT_WRITEDATA, &cbdata);
  754. if ((r = curl_easy_perform (curl)) != CURLE_OK) {
  755. if (!must_exist) {
  756. ucl_create_err (err, "error fetching URL %s: %s",
  757. url, curl_easy_strerror (r));
  758. }
  759. curl_easy_cleanup (curl);
  760. if (cbdata.buf) {
  761. free (cbdata.buf);
  762. }
  763. return false;
  764. }
  765. *buf = cbdata.buf;
  766. *buflen = cbdata.buflen;
  767. curl_easy_cleanup (curl);
  768. return true;
  769. #else
  770. ucl_create_err (err, "URL support is disabled");
  771. return false;
  772. #endif
  773. }
  774. /**
  775. * Fetch a file and save results to the memory buffer
  776. * @param filename filename to fetch
  777. * @param len length of filename
  778. * @param buf target buffer
  779. * @param buflen target length
  780. * @return
  781. */
  782. bool
  783. ucl_fetch_file (const unsigned char *filename, unsigned char **buf, size_t *buflen,
  784. UT_string **err, bool must_exist)
  785. {
  786. int fd;
  787. struct stat st;
  788. if ((fd = open (filename, O_RDONLY)) == -1) {
  789. ucl_create_err (err, "cannot open file %s: %s",
  790. filename, strerror (errno));
  791. return false;
  792. }
  793. if (fstat (fd, &st) == -1) {
  794. if (must_exist || errno == EPERM) {
  795. ucl_create_err (err, "cannot stat file %s: %s",
  796. filename, strerror (errno));
  797. }
  798. close (fd);
  799. return false;
  800. }
  801. if (!S_ISREG (st.st_mode)) {
  802. if (must_exist) {
  803. ucl_create_err (err, "file %s is not a regular file", filename);
  804. }
  805. close (fd);
  806. return false;
  807. }
  808. if (st.st_size == 0) {
  809. /* Do not map empty files */
  810. *buf = NULL;
  811. *buflen = 0;
  812. }
  813. else {
  814. if ((*buf = ucl_mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
  815. close(fd);
  816. ucl_create_err(err, "cannot mmap file %s: %s",
  817. filename, strerror(errno));
  818. *buf = NULL;
  819. return false;
  820. }
  821. *buflen = st.st_size;
  822. }
  823. close (fd);
  824. return true;
  825. }
  826. #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
  827. static inline bool
  828. ucl_sig_check (const unsigned char *data, size_t datalen,
  829. const unsigned char *sig, size_t siglen, struct ucl_parser *parser)
  830. {
  831. struct ucl_pubkey *key;
  832. char dig[EVP_MAX_MD_SIZE];
  833. unsigned int diglen;
  834. EVP_PKEY_CTX *key_ctx;
  835. EVP_MD_CTX *sign_ctx = NULL;
  836. sign_ctx = EVP_MD_CTX_create ();
  837. LL_FOREACH (parser->keys, key) {
  838. key_ctx = EVP_PKEY_CTX_new (key->key, NULL);
  839. if (key_ctx != NULL) {
  840. if (EVP_PKEY_verify_init (key_ctx) <= 0) {
  841. EVP_PKEY_CTX_free (key_ctx);
  842. continue;
  843. }
  844. if (EVP_PKEY_CTX_set_rsa_padding (key_ctx, RSA_PKCS1_PADDING) <= 0) {
  845. EVP_PKEY_CTX_free (key_ctx);
  846. continue;
  847. }
  848. if (EVP_PKEY_CTX_set_signature_md (key_ctx, EVP_sha256 ()) <= 0) {
  849. EVP_PKEY_CTX_free (key_ctx);
  850. continue;
  851. }
  852. EVP_DigestInit (sign_ctx, EVP_sha256 ());
  853. EVP_DigestUpdate (sign_ctx, data, datalen);
  854. EVP_DigestFinal (sign_ctx, dig, &diglen);
  855. if (EVP_PKEY_verify (key_ctx, sig, siglen, dig, diglen) == 1) {
  856. EVP_MD_CTX_destroy (sign_ctx);
  857. EVP_PKEY_CTX_free (key_ctx);
  858. return true;
  859. }
  860. EVP_PKEY_CTX_free (key_ctx);
  861. }
  862. }
  863. EVP_MD_CTX_destroy (sign_ctx);
  864. return false;
  865. }
  866. #endif
  867. struct ucl_include_params {
  868. bool check_signature;
  869. bool must_exist;
  870. bool use_glob;
  871. bool use_prefix;
  872. bool soft_fail;
  873. bool allow_glob;
  874. unsigned priority;
  875. enum ucl_duplicate_strategy strat;
  876. enum ucl_parse_type parse_type;
  877. const char *prefix;
  878. const char *target;
  879. };
  880. /**
  881. * Include an url to configuration
  882. * @param data
  883. * @param len
  884. * @param parser
  885. * @param err
  886. * @return
  887. */
  888. static bool
  889. ucl_include_url (const unsigned char *data, size_t len,
  890. struct ucl_parser *parser,
  891. struct ucl_include_params *params)
  892. {
  893. bool res;
  894. unsigned char *buf = NULL;
  895. size_t buflen = 0;
  896. struct ucl_chunk *chunk;
  897. char urlbuf[PATH_MAX];
  898. int prev_state;
  899. snprintf (urlbuf, sizeof (urlbuf), "%.*s", (int)len, data);
  900. if (!ucl_fetch_url (urlbuf, &buf, &buflen, &parser->err, params->must_exist)) {
  901. if (!params->must_exist) {
  902. ucl_parser_clear_error (parser);
  903. }
  904. return !params->must_exist;
  905. }
  906. if (params->check_signature) {
  907. #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
  908. unsigned char *sigbuf = NULL;
  909. size_t siglen = 0;
  910. /* We need to check signature first */
  911. snprintf (urlbuf, sizeof (urlbuf), "%.*s.sig", (int)len, data);
  912. if (!ucl_fetch_url (urlbuf, &sigbuf, &siglen, &parser->err, true)) {
  913. return false;
  914. }
  915. if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
  916. ucl_create_err (&parser->err, "cannot verify url %s: %s",
  917. urlbuf,
  918. ERR_error_string (ERR_get_error (), NULL));
  919. if (siglen > 0) {
  920. ucl_munmap (sigbuf, siglen);
  921. }
  922. return false;
  923. }
  924. if (siglen > 0) {
  925. ucl_munmap (sigbuf, siglen);
  926. }
  927. #endif
  928. }
  929. prev_state = parser->state;
  930. parser->state = UCL_STATE_INIT;
  931. res = ucl_parser_add_chunk_full (parser, buf, buflen, params->priority,
  932. params->strat, params->parse_type);
  933. if (res == true) {
  934. /* Remove chunk from the stack */
  935. chunk = parser->chunks;
  936. if (chunk != NULL) {
  937. parser->chunks = chunk->next;
  938. ucl_chunk_free (chunk);
  939. }
  940. }
  941. parser->state = prev_state;
  942. free (buf);
  943. return res;
  944. }
  945. /**
  946. * Include a single file to the parser
  947. * @param data
  948. * @param len
  949. * @param parser
  950. * @param check_signature
  951. * @param must_exist
  952. * @param allow_glob
  953. * @param priority
  954. * @return
  955. */
  956. static bool
  957. ucl_include_file_single (const unsigned char *data, size_t len,
  958. struct ucl_parser *parser, struct ucl_include_params *params)
  959. {
  960. bool res;
  961. struct ucl_chunk *chunk;
  962. unsigned char *buf = NULL;
  963. char *old_curfile, *ext;
  964. size_t buflen = 0;
  965. char filebuf[PATH_MAX], realbuf[PATH_MAX];
  966. int prev_state;
  967. struct ucl_variable *cur_var, *tmp_var, *old_curdir = NULL,
  968. *old_filename = NULL;
  969. ucl_object_t *nest_obj = NULL, *old_obj = NULL, *new_obj = NULL;
  970. ucl_hash_t *container = NULL;
  971. struct ucl_stack *st = NULL;
  972. if (parser->state == UCL_STATE_ERROR) {
  973. /* Return immediately if we are in the error state... */
  974. return false;
  975. }
  976. snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data);
  977. if (ucl_realpath (filebuf, realbuf) == NULL) {
  978. if (params->soft_fail) {
  979. return false;
  980. }
  981. if (!params->must_exist && errno != EPERM) {
  982. return true;
  983. }
  984. ucl_create_err (&parser->err, "cannot open file %s: %s",
  985. filebuf,
  986. strerror (errno));
  987. return false;
  988. }
  989. if (parser->cur_file && strcmp (realbuf, parser->cur_file) == 0) {
  990. /* We are likely including the file itself */
  991. if (params->soft_fail) {
  992. return false;
  993. }
  994. ucl_create_err (&parser->err, "trying to include the file %s from itself",
  995. realbuf);
  996. return false;
  997. }
  998. if (!ucl_fetch_file (realbuf, &buf, &buflen, &parser->err, params->must_exist)) {
  999. if (params->soft_fail) {
  1000. return false;
  1001. }
  1002. if (params->must_exist || parser->err != NULL) {
  1003. /* The case of fatal errors */
  1004. return false;
  1005. }
  1006. ucl_parser_clear_error (parser);
  1007. return true;
  1008. }
  1009. if (params->check_signature) {
  1010. #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
  1011. unsigned char *sigbuf = NULL;
  1012. size_t siglen = 0;
  1013. /* We need to check signature first */
  1014. snprintf (filebuf, sizeof (filebuf), "%s.sig", realbuf);
  1015. if (!ucl_fetch_file (filebuf, &sigbuf, &siglen, &parser->err, true)) {
  1016. if (buf) {
  1017. ucl_munmap (buf, buflen);
  1018. }
  1019. return false;
  1020. }
  1021. if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
  1022. ucl_create_err (&parser->err, "cannot verify file %s: %s",
  1023. filebuf,
  1024. ERR_error_string (ERR_get_error (), NULL));
  1025. if (sigbuf) {
  1026. ucl_munmap (sigbuf, siglen);
  1027. }
  1028. if (buf) {
  1029. ucl_munmap (buf, buflen);
  1030. }
  1031. return false;
  1032. }
  1033. if (sigbuf) {
  1034. ucl_munmap (sigbuf, siglen);
  1035. }
  1036. #endif
  1037. }
  1038. old_curfile = parser->cur_file;
  1039. parser->cur_file = NULL;
  1040. /* Store old file vars */
  1041. DL_FOREACH_SAFE (parser->variables, cur_var, tmp_var) {
  1042. if (strcmp (cur_var->var, "CURDIR") == 0) {
  1043. old_curdir = cur_var;
  1044. DL_DELETE (parser->variables, cur_var);
  1045. }
  1046. else if (strcmp (cur_var->var, "FILENAME") == 0) {
  1047. old_filename = cur_var;
  1048. DL_DELETE (parser->variables, cur_var);
  1049. }
  1050. }
  1051. ucl_parser_set_filevars (parser, realbuf, false);
  1052. prev_state = parser->state;
  1053. parser->state = UCL_STATE_INIT;
  1054. if (params->use_prefix && params->prefix == NULL) {
  1055. /* Auto generate a key name based on the included filename */
  1056. params->prefix = basename (realbuf);
  1057. ext = strrchr (params->prefix, '.');
  1058. if (ext != NULL && (strcmp (ext, ".conf") == 0 || strcmp (ext, ".ucl") == 0)) {
  1059. /* Strip off .conf or .ucl */
  1060. *ext = '\0';
  1061. }
  1062. }
  1063. if (params->prefix != NULL) {
  1064. /* This is a prefixed include */
  1065. container = parser->stack->obj->value.ov;
  1066. old_obj = __DECONST (ucl_object_t *, ucl_hash_search (container,
  1067. params->prefix, strlen (params->prefix)));
  1068. if (strcasecmp (params->target, "array") == 0) {
  1069. if (old_obj == NULL) {
  1070. /* Create an array with key: prefix */
  1071. old_obj = ucl_object_new_full (UCL_ARRAY, params->priority);
  1072. old_obj->key = params->prefix;
  1073. old_obj->keylen = strlen (params->prefix);
  1074. ucl_copy_key_trash (old_obj);
  1075. old_obj->prev = old_obj;
  1076. old_obj->next = NULL;
  1077. container = ucl_hash_insert_object (container, old_obj,
  1078. parser->flags & UCL_PARSER_KEY_LOWERCASE);
  1079. parser->stack->obj->len++;
  1080. nest_obj = ucl_object_new_full (UCL_OBJECT, params->priority);
  1081. nest_obj->prev = nest_obj;
  1082. nest_obj->next = NULL;
  1083. ucl_array_append (old_obj, nest_obj);
  1084. }
  1085. else {
  1086. if (ucl_object_type (old_obj) == UCL_ARRAY) {
  1087. /* Append to the existing array */
  1088. nest_obj = ucl_object_new_full (UCL_OBJECT,
  1089. params->priority);
  1090. if (nest_obj == NULL) {
  1091. ucl_create_err (&parser->err,
  1092. "cannot allocate memory for an object");
  1093. if (buf) {
  1094. ucl_munmap (buf, buflen);
  1095. }
  1096. return false;
  1097. }
  1098. nest_obj->prev = nest_obj;
  1099. nest_obj->next = NULL;
  1100. ucl_array_append (old_obj, nest_obj);
  1101. }
  1102. else {
  1103. /* Convert the object to an array */
  1104. new_obj = ucl_object_typed_new (UCL_ARRAY);
  1105. if (new_obj == NULL) {
  1106. ucl_create_err (&parser->err,
  1107. "cannot allocate memory for an object");
  1108. if (buf) {
  1109. ucl_munmap (buf, buflen);
  1110. }
  1111. return false;
  1112. }
  1113. new_obj->key = old_obj->key;
  1114. new_obj->keylen = old_obj->keylen;
  1115. new_obj->flags |= UCL_OBJECT_MULTIVALUE;
  1116. new_obj->prev = new_obj;
  1117. new_obj->next = NULL;
  1118. nest_obj = ucl_object_new_full (UCL_OBJECT,
  1119. params->priority);
  1120. if (nest_obj == NULL) {
  1121. ucl_create_err (&parser->err,
  1122. "cannot allocate memory for an object");
  1123. if (buf) {
  1124. ucl_munmap (buf, buflen);
  1125. }
  1126. ucl_object_unref (new_obj);
  1127. return false;
  1128. }
  1129. nest_obj->prev = nest_obj;
  1130. nest_obj->next = NULL;
  1131. ucl_array_append (new_obj, old_obj);
  1132. ucl_array_append (new_obj, nest_obj);
  1133. ucl_hash_replace (container, old_obj, new_obj);
  1134. }
  1135. }
  1136. }
  1137. else {
  1138. /* Case of object */
  1139. if (old_obj == NULL) {
  1140. /* Create an object with key: prefix */
  1141. nest_obj = ucl_object_new_full (UCL_OBJECT, params->priority);
  1142. if (nest_obj == NULL) {
  1143. ucl_create_err (&parser->err, "cannot allocate memory for an object");
  1144. if (buf) {
  1145. ucl_munmap (buf, buflen);
  1146. }
  1147. return false;
  1148. }
  1149. nest_obj->key = params->prefix;
  1150. nest_obj->keylen = strlen (params->prefix);
  1151. ucl_copy_key_trash(nest_obj);
  1152. nest_obj->prev = nest_obj;
  1153. nest_obj->next = NULL;
  1154. container = ucl_hash_insert_object (container, nest_obj,
  1155. parser->flags & UCL_PARSER_KEY_LOWERCASE);
  1156. parser->stack->obj->len ++;
  1157. }
  1158. else {
  1159. if (ucl_object_type (old_obj) == UCL_OBJECT) {
  1160. /* Append to existing Object*/
  1161. nest_obj = old_obj;
  1162. }
  1163. else {
  1164. /* The key is not an object */
  1165. ucl_create_err (&parser->err,
  1166. "Conflicting type for key: %s, asked %s, has %s",
  1167. params->prefix, params->target,
  1168. ucl_object_type_to_string (ucl_object_type (old_obj)));
  1169. if (buf) {
  1170. ucl_munmap (buf, buflen);
  1171. }
  1172. return false;
  1173. }
  1174. }
  1175. }
  1176. /* Put all of the content of the include inside that object */
  1177. parser->stack->obj->value.ov = container;
  1178. st = UCL_ALLOC (sizeof (struct ucl_stack));
  1179. if (st == NULL) {
  1180. ucl_create_err (&parser->err, "cannot allocate memory for an object");
  1181. ucl_object_unref (nest_obj);
  1182. if (buf) {
  1183. ucl_munmap (buf, buflen);
  1184. }
  1185. return false;
  1186. }
  1187. st->obj = nest_obj;
  1188. st->e.params.level = parser->stack->e.params.level;
  1189. st->e.params.flags = parser->stack->e.params.flags;
  1190. st->e.params.line = parser->stack->e.params.line;
  1191. st->chunk = parser->chunks;
  1192. LL_PREPEND (parser->stack, st);
  1193. parser->cur_obj = nest_obj;
  1194. }
  1195. res = ucl_parser_add_chunk_full (parser, buf, buflen, params->priority,
  1196. params->strat, params->parse_type);
  1197. if (res) {
  1198. /* Stop nesting the include, take 1 level off the stack */
  1199. if (params->prefix != NULL && nest_obj != NULL) {
  1200. parser->stack = st->next;
  1201. UCL_FREE (sizeof (struct ucl_stack), st);
  1202. }
  1203. /* Remove chunk from the stack */
  1204. chunk = parser->chunks;
  1205. if (chunk != NULL) {
  1206. parser->chunks = chunk->next;
  1207. ucl_chunk_free (chunk);
  1208. parser->recursion--;
  1209. }
  1210. /* Restore old file vars */
  1211. if (parser->cur_file) {
  1212. free (parser->cur_file);
  1213. }
  1214. parser->cur_file = old_curfile;
  1215. DL_FOREACH_SAFE (parser->variables, cur_var, tmp_var) {
  1216. if (strcmp (cur_var->var, "CURDIR") == 0 && old_curdir) {
  1217. DL_DELETE (parser->variables, cur_var);
  1218. free (cur_var->var);
  1219. free (cur_var->value);
  1220. UCL_FREE (sizeof (struct ucl_variable), cur_var);
  1221. } else if (strcmp (cur_var->var, "FILENAME") == 0 && old_filename) {
  1222. DL_DELETE (parser->variables, cur_var);
  1223. free (cur_var->var);
  1224. free (cur_var->value);
  1225. UCL_FREE (sizeof (struct ucl_variable), cur_var);
  1226. }
  1227. }
  1228. if (old_filename) {
  1229. DL_APPEND (parser->variables, old_filename);
  1230. }
  1231. if (old_curdir) {
  1232. DL_APPEND (parser->variables, old_curdir);
  1233. }
  1234. parser->state = prev_state;
  1235. }
  1236. if (buflen > 0) {
  1237. ucl_munmap (buf, buflen);
  1238. }
  1239. return res;
  1240. }
  1241. /**
  1242. * Include a file to configuration
  1243. * @param data
  1244. * @param len
  1245. * @param parser
  1246. * @param err
  1247. * @return
  1248. */
  1249. static bool
  1250. ucl_include_file (const unsigned char *data, size_t len,
  1251. struct ucl_parser *parser,
  1252. struct ucl_include_params *params,
  1253. const ucl_object_t *args)
  1254. {
  1255. const unsigned char *p = data, *end = data + len;
  1256. bool need_glob = false;
  1257. int cnt = 0;
  1258. char glob_pattern[PATH_MAX];
  1259. size_t i;
  1260. #ifndef _WIN32
  1261. if (!params->allow_glob) {
  1262. return ucl_include_file_single (data, len, parser, params);
  1263. }
  1264. else {
  1265. /* Check for special symbols in a filename */
  1266. while (p != end) {
  1267. if (*p == '*' || *p == '?') {
  1268. need_glob = true;
  1269. break;
  1270. }
  1271. p ++;
  1272. }
  1273. if (need_glob) {
  1274. glob_t globbuf;
  1275. memset (&globbuf, 0, sizeof (globbuf));
  1276. ucl_strlcpy (glob_pattern, (const char *)data,
  1277. (len + 1 < sizeof (glob_pattern) ? len + 1 : sizeof (glob_pattern)));
  1278. if (glob (glob_pattern, 0, NULL, &globbuf) != 0) {
  1279. return (!params->must_exist || false);
  1280. }
  1281. for (i = 0; i < globbuf.gl_pathc; i ++) {
  1282. if (parser->include_trace_func) {
  1283. const ucl_object_t *parent = NULL;
  1284. if (parser->stack) {
  1285. parent = parser->stack->obj;
  1286. }
  1287. parser->include_trace_func (parser, parent, NULL,
  1288. globbuf.gl_pathv[i],
  1289. strlen (globbuf.gl_pathv[i]),
  1290. parser->include_trace_ud);
  1291. }
  1292. if (!ucl_include_file_single ((unsigned char *)globbuf.gl_pathv[i],
  1293. strlen (globbuf.gl_pathv[i]), parser, params)) {
  1294. if (params->soft_fail) {
  1295. continue;
  1296. }
  1297. globfree (&globbuf);
  1298. return false;
  1299. }
  1300. cnt ++;
  1301. }
  1302. globfree (&globbuf);
  1303. if (cnt == 0 && params->must_exist) {
  1304. ucl_create_err (&parser->err, "cannot match any files for pattern %s",
  1305. glob_pattern);
  1306. return false;
  1307. }
  1308. }
  1309. else {
  1310. return ucl_include_file_single (data, len, parser, params);
  1311. }
  1312. }
  1313. #else
  1314. /* Win32 compilers do not support globbing. Therefore, for Win32,
  1315. treat allow_glob/need_glob as a NOOP and just return */
  1316. return ucl_include_file_single (data, len, parser, params);
  1317. #endif
  1318. return true;
  1319. }
  1320. /**
  1321. * Common function to handle .*include* macros
  1322. * @param data
  1323. * @param len
  1324. * @param args
  1325. * @param parser
  1326. * @param default_try
  1327. * @param default_sign
  1328. * @return
  1329. */
  1330. static bool
  1331. ucl_include_common (const unsigned char *data, size_t len,
  1332. const ucl_object_t *args, struct ucl_parser *parser,
  1333. bool default_try,
  1334. bool default_sign)
  1335. {
  1336. bool allow_url = false, search = false;
  1337. const char *duplicate;
  1338. const ucl_object_t *param;
  1339. ucl_object_iter_t it = NULL, ip = NULL;
  1340. char ipath[PATH_MAX];
  1341. struct ucl_include_params params;
  1342. /* Default values */
  1343. params.soft_fail = default_try;
  1344. params.allow_glob = false;
  1345. params.check_signature = default_sign;
  1346. params.use_prefix = false;
  1347. params.target = "object";
  1348. params.prefix = NULL;
  1349. params.priority = 0;
  1350. params.parse_type = UCL_PARSE_UCL;
  1351. params.strat = UCL_DUPLICATE_APPEND;
  1352. params.must_exist = !default_try;
  1353. if (parser->include_trace_func) {
  1354. const ucl_object_t *parent = NULL;
  1355. if (parser->stack) {
  1356. parent = parser->stack->obj;
  1357. }
  1358. parser->include_trace_func (parser, parent, args,
  1359. data, len, parser->include_trace_ud);
  1360. }
  1361. /* Process arguments */
  1362. if (args != NULL && args->type == UCL_OBJECT) {
  1363. while ((param = ucl_object_iterate (args, &it, true)) != NULL) {
  1364. if (param->type == UCL_BOOLEAN) {
  1365. if (strncmp (param->key, "try", param->keylen) == 0) {
  1366. params.must_exist = !ucl_object_toboolean (param);
  1367. }
  1368. else if (strncmp (param->key, "sign", param->keylen) == 0) {
  1369. params.check_signature = ucl_object_toboolean (param);
  1370. }
  1371. else if (strncmp (param->key, "glob", param->keylen) == 0) {
  1372. params.allow_glob = ucl_object_toboolean (param);
  1373. }
  1374. else if (strncmp (param->key, "url", param->keylen) == 0) {
  1375. allow_url = ucl_object_toboolean (param);
  1376. }
  1377. else if (strncmp (param->key, "prefix", param->keylen) == 0) {
  1378. params.use_prefix = ucl_object_toboolean (param);
  1379. }
  1380. }
  1381. else if (param->type == UCL_STRING) {
  1382. if (strncmp (param->key, "key", param->keylen) == 0) {
  1383. params.prefix = ucl_object_tostring (param);
  1384. }
  1385. else if (strncmp (param->key, "target", param->keylen) == 0) {
  1386. params.target = ucl_object_tostring (param);
  1387. }
  1388. else if (strncmp (param->key, "duplicate", param->keylen) == 0) {
  1389. duplicate = ucl_object_tostring (param);
  1390. if (strcmp (duplicate, "append") == 0) {
  1391. params.strat = UCL_DUPLICATE_APPEND;
  1392. }
  1393. else if (strcmp (duplicate, "merge") == 0) {
  1394. params.strat = UCL_DUPLICATE_MERGE;
  1395. }
  1396. else if (strcmp (duplicate, "rewrite") == 0) {
  1397. params.strat = UCL_DUPLICATE_REWRITE;
  1398. }
  1399. else if (strcmp (duplicate, "error") == 0) {
  1400. params.strat = UCL_DUPLICATE_ERROR;
  1401. }
  1402. }
  1403. }
  1404. else if (param->type == UCL_ARRAY) {
  1405. if (strncmp (param->key, "path", param->keylen) == 0) {
  1406. ucl_set_include_path (parser, __DECONST(ucl_object_t *, param));
  1407. }
  1408. }
  1409. else if (param->type == UCL_INT) {
  1410. if (strncmp (param->key, "priority", param->keylen) == 0) {
  1411. params.priority = ucl_object_toint (param);
  1412. }
  1413. }
  1414. }
  1415. }
  1416. if (parser->includepaths == NULL) {
  1417. if (allow_url && ucl_strnstr (data, "://", len) != NULL) {
  1418. /* Globbing is not used for URL's */
  1419. return ucl_include_url (data, len, parser, &params);
  1420. }
  1421. else if (data != NULL) {
  1422. /* Try to load a file */
  1423. return ucl_include_file (data, len, parser, &params, args);
  1424. }
  1425. }
  1426. else {
  1427. if (allow_url && ucl_strnstr (data, "://", len) != NULL) {
  1428. /* Globbing is not used for URL's */
  1429. return ucl_include_url (data, len, parser, &params);
  1430. }
  1431. ip = ucl_object_iterate_new (parser->includepaths);
  1432. while ((param = ucl_object_iterate_safe (ip, true)) != NULL) {
  1433. if (ucl_object_type(param) == UCL_STRING) {
  1434. snprintf (ipath, sizeof (ipath), "%s/%.*s", ucl_object_tostring(param),
  1435. (int)len, data);
  1436. if ((search = ucl_include_file (ipath, strlen (ipath),
  1437. parser, &params, args))) {
  1438. if (!params.allow_glob) {
  1439. break;
  1440. }
  1441. }
  1442. }
  1443. }
  1444. ucl_object_iterate_free (ip);
  1445. if (search == true) {
  1446. return true;
  1447. }
  1448. else {
  1449. ucl_create_err (&parser->err,
  1450. "cannot find file: %.*s in search path",
  1451. (int)len, data);
  1452. return false;
  1453. }
  1454. }
  1455. return false;
  1456. }
  1457. /**
  1458. * Handle include macro
  1459. * @param data include data
  1460. * @param len length of data
  1461. * @param args UCL object representing arguments to the macro
  1462. * @param ud user data
  1463. * @return
  1464. */
  1465. bool
  1466. ucl_include_handler (const unsigned char *data, size_t len,
  1467. const ucl_object_t *args, void* ud)
  1468. {
  1469. struct ucl_parser *parser = ud;
  1470. return ucl_include_common (data, len, args, parser, false, false);
  1471. }
  1472. /**
  1473. * Handle includes macro
  1474. * @param data include data
  1475. * @param len length of data
  1476. * @param args UCL object representing arguments to the macro
  1477. * @param ud user data
  1478. * @return
  1479. */
  1480. bool
  1481. ucl_includes_handler (const unsigned char *data, size_t len,
  1482. const ucl_object_t *args, void* ud)
  1483. {
  1484. struct ucl_parser *parser = ud;
  1485. return ucl_include_common (data, len, args, parser, false, true);
  1486. }
  1487. /**
  1488. * Handle tryinclude macro
  1489. * @param data include data
  1490. * @param len length of data
  1491. * @param args UCL object representing arguments to the macro
  1492. * @param ud user data
  1493. * @return
  1494. */
  1495. bool
  1496. ucl_try_include_handler (const unsigned char *data, size_t len,
  1497. const ucl_object_t *args, void* ud)
  1498. {
  1499. struct ucl_parser *parser = ud;
  1500. return ucl_include_common (data, len, args, parser, true, false);
  1501. }
  1502. /**
  1503. * Handle priority macro
  1504. * @param data include data
  1505. * @param len length of data
  1506. * @param args UCL object representing arguments to the macro
  1507. * @param ud user data
  1508. * @return
  1509. */
  1510. bool
  1511. ucl_priority_handler (const unsigned char *data, size_t len,
  1512. const ucl_object_t *args, void* ud)
  1513. {
  1514. struct ucl_parser *parser = ud;
  1515. unsigned priority = 255;
  1516. const ucl_object_t *param;
  1517. bool found = false;
  1518. char *value = NULL, *leftover = NULL;
  1519. ucl_object_iter_t it = NULL;
  1520. if (parser == NULL) {
  1521. return false;
  1522. }
  1523. /* Process arguments */
  1524. if (args != NULL && args->type == UCL_OBJECT) {
  1525. while ((param = ucl_object_iterate (args, &it, true)) != NULL) {
  1526. if (param->type == UCL_INT) {
  1527. if (strncmp (param->key, "priority", param->keylen) == 0) {
  1528. priority = ucl_object_toint (param);
  1529. found = true;
  1530. }
  1531. }
  1532. }
  1533. }
  1534. if (len > 0) {
  1535. value = malloc(len + 1);
  1536. ucl_strlcpy(value, (const char *)data, len + 1);
  1537. priority = strtol(value, &leftover, 10);
  1538. if (*leftover != '\0') {
  1539. ucl_create_err (&parser->err, "Invalid priority value in macro: %s",
  1540. value);
  1541. free(value);
  1542. return false;
  1543. }
  1544. free(value);
  1545. found = true;
  1546. }
  1547. if (found == true) {
  1548. parser->chunks->priority = priority;
  1549. return true;
  1550. }
  1551. ucl_create_err (&parser->err, "Unable to parse priority macro");
  1552. return false;
  1553. }
  1554. /**
  1555. * Handle load macro
  1556. * @param data include data
  1557. * @param len length of data
  1558. * @param args UCL object representing arguments to the macro
  1559. * @param ud user data
  1560. * @return
  1561. */
  1562. bool
  1563. ucl_load_handler (const unsigned char *data, size_t len,
  1564. const ucl_object_t *args, void* ud)
  1565. {
  1566. struct ucl_parser *parser = ud;
  1567. const ucl_object_t *param;
  1568. ucl_object_t *obj, *old_obj;
  1569. ucl_object_iter_t it = NULL;
  1570. bool try_load, multiline, test;
  1571. const char *target, *prefix;
  1572. char *load_file, *tmp;
  1573. unsigned char *buf;
  1574. size_t buflen;
  1575. unsigned priority;
  1576. int64_t iv;
  1577. ucl_object_t *container = NULL;
  1578. enum ucl_string_flags flags;
  1579. /* Default values */
  1580. try_load = false;
  1581. multiline = false;
  1582. test = false;
  1583. target = "string";
  1584. prefix = NULL;
  1585. load_file = NULL;
  1586. buf = NULL;
  1587. buflen = 0;
  1588. priority = 0;
  1589. obj = NULL;
  1590. old_obj = NULL;
  1591. flags = 0;
  1592. if (parser == NULL) {
  1593. return false;
  1594. }
  1595. /* Process arguments */
  1596. if (args != NULL && args->type == UCL_OBJECT) {
  1597. while ((param = ucl_object_iterate (args, &it, true)) != NULL) {
  1598. if (param->type == UCL_BOOLEAN) {
  1599. if (strncmp (param->key, "try", param->keylen) == 0) {
  1600. try_load = ucl_object_toboolean (param);
  1601. }
  1602. else if (strncmp (param->key, "multiline", param->keylen) == 0) {
  1603. multiline = ucl_object_toboolean (param);
  1604. }
  1605. else if (strncmp (param->key, "escape", param->keylen) == 0) {
  1606. test = ucl_object_toboolean (param);
  1607. if (test) {
  1608. flags |= UCL_STRING_ESCAPE;
  1609. }
  1610. }
  1611. else if (strncmp (param->key, "trim", param->keylen) == 0) {
  1612. test = ucl_object_toboolean (param);
  1613. if (test) {
  1614. flags |= UCL_STRING_TRIM;
  1615. }
  1616. }
  1617. }
  1618. else if (param->type == UCL_STRING) {
  1619. if (strncmp (param->key, "key", param->keylen) == 0) {
  1620. prefix = ucl_object_tostring (param);
  1621. }
  1622. else if (strncmp (param->key, "target", param->keylen) == 0) {
  1623. target = ucl_object_tostring (param);
  1624. }
  1625. }
  1626. else if (param->type == UCL_INT) {
  1627. if (strncmp (param->key, "priority", param->keylen) == 0) {
  1628. priority = ucl_object_toint (param);
  1629. }
  1630. }
  1631. }
  1632. }
  1633. if (prefix == NULL || strlen (prefix) == 0) {
  1634. ucl_create_err (&parser->err, "No Key specified in load macro");
  1635. return false;
  1636. }
  1637. if (len > 0) {
  1638. load_file = malloc (len + 1);
  1639. if (!load_file) {
  1640. ucl_create_err (&parser->err, "cannot allocate memory for suffix");
  1641. return false;
  1642. }
  1643. snprintf (load_file, len + 1, "%.*s", (int)len, data);
  1644. if (!ucl_fetch_file (load_file, &buf, &buflen, &parser->err,
  1645. !try_load)) {
  1646. free (load_file);
  1647. if (try_load) {
  1648. ucl_parser_clear_error (parser);
  1649. }
  1650. return (try_load || false);
  1651. }
  1652. free (load_file);
  1653. container = parser->stack->obj;
  1654. old_obj = __DECONST (ucl_object_t *, ucl_object_lookup (container,
  1655. prefix));
  1656. if (old_obj != NULL) {
  1657. ucl_create_err (&parser->err, "Key %s already exists", prefix);
  1658. if (buf) {
  1659. ucl_munmap (buf, buflen);
  1660. }
  1661. return false;
  1662. }
  1663. if (strcasecmp (target, "string") == 0) {
  1664. obj = ucl_object_fromstring_common (buf, buflen, flags);
  1665. ucl_copy_value_trash (obj);
  1666. if (multiline) {
  1667. obj->flags |= UCL_OBJECT_MULTILINE;
  1668. }
  1669. }
  1670. else if (strcasecmp (target, "int") == 0) {
  1671. tmp = malloc (buflen + 1);
  1672. if (tmp == NULL) {
  1673. ucl_create_err (&parser->err, "Memory allocation failed");
  1674. if (buf) {
  1675. ucl_munmap (buf, buflen);
  1676. }
  1677. return false;
  1678. }
  1679. snprintf (tmp, buflen + 1, "%.*s", (int)buflen, buf);
  1680. iv = strtoll (tmp, NULL, 10);
  1681. obj = ucl_object_fromint (iv);
  1682. free (tmp);
  1683. }
  1684. if (buf) {
  1685. ucl_munmap (buf, buflen);
  1686. }
  1687. if (obj != NULL) {
  1688. obj->key = prefix;
  1689. obj->keylen = strlen (prefix);
  1690. ucl_copy_key_trash (obj);
  1691. obj->prev = obj;
  1692. obj->next = NULL;
  1693. ucl_object_set_priority (obj, priority);
  1694. ucl_object_insert_key (container, obj, obj->key, obj->keylen, false);
  1695. }
  1696. return true;
  1697. }
  1698. ucl_create_err (&parser->err, "Unable to parse load macro");
  1699. return false;
  1700. }
  1701. bool
  1702. ucl_inherit_handler (const unsigned char *data, size_t len,
  1703. const ucl_object_t *args, const ucl_object_t *ctx, void* ud)
  1704. {
  1705. const ucl_object_t *parent, *cur;
  1706. ucl_object_t *target, *copy;
  1707. ucl_object_iter_t it = NULL;
  1708. bool replace = false;
  1709. struct ucl_parser *parser = ud;
  1710. parent = ucl_object_lookup_len (ctx, data, len);
  1711. /* Some sanity checks */
  1712. if (parent == NULL || ucl_object_type (parent) != UCL_OBJECT) {
  1713. ucl_create_err (&parser->err, "Unable to find inherited object %.*s",
  1714. (int)len, data);
  1715. return false;
  1716. }
  1717. if (parser->stack == NULL || parser->stack->obj == NULL ||
  1718. ucl_object_type (parser->stack->obj) != UCL_OBJECT) {
  1719. ucl_create_err (&parser->err, "Invalid inherit context");
  1720. return false;
  1721. }
  1722. target = parser->stack->obj;
  1723. if (args && (cur = ucl_object_lookup (args, "replace")) != NULL) {
  1724. replace = ucl_object_toboolean (cur);
  1725. }
  1726. while ((cur = ucl_object_iterate (parent, &it, true))) {
  1727. /* We do not replace existing keys */
  1728. if (!replace && ucl_object_lookup_len (target, cur->key, cur->keylen)) {
  1729. continue;
  1730. }
  1731. copy = ucl_object_copy (cur);
  1732. if (!replace) {
  1733. copy->flags |= UCL_OBJECT_INHERITED;
  1734. }
  1735. ucl_object_insert_key (target, copy, copy->key,
  1736. copy->keylen, false);
  1737. }
  1738. return true;
  1739. }
  1740. bool
  1741. ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand)
  1742. {
  1743. char realbuf[PATH_MAX], *curdir;
  1744. if (filename != NULL) {
  1745. if (need_expand) {
  1746. if (ucl_realpath (filename, realbuf) == NULL) {
  1747. return false;
  1748. }
  1749. }
  1750. else {
  1751. ucl_strlcpy (realbuf, filename, sizeof (realbuf));
  1752. }
  1753. if (parser->cur_file) {
  1754. free (parser->cur_file);
  1755. }
  1756. parser->cur_file = strdup (realbuf);
  1757. /* Define variables */
  1758. ucl_parser_register_variable (parser, "FILENAME", realbuf);
  1759. curdir = dirname (realbuf);
  1760. ucl_parser_register_variable (parser, "CURDIR", curdir);
  1761. }
  1762. else {
  1763. /* Set everything from the current dir */
  1764. curdir = getcwd (realbuf, sizeof (realbuf));
  1765. ucl_parser_register_variable (parser, "FILENAME", "undef");
  1766. ucl_parser_register_variable (parser, "CURDIR", curdir);
  1767. }
  1768. return true;
  1769. }
  1770. bool
  1771. ucl_parser_add_file_full (struct ucl_parser *parser, const char *filename,
  1772. unsigned priority, enum ucl_duplicate_strategy strat,
  1773. enum ucl_parse_type parse_type)
  1774. {
  1775. unsigned char *buf;
  1776. size_t len;
  1777. bool ret;
  1778. char realbuf[PATH_MAX];
  1779. if (ucl_realpath (filename, realbuf) == NULL) {
  1780. ucl_create_err (&parser->err, "cannot open file %s: %s",
  1781. filename,
  1782. strerror (errno));
  1783. return false;
  1784. }
  1785. if (!ucl_fetch_file (realbuf, &buf, &len, &parser->err, true)) {
  1786. return false;
  1787. }
  1788. ucl_parser_set_filevars (parser, realbuf, false);
  1789. ret = ucl_parser_add_chunk_full (parser, buf, len, priority, strat,
  1790. parse_type);
  1791. if (len > 0) {
  1792. ucl_munmap (buf, len);
  1793. }
  1794. return ret;
  1795. }
  1796. bool
  1797. ucl_parser_add_file_priority (struct ucl_parser *parser, const char *filename,
  1798. unsigned priority)
  1799. {
  1800. if (parser == NULL) {
  1801. return false;
  1802. }
  1803. return ucl_parser_add_file_full(parser, filename, priority,
  1804. UCL_DUPLICATE_APPEND, UCL_PARSE_UCL);
  1805. }
  1806. bool
  1807. ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
  1808. {
  1809. if (parser == NULL) {
  1810. return false;
  1811. }
  1812. return ucl_parser_add_file_full(parser, filename,
  1813. parser->default_priority, UCL_DUPLICATE_APPEND,
  1814. UCL_PARSE_UCL);
  1815. }
  1816. bool
  1817. ucl_parser_add_fd_full (struct ucl_parser *parser, int fd,
  1818. unsigned priority, enum ucl_duplicate_strategy strat,
  1819. enum ucl_parse_type parse_type)
  1820. {
  1821. unsigned char *buf;
  1822. size_t len;
  1823. bool ret;
  1824. struct stat st;
  1825. if (fstat (fd, &st) == -1) {
  1826. ucl_create_err (&parser->err, "cannot stat fd %d: %s",
  1827. fd, strerror (errno));
  1828. return false;
  1829. }
  1830. if (st.st_size == 0) {
  1831. return true;
  1832. }
  1833. if ((buf = ucl_mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
  1834. ucl_create_err (&parser->err, "cannot mmap fd %d: %s",
  1835. fd, strerror (errno));
  1836. return false;
  1837. }
  1838. if (parser->cur_file) {
  1839. free (parser->cur_file);
  1840. }
  1841. parser->cur_file = NULL;
  1842. len = st.st_size;
  1843. ret = ucl_parser_add_chunk_full (parser, buf, len, priority, strat,
  1844. parse_type);
  1845. if (len > 0) {
  1846. ucl_munmap (buf, len);
  1847. }
  1848. return ret;
  1849. }
  1850. bool
  1851. ucl_parser_add_fd_priority (struct ucl_parser *parser, int fd,
  1852. unsigned priority)
  1853. {
  1854. if (parser == NULL) {
  1855. return false;
  1856. }
  1857. return ucl_parser_add_fd_full(parser, fd, parser->default_priority,
  1858. UCL_DUPLICATE_APPEND, UCL_PARSE_UCL);
  1859. }
  1860. bool
  1861. ucl_parser_add_fd (struct ucl_parser *parser, int fd)
  1862. {
  1863. if (parser == NULL) {
  1864. return false;
  1865. }
  1866. return ucl_parser_add_fd_priority(parser, fd, parser->default_priority);
  1867. }
  1868. size_t
  1869. ucl_strlcpy (char *dst, const char *src, size_t siz)
  1870. {
  1871. char *d = dst;
  1872. const char *s = src;
  1873. size_t n = siz;
  1874. /* Copy as many bytes as will fit */
  1875. if (n != 0) {
  1876. while (--n != 0) {
  1877. if ((*d++ = *s++) == '\0') {
  1878. break;
  1879. }
  1880. }
  1881. }
  1882. if (n == 0 && siz != 0) {
  1883. *d = '\0';
  1884. }
  1885. return (s - src - 1); /* count does not include NUL */
  1886. }
  1887. size_t
  1888. ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz)
  1889. {
  1890. memcpy (dst, src, siz - 1);
  1891. dst[siz - 1] = '\0';
  1892. return siz - 1;
  1893. }
  1894. size_t
  1895. ucl_strlcpy_tolower (char *dst, const char *src, size_t siz)
  1896. {
  1897. char *d = dst;
  1898. const char *s = src;
  1899. size_t n = siz;
  1900. /* Copy as many bytes as will fit */
  1901. if (n != 0) {
  1902. while (--n != 0) {
  1903. if ((*d++ = tolower (*s++)) == '\0') {
  1904. break;
  1905. }
  1906. }
  1907. }
  1908. if (n == 0 && siz != 0) {
  1909. *d = '\0';
  1910. }
  1911. return (s - src); /* count does not include NUL */
  1912. }
  1913. /*
  1914. * Find the first occurrence of find in s
  1915. */
  1916. char *
  1917. ucl_strnstr (const char *s, const char *find, int len)
  1918. {
  1919. char c, sc;
  1920. int mlen;
  1921. if ((c = *find++) != 0) {
  1922. mlen = strlen (find);
  1923. do {
  1924. do {
  1925. if ((sc = *s++) == 0 || len-- < mlen)
  1926. return (NULL);
  1927. } while (sc != c);
  1928. } while (strncmp (s, find, mlen) != 0);
  1929. s--;
  1930. }
  1931. return ((char *)s);
  1932. }
  1933. /*
  1934. * Find the first occurrence of find in s, ignore case.
  1935. */
  1936. char *
  1937. ucl_strncasestr (const char *s, const char *find, int len)
  1938. {
  1939. char c, sc;
  1940. int mlen;
  1941. if ((c = *find++) != 0) {
  1942. c = tolower (c);
  1943. mlen = strlen (find);
  1944. do {
  1945. do {
  1946. if ((sc = *s++) == 0 || len-- == 0)
  1947. return (NULL);
  1948. } while (tolower (sc) != c);
  1949. } while (strncasecmp (s, find, mlen) != 0);
  1950. s--;
  1951. }
  1952. return ((char *)s);
  1953. }
  1954. ucl_object_t *
  1955. ucl_object_fromstring_common (const char *str, size_t len, enum ucl_string_flags flags)
  1956. {
  1957. ucl_object_t *obj;
  1958. const char *start, *end, *p, *pos;
  1959. char *dst, *d;
  1960. size_t escaped_len;
  1961. if (str == NULL) {
  1962. return NULL;
  1963. }
  1964. obj = ucl_object_new ();
  1965. if (obj) {
  1966. if (len == 0) {
  1967. len = strlen (str);
  1968. }
  1969. if (flags & UCL_STRING_TRIM) {
  1970. /* Skip leading spaces */
  1971. for (start = str; (size_t)(start - str) < len; start ++) {
  1972. if (!ucl_test_character (*start, UCL_CHARACTER_WHITESPACE_UNSAFE)) {
  1973. break;
  1974. }
  1975. }
  1976. /* Skip trailing spaces */
  1977. for (end = str + len - 1; end > start; end --) {
  1978. if (!ucl_test_character (*end, UCL_CHARACTER_WHITESPACE_UNSAFE)) {
  1979. break;
  1980. }
  1981. }
  1982. end ++;
  1983. }
  1984. else {
  1985. start = str;
  1986. end = str + len;
  1987. }
  1988. obj->type = UCL_STRING;
  1989. if (flags & UCL_STRING_ESCAPE) {
  1990. for (p = start, escaped_len = 0; p < end; p ++, escaped_len ++) {
  1991. if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE | UCL_CHARACTER_WHITESPACE_UNSAFE)) {
  1992. switch (*p) {
  1993. case '\v':
  1994. case '\0':
  1995. escaped_len += 5;
  1996. break;
  1997. case ' ':
  1998. break;
  1999. default:
  2000. escaped_len ++;
  2001. break;
  2002. }
  2003. }
  2004. }
  2005. dst = malloc (escaped_len + 1);
  2006. if (dst != NULL) {
  2007. for (p = start, d = dst; p < end; p ++, d ++) {
  2008. if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE | UCL_CHARACTER_WHITESPACE_UNSAFE)) {
  2009. switch (*p) {
  2010. case '\n':
  2011. *d++ = '\\';
  2012. *d = 'n';
  2013. break;
  2014. case '\r':
  2015. *d++ = '\\';
  2016. *d = 'r';
  2017. break;
  2018. case '\b':
  2019. *d++ = '\\';
  2020. *d = 'b';
  2021. break;
  2022. case '\t':
  2023. *d++ = '\\';
  2024. *d = 't';
  2025. break;
  2026. case '\f':
  2027. *d++ = '\\';
  2028. *d = 'f';
  2029. break;
  2030. case '\0':
  2031. *d++ = '\\';
  2032. *d++ = 'u';
  2033. *d++ = '0';
  2034. *d++ = '0';
  2035. *d++ = '0';
  2036. *d = '0';
  2037. break;
  2038. case '\v':
  2039. *d++ = '\\';
  2040. *d++ = 'u';
  2041. *d++ = '0';
  2042. *d++ = '0';
  2043. *d++ = '0';
  2044. *d = 'B';
  2045. break;
  2046. case '\\':
  2047. *d++ = '\\';
  2048. *d = '\\';
  2049. break;
  2050. case ' ':
  2051. *d = ' ';
  2052. break;
  2053. case '"':
  2054. *d++ = '\\';
  2055. *d = '"';
  2056. break;
  2057. }
  2058. }
  2059. else {
  2060. *d = *p;
  2061. }
  2062. }
  2063. *d = '\0';
  2064. obj->value.sv = dst;
  2065. obj->trash_stack[UCL_TRASH_VALUE] = dst;
  2066. obj->len = escaped_len;
  2067. }
  2068. }
  2069. else {
  2070. dst = malloc (end - start + 1);
  2071. if (dst != NULL) {
  2072. ucl_strlcpy_unsafe (dst, start, end - start + 1);
  2073. obj->value.sv = dst;
  2074. obj->trash_stack[UCL_TRASH_VALUE] = dst;
  2075. obj->len = end - start;
  2076. }
  2077. }
  2078. if ((flags & UCL_STRING_PARSE) && dst != NULL) {
  2079. /* Parse what we have */
  2080. if (flags & UCL_STRING_PARSE_BOOLEAN) {
  2081. if (!ucl_maybe_parse_boolean (obj, dst, obj->len) && (flags & UCL_STRING_PARSE_NUMBER)) {
  2082. ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
  2083. flags & UCL_STRING_PARSE_DOUBLE,
  2084. flags & UCL_STRING_PARSE_BYTES,
  2085. flags & UCL_STRING_PARSE_TIME);
  2086. }
  2087. }
  2088. else {
  2089. ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
  2090. flags & UCL_STRING_PARSE_DOUBLE,
  2091. flags & UCL_STRING_PARSE_BYTES,
  2092. flags & UCL_STRING_PARSE_TIME);
  2093. }
  2094. }
  2095. }
  2096. return obj;
  2097. }
  2098. static bool
  2099. ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt,
  2100. const char *key, size_t keylen, bool copy_key, bool merge, bool replace)
  2101. {
  2102. ucl_object_t *found, *tmp;
  2103. const ucl_object_t *cur;
  2104. ucl_object_iter_t it = NULL;
  2105. const char *p;
  2106. int ret = true;
  2107. if (elt == NULL || key == NULL) {
  2108. return false;
  2109. }
  2110. if (top == NULL) {
  2111. return false;
  2112. }
  2113. if (top->type != UCL_OBJECT) {
  2114. /* It is possible to convert NULL type to an object */
  2115. if (top->type == UCL_NULL) {
  2116. top->type = UCL_OBJECT;
  2117. }
  2118. else {
  2119. /* Refuse converting of other object types */
  2120. return false;
  2121. }
  2122. }
  2123. if (top->value.ov == NULL) {
  2124. top->value.ov = ucl_hash_create (false);
  2125. }
  2126. if (keylen == 0) {
  2127. keylen = strlen (key);
  2128. }
  2129. for (p = key; p < key + keylen; p ++) {
  2130. if (ucl_test_character (*p, UCL_CHARACTER_UCL_UNSAFE)) {
  2131. elt->flags |= UCL_OBJECT_NEED_KEY_ESCAPE;
  2132. break;
  2133. }
  2134. }
  2135. /* workaround for some use cases */
  2136. if (elt->trash_stack[UCL_TRASH_KEY] != NULL &&
  2137. key != (const char *)elt->trash_stack[UCL_TRASH_KEY]) {
  2138. /* Remove copied key */
  2139. free (elt->trash_stack[UCL_TRASH_KEY]);
  2140. elt->trash_stack[UCL_TRASH_KEY] = NULL;
  2141. elt->flags &= ~UCL_OBJECT_ALLOCATED_KEY;
  2142. }
  2143. elt->key = key;
  2144. elt->keylen = keylen;
  2145. if (copy_key) {
  2146. ucl_copy_key_trash (elt);
  2147. }
  2148. found = __DECONST (ucl_object_t *, ucl_hash_search_obj (top->value.ov, elt));
  2149. if (found == NULL) {
  2150. top->value.ov = ucl_hash_insert_object (top->value.ov, elt, false);
  2151. top->len ++;
  2152. if (replace) {
  2153. ret = false;
  2154. }
  2155. }
  2156. else {
  2157. if (replace) {
  2158. ucl_hash_replace (top->value.ov, found, elt);
  2159. ucl_object_unref (found);
  2160. }
  2161. else if (merge) {
  2162. if (found->type != UCL_OBJECT && elt->type == UCL_OBJECT) {
  2163. /* Insert old elt to new one */
  2164. ucl_object_insert_key_common (elt, found, found->key,
  2165. found->keylen, copy_key, false, false);
  2166. ucl_hash_delete (top->value.ov, found);
  2167. top->value.ov = ucl_hash_insert_object (top->value.ov, elt, false);
  2168. }
  2169. else if (found->type == UCL_OBJECT && elt->type != UCL_OBJECT) {
  2170. /* Insert new to old */
  2171. ucl_object_insert_key_common (found, elt, elt->key,
  2172. elt->keylen, copy_key, false, false);
  2173. }
  2174. else if (found->type == UCL_OBJECT && elt->type == UCL_OBJECT) {
  2175. /* Mix two hashes */
  2176. while ((cur = ucl_object_iterate (elt, &it, true)) != NULL) {
  2177. tmp = ucl_object_ref (cur);
  2178. ucl_object_insert_key_common (found, tmp, cur->key,
  2179. cur->keylen, copy_key, true, false);
  2180. }
  2181. ucl_object_unref (elt);
  2182. }
  2183. else {
  2184. /* Just make a list of scalars */
  2185. DL_CONCAT (found, elt);
  2186. }
  2187. }
  2188. else {
  2189. DL_CONCAT (found, elt);
  2190. }
  2191. }
  2192. return ret;
  2193. }
  2194. bool
  2195. ucl_object_delete_keyl (ucl_object_t *top, const char *key, size_t keylen)
  2196. {
  2197. ucl_object_t *found;
  2198. if (top == NULL || key == NULL) {
  2199. return false;
  2200. }
  2201. found = __DECONST (ucl_object_t *, ucl_object_lookup_len (top, key, keylen));
  2202. if (found == NULL) {
  2203. return false;
  2204. }
  2205. ucl_hash_delete (top->value.ov, found);
  2206. ucl_object_unref (found);
  2207. top->len --;
  2208. return true;
  2209. }
  2210. bool
  2211. ucl_object_delete_key (ucl_object_t *top, const char *key)
  2212. {
  2213. return ucl_object_delete_keyl (top, key, strlen (key));
  2214. }
  2215. ucl_object_t*
  2216. ucl_object_pop_keyl (ucl_object_t *top, const char *key, size_t keylen)
  2217. {
  2218. const ucl_object_t *found;
  2219. if (top == NULL || key == NULL) {
  2220. return false;
  2221. }
  2222. found = ucl_object_lookup_len (top, key, keylen);
  2223. if (found == NULL) {
  2224. return NULL;
  2225. }
  2226. ucl_hash_delete (top->value.ov, found);
  2227. top->len --;
  2228. return __DECONST (ucl_object_t *, found);
  2229. }
  2230. ucl_object_t*
  2231. ucl_object_pop_key (ucl_object_t *top, const char *key)
  2232. {
  2233. return ucl_object_pop_keyl (top, key, strlen (key));
  2234. }
  2235. bool
  2236. ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt,
  2237. const char *key, size_t keylen, bool copy_key)
  2238. {
  2239. return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, false);
  2240. }
  2241. bool
  2242. ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt,
  2243. const char *key, size_t keylen, bool copy_key)
  2244. {
  2245. return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, true, false);
  2246. }
  2247. bool
  2248. ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt,
  2249. const char *key, size_t keylen, bool copy_key)
  2250. {
  2251. return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, true);
  2252. }
  2253. bool
  2254. ucl_object_merge (ucl_object_t *top, ucl_object_t *elt, bool copy)
  2255. {
  2256. ucl_object_t *cur = NULL, *cp = NULL, *found = NULL;
  2257. ucl_object_iter_t iter = NULL;
  2258. if (top == NULL || elt == NULL) {
  2259. return false;
  2260. }
  2261. if (top->type == UCL_ARRAY) {
  2262. if (elt->type == UCL_ARRAY) {
  2263. /* Merge two arrays */
  2264. return ucl_array_merge (top, elt, copy);
  2265. }
  2266. else {
  2267. if (copy) {
  2268. ucl_array_append (top, ucl_object_copy (elt));
  2269. return true;
  2270. }
  2271. else {
  2272. ucl_array_append (top, ucl_object_ref (elt));
  2273. return true;
  2274. }
  2275. }
  2276. }
  2277. else if (top->type == UCL_OBJECT) {
  2278. if (elt->type == UCL_OBJECT) {
  2279. /* Mix two hashes */
  2280. while ((cur = (ucl_object_t *) ucl_hash_iterate (elt->value.ov,
  2281. &iter))) {
  2282. if (copy) {
  2283. cp = ucl_object_copy (cur);
  2284. } else {
  2285. cp = ucl_object_ref (cur);
  2286. }
  2287. found = __DECONST(ucl_object_t *,
  2288. ucl_hash_search (top->value.ov, cp->key, cp->keylen));
  2289. if (found == NULL) {
  2290. /* The key does not exist */
  2291. top->value.ov = ucl_hash_insert_object (top->value.ov, cp,
  2292. false);
  2293. top->len++;
  2294. }
  2295. else {
  2296. /* The key already exists, merge it recursively */
  2297. if (found->type == UCL_OBJECT || found->type == UCL_ARRAY) {
  2298. if (!ucl_object_merge (found, cp, copy)) {
  2299. return false;
  2300. }
  2301. ucl_object_unref (cp);
  2302. }
  2303. else {
  2304. ucl_hash_replace (top->value.ov, found, cp);
  2305. ucl_object_unref (found);
  2306. }
  2307. }
  2308. }
  2309. }
  2310. else {
  2311. if (copy) {
  2312. cp = ucl_object_copy (elt);
  2313. }
  2314. else {
  2315. cp = ucl_object_ref (elt);
  2316. }
  2317. found = __DECONST(ucl_object_t *,
  2318. ucl_hash_search (top->value.ov, cp->key, cp->keylen));
  2319. if (found == NULL) {
  2320. /* The key does not exist */
  2321. top->value.ov = ucl_hash_insert_object (top->value.ov, cp,
  2322. false);
  2323. top->len++;
  2324. }
  2325. else {
  2326. /* The key already exists, merge it recursively */
  2327. if (found->type == UCL_OBJECT || found->type == UCL_ARRAY) {
  2328. if (!ucl_object_merge (found, cp, copy)) {
  2329. return false;
  2330. }
  2331. ucl_object_unref (cp);
  2332. }
  2333. else {
  2334. ucl_hash_replace (top->value.ov, found, cp);
  2335. ucl_object_unref (found);
  2336. }
  2337. }
  2338. }
  2339. }
  2340. else {
  2341. /* Cannot merge trivial objects */
  2342. return false;
  2343. }
  2344. return true;
  2345. }
  2346. const ucl_object_t *
  2347. ucl_object_lookup_len (const ucl_object_t *obj, const char *key, size_t klen)
  2348. {
  2349. const ucl_object_t *ret;
  2350. ucl_object_t srch;
  2351. if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) {
  2352. return NULL;
  2353. }
  2354. srch.key = key;
  2355. srch.keylen = klen;
  2356. ret = ucl_hash_search_obj (obj->value.ov, &srch);
  2357. return ret;
  2358. }
  2359. const ucl_object_t *
  2360. ucl_object_lookup (const ucl_object_t *obj, const char *key)
  2361. {
  2362. if (key == NULL) {
  2363. return NULL;
  2364. }
  2365. return ucl_object_lookup_len (obj, key, strlen (key));
  2366. }
  2367. const ucl_object_t*
  2368. ucl_object_lookup_any (const ucl_object_t *obj,
  2369. const char *key, ...)
  2370. {
  2371. va_list ap;
  2372. const ucl_object_t *ret = NULL;
  2373. const char *nk = NULL;
  2374. if (obj == NULL || key == NULL) {
  2375. return NULL;
  2376. }
  2377. ret = ucl_object_lookup_len (obj, key, strlen (key));
  2378. if (ret == NULL) {
  2379. va_start (ap, key);
  2380. while (ret == NULL) {
  2381. nk = va_arg (ap, const char *);
  2382. if (nk == NULL) {
  2383. break;
  2384. }
  2385. else {
  2386. ret = ucl_object_lookup_len (obj, nk, strlen (nk));
  2387. }
  2388. }
  2389. va_end (ap);
  2390. }
  2391. return ret;
  2392. }
  2393. const ucl_object_t*
  2394. ucl_object_iterate_with_error (const ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values,
  2395. int *ep)
  2396. {
  2397. const ucl_object_t *elt = NULL;
  2398. if (obj == NULL || iter == NULL) {
  2399. return NULL;
  2400. }
  2401. if (expand_values) {
  2402. switch (obj->type) {
  2403. case UCL_OBJECT:
  2404. return (const ucl_object_t*)ucl_hash_iterate2 (obj->value.ov, iter, ep);
  2405. break;
  2406. case UCL_ARRAY: {
  2407. unsigned int idx;
  2408. UCL_ARRAY_GET (vec, obj);
  2409. idx = (unsigned int)(uintptr_t)(*iter);
  2410. if (vec != NULL) {
  2411. while (idx < kv_size (*vec)) {
  2412. if ((elt = kv_A (*vec, idx)) != NULL) {
  2413. idx ++;
  2414. break;
  2415. }
  2416. idx ++;
  2417. }
  2418. *iter = (void *)(uintptr_t)idx;
  2419. }
  2420. return elt;
  2421. break;
  2422. }
  2423. default:
  2424. /* Go to linear iteration */
  2425. break;
  2426. }
  2427. }
  2428. /* Treat everything as a linear list */
  2429. elt = *iter;
  2430. if (elt == NULL) {
  2431. elt = obj;
  2432. }
  2433. else if (elt == obj) {
  2434. return NULL;
  2435. }
  2436. *iter = __DECONST (void *, elt->next ? elt->next : obj);
  2437. return elt;
  2438. /* Not reached */
  2439. return NULL;
  2440. }
  2441. enum ucl_safe_iter_flags {
  2442. UCL_ITERATE_FLAG_UNDEFINED = 0,
  2443. UCL_ITERATE_FLAG_INSIDE_ARRAY,
  2444. UCL_ITERATE_FLAG_INSIDE_OBJECT,
  2445. UCL_ITERATE_FLAG_IMPLICIT,
  2446. UCL_ITERATE_FLAG_EXCEPTION
  2447. };
  2448. static const char safe_iter_magic[4] = {'u', 'i', 't', 'e'};
  2449. struct ucl_object_safe_iter {
  2450. char magic[4]; /* safety check */
  2451. uint32_t flags;
  2452. const ucl_object_t *impl_it; /* implicit object iteration */
  2453. ucl_object_iter_t expl_it; /* explicit iteration */
  2454. };
  2455. #define UCL_SAFE_ITER(ptr) (struct ucl_object_safe_iter *)(ptr)
  2456. #define UCL_SAFE_ITER_CHECK(it) do { \
  2457. assert (it != NULL); \
  2458. assert (memcmp (it->magic, safe_iter_magic, sizeof (it->magic)) == 0); \
  2459. } while (0)
  2460. ucl_object_iter_t
  2461. ucl_object_iterate_new (const ucl_object_t *obj)
  2462. {
  2463. struct ucl_object_safe_iter *it;
  2464. it = UCL_ALLOC (sizeof (*it));
  2465. if (it != NULL) {
  2466. memcpy (it->magic, safe_iter_magic, sizeof (it->magic));
  2467. it->flags = UCL_ITERATE_FLAG_UNDEFINED;
  2468. it->expl_it = NULL;
  2469. it->impl_it = obj;
  2470. }
  2471. return (ucl_object_iter_t)it;
  2472. }
  2473. bool
  2474. ucl_object_iter_chk_excpn(ucl_object_iter_t *it)
  2475. {
  2476. struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it);
  2477. UCL_SAFE_ITER_CHECK (rit);
  2478. return (rit->flags == UCL_ITERATE_FLAG_EXCEPTION);
  2479. }
  2480. ucl_object_iter_t
  2481. ucl_object_iterate_reset (ucl_object_iter_t it, const ucl_object_t *obj)
  2482. {
  2483. struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it);
  2484. UCL_SAFE_ITER_CHECK (rit);
  2485. if (rit->expl_it != NULL) {
  2486. if (rit->flags == UCL_ITERATE_FLAG_INSIDE_OBJECT) {
  2487. UCL_FREE (sizeof (*rit->expl_it), rit->expl_it);
  2488. }
  2489. }
  2490. rit->impl_it = obj;
  2491. rit->expl_it = NULL;
  2492. rit->flags = UCL_ITERATE_FLAG_UNDEFINED;
  2493. return it;
  2494. }
  2495. const ucl_object_t*
  2496. ucl_object_iterate_safe (ucl_object_iter_t it, bool expand_values)
  2497. {
  2498. return ucl_object_iterate_full (it, expand_values ? UCL_ITERATE_BOTH :
  2499. UCL_ITERATE_IMPLICIT);
  2500. }
  2501. const ucl_object_t*
  2502. ucl_object_iterate_full (ucl_object_iter_t it, enum ucl_iterate_type type)
  2503. {
  2504. struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it);
  2505. const ucl_object_t *ret = NULL;
  2506. int ern;
  2507. UCL_SAFE_ITER_CHECK (rit);
  2508. if (rit->impl_it == NULL) {
  2509. return NULL;
  2510. }
  2511. if (rit->impl_it->type == UCL_OBJECT) {
  2512. rit->flags = UCL_ITERATE_FLAG_INSIDE_OBJECT;
  2513. ret = ucl_object_iterate_with_error (rit->impl_it, &rit->expl_it, true, &ern);
  2514. if (ret == NULL && ern != 0) {
  2515. rit->flags = UCL_ITERATE_FLAG_EXCEPTION;
  2516. return NULL;
  2517. }
  2518. if (ret == NULL && (type & UCL_ITERATE_IMPLICIT)) {
  2519. /* Need to switch to another implicit object in chain */
  2520. rit->impl_it = rit->impl_it->next;
  2521. rit->expl_it = NULL;
  2522. return ucl_object_iterate_safe (it, type);
  2523. }
  2524. }
  2525. else if (rit->impl_it->type == UCL_ARRAY) {
  2526. rit->flags = UCL_ITERATE_FLAG_INSIDE_ARRAY;
  2527. ret = ucl_object_iterate (rit->impl_it, &rit->expl_it, true);
  2528. if (ret == NULL && (type & UCL_ITERATE_IMPLICIT)) {
  2529. /* Need to switch to another implicit object in chain */
  2530. rit->impl_it = rit->impl_it->next;
  2531. rit->expl_it = NULL;
  2532. return ucl_object_iterate_safe (it, type);
  2533. }
  2534. }
  2535. else {
  2536. /* Just iterate over the implicit array */
  2537. rit->flags = UCL_ITERATE_FLAG_IMPLICIT;
  2538. ret = rit->impl_it;
  2539. rit->impl_it = rit->impl_it->next;
  2540. if (type & UCL_ITERATE_EXPLICIT) {
  2541. /* We flatten objects if need to expand values */
  2542. if (ret->type == UCL_OBJECT || ret->type == UCL_ARRAY) {
  2543. return ucl_object_iterate_safe (it, type);
  2544. }
  2545. }
  2546. }
  2547. return ret;
  2548. }
  2549. void
  2550. ucl_object_iterate_free (ucl_object_iter_t it)
  2551. {
  2552. struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it);
  2553. UCL_SAFE_ITER_CHECK (rit);
  2554. if (rit->expl_it != NULL) {
  2555. if (rit->flags == UCL_ITERATE_FLAG_INSIDE_OBJECT) {
  2556. UCL_FREE (sizeof (*rit->expl_it), rit->expl_it);
  2557. }
  2558. }
  2559. UCL_FREE (sizeof (*rit), it);
  2560. }
  2561. const ucl_object_t *
  2562. ucl_object_lookup_path (const ucl_object_t *top, const char *path_in) {
  2563. return ucl_object_lookup_path_char (top, path_in, '.');
  2564. }
  2565. const ucl_object_t *
  2566. ucl_object_lookup_path_char (const ucl_object_t *top, const char *path_in, const char sep) {
  2567. const ucl_object_t *o = NULL, *found;
  2568. const char *p, *c;
  2569. char *err_str;
  2570. unsigned index;
  2571. if (path_in == NULL || top == NULL) {
  2572. return NULL;
  2573. }
  2574. found = NULL;
  2575. p = path_in;
  2576. /* Skip leading dots */
  2577. while (*p == sep) {
  2578. p ++;
  2579. }
  2580. c = p;
  2581. while (*p != '\0') {
  2582. p ++;
  2583. if (*p == sep || *p == '\0') {
  2584. if (p > c) {
  2585. switch (top->type) {
  2586. case UCL_ARRAY:
  2587. /* Key should be an int */
  2588. index = strtoul (c, &err_str, 10);
  2589. if (err_str != NULL && (*err_str != sep && *err_str != '\0')) {
  2590. return NULL;
  2591. }
  2592. o = ucl_array_find_index (top, index);
  2593. break;
  2594. default:
  2595. o = ucl_object_lookup_len (top, c, p - c);
  2596. break;
  2597. }
  2598. if (o == NULL) {
  2599. return NULL;
  2600. }
  2601. top = o;
  2602. }
  2603. if (*p != '\0') {
  2604. c = p + 1;
  2605. }
  2606. }
  2607. }
  2608. found = o;
  2609. return found;
  2610. }
  2611. ucl_object_t *
  2612. ucl_object_new (void)
  2613. {
  2614. return ucl_object_typed_new (UCL_NULL);
  2615. }
  2616. ucl_object_t *
  2617. ucl_object_typed_new (ucl_type_t type)
  2618. {
  2619. return ucl_object_new_full (type, 0);
  2620. }
  2621. ucl_object_t *
  2622. ucl_object_new_full (ucl_type_t type, unsigned priority)
  2623. {
  2624. ucl_object_t *new;
  2625. if (type != UCL_USERDATA) {
  2626. new = UCL_ALLOC (sizeof (ucl_object_t));
  2627. if (new != NULL) {
  2628. memset (new, 0, sizeof (ucl_object_t));
  2629. new->ref = 1;
  2630. new->type = (type <= UCL_NULL ? type : UCL_NULL);
  2631. new->next = NULL;
  2632. new->prev = new;
  2633. ucl_object_set_priority (new, priority);
  2634. if (type == UCL_ARRAY) {
  2635. new->value.av = UCL_ALLOC (sizeof (ucl_array_t));
  2636. if (new->value.av) {
  2637. memset (new->value.av, 0, sizeof (ucl_array_t));
  2638. UCL_ARRAY_GET (vec, new);
  2639. /* Preallocate some space for arrays */
  2640. kv_resize_safe (ucl_object_t *, *vec, 8, enomem);
  2641. }
  2642. }
  2643. }
  2644. }
  2645. else {
  2646. new = ucl_object_new_userdata (NULL, NULL, NULL);
  2647. ucl_object_set_priority (new, priority);
  2648. }
  2649. enomem:
  2650. return new;
  2651. }
  2652. bool ucl_object_reserve (ucl_object_t *obj, size_t reserved)
  2653. {
  2654. if (obj->type == UCL_ARRAY) {
  2655. UCL_ARRAY_GET (vec, obj);
  2656. if (vec->m < reserved) {
  2657. /* Preallocate some space for arrays */
  2658. kv_resize_safe (ucl_object_t *, *vec, reserved, e0);
  2659. }
  2660. }
  2661. else if (obj->type == UCL_OBJECT) {
  2662. ucl_hash_reserve (obj->value.ov, reserved);
  2663. }
  2664. return true;
  2665. e0:
  2666. return false;
  2667. }
  2668. ucl_object_t*
  2669. ucl_object_new_userdata (ucl_userdata_dtor dtor,
  2670. ucl_userdata_emitter emitter,
  2671. void *ptr)
  2672. {
  2673. struct ucl_object_userdata *new;
  2674. size_t nsize = sizeof (*new);
  2675. new = UCL_ALLOC (nsize);
  2676. if (new != NULL) {
  2677. memset (new, 0, nsize);
  2678. new->obj.ref = 1;
  2679. new->obj.type = UCL_USERDATA;
  2680. new->obj.next = NULL;
  2681. new->obj.prev = (ucl_object_t *)new;
  2682. new->dtor = dtor;
  2683. new->emitter = emitter;
  2684. new->obj.value.ud = ptr;
  2685. }
  2686. return (ucl_object_t *)new;
  2687. }
  2688. ucl_type_t
  2689. ucl_object_type (const ucl_object_t *obj)
  2690. {
  2691. if (obj == NULL) {
  2692. return UCL_NULL;
  2693. }
  2694. return obj->type;
  2695. }
  2696. ucl_object_t*
  2697. ucl_object_fromstring (const char *str)
  2698. {
  2699. return ucl_object_fromstring_common (str, 0, UCL_STRING_RAW);
  2700. }
  2701. ucl_object_t *
  2702. ucl_object_fromlstring (const char *str, size_t len)
  2703. {
  2704. return ucl_object_fromstring_common (str, len, UCL_STRING_RAW);
  2705. }
  2706. ucl_object_t *
  2707. ucl_object_fromint (int64_t iv)
  2708. {
  2709. ucl_object_t *obj;
  2710. obj = ucl_object_new ();
  2711. if (obj != NULL) {
  2712. obj->type = UCL_INT;
  2713. obj->value.iv = iv;
  2714. }
  2715. return obj;
  2716. }
  2717. ucl_object_t *
  2718. ucl_object_fromdouble (double dv)
  2719. {
  2720. ucl_object_t *obj;
  2721. obj = ucl_object_new ();
  2722. if (obj != NULL) {
  2723. obj->type = UCL_FLOAT;
  2724. obj->value.dv = dv;
  2725. }
  2726. return obj;
  2727. }
  2728. ucl_object_t*
  2729. ucl_object_frombool (bool bv)
  2730. {
  2731. ucl_object_t *obj;
  2732. obj = ucl_object_new ();
  2733. if (obj != NULL) {
  2734. obj->type = UCL_BOOLEAN;
  2735. obj->value.iv = bv;
  2736. }
  2737. return obj;
  2738. }
  2739. bool
  2740. ucl_array_append (ucl_object_t *top, ucl_object_t *elt)
  2741. {
  2742. if (top->type != UCL_ARRAY) {
  2743. return false;
  2744. }
  2745. UCL_ARRAY_GET (vec, top);
  2746. if (elt == NULL || top == NULL) {
  2747. return false;
  2748. }
  2749. if (vec == NULL) {
  2750. vec = UCL_ALLOC (sizeof (*vec));
  2751. if (vec == NULL) {
  2752. return false;
  2753. }
  2754. kv_init (*vec);
  2755. top->value.av = (void *)vec;
  2756. }
  2757. kv_push_safe (ucl_object_t *, *vec, elt, e0);
  2758. top->len ++;
  2759. return true;
  2760. e0:
  2761. return false;
  2762. }
  2763. bool
  2764. ucl_array_prepend (ucl_object_t *top, ucl_object_t *elt)
  2765. {
  2766. if (top->type != UCL_ARRAY) {
  2767. return false;
  2768. }
  2769. UCL_ARRAY_GET (vec, top);
  2770. if (elt == NULL || top == NULL) {
  2771. return false;
  2772. }
  2773. if (vec == NULL) {
  2774. vec = UCL_ALLOC (sizeof (*vec));
  2775. kv_init (*vec);
  2776. top->value.av = (void *)vec;
  2777. kv_push_safe (ucl_object_t *, *vec, elt, e0);
  2778. }
  2779. else {
  2780. /* Slow O(n) algorithm */
  2781. kv_prepend_safe (ucl_object_t *, *vec, elt, e0);
  2782. }
  2783. top->len ++;
  2784. return true;
  2785. e0:
  2786. return false;
  2787. }
  2788. bool
  2789. ucl_array_merge (ucl_object_t *top, ucl_object_t *elt, bool copy)
  2790. {
  2791. unsigned i;
  2792. ucl_object_t *cp = NULL;
  2793. ucl_object_t **obj;
  2794. if (elt == NULL || top == NULL || top->type != UCL_ARRAY || elt->type != UCL_ARRAY) {
  2795. return false;
  2796. }
  2797. if (copy) {
  2798. cp = ucl_object_copy (elt);
  2799. }
  2800. else {
  2801. cp = ucl_object_ref (elt);
  2802. }
  2803. UCL_ARRAY_GET (v1, top);
  2804. UCL_ARRAY_GET (v2, cp);
  2805. if (v1 && v2) {
  2806. kv_concat_safe (ucl_object_t *, *v1, *v2, e0);
  2807. for (i = v2->n; i < v1->n; i ++) {
  2808. obj = &kv_A (*v1, i);
  2809. if (*obj == NULL) {
  2810. continue;
  2811. }
  2812. top->len ++;
  2813. }
  2814. }
  2815. return true;
  2816. e0:
  2817. return false;
  2818. }
  2819. ucl_object_t *
  2820. ucl_array_delete (ucl_object_t *top, ucl_object_t *elt)
  2821. {
  2822. if (top->type != UCL_ARRAY) {
  2823. return NULL;
  2824. }
  2825. UCL_ARRAY_GET (vec, top);
  2826. ucl_object_t *ret = NULL;
  2827. unsigned i;
  2828. if (vec == NULL) {
  2829. return NULL;
  2830. }
  2831. for (i = 0; i < vec->n; i ++) {
  2832. if (kv_A (*vec, i) == elt) {
  2833. kv_del (ucl_object_t *, *vec, i);
  2834. ret = elt;
  2835. top->len --;
  2836. break;
  2837. }
  2838. }
  2839. return ret;
  2840. }
  2841. const ucl_object_t *
  2842. ucl_array_head (const ucl_object_t *top)
  2843. {
  2844. UCL_ARRAY_GET (vec, top);
  2845. if (vec == NULL || top == NULL || top->type != UCL_ARRAY ||
  2846. top->value.av == NULL) {
  2847. return NULL;
  2848. }
  2849. return (vec->n > 0 ? vec->a[0] : NULL);
  2850. }
  2851. const ucl_object_t *
  2852. ucl_array_tail (const ucl_object_t *top)
  2853. {
  2854. UCL_ARRAY_GET (vec, top);
  2855. if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
  2856. return NULL;
  2857. }
  2858. return (vec->n > 0 ? vec->a[vec->n - 1] : NULL);
  2859. }
  2860. ucl_object_t *
  2861. ucl_array_pop_last (ucl_object_t *top)
  2862. {
  2863. if (top->type != UCL_ARRAY) {
  2864. return NULL;
  2865. }
  2866. UCL_ARRAY_GET (vec, top);
  2867. ucl_object_t **obj, *ret = NULL;
  2868. if (vec != NULL && vec->n > 0) {
  2869. obj = &kv_A (*vec, vec->n - 1);
  2870. ret = *obj;
  2871. kv_del (ucl_object_t *, *vec, vec->n - 1);
  2872. top->len --;
  2873. }
  2874. return ret;
  2875. }
  2876. ucl_object_t *
  2877. ucl_array_pop_first (ucl_object_t *top)
  2878. {
  2879. if (top->type != UCL_ARRAY) {
  2880. return NULL;
  2881. }
  2882. UCL_ARRAY_GET (vec, top);
  2883. ucl_object_t **obj, *ret = NULL;
  2884. if (vec != NULL && vec->n > 0) {
  2885. obj = &kv_A (*vec, 0);
  2886. ret = *obj;
  2887. kv_del (ucl_object_t *, *vec, 0);
  2888. top->len --;
  2889. }
  2890. return ret;
  2891. }
  2892. unsigned int
  2893. ucl_array_size (const ucl_object_t *top)
  2894. {
  2895. if (top == NULL || top->type != UCL_ARRAY) {
  2896. return 0;
  2897. }
  2898. UCL_ARRAY_GET (vec, top);
  2899. if (vec != NULL) {
  2900. return kv_size(*vec);
  2901. }
  2902. return 0;
  2903. }
  2904. const ucl_object_t *
  2905. ucl_array_find_index (const ucl_object_t *top, unsigned int index)
  2906. {
  2907. if (top->type != UCL_ARRAY) {
  2908. return NULL;
  2909. }
  2910. UCL_ARRAY_GET (vec, top);
  2911. if (vec != NULL && vec->n > 0 && index < vec->n) {
  2912. return kv_A (*vec, index);
  2913. }
  2914. return NULL;
  2915. }
  2916. unsigned int
  2917. ucl_array_index_of (ucl_object_t *top, ucl_object_t *elt)
  2918. {
  2919. if (top->type != UCL_ARRAY) {
  2920. return (unsigned int)(-1);
  2921. }
  2922. UCL_ARRAY_GET (vec, top);
  2923. unsigned i;
  2924. if (vec == NULL) {
  2925. return (unsigned int)(-1);
  2926. }
  2927. for (i = 0; i < vec->n; i ++) {
  2928. if (kv_A (*vec, i) == elt) {
  2929. return i;
  2930. }
  2931. }
  2932. return (unsigned int)(-1);
  2933. }
  2934. ucl_object_t *
  2935. ucl_array_replace_index (ucl_object_t *top, ucl_object_t *elt,
  2936. unsigned int index)
  2937. {
  2938. if (top->type != UCL_ARRAY) {
  2939. return NULL;
  2940. }
  2941. UCL_ARRAY_GET (vec, top);
  2942. ucl_object_t *ret = NULL;
  2943. if (vec != NULL && vec->n > 0 && index < vec->n) {
  2944. ret = kv_A (*vec, index);
  2945. kv_A (*vec, index) = elt;
  2946. }
  2947. return ret;
  2948. }
  2949. ucl_object_t *
  2950. ucl_elt_append (ucl_object_t *head, ucl_object_t *elt)
  2951. {
  2952. if (head == NULL) {
  2953. elt->next = NULL;
  2954. elt->prev = elt;
  2955. head = elt;
  2956. }
  2957. else {
  2958. if (head->type == UCL_USERDATA) {
  2959. /* Userdata objects are VERY special! */
  2960. struct ucl_object_userdata *ud = (struct ucl_object_userdata *)head;
  2961. elt->prev = ud->obj.prev;
  2962. ud->obj.prev->next = elt;
  2963. ud->obj.prev = elt;
  2964. elt->next = NULL;
  2965. }
  2966. else {
  2967. elt->prev = head->prev;
  2968. head->prev->next = elt;
  2969. head->prev = elt;
  2970. elt->next = NULL;
  2971. }
  2972. }
  2973. return head;
  2974. }
  2975. bool
  2976. ucl_object_todouble_safe (const ucl_object_t *obj, double *target)
  2977. {
  2978. if (obj == NULL || target == NULL) {
  2979. return false;
  2980. }
  2981. switch (obj->type) {
  2982. case UCL_INT:
  2983. *target = obj->value.iv; /* Probably could cause overflow */
  2984. break;
  2985. case UCL_FLOAT:
  2986. case UCL_TIME:
  2987. *target = obj->value.dv;
  2988. break;
  2989. default:
  2990. return false;
  2991. }
  2992. return true;
  2993. }
  2994. double
  2995. ucl_object_todouble (const ucl_object_t *obj)
  2996. {
  2997. double result = 0.;
  2998. ucl_object_todouble_safe (obj, &result);
  2999. return result;
  3000. }
  3001. bool
  3002. ucl_object_toint_safe (const ucl_object_t *obj, int64_t *target)
  3003. {
  3004. if (obj == NULL || target == NULL) {
  3005. return false;
  3006. }
  3007. switch (obj->type) {
  3008. case UCL_INT:
  3009. *target = obj->value.iv;
  3010. break;
  3011. case UCL_FLOAT:
  3012. case UCL_TIME:
  3013. *target = obj->value.dv; /* Losing of decimal points */
  3014. break;
  3015. default:
  3016. return false;
  3017. }
  3018. return true;
  3019. }
  3020. int64_t
  3021. ucl_object_toint (const ucl_object_t *obj)
  3022. {
  3023. int64_t result = 0;
  3024. ucl_object_toint_safe (obj, &result);
  3025. return result;
  3026. }
  3027. bool
  3028. ucl_object_toboolean_safe (const ucl_object_t *obj, bool *target)
  3029. {
  3030. if (obj == NULL || target == NULL) {
  3031. return false;
  3032. }
  3033. switch (obj->type) {
  3034. case UCL_BOOLEAN:
  3035. *target = (obj->value.iv == true);
  3036. break;
  3037. default:
  3038. return false;
  3039. }
  3040. return true;
  3041. }
  3042. bool
  3043. ucl_object_toboolean (const ucl_object_t *obj)
  3044. {
  3045. bool result = false;
  3046. ucl_object_toboolean_safe (obj, &result);
  3047. return result;
  3048. }
  3049. bool
  3050. ucl_object_tostring_safe (const ucl_object_t *obj, const char **target)
  3051. {
  3052. if (obj == NULL || target == NULL) {
  3053. return false;
  3054. }
  3055. switch (obj->type) {
  3056. case UCL_STRING:
  3057. if (!(obj->flags & UCL_OBJECT_BINARY)) {
  3058. *target = ucl_copy_value_trash (obj);
  3059. }
  3060. break;
  3061. default:
  3062. return false;
  3063. }
  3064. return true;
  3065. }
  3066. const char *
  3067. ucl_object_tostring (const ucl_object_t *obj)
  3068. {
  3069. const char *result = NULL;
  3070. ucl_object_tostring_safe (obj, &result);
  3071. return result;
  3072. }
  3073. const char *
  3074. ucl_object_tostring_forced (const ucl_object_t *obj)
  3075. {
  3076. /* TODO: For binary strings we might encode string here */
  3077. if (!(obj->flags & UCL_OBJECT_BINARY)) {
  3078. return ucl_copy_value_trash (obj);
  3079. }
  3080. return NULL;
  3081. }
  3082. bool
  3083. ucl_object_tolstring_safe (const ucl_object_t *obj, const char **target, size_t *tlen)
  3084. {
  3085. if (obj == NULL || target == NULL) {
  3086. return false;
  3087. }
  3088. switch (obj->type) {
  3089. case UCL_STRING:
  3090. *target = obj->value.sv;
  3091. if (tlen != NULL) {
  3092. *tlen = obj->len;
  3093. }
  3094. break;
  3095. default:
  3096. return false;
  3097. }
  3098. return true;
  3099. }
  3100. const char *
  3101. ucl_object_tolstring (const ucl_object_t *obj, size_t *tlen)
  3102. {
  3103. const char *result = NULL;
  3104. ucl_object_tolstring_safe (obj, &result, tlen);
  3105. return result;
  3106. }
  3107. const char *
  3108. ucl_object_key (const ucl_object_t *obj)
  3109. {
  3110. return ucl_copy_key_trash (obj);
  3111. }
  3112. const char *
  3113. ucl_object_keyl (const ucl_object_t *obj, size_t *len)
  3114. {
  3115. if (len == NULL || obj == NULL) {
  3116. return NULL;
  3117. }
  3118. *len = obj->keylen;
  3119. return obj->key;
  3120. }
  3121. ucl_object_t *
  3122. ucl_object_ref (const ucl_object_t *obj)
  3123. {
  3124. ucl_object_t *res = NULL;
  3125. if (obj != NULL) {
  3126. if (obj->flags & UCL_OBJECT_EPHEMERAL) {
  3127. /*
  3128. * Use deep copy for ephemeral objects, note that its refcount
  3129. * is NOT increased, since ephemeral objects does not need refcount
  3130. * at all
  3131. */
  3132. res = ucl_object_copy (obj);
  3133. }
  3134. else {
  3135. res = __DECONST (ucl_object_t *, obj);
  3136. #ifdef HAVE_ATOMIC_BUILTINS
  3137. (void)__sync_add_and_fetch (&res->ref, 1);
  3138. #else
  3139. res->ref ++;
  3140. #endif
  3141. }
  3142. }
  3143. return res;
  3144. }
  3145. static ucl_object_t *
  3146. ucl_object_copy_internal (const ucl_object_t *other, bool allow_array)
  3147. {
  3148. ucl_object_t *new;
  3149. ucl_object_iter_t it = NULL;
  3150. const ucl_object_t *cur;
  3151. size_t sz = sizeof(*new);
  3152. if (other->type == UCL_USERDATA) {
  3153. sz = sizeof (struct ucl_object_userdata);
  3154. }
  3155. new = malloc (sz);
  3156. if (new != NULL) {
  3157. memcpy (new, other, sz);
  3158. if (other->flags & UCL_OBJECT_EPHEMERAL) {
  3159. /* Copied object is always non ephemeral */
  3160. new->flags &= ~UCL_OBJECT_EPHEMERAL;
  3161. }
  3162. new->ref = 1;
  3163. /* Unlink from others */
  3164. new->next = NULL;
  3165. new->prev = new;
  3166. /* deep copy of values stored */
  3167. if (other->trash_stack[UCL_TRASH_KEY] != NULL) {
  3168. new->trash_stack[UCL_TRASH_KEY] = NULL;
  3169. if (other->key == (const char *)other->trash_stack[UCL_TRASH_KEY]) {
  3170. new->trash_stack[UCL_TRASH_KEY] = malloc(other->keylen + 1);
  3171. memcpy(new->trash_stack[UCL_TRASH_KEY], other->trash_stack[UCL_TRASH_KEY], other->keylen);
  3172. new->trash_stack[UCL_TRASH_KEY][other->keylen] = '\0';
  3173. new->key = new->trash_stack[UCL_TRASH_KEY];
  3174. }
  3175. }
  3176. if (other->trash_stack[UCL_TRASH_VALUE] != NULL) {
  3177. new->trash_stack[UCL_TRASH_VALUE] =
  3178. strdup (other->trash_stack[UCL_TRASH_VALUE]);
  3179. if (new->type == UCL_STRING) {
  3180. new->value.sv = new->trash_stack[UCL_TRASH_VALUE];
  3181. }
  3182. }
  3183. if (other->type == UCL_ARRAY || other->type == UCL_OBJECT) {
  3184. /* reset old value */
  3185. memset (&new->value, 0, sizeof (new->value));
  3186. while ((cur = ucl_object_iterate (other, &it, true)) != NULL) {
  3187. if (other->type == UCL_ARRAY) {
  3188. ucl_array_append (new, ucl_object_copy_internal (cur, false));
  3189. }
  3190. else {
  3191. ucl_object_t *cp = ucl_object_copy_internal (cur, true);
  3192. if (cp != NULL) {
  3193. ucl_object_insert_key (new, cp, cp->key, cp->keylen,
  3194. false);
  3195. }
  3196. }
  3197. }
  3198. }
  3199. else if (allow_array && other->next != NULL) {
  3200. LL_FOREACH (other->next, cur) {
  3201. ucl_object_t *cp = ucl_object_copy_internal (cur, false);
  3202. if (cp != NULL) {
  3203. DL_APPEND (new, cp);
  3204. }
  3205. }
  3206. }
  3207. }
  3208. return new;
  3209. }
  3210. ucl_object_t *
  3211. ucl_object_copy (const ucl_object_t *other)
  3212. {
  3213. return ucl_object_copy_internal (other, true);
  3214. }
  3215. void
  3216. ucl_object_unref (ucl_object_t *obj)
  3217. {
  3218. if (obj != NULL) {
  3219. #ifdef HAVE_ATOMIC_BUILTINS
  3220. unsigned int rc = __sync_sub_and_fetch (&obj->ref, 1);
  3221. if (rc == 0) {
  3222. #else
  3223. if (--obj->ref == 0) {
  3224. #endif
  3225. ucl_object_free_internal (obj, true, ucl_object_dtor_unref);
  3226. }
  3227. }
  3228. }
  3229. int
  3230. ucl_object_compare (const ucl_object_t *o1, const ucl_object_t *o2)
  3231. {
  3232. const ucl_object_t *it1, *it2;
  3233. ucl_object_iter_t iter = NULL;
  3234. int ret = 0;
  3235. if (o1->type != o2->type) {
  3236. return (o1->type) - (o2->type);
  3237. }
  3238. switch (o1->type) {
  3239. case UCL_STRING:
  3240. if (o1->len == o2->len && o1->len > 0) {
  3241. ret = strcmp (ucl_object_tostring(o1), ucl_object_tostring(o2));
  3242. }
  3243. else {
  3244. ret = o1->len - o2->len;
  3245. }
  3246. break;
  3247. case UCL_FLOAT:
  3248. case UCL_INT:
  3249. case UCL_TIME:
  3250. ret = ucl_object_todouble (o1) - ucl_object_todouble (o2);
  3251. break;
  3252. case UCL_BOOLEAN:
  3253. ret = ucl_object_toboolean (o1) - ucl_object_toboolean (o2);
  3254. break;
  3255. case UCL_ARRAY:
  3256. if (o1->len == o2->len && o1->len > 0) {
  3257. UCL_ARRAY_GET (vec1, o1);
  3258. UCL_ARRAY_GET (vec2, o2);
  3259. unsigned i;
  3260. /* Compare all elements in both arrays */
  3261. for (i = 0; i < vec1->n; i ++) {
  3262. it1 = kv_A (*vec1, i);
  3263. it2 = kv_A (*vec2, i);
  3264. if (it1 == NULL && it2 != NULL) {
  3265. return -1;
  3266. }
  3267. else if (it2 == NULL && it1 != NULL) {
  3268. return 1;
  3269. }
  3270. else if (it1 != NULL && it2 != NULL) {
  3271. ret = ucl_object_compare (it1, it2);
  3272. if (ret != 0) {
  3273. break;
  3274. }
  3275. }
  3276. }
  3277. }
  3278. else {
  3279. ret = o1->len - o2->len;
  3280. }
  3281. break;
  3282. case UCL_OBJECT:
  3283. if (o1->len == o2->len && o1->len > 0) {
  3284. while ((it1 = ucl_object_iterate (o1, &iter, true)) != NULL) {
  3285. it2 = ucl_object_lookup (o2, ucl_object_key (it1));
  3286. if (it2 == NULL) {
  3287. ret = 1;
  3288. break;
  3289. }
  3290. ret = ucl_object_compare (it1, it2);
  3291. if (ret != 0) {
  3292. break;
  3293. }
  3294. }
  3295. }
  3296. else {
  3297. ret = o1->len - o2->len;
  3298. }
  3299. break;
  3300. default:
  3301. ret = 0;
  3302. break;
  3303. }
  3304. return ret;
  3305. }
  3306. int
  3307. ucl_object_compare_qsort (const ucl_object_t **o1,
  3308. const ucl_object_t **o2)
  3309. {
  3310. return ucl_object_compare (*o1, *o2);
  3311. }
  3312. void
  3313. ucl_object_array_sort (ucl_object_t *ar,
  3314. int (*cmp)(const ucl_object_t **o1, const ucl_object_t **o2))
  3315. {
  3316. UCL_ARRAY_GET (vec, ar);
  3317. if (cmp == NULL || ar == NULL || ar->type != UCL_ARRAY) {
  3318. return;
  3319. }
  3320. qsort (vec->a, vec->n, sizeof (ucl_object_t *),
  3321. (int (*)(const void *, const void *))cmp);
  3322. }
  3323. void ucl_object_sort_keys (ucl_object_t *obj,
  3324. enum ucl_object_keys_sort_flags how)
  3325. {
  3326. if (obj != NULL && obj->type == UCL_OBJECT) {
  3327. ucl_hash_sort (obj->value.ov, how);
  3328. }
  3329. }
  3330. #define PRIOBITS 4
  3331. unsigned int
  3332. ucl_object_get_priority (const ucl_object_t *obj)
  3333. {
  3334. if (obj == NULL) {
  3335. return 0;
  3336. }
  3337. return (obj->flags >> ((sizeof (obj->flags) * NBBY) - PRIOBITS));
  3338. }
  3339. void
  3340. ucl_object_set_priority (ucl_object_t *obj,
  3341. unsigned int priority)
  3342. {
  3343. if (obj != NULL) {
  3344. priority &= (0x1 << PRIOBITS) - 1;
  3345. priority <<= ((sizeof (obj->flags) * NBBY) - PRIOBITS);
  3346. priority |= obj->flags & ((1 << ((sizeof (obj->flags) * NBBY) -
  3347. PRIOBITS)) - 1);
  3348. obj->flags = priority;
  3349. }
  3350. }
  3351. bool
  3352. ucl_object_string_to_type (const char *input, ucl_type_t *res)
  3353. {
  3354. if (strcasecmp (input, "object") == 0) {
  3355. *res = UCL_OBJECT;
  3356. }
  3357. else if (strcasecmp (input, "array") == 0) {
  3358. *res = UCL_ARRAY;
  3359. }
  3360. else if (strcasecmp (input, "integer") == 0) {
  3361. *res = UCL_INT;
  3362. }
  3363. else if (strcasecmp (input, "number") == 0) {
  3364. *res = UCL_FLOAT;
  3365. }
  3366. else if (strcasecmp (input, "string") == 0) {
  3367. *res = UCL_STRING;
  3368. }
  3369. else if (strcasecmp (input, "boolean") == 0) {
  3370. *res = UCL_BOOLEAN;
  3371. }
  3372. else if (strcasecmp (input, "null") == 0) {
  3373. *res = UCL_NULL;
  3374. }
  3375. else if (strcasecmp (input, "userdata") == 0) {
  3376. *res = UCL_USERDATA;
  3377. }
  3378. else {
  3379. return false;
  3380. }
  3381. return true;
  3382. }
  3383. const char *
  3384. ucl_object_type_to_string (ucl_type_t type)
  3385. {
  3386. const char *res = "unknown";
  3387. switch (type) {
  3388. case UCL_OBJECT:
  3389. res = "object";
  3390. break;
  3391. case UCL_ARRAY:
  3392. res = "array";
  3393. break;
  3394. case UCL_INT:
  3395. res = "integer";
  3396. break;
  3397. case UCL_FLOAT:
  3398. case UCL_TIME:
  3399. res = "number";
  3400. break;
  3401. case UCL_STRING:
  3402. res = "string";
  3403. break;
  3404. case UCL_BOOLEAN:
  3405. res = "boolean";
  3406. break;
  3407. case UCL_USERDATA:
  3408. res = "userdata";
  3409. break;
  3410. case UCL_NULL:
  3411. res = "null";
  3412. break;
  3413. }
  3414. return res;
  3415. }
  3416. const ucl_object_t *
  3417. ucl_parser_get_comments (struct ucl_parser *parser)
  3418. {
  3419. if (parser && parser->comments) {
  3420. return parser->comments;
  3421. }
  3422. return NULL;
  3423. }
  3424. const ucl_object_t *
  3425. ucl_comments_find (const ucl_object_t *comments,
  3426. const ucl_object_t *srch)
  3427. {
  3428. if (comments && srch) {
  3429. return ucl_object_lookup_len (comments, (const char *)&srch,
  3430. sizeof (void *));
  3431. }
  3432. return NULL;
  3433. }
  3434. bool
  3435. ucl_comments_move (ucl_object_t *comments,
  3436. const ucl_object_t *from, const ucl_object_t *to)
  3437. {
  3438. const ucl_object_t *found;
  3439. ucl_object_t *obj;
  3440. if (comments && from && to) {
  3441. found = ucl_object_lookup_len (comments,
  3442. (const char *)&from, sizeof (void *));
  3443. if (found) {
  3444. /* Replace key */
  3445. obj = ucl_object_ref (found);
  3446. ucl_object_delete_keyl (comments, (const char *)&from,
  3447. sizeof (void *));
  3448. ucl_object_insert_key (comments, obj, (const char *)&to,
  3449. sizeof (void *), true);
  3450. return true;
  3451. }
  3452. }
  3453. return false;
  3454. }
  3455. void
  3456. ucl_comments_add (ucl_object_t *comments, const ucl_object_t *obj,
  3457. const char *comment)
  3458. {
  3459. if (comments && obj && comment) {
  3460. ucl_object_insert_key (comments, ucl_object_fromstring (comment),
  3461. (const char *)&obj, sizeof (void *), true);
  3462. }
  3463. }
  3464. void
  3465. ucl_parser_set_include_tracer (struct ucl_parser *parser,
  3466. ucl_include_trace_func_t func,
  3467. void *user_data)
  3468. {
  3469. parser->include_trace_func = func;
  3470. parser->include_trace_ud = user_data;
  3471. }
  3472. const char *
  3473. ucl_parser_get_cur_file (struct ucl_parser *parser)
  3474. {
  3475. return parser->cur_file;
  3476. }