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