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