xref: /freebsd/contrib/libucl/src/ucl_util.c (revision 84e51a1b679bececc13cbe3cd3cb9b7d461b9fe7)
1 /* Copyright (c) 2013, Vsevolod Stakhov
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *       * Redistributions of source code must retain the above copyright
7  *         notice, this list of conditions and the following disclaimer.
8  *       * Redistributions in binary form must reproduce the above copyright
9  *         notice, this list of conditions and the following disclaimer in the
10  *         documentation and/or other materials provided with the distribution.
11  *
12  * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
13  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15  * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
16  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
19  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22  */
23 
24 #include "ucl.h"
25 #include "ucl_internal.h"
26 #include "ucl_chartable.h"
27 
28 #ifdef HAVE_LIBGEN_H
29 #include <libgen.h> /* For dirname */
30 #endif
31 
32 #ifdef HAVE_OPENSSL
33 #include <openssl/err.h>
34 #include <openssl/sha.h>
35 #include <openssl/rsa.h>
36 #include <openssl/ssl.h>
37 #include <openssl/evp.h>
38 #endif
39 
40 #ifdef CURL_FOUND
41 #include <curl/curl.h>
42 #endif
43 #ifdef HAVE_FETCH_H
44 #include <fetch.h>
45 #endif
46 
47 #ifdef _WIN32
48 #include <windows.h>
49 
50 #ifndef PROT_READ
51 #define PROT_READ       1
52 #endif
53 #ifndef PROT_WRITE
54 #define PROT_WRITE      2
55 #endif
56 #ifndef PROT_READWRITE
57 #define PROT_READWRITE  3
58 #endif
59 #ifndef MAP_SHARED
60 #define MAP_SHARED      1
61 #endif
62 #ifndef MAP_PRIVATE
63 #define MAP_PRIVATE     2
64 #endif
65 #ifndef MAP_FAILED
66 #define MAP_FAILED      ((void *) -1)
67 #endif
68 
69 static void *ucl_mmap(char *addr, size_t length, int prot, int access, int fd, off_t offset)
70 {
71 	void *map = NULL;
72 	HANDLE handle = INVALID_HANDLE_VALUE;
73 
74 	switch (prot) {
75 	default:
76 	case PROT_READ:
77 		{
78 			handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READONLY, 0, length, 0);
79 			if (!handle) break;
80 			map = (void *) MapViewOfFile(handle, FILE_MAP_READ, 0, 0, length);
81 			CloseHandle(handle);
82 			break;
83 		}
84 	case PROT_WRITE:
85 		{
86 			handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READWRITE, 0, length, 0);
87 			if (!handle) break;
88 			map = (void *) MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, length);
89 			CloseHandle(handle);
90 			break;
91 		}
92 	case PROT_READWRITE:
93 		{
94 			handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READWRITE, 0, length, 0);
95 			if (!handle) break;
96 			map = (void *) MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, length);
97 			CloseHandle(handle);
98 			break;
99 		}
100 	}
101 	if (map == (void *) NULL) {
102 		return (void *) MAP_FAILED;
103 	}
104 	return (void *) ((char *) map + offset);
105 }
106 
107 static int ucl_munmap(void *map,size_t length)
108 {
109 	if (!UnmapViewOfFile(map)) {
110 		return(-1);
111 	}
112 	return(0);
113 }
114 
115 static char* ucl_realpath(const char *path, char *resolved_path) {
116     char *p;
117     char tmp[MAX_PATH + 1];
118     strncpy(tmp, path, sizeof(tmp)-1);
119     p = tmp;
120     while(*p) {
121         if (*p == '/') *p = '\\';
122         p++;
123     }
124     return _fullpath(resolved_path, tmp, MAX_PATH);
125 }
126 #else
127 #define ucl_mmap mmap
128 #define ucl_munmap munmap
129 #define ucl_realpath realpath
130 #endif
131 
132 /**
133  * @file rcl_util.c
134  * Utilities for rcl parsing
135  */
136 
137 
138 static void
139 ucl_object_free_internal (ucl_object_t *obj, bool allow_rec)
140 {
141 	ucl_object_t *sub, *tmp;
142 
143 	while (obj != NULL) {
144 		if (obj->trash_stack[UCL_TRASH_KEY] != NULL) {
145 			UCL_FREE (obj->hh.keylen, obj->trash_stack[UCL_TRASH_KEY]);
146 		}
147 		if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
148 			UCL_FREE (obj->len, obj->trash_stack[UCL_TRASH_VALUE]);
149 		}
150 
151 		if (obj->type == UCL_ARRAY) {
152 			sub = obj->value.av;
153 			while (sub != NULL) {
154 				tmp = sub->next;
155 				ucl_object_free_internal (sub, false);
156 				sub = tmp;
157 			}
158 		}
159 		else if (obj->type == UCL_OBJECT) {
160 			if (obj->value.ov != NULL) {
161 				ucl_hash_destroy (obj->value.ov, (ucl_hash_free_func *)ucl_object_unref);
162 			}
163 		}
164 		tmp = obj->next;
165 		UCL_FREE (sizeof (ucl_object_t), obj);
166 		obj = tmp;
167 
168 		if (!allow_rec) {
169 			break;
170 		}
171 	}
172 }
173 
174 void
175 ucl_object_free (ucl_object_t *obj)
176 {
177 	ucl_object_free_internal (obj, true);
178 }
179 
180 size_t
181 ucl_unescape_json_string (char *str, size_t len)
182 {
183 	char *t = str, *h = str;
184 	int i, uval;
185 
186 	if (len <= 1) {
187 		return len;
188 	}
189 	/* t is target (tortoise), h is source (hare) */
190 
191 	while (len) {
192 		if (*h == '\\') {
193 			h ++;
194 			switch (*h) {
195 			case 'n':
196 				*t++ = '\n';
197 				break;
198 			case 'r':
199 				*t++ = '\r';
200 				break;
201 			case 'b':
202 				*t++ = '\b';
203 				break;
204 			case 't':
205 				*t++ = '\t';
206 				break;
207 			case 'f':
208 				*t++ = '\f';
209 				break;
210 			case '\\':
211 				*t++ = '\\';
212 				break;
213 			case '"':
214 				*t++ = '"';
215 				break;
216 			case 'u':
217 				/* Unicode escape */
218 				uval = 0;
219 				if (len > 3) {
220 					for (i = 0; i < 4; i++) {
221 						uval <<= 4;
222 						if (isdigit (h[i])) {
223 							uval += h[i] - '0';
224 						}
225 						else if (h[i] >= 'a' && h[i] <= 'f') {
226 							uval += h[i] - 'a' + 10;
227 						}
228 						else if (h[i] >= 'A' && h[i] <= 'F') {
229 							uval += h[i] - 'A' + 10;
230 						}
231 						else {
232 							break;
233 						}
234 					}
235 					h += 3;
236 					len -= 3;
237 					/* Encode */
238 					if(uval < 0x80) {
239 						t[0] = (char)uval;
240 						t ++;
241 					}
242 					else if(uval < 0x800) {
243 						t[0] = 0xC0 + ((uval & 0x7C0) >> 6);
244 						t[1] = 0x80 + ((uval & 0x03F));
245 						t += 2;
246 					}
247 					else if(uval < 0x10000) {
248 						t[0] = 0xE0 + ((uval & 0xF000) >> 12);
249 						t[1] = 0x80 + ((uval & 0x0FC0) >> 6);
250 						t[2] = 0x80 + ((uval & 0x003F));
251 						t += 3;
252 					}
253 					else if(uval <= 0x10FFFF) {
254 						t[0] = 0xF0 + ((uval & 0x1C0000) >> 18);
255 						t[1] = 0x80 + ((uval & 0x03F000) >> 12);
256 						t[2] = 0x80 + ((uval & 0x000FC0) >> 6);
257 						t[3] = 0x80 + ((uval & 0x00003F));
258 						t += 4;
259 					}
260 					else {
261 						*t++ = '?';
262 					}
263 				}
264 				else {
265 					*t++ = 'u';
266 				}
267 				break;
268 			default:
269 				*t++ = *h;
270 				break;
271 			}
272 			h ++;
273 			len --;
274 		}
275 		else {
276 			*t++ = *h++;
277 		}
278 		len --;
279 	}
280 	*t = '\0';
281 
282 	return (t - str);
283 }
284 
285 UCL_EXTERN char *
286 ucl_copy_key_trash (ucl_object_t *obj)
287 {
288 	if (obj == NULL) {
289 		return NULL;
290 	}
291 	if (obj->trash_stack[UCL_TRASH_KEY] == NULL && obj->key != NULL) {
292 		obj->trash_stack[UCL_TRASH_KEY] = malloc (obj->keylen + 1);
293 		if (obj->trash_stack[UCL_TRASH_KEY] != NULL) {
294 			memcpy (obj->trash_stack[UCL_TRASH_KEY], obj->key, obj->keylen);
295 			obj->trash_stack[UCL_TRASH_KEY][obj->keylen] = '\0';
296 		}
297 		obj->key = obj->trash_stack[UCL_TRASH_KEY];
298 		obj->flags |= UCL_OBJECT_ALLOCATED_KEY;
299 	}
300 
301 	return obj->trash_stack[UCL_TRASH_KEY];
302 }
303 
304 UCL_EXTERN char *
305 ucl_copy_value_trash (ucl_object_t *obj)
306 {
307 	if (obj == NULL) {
308 		return NULL;
309 	}
310 	if (obj->trash_stack[UCL_TRASH_VALUE] == NULL) {
311 		if (obj->type == UCL_STRING) {
312 			/* Special case for strings */
313 			obj->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len + 1);
314 			if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
315 				memcpy (obj->trash_stack[UCL_TRASH_VALUE], obj->value.sv, obj->len);
316 				obj->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0';
317 				obj->value.sv = obj->trash_stack[UCL_TRASH_VALUE];
318 			}
319 		}
320 		else {
321 			/* Just emit value in json notation */
322 			obj->trash_stack[UCL_TRASH_VALUE] = ucl_object_emit_single_json (obj);
323 			obj->len = strlen (obj->trash_stack[UCL_TRASH_VALUE]);
324 		}
325 		obj->flags |= UCL_OBJECT_ALLOCATED_VALUE;
326 	}
327 	return obj->trash_stack[UCL_TRASH_VALUE];
328 }
329 
330 UCL_EXTERN ucl_object_t*
331 ucl_parser_get_object (struct ucl_parser *parser)
332 {
333 	if (parser->state != UCL_STATE_ERROR && parser->top_obj != NULL) {
334 		return ucl_object_ref (parser->top_obj);
335 	}
336 
337 	return NULL;
338 }
339 
340 UCL_EXTERN void
341 ucl_parser_free (struct ucl_parser *parser)
342 {
343 	struct ucl_stack *stack, *stmp;
344 	struct ucl_macro *macro, *mtmp;
345 	struct ucl_chunk *chunk, *ctmp;
346 	struct ucl_pubkey *key, *ktmp;
347 	struct ucl_variable *var, *vtmp;
348 
349 	if (parser == NULL) {
350 		return;
351 	}
352 
353 	if (parser->top_obj != NULL) {
354 		ucl_object_unref (parser->top_obj);
355 	}
356 
357 	LL_FOREACH_SAFE (parser->stack, stack, stmp) {
358 		free (stack);
359 	}
360 	HASH_ITER (hh, parser->macroes, macro, mtmp) {
361 		free (macro->name);
362 		HASH_DEL (parser->macroes, macro);
363 		UCL_FREE (sizeof (struct ucl_macro), macro);
364 	}
365 	LL_FOREACH_SAFE (parser->chunks, chunk, ctmp) {
366 		UCL_FREE (sizeof (struct ucl_chunk), chunk);
367 	}
368 	LL_FOREACH_SAFE (parser->keys, key, ktmp) {
369 		UCL_FREE (sizeof (struct ucl_pubkey), key);
370 	}
371 	LL_FOREACH_SAFE (parser->variables, var, vtmp) {
372 		free (var->value);
373 		free (var->var);
374 		UCL_FREE (sizeof (struct ucl_variable), var);
375 	}
376 
377 	if (parser->err != NULL) {
378 		utstring_free(parser->err);
379 	}
380 
381 	UCL_FREE (sizeof (struct ucl_parser), parser);
382 }
383 
384 UCL_EXTERN const char *
385 ucl_parser_get_error(struct ucl_parser *parser)
386 {
387 	if (parser == NULL) {
388 		return NULL;
389 	}
390 
391 	if (parser->err == NULL)
392 		return NULL;
393 
394 	return utstring_body(parser->err);
395 }
396 
397 UCL_EXTERN bool
398 ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len)
399 {
400 #ifndef HAVE_OPENSSL
401 	ucl_create_err (&parser->err, "cannot check signatures without openssl");
402 	return false;
403 #else
404 # if (OPENSSL_VERSION_NUMBER < 0x10000000L)
405 	ucl_create_err (&parser->err, "cannot check signatures, openssl version is unsupported");
406 	return EXIT_FAILURE;
407 # else
408 	struct ucl_pubkey *nkey;
409 	BIO *mem;
410 
411 	mem = BIO_new_mem_buf ((void *)key, len);
412 	nkey = UCL_ALLOC (sizeof (struct ucl_pubkey));
413 	if (nkey == NULL) {
414 		ucl_create_err (&parser->err, "cannot allocate memory for key");
415 		return false;
416 	}
417 	nkey->key = PEM_read_bio_PUBKEY (mem, &nkey->key, NULL, NULL);
418 	BIO_free (mem);
419 	if (nkey->key == NULL) {
420 		UCL_FREE (sizeof (struct ucl_pubkey), nkey);
421 		ucl_create_err (&parser->err, "%s",
422 				ERR_error_string (ERR_get_error (), NULL));
423 		return false;
424 	}
425 	LL_PREPEND (parser->keys, nkey);
426 # endif
427 #endif
428 	return true;
429 }
430 
431 #ifdef CURL_FOUND
432 struct ucl_curl_cbdata {
433 	unsigned char *buf;
434 	size_t buflen;
435 };
436 
437 static size_t
438 ucl_curl_write_callback (void* contents, size_t size, size_t nmemb, void* ud)
439 {
440 	struct ucl_curl_cbdata *cbdata = ud;
441 	size_t realsize = size * nmemb;
442 
443 	cbdata->buf = realloc (cbdata->buf, cbdata->buflen + realsize + 1);
444 	if (cbdata->buf == NULL) {
445 		return 0;
446 	}
447 
448 	memcpy (&(cbdata->buf[cbdata->buflen]), contents, realsize);
449 	cbdata->buflen += realsize;
450 	cbdata->buf[cbdata->buflen] = 0;
451 
452 	return realsize;
453 }
454 #endif
455 
456 /**
457  * Fetch a url and save results to the memory buffer
458  * @param url url to fetch
459  * @param len length of url
460  * @param buf target buffer
461  * @param buflen target length
462  * @return
463  */
464 static bool
465 ucl_fetch_url (const unsigned char *url, unsigned char **buf, size_t *buflen,
466 		UT_string **err, bool must_exist)
467 {
468 
469 #ifdef HAVE_FETCH_H
470 	struct url *fetch_url;
471 	struct url_stat us;
472 	FILE *in;
473 
474 	fetch_url = fetchParseURL (url);
475 	if (fetch_url == NULL) {
476 		ucl_create_err (err, "invalid URL %s: %s",
477 				url, strerror (errno));
478 		return false;
479 	}
480 	if ((in = fetchXGet (fetch_url, &us, "")) == NULL) {
481 		if (!must_exist) {
482 			ucl_create_err (err, "cannot fetch URL %s: %s",
483 				url, strerror (errno));
484 		}
485 		fetchFreeURL (fetch_url);
486 		return false;
487 	}
488 
489 	*buflen = us.size;
490 	*buf = malloc (*buflen);
491 	if (*buf == NULL) {
492 		ucl_create_err (err, "cannot allocate buffer for URL %s: %s",
493 				url, strerror (errno));
494 		fclose (in);
495 		fetchFreeURL (fetch_url);
496 		return false;
497 	}
498 
499 	if (fread (*buf, *buflen, 1, in) != 1) {
500 		ucl_create_err (err, "cannot read URL %s: %s",
501 				url, strerror (errno));
502 		fclose (in);
503 		fetchFreeURL (fetch_url);
504 		return false;
505 	}
506 
507 	fetchFreeURL (fetch_url);
508 	return true;
509 #elif defined(CURL_FOUND)
510 	CURL *curl;
511 	int r;
512 	struct ucl_curl_cbdata cbdata;
513 
514 	curl = curl_easy_init ();
515 	if (curl == NULL) {
516 		ucl_create_err (err, "CURL interface is broken");
517 		return false;
518 	}
519 	if ((r = curl_easy_setopt (curl, CURLOPT_URL, url)) != CURLE_OK) {
520 		ucl_create_err (err, "invalid URL %s: %s",
521 				url, curl_easy_strerror (r));
522 		curl_easy_cleanup (curl);
523 		return false;
524 	}
525 	curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, ucl_curl_write_callback);
526 	cbdata.buf = *buf;
527 	cbdata.buflen = *buflen;
528 	curl_easy_setopt (curl, CURLOPT_WRITEDATA, &cbdata);
529 
530 	if ((r = curl_easy_perform (curl)) != CURLE_OK) {
531 		if (!must_exist) {
532 			ucl_create_err (err, "error fetching URL %s: %s",
533 				url, curl_easy_strerror (r));
534 		}
535 		curl_easy_cleanup (curl);
536 		if (cbdata.buf) {
537 			free (cbdata.buf);
538 		}
539 		return false;
540 	}
541 	*buf = cbdata.buf;
542 	*buflen = cbdata.buflen;
543 
544 	return true;
545 #else
546 	ucl_create_err (err, "URL support is disabled");
547 	return false;
548 #endif
549 }
550 
551 /**
552  * Fetch a file and save results to the memory buffer
553  * @param filename filename to fetch
554  * @param len length of filename
555  * @param buf target buffer
556  * @param buflen target length
557  * @return
558  */
559 static bool
560 ucl_fetch_file (const unsigned char *filename, unsigned char **buf, size_t *buflen,
561 		UT_string **err, bool must_exist)
562 {
563 	int fd;
564 	struct stat st;
565 
566 	if (stat (filename, &st) == -1 || !S_ISREG (st.st_mode)) {
567 		if (must_exist) {
568 			ucl_create_err (err, "cannot stat file %s: %s",
569 					filename, strerror (errno));
570 		}
571 		return false;
572 	}
573 	if (st.st_size == 0) {
574 		/* Do not map empty files */
575 		*buf = "";
576 		*buflen = 0;
577 	}
578 	else {
579 		if ((fd = open (filename, O_RDONLY)) == -1) {
580 			ucl_create_err (err, "cannot open file %s: %s",
581 					filename, strerror (errno));
582 			return false;
583 		}
584 		if ((*buf = ucl_mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
585 			close (fd);
586 			ucl_create_err (err, "cannot mmap file %s: %s",
587 					filename, strerror (errno));
588 			return false;
589 		}
590 		*buflen = st.st_size;
591 		close (fd);
592 	}
593 
594 	return true;
595 }
596 
597 
598 #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
599 static inline bool
600 ucl_sig_check (const unsigned char *data, size_t datalen,
601 		const unsigned char *sig, size_t siglen, struct ucl_parser *parser)
602 {
603 	struct ucl_pubkey *key;
604 	char dig[EVP_MAX_MD_SIZE];
605 	unsigned int diglen;
606 	EVP_PKEY_CTX *key_ctx;
607 	EVP_MD_CTX *sign_ctx = NULL;
608 
609 	sign_ctx = EVP_MD_CTX_create ();
610 
611 	LL_FOREACH (parser->keys, key) {
612 		key_ctx = EVP_PKEY_CTX_new (key->key, NULL);
613 		if (key_ctx != NULL) {
614 			if (EVP_PKEY_verify_init (key_ctx) <= 0) {
615 				EVP_PKEY_CTX_free (key_ctx);
616 				continue;
617 			}
618 			if (EVP_PKEY_CTX_set_rsa_padding (key_ctx, RSA_PKCS1_PADDING) <= 0) {
619 				EVP_PKEY_CTX_free (key_ctx);
620 				continue;
621 			}
622 			if (EVP_PKEY_CTX_set_signature_md (key_ctx, EVP_sha256 ()) <= 0) {
623 				EVP_PKEY_CTX_free (key_ctx);
624 				continue;
625 			}
626 			EVP_DigestInit (sign_ctx, EVP_sha256 ());
627 			EVP_DigestUpdate (sign_ctx, data, datalen);
628 			EVP_DigestFinal (sign_ctx, dig, &diglen);
629 
630 			if (EVP_PKEY_verify (key_ctx, sig, siglen, dig, diglen) == 1) {
631 				EVP_MD_CTX_destroy (sign_ctx);
632 				EVP_PKEY_CTX_free (key_ctx);
633 				return true;
634 			}
635 
636 			EVP_PKEY_CTX_free (key_ctx);
637 		}
638 	}
639 
640 	EVP_MD_CTX_destroy (sign_ctx);
641 
642 	return false;
643 }
644 #endif
645 
646 /**
647  * Include an url to configuration
648  * @param data
649  * @param len
650  * @param parser
651  * @param err
652  * @return
653  */
654 static bool
655 ucl_include_url (const unsigned char *data, size_t len,
656 		struct ucl_parser *parser, bool check_signature, bool must_exist)
657 {
658 
659 	bool res;
660 	unsigned char *buf = NULL;
661 	size_t buflen = 0;
662 	struct ucl_chunk *chunk;
663 	char urlbuf[PATH_MAX];
664 	int prev_state;
665 
666 	snprintf (urlbuf, sizeof (urlbuf), "%.*s", (int)len, data);
667 
668 	if (!ucl_fetch_url (urlbuf, &buf, &buflen, &parser->err, must_exist)) {
669 		return (!must_exist || false);
670 	}
671 
672 	if (check_signature) {
673 #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
674 		unsigned char *sigbuf = NULL;
675 		size_t siglen = 0;
676 		/* We need to check signature first */
677 		snprintf (urlbuf, sizeof (urlbuf), "%.*s.sig", (int)len, data);
678 		if (!ucl_fetch_url (urlbuf, &sigbuf, &siglen, &parser->err, true)) {
679 			return false;
680 		}
681 		if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
682 			ucl_create_err (&parser->err, "cannot verify url %s: %s",
683 							urlbuf,
684 							ERR_error_string (ERR_get_error (), NULL));
685 			if (siglen > 0) {
686 				ucl_munmap (sigbuf, siglen);
687 			}
688 			return false;
689 		}
690 		if (siglen > 0) {
691 			ucl_munmap (sigbuf, siglen);
692 		}
693 #endif
694 	}
695 
696 	prev_state = parser->state;
697 	parser->state = UCL_STATE_INIT;
698 
699 	res = ucl_parser_add_chunk (parser, buf, buflen);
700 	if (res == true) {
701 		/* Remove chunk from the stack */
702 		chunk = parser->chunks;
703 		if (chunk != NULL) {
704 			parser->chunks = chunk->next;
705 			UCL_FREE (sizeof (struct ucl_chunk), chunk);
706 		}
707 	}
708 
709 	parser->state = prev_state;
710 	free (buf);
711 
712 	return res;
713 }
714 
715 /**
716  * Include a file to configuration
717  * @param data
718  * @param len
719  * @param parser
720  * @param err
721  * @return
722  */
723 static bool
724 ucl_include_file (const unsigned char *data, size_t len,
725 		struct ucl_parser *parser, bool check_signature, bool must_exist)
726 {
727 	bool res;
728 	struct ucl_chunk *chunk;
729 	unsigned char *buf = NULL;
730 	size_t buflen;
731 	char filebuf[PATH_MAX], realbuf[PATH_MAX];
732 	int prev_state;
733 
734 	snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data);
735 	if (ucl_realpath (filebuf, realbuf) == NULL) {
736 		if (!must_exist) {
737 			return true;
738 		}
739 		ucl_create_err (&parser->err, "cannot open file %s: %s",
740 									filebuf,
741 									strerror (errno));
742 		return false;
743 	}
744 
745 	if (!ucl_fetch_file (realbuf, &buf, &buflen, &parser->err, must_exist)) {
746 		return (!must_exist || false);
747 	}
748 
749 	if (check_signature) {
750 #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
751 		unsigned char *sigbuf = NULL;
752 		size_t siglen = 0;
753 		/* We need to check signature first */
754 		snprintf (filebuf, sizeof (filebuf), "%s.sig", realbuf);
755 		if (!ucl_fetch_file (filebuf, &sigbuf, &siglen, &parser->err, true)) {
756 			return false;
757 		}
758 		if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
759 			ucl_create_err (&parser->err, "cannot verify file %s: %s",
760 							filebuf,
761 							ERR_error_string (ERR_get_error (), NULL));
762 			if (siglen > 0) {
763 				ucl_munmap (sigbuf, siglen);
764 			}
765 			return false;
766 		}
767 		if (siglen > 0) {
768 			ucl_munmap (sigbuf, siglen);
769 		}
770 #endif
771 	}
772 
773 	ucl_parser_set_filevars (parser, realbuf, false);
774 
775 	prev_state = parser->state;
776 	parser->state = UCL_STATE_INIT;
777 
778 	res = ucl_parser_add_chunk (parser, buf, buflen);
779 	if (res == true) {
780 		/* Remove chunk from the stack */
781 		chunk = parser->chunks;
782 		if (chunk != NULL) {
783 			parser->chunks = chunk->next;
784 			UCL_FREE (sizeof (struct ucl_chunk), chunk);
785 		}
786 	}
787 
788 	parser->state = prev_state;
789 
790 	if (buflen > 0) {
791 		ucl_munmap (buf, buflen);
792 	}
793 
794 	return res;
795 }
796 
797 /**
798  * Handle include macro
799  * @param data include data
800  * @param len length of data
801  * @param ud user data
802  * @param err error ptr
803  * @return
804  */
805 UCL_EXTERN bool
806 ucl_include_handler (const unsigned char *data, size_t len, void* ud)
807 {
808 	struct ucl_parser *parser = ud;
809 
810 	if (*data == '/' || *data == '.') {
811 		/* Try to load a file */
812 		return ucl_include_file (data, len, parser, false, true);
813 	}
814 
815 	return ucl_include_url (data, len, parser, false, true);
816 }
817 
818 /**
819  * Handle includes macro
820  * @param data include data
821  * @param len length of data
822  * @param ud user data
823  * @param err error ptr
824  * @return
825  */
826 UCL_EXTERN bool
827 ucl_includes_handler (const unsigned char *data, size_t len, void* ud)
828 {
829 	struct ucl_parser *parser = ud;
830 
831 	if (*data == '/' || *data == '.') {
832 		/* Try to load a file */
833 		return ucl_include_file (data, len, parser, true, true);
834 	}
835 
836 	return ucl_include_url (data, len, parser, true, true);
837 }
838 
839 
840 UCL_EXTERN bool
841 ucl_try_include_handler (const unsigned char *data, size_t len, void* ud)
842 {
843 	struct ucl_parser *parser = ud;
844 
845 	if (*data == '/' || *data == '.') {
846 		/* Try to load a file */
847 		return ucl_include_file (data, len, parser, false, false);
848 	}
849 
850 	return ucl_include_url (data, len, parser, false, false);
851 }
852 
853 UCL_EXTERN bool
854 ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand)
855 {
856 	char realbuf[PATH_MAX], *curdir;
857 
858 	if (filename != NULL) {
859 		if (need_expand) {
860 			if (ucl_realpath (filename, realbuf) == NULL) {
861 				return false;
862 			}
863 		}
864 		else {
865 			ucl_strlcpy (realbuf, filename, sizeof (realbuf));
866 		}
867 
868 		/* Define variables */
869 		ucl_parser_register_variable (parser, "FILENAME", realbuf);
870 		curdir = dirname (realbuf);
871 		ucl_parser_register_variable (parser, "CURDIR", curdir);
872 	}
873 	else {
874 		/* Set everything from the current dir */
875 		curdir = getcwd (realbuf, sizeof (realbuf));
876 		ucl_parser_register_variable (parser, "FILENAME", "undef");
877 		ucl_parser_register_variable (parser, "CURDIR", curdir);
878 	}
879 
880 	return true;
881 }
882 
883 UCL_EXTERN bool
884 ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
885 {
886 	unsigned char *buf;
887 	size_t len;
888 	bool ret;
889 	char realbuf[PATH_MAX];
890 
891 	if (ucl_realpath (filename, realbuf) == NULL) {
892 		ucl_create_err (&parser->err, "cannot open file %s: %s",
893 				filename,
894 				strerror (errno));
895 		return false;
896 	}
897 
898 	if (!ucl_fetch_file (realbuf, &buf, &len, &parser->err, true)) {
899 		return false;
900 	}
901 
902 	ucl_parser_set_filevars (parser, realbuf, false);
903 	ret = ucl_parser_add_chunk (parser, buf, len);
904 
905 	if (len > 0) {
906 		ucl_munmap (buf, len);
907 	}
908 
909 	return ret;
910 }
911 
912 size_t
913 ucl_strlcpy (char *dst, const char *src, size_t siz)
914 {
915 	char *d = dst;
916 	const char *s = src;
917 	size_t n = siz;
918 
919 	/* Copy as many bytes as will fit */
920 	if (n != 0) {
921 		while (--n != 0) {
922 			if ((*d++ = *s++) == '\0') {
923 				break;
924 			}
925 		}
926 	}
927 
928 	if (n == 0 && siz != 0) {
929 		*d = '\0';
930 	}
931 
932 	return (s - src - 1);    /* count does not include NUL */
933 }
934 
935 size_t
936 ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz)
937 {
938 	memcpy (dst, src, siz - 1);
939 	dst[siz - 1] = '\0';
940 
941 	return siz - 1;
942 }
943 
944 size_t
945 ucl_strlcpy_tolower (char *dst, const char *src, size_t siz)
946 {
947 	char *d = dst;
948 	const char *s = src;
949 	size_t n = siz;
950 
951 	/* Copy as many bytes as will fit */
952 	if (n != 0) {
953 		while (--n != 0) {
954 			if ((*d++ = tolower (*s++)) == '\0') {
955 				break;
956 			}
957 		}
958 	}
959 
960 	if (n == 0 && siz != 0) {
961 		*d = '\0';
962 	}
963 
964 	return (s - src);    /* count does not include NUL */
965 }
966 
967 ucl_object_t *
968 ucl_object_fromstring_common (const char *str, size_t len, enum ucl_string_flags flags)
969 {
970 	ucl_object_t *obj;
971 	const char *start, *end, *p, *pos;
972 	char *dst, *d;
973 	size_t escaped_len;
974 
975 	if (str == NULL) {
976 		return NULL;
977 	}
978 
979 	obj = ucl_object_new ();
980 	if (obj) {
981 		if (len == 0) {
982 			len = strlen (str);
983 		}
984 		if (flags & UCL_STRING_TRIM) {
985 			/* Skip leading spaces */
986 			for (start = str; (size_t)(start - str) < len; start ++) {
987 				if (!ucl_test_character (*start, UCL_CHARACTER_WHITESPACE_UNSAFE)) {
988 					break;
989 				}
990 			}
991 			/* Skip trailing spaces */
992 			for (end = str + len - 1; end > start; end --) {
993 				if (!ucl_test_character (*end, UCL_CHARACTER_WHITESPACE_UNSAFE)) {
994 					break;
995 				}
996 			}
997 			end ++;
998 		}
999 		else {
1000 			start = str;
1001 			end = str + len;
1002 		}
1003 
1004 		obj->type = UCL_STRING;
1005 		if (flags & UCL_STRING_ESCAPE) {
1006 			for (p = start, escaped_len = 0; p < end; p ++, escaped_len ++) {
1007 				if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) {
1008 					escaped_len ++;
1009 				}
1010 			}
1011 			dst = malloc (escaped_len + 1);
1012 			if (dst != NULL) {
1013 				for (p = start, d = dst; p < end; p ++, d ++) {
1014 					if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) {
1015 						switch (*p) {
1016 						case '\n':
1017 							*d++ = '\\';
1018 							*d = 'n';
1019 							break;
1020 						case '\r':
1021 							*d++ = '\\';
1022 							*d = 'r';
1023 							break;
1024 						case '\b':
1025 							*d++ = '\\';
1026 							*d = 'b';
1027 							break;
1028 						case '\t':
1029 							*d++ = '\\';
1030 							*d = 't';
1031 							break;
1032 						case '\f':
1033 							*d++ = '\\';
1034 							*d = 'f';
1035 							break;
1036 						case '\\':
1037 							*d++ = '\\';
1038 							*d = '\\';
1039 							break;
1040 						case '"':
1041 							*d++ = '\\';
1042 							*d = '"';
1043 							break;
1044 						}
1045 					}
1046 					else {
1047 						*d = *p;
1048 					}
1049 				}
1050 				*d = '\0';
1051 				obj->value.sv = dst;
1052 				obj->trash_stack[UCL_TRASH_VALUE] = dst;
1053 				obj->len = escaped_len;
1054 			}
1055 		}
1056 		else {
1057 			dst = malloc (end - start + 1);
1058 			if (dst != NULL) {
1059 				ucl_strlcpy_unsafe (dst, start, end - start + 1);
1060 				obj->value.sv = dst;
1061 				obj->trash_stack[UCL_TRASH_VALUE] = dst;
1062 				obj->len = end - start;
1063 			}
1064 		}
1065 		if ((flags & UCL_STRING_PARSE) && dst != NULL) {
1066 			/* Parse what we have */
1067 			if (flags & UCL_STRING_PARSE_BOOLEAN) {
1068 				if (!ucl_maybe_parse_boolean (obj, dst, obj->len) && (flags & UCL_STRING_PARSE_NUMBER)) {
1069 					ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
1070 							flags & UCL_STRING_PARSE_DOUBLE,
1071 							flags & UCL_STRING_PARSE_BYTES,
1072 							flags & UCL_STRING_PARSE_TIME);
1073 				}
1074 			}
1075 			else {
1076 				ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
1077 						flags & UCL_STRING_PARSE_DOUBLE,
1078 						flags & UCL_STRING_PARSE_BYTES,
1079 						flags & UCL_STRING_PARSE_TIME);
1080 			}
1081 		}
1082 	}
1083 
1084 	return obj;
1085 }
1086 
1087 static ucl_object_t *
1088 ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt,
1089 		const char *key, size_t keylen, bool copy_key, bool merge, bool replace)
1090 {
1091 	ucl_object_t *found, *cur;
1092 	ucl_object_iter_t it = NULL;
1093 	const char *p;
1094 
1095 	if (elt == NULL || key == NULL) {
1096 		return NULL;
1097 	}
1098 
1099 	if (top == NULL) {
1100 		top = ucl_object_new ();
1101 		top->type = UCL_OBJECT;
1102 	}
1103 
1104 	if (top->type != UCL_OBJECT) {
1105 		/* It is possible to convert NULL type to an object */
1106 		if (top->type == UCL_NULL) {
1107 			top->type = UCL_OBJECT;
1108 		}
1109 		else {
1110 			/* Refuse converting of other object types */
1111 			return top;
1112 		}
1113 	}
1114 
1115 	if (top->value.ov == NULL) {
1116 		top->value.ov = ucl_hash_create ();
1117 	}
1118 
1119 	if (keylen == 0) {
1120 		keylen = strlen (key);
1121 	}
1122 
1123 	for (p = key; p < key + keylen; p ++) {
1124 		if (ucl_test_character (*p, UCL_CHARACTER_UCL_UNSAFE)) {
1125 			elt->flags |= UCL_OBJECT_NEED_KEY_ESCAPE;
1126 			break;
1127 		}
1128 	}
1129 
1130 	elt->key = key;
1131 	elt->keylen = keylen;
1132 
1133 	if (copy_key) {
1134 		ucl_copy_key_trash (elt);
1135 	}
1136 
1137 	found = ucl_hash_search_obj (top->value.ov, elt);
1138 
1139 	if (!found) {
1140 		top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
1141 		DL_APPEND (found, elt);
1142 		top->len ++;
1143 	}
1144 	else {
1145 		if (replace) {
1146 			ucl_hash_delete (top->value.ov, found);
1147 			ucl_object_unref (found);
1148 			top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
1149 			found = NULL;
1150 			DL_APPEND (found, elt);
1151 		}
1152 		else if (merge) {
1153 			if (found->type != UCL_OBJECT && elt->type == UCL_OBJECT) {
1154 				/* Insert old elt to new one */
1155 				elt = ucl_object_insert_key_common (elt, found, found->key, found->keylen, copy_key, false, false);
1156 				ucl_hash_delete (top->value.ov, found);
1157 				top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
1158 			}
1159 			else if (found->type == UCL_OBJECT && elt->type != UCL_OBJECT) {
1160 				/* Insert new to old */
1161 				found = ucl_object_insert_key_common (found, elt, elt->key, elt->keylen, copy_key, false, false);
1162 			}
1163 			else if (found->type == UCL_OBJECT && elt->type == UCL_OBJECT) {
1164 				/* Mix two hashes */
1165 				while ((cur = ucl_iterate_object (elt, &it, true)) != NULL) {
1166 					ucl_object_ref (cur);
1167 					found = ucl_object_insert_key_common (found, cur, cur->key, cur->keylen, copy_key, false, false);
1168 				}
1169 				ucl_object_unref (elt);
1170 			}
1171 			else {
1172 				/* Just make a list of scalars */
1173 				DL_APPEND (found, elt);
1174 			}
1175 		}
1176 		else {
1177 			DL_APPEND (found, elt);
1178 		}
1179 	}
1180 
1181 	return top;
1182 }
1183 
1184 bool
1185 ucl_object_delete_keyl(ucl_object_t *top, const char *key, size_t keylen)
1186 {
1187 	ucl_object_t *found;
1188 
1189 	if (top == NULL || key == NULL) {
1190 		return false;
1191 	}
1192 
1193 	found = ucl_object_find_keyl(top, key, keylen);
1194 
1195 	if (found == NULL) {
1196 		return false;
1197 	}
1198 
1199 	ucl_hash_delete(top->value.ov, found);
1200 	ucl_object_unref (found);
1201 	top->len --;
1202 
1203 	return true;
1204 }
1205 
1206 bool
1207 ucl_object_delete_key(ucl_object_t *top, const char *key)
1208 {
1209 	return ucl_object_delete_keyl(top, key, 0);
1210 }
1211 
1212 ucl_object_t*
1213 ucl_object_pop_keyl (ucl_object_t *top, const char *key, size_t keylen)
1214 {
1215 	ucl_object_t *found;
1216 
1217 	if (top == NULL || key == NULL) {
1218 		return false;
1219 	}
1220 	found = ucl_object_find_keyl(top, key, keylen);
1221 
1222 	if (found == NULL) {
1223 		return NULL;
1224 	}
1225 	ucl_hash_delete(top->value.ov, found);
1226 	top->len --;
1227 
1228 	return found;
1229 }
1230 
1231 ucl_object_t*
1232 ucl_object_pop_key (ucl_object_t *top, const char *key)
1233 {
1234 	return ucl_object_pop_keyl (top, key, 0);
1235 }
1236 
1237 ucl_object_t *
1238 ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt,
1239 		const char *key, size_t keylen, bool copy_key)
1240 {
1241 	return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, false);
1242 }
1243 
1244 ucl_object_t *
1245 ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt,
1246 		const char *key, size_t keylen, bool copy_key)
1247 {
1248 	return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, true, false);
1249 }
1250 
1251 ucl_object_t *
1252 ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt,
1253 		const char *key, size_t keylen, bool copy_key)
1254 {
1255 	return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, true);
1256 }
1257 
1258 ucl_object_t *
1259 ucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen)
1260 {
1261 	ucl_object_t *ret, srch;
1262 
1263 	if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) {
1264 		return NULL;
1265 	}
1266 
1267 	srch.key = key;
1268 	srch.keylen = klen;
1269 	ret = ucl_hash_search_obj (obj->value.ov, &srch);
1270 
1271 	return ret;
1272 }
1273 
1274 ucl_object_t *
1275 ucl_object_find_key (ucl_object_t *obj, const char *key)
1276 {
1277 	size_t klen;
1278 	ucl_object_t *ret, srch;
1279 
1280 	if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) {
1281 		return NULL;
1282 	}
1283 
1284 	klen = strlen (key);
1285 	srch.key = key;
1286 	srch.keylen = klen;
1287 	ret = ucl_hash_search_obj (obj->value.ov, &srch);
1288 
1289 	return ret;
1290 }
1291 
1292 ucl_object_t*
1293 ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values)
1294 {
1295 	ucl_object_t *elt;
1296 
1297 	if (obj == NULL || iter == NULL) {
1298 		return NULL;
1299 	}
1300 
1301 	if (expand_values) {
1302 		switch (obj->type) {
1303 		case UCL_OBJECT:
1304 			return (ucl_object_t*)ucl_hash_iterate (obj->value.ov, iter);
1305 			break;
1306 		case UCL_ARRAY:
1307 			elt = *iter;
1308 			if (elt == NULL) {
1309 				elt = obj->value.av;
1310 				if (elt == NULL) {
1311 					return NULL;
1312 				}
1313 			}
1314 			else if (elt == obj->value.av) {
1315 				return NULL;
1316 			}
1317 			*iter = elt->next ? elt->next : obj->value.av;
1318 			return elt;
1319 		default:
1320 			/* Go to linear iteration */
1321 			break;
1322 		}
1323 	}
1324 	/* Treat everything as a linear list */
1325 	elt = *iter;
1326 	if (elt == NULL) {
1327 		elt = obj;
1328 		if (elt == NULL) {
1329 			return NULL;
1330 		}
1331 	}
1332 	else if (elt == obj) {
1333 		return NULL;
1334 	}
1335 	*iter = elt->next ? elt->next : obj;
1336 	return elt;
1337 
1338 	/* Not reached */
1339 	return NULL;
1340 }
1341 
1342 
1343 ucl_object_t *
1344 ucl_object_new (void)
1345 {
1346 	ucl_object_t *new;
1347 	new = malloc (sizeof (ucl_object_t));
1348 	if (new != NULL) {
1349 		memset (new, 0, sizeof (ucl_object_t));
1350 		new->ref = 1;
1351 		new->type = UCL_NULL;
1352 	}
1353 	return new;
1354 }
1355 
1356 ucl_object_t *
1357 ucl_object_typed_new (unsigned int type)
1358 {
1359 	ucl_object_t *new;
1360 	new = malloc (sizeof (ucl_object_t));
1361 	if (new != NULL) {
1362 		memset (new, 0, sizeof (ucl_object_t));
1363 		new->ref = 1;
1364 		new->type = (type <= UCL_NULL ? type : UCL_NULL);
1365 	}
1366 	return new;
1367 }
1368 
1369 ucl_object_t*
1370 ucl_object_fromstring (const char *str)
1371 {
1372 	return ucl_object_fromstring_common (str, 0, UCL_STRING_ESCAPE);
1373 }
1374 
1375 ucl_object_t *
1376 ucl_object_fromlstring (const char *str, size_t len)
1377 {
1378 	return ucl_object_fromstring_common (str, len, UCL_STRING_ESCAPE);
1379 }
1380 
1381 ucl_object_t *
1382 ucl_object_fromint (int64_t iv)
1383 {
1384 	ucl_object_t *obj;
1385 
1386 	obj = ucl_object_new ();
1387 	if (obj != NULL) {
1388 		obj->type = UCL_INT;
1389 		obj->value.iv = iv;
1390 	}
1391 
1392 	return obj;
1393 }
1394 
1395 ucl_object_t *
1396 ucl_object_fromdouble (double dv)
1397 {
1398 	ucl_object_t *obj;
1399 
1400 	obj = ucl_object_new ();
1401 	if (obj != NULL) {
1402 		obj->type = UCL_FLOAT;
1403 		obj->value.dv = dv;
1404 	}
1405 
1406 	return obj;
1407 }
1408 
1409 ucl_object_t*
1410 ucl_object_frombool (bool bv)
1411 {
1412 	ucl_object_t *obj;
1413 
1414 	obj = ucl_object_new ();
1415 	if (obj != NULL) {
1416 		obj->type = UCL_BOOLEAN;
1417 		obj->value.iv = bv;
1418 	}
1419 
1420 	return obj;
1421 }
1422 
1423 ucl_object_t *
1424 ucl_array_append (ucl_object_t *top, ucl_object_t *elt)
1425 {
1426 	ucl_object_t *head;
1427 
1428 	if (elt == NULL) {
1429 		return NULL;
1430 	}
1431 
1432 	if (top == NULL) {
1433 		top = ucl_object_typed_new (UCL_ARRAY);
1434 		top->value.av = elt;
1435 		elt->next = NULL;
1436 		elt->prev = elt;
1437 		top->len = 1;
1438 	}
1439 	else {
1440 		head = top->value.av;
1441 		if (head == NULL) {
1442 			top->value.av = elt;
1443 			elt->prev = elt;
1444 		}
1445 		else {
1446 			elt->prev = head->prev;
1447 			head->prev->next = elt;
1448 			head->prev = elt;
1449 		}
1450 		elt->next = NULL;
1451 		top->len ++;
1452 	}
1453 
1454 	return top;
1455 }
1456 
1457 ucl_object_t *
1458 ucl_array_prepend (ucl_object_t *top, ucl_object_t *elt)
1459 {
1460 	ucl_object_t *head;
1461 
1462 	if (elt == NULL) {
1463 		return NULL;
1464 	}
1465 
1466 	if (top == NULL) {
1467 		top = ucl_object_typed_new (UCL_ARRAY);
1468 		top->value.av = elt;
1469 		elt->next = NULL;
1470 		elt->prev = elt;
1471 		top->len = 1;
1472 	}
1473 	else {
1474 		head = top->value.av;
1475 		if (head == NULL) {
1476 			top->value.av = elt;
1477 			elt->prev = elt;
1478 		}
1479 		else {
1480 			elt->prev = head->prev;
1481 			head->prev = elt;
1482 		}
1483 		elt->next = head;
1484 		top->value.av = elt;
1485 		top->len ++;
1486 	}
1487 
1488 	return top;
1489 }
1490 
1491 ucl_object_t *
1492 ucl_array_delete (ucl_object_t *top, ucl_object_t *elt)
1493 {
1494 	ucl_object_t *head;
1495 
1496 	if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
1497 		return NULL;
1498 	}
1499 	head = top->value.av;
1500 
1501 	if (elt->prev == elt) {
1502 		top->value.av = NULL;
1503 	}
1504 	else if (elt == head) {
1505 		elt->next->prev = elt->prev;
1506 		top->value.av = elt->next;
1507 	}
1508 	else {
1509 		elt->prev->next = elt->next;
1510 		if (elt->next) {
1511 			elt->next->prev = elt->prev;
1512 		}
1513 		else {
1514 			head->prev = elt->prev;
1515 		}
1516 	}
1517 	elt->next = NULL;
1518 	elt->prev = elt;
1519 	top->len --;
1520 
1521 	return elt;
1522 }
1523 
1524 ucl_object_t *
1525 ucl_array_head (ucl_object_t *top)
1526 {
1527 	if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
1528 		return NULL;
1529 	}
1530 	return top->value.av;
1531 }
1532 
1533 ucl_object_t *
1534 ucl_array_tail (ucl_object_t *top)
1535 {
1536 	if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
1537 		return NULL;
1538 	}
1539 	return top->value.av->prev;
1540 }
1541 
1542 ucl_object_t *
1543 ucl_array_pop_last (ucl_object_t *top)
1544 {
1545 	return ucl_array_delete (top, ucl_array_tail (top));
1546 }
1547 
1548 ucl_object_t *
1549 ucl_array_pop_first (ucl_object_t *top)
1550 {
1551 	return ucl_array_delete (top, ucl_array_head (top));
1552 }
1553 
1554 ucl_object_t *
1555 ucl_elt_append (ucl_object_t *head, ucl_object_t *elt)
1556 {
1557 
1558 	if (head == NULL) {
1559 		elt->next = NULL;
1560 		elt->prev = elt;
1561 		head = elt;
1562 	}
1563 	else {
1564 		elt->prev = head->prev;
1565 		head->prev->next = elt;
1566 		head->prev = elt;
1567 		elt->next = NULL;
1568 	}
1569 
1570 	return head;
1571 }
1572 
1573 bool
1574 ucl_object_todouble_safe (ucl_object_t *obj, double *target)
1575 {
1576 	if (obj == NULL || target == NULL) {
1577 		return false;
1578 	}
1579 	switch (obj->type) {
1580 	case UCL_INT:
1581 		*target = obj->value.iv; /* Probaly could cause overflow */
1582 		break;
1583 	case UCL_FLOAT:
1584 	case UCL_TIME:
1585 		*target = obj->value.dv;
1586 		break;
1587 	default:
1588 		return false;
1589 	}
1590 
1591 	return true;
1592 }
1593 
1594 double
1595 ucl_object_todouble (ucl_object_t *obj)
1596 {
1597 	double result = 0.;
1598 
1599 	ucl_object_todouble_safe (obj, &result);
1600 	return result;
1601 }
1602 
1603 bool
1604 ucl_object_toint_safe (ucl_object_t *obj, int64_t *target)
1605 {
1606 	if (obj == NULL || target == NULL) {
1607 		return false;
1608 	}
1609 	switch (obj->type) {
1610 	case UCL_INT:
1611 		*target = obj->value.iv;
1612 		break;
1613 	case UCL_FLOAT:
1614 	case UCL_TIME:
1615 		*target = obj->value.dv; /* Loosing of decimal points */
1616 		break;
1617 	default:
1618 		return false;
1619 	}
1620 
1621 	return true;
1622 }
1623 
1624 int64_t
1625 ucl_object_toint (ucl_object_t *obj)
1626 {
1627 	int64_t result = 0;
1628 
1629 	ucl_object_toint_safe (obj, &result);
1630 	return result;
1631 }
1632 
1633 bool
1634 ucl_object_toboolean_safe (ucl_object_t *obj, bool *target)
1635 {
1636 	if (obj == NULL || target == NULL) {
1637 		return false;
1638 	}
1639 	switch (obj->type) {
1640 	case UCL_BOOLEAN:
1641 		*target = (obj->value.iv == true);
1642 		break;
1643 	default:
1644 		return false;
1645 	}
1646 
1647 	return true;
1648 }
1649 
1650 bool
1651 ucl_object_toboolean (ucl_object_t *obj)
1652 {
1653 	bool result = false;
1654 
1655 	ucl_object_toboolean_safe (obj, &result);
1656 	return result;
1657 }
1658 
1659 bool
1660 ucl_object_tostring_safe (ucl_object_t *obj, const char **target)
1661 {
1662 	if (obj == NULL || target == NULL) {
1663 		return false;
1664 	}
1665 
1666 	switch (obj->type) {
1667 	case UCL_STRING:
1668 		*target = ucl_copy_value_trash (obj);
1669 		break;
1670 	default:
1671 		return false;
1672 	}
1673 
1674 	return true;
1675 }
1676 
1677 const char *
1678 ucl_object_tostring (ucl_object_t *obj)
1679 {
1680 	const char *result = NULL;
1681 
1682 	ucl_object_tostring_safe (obj, &result);
1683 	return result;
1684 }
1685 
1686 const char *
1687 ucl_object_tostring_forced (ucl_object_t *obj)
1688 {
1689 	return ucl_copy_value_trash (obj);
1690 }
1691 
1692 bool
1693 ucl_object_tolstring_safe (ucl_object_t *obj, const char **target, size_t *tlen)
1694 {
1695 	if (obj == NULL || target == NULL) {
1696 		return false;
1697 	}
1698 	switch (obj->type) {
1699 	case UCL_STRING:
1700 		*target = obj->value.sv;
1701 		if (tlen != NULL) {
1702 			*tlen = obj->len;
1703 		}
1704 		break;
1705 	default:
1706 		return false;
1707 	}
1708 
1709 	return true;
1710 }
1711 
1712 const char *
1713 ucl_object_tolstring (ucl_object_t *obj, size_t *tlen)
1714 {
1715 	const char *result = NULL;
1716 
1717 	ucl_object_tolstring_safe (obj, &result, tlen);
1718 	return result;
1719 }
1720 
1721 const char *
1722 ucl_object_key (ucl_object_t *obj)
1723 {
1724 	return ucl_copy_key_trash (obj);
1725 }
1726 
1727 const char *
1728 ucl_object_keyl (ucl_object_t *obj, size_t *len)
1729 {
1730 	if (len == NULL || obj == NULL) {
1731 		return NULL;
1732 	}
1733 	*len = obj->keylen;
1734 	return obj->key;
1735 }
1736 
1737 ucl_object_t *
1738 ucl_object_ref (ucl_object_t *obj)
1739 {
1740 	if (obj != NULL) {
1741 		obj->ref ++;
1742 	}
1743 	return obj;
1744 }
1745 
1746 void
1747 ucl_object_unref (ucl_object_t *obj)
1748 {
1749 	if (obj != NULL && --obj->ref <= 0) {
1750 		ucl_object_free (obj);
1751 	}
1752 }
1753 
1754 int
1755 ucl_object_compare (ucl_object_t *o1, ucl_object_t *o2)
1756 {
1757 	ucl_object_t *it1, *it2;
1758 	ucl_object_iter_t iter = NULL;
1759 	int ret = 0;
1760 
1761 	if (o1->type != o2->type) {
1762 		return (o1->type) - (o2->type);
1763 	}
1764 
1765 	switch (o1->type) {
1766 	case UCL_STRING:
1767 		if (o1->len == o2->len) {
1768 			ret = strcmp (ucl_object_tostring(o1), ucl_object_tostring(o2));
1769 		}
1770 		else {
1771 			ret = o1->len - o2->len;
1772 		}
1773 		break;
1774 	case UCL_FLOAT:
1775 	case UCL_INT:
1776 	case UCL_TIME:
1777 		ret = ucl_object_todouble (o1) - ucl_object_todouble (o2);
1778 		break;
1779 	case UCL_BOOLEAN:
1780 		ret = ucl_object_toboolean (o1) - ucl_object_toboolean (o2);
1781 		break;
1782 	case UCL_ARRAY:
1783 		if (o1->len == o2->len) {
1784 			it1 = o1->value.av;
1785 			it2 = o2->value.av;
1786 			/* Compare all elements in both arrays */
1787 			while (it1 != NULL && it2 != NULL) {
1788 				ret = ucl_object_compare (it1, it2);
1789 				if (ret != 0) {
1790 					break;
1791 				}
1792 				it1 = it1->next;
1793 				it2 = it2->next;
1794 			}
1795 		}
1796 		else {
1797 			ret = o1->len - o2->len;
1798 		}
1799 		break;
1800 	case UCL_OBJECT:
1801 		if (o1->len == o2->len) {
1802 			while ((it1 = ucl_iterate_object (o1, &iter, true)) != NULL) {
1803 				it2 = ucl_object_find_key (o2, ucl_object_key (it1));
1804 				if (it2 == NULL) {
1805 					ret = 1;
1806 					break;
1807 				}
1808 				ret = ucl_object_compare (it1, it2);
1809 				if (ret != 0) {
1810 					break;
1811 				}
1812 			}
1813 		}
1814 		else {
1815 			ret = o1->len - o2->len;
1816 		}
1817 		break;
1818 	default:
1819 		ret = 0;
1820 		break;
1821 	}
1822 
1823 	return ret;
1824 }
1825 
1826 void
1827 ucl_object_array_sort (ucl_object_t *ar,
1828 		int (*cmp)(ucl_object_t *o1, ucl_object_t *o2))
1829 {
1830 	if (cmp == NULL || ar == NULL || ar->type != UCL_ARRAY) {
1831 		return;
1832 	}
1833 
1834 	DL_SORT (ar->value.av, cmp);
1835 }
1836