]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/libucl/src/ucl_util.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / libucl / src / ucl_util.c
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 typedef void (*ucl_object_dtor) (ucl_object_t *obj);
138 static void ucl_object_free_internal (ucl_object_t *obj, bool allow_rec,
139                 ucl_object_dtor dtor);
140 static void ucl_object_dtor_unref (ucl_object_t *obj);
141
142 static void
143 ucl_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  */
159 static void
160 ucl_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
174 static void
175 ucl_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
186 static void
187 ucl_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
215 void
216 ucl_object_free (ucl_object_t *obj)
217 {
218         ucl_object_free_internal (obj, true, ucl_object_dtor_free);
219 }
220
221 size_t
222 ucl_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
326 char *
327 ucl_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
348 char *
349 ucl_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
378 UCL_EXTERN ucl_object_t*
379 ucl_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
388 UCL_EXTERN void
389 ucl_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
432 UCL_EXTERN const char *
433 ucl_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
445 UCL_EXTERN bool
446 ucl_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
480 struct ucl_curl_cbdata {
481         unsigned char *buf;
482         size_t buflen;
483 };
484
485 static size_t
486 ucl_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  */
512 static bool
513 ucl_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  */
607 static bool
608 ucl_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)
647 static inline bool
648 ucl_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  */
702 static bool
703 ucl_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  */
771 static bool
772 ucl_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  */
853 UCL_EXTERN bool
854 ucl_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  */
874 UCL_EXTERN bool
875 ucl_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
888 UCL_EXTERN bool
889 ucl_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
901 UCL_EXTERN bool
902 ucl_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
931 UCL_EXTERN bool
932 ucl_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
960 size_t
961 ucl_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
983 size_t
984 ucl_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
992 size_t
993 ucl_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
1015 ucl_object_t *
1016 ucl_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
1135 static bool
1136 ucl_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
1239 bool
1240 ucl_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
1261 bool
1262 ucl_object_delete_key (ucl_object_t *top, const char *key)
1263 {
1264         return ucl_object_delete_keyl (top, key, strlen(key));
1265 }
1266
1267 ucl_object_t*
1268 ucl_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
1286 ucl_object_t*
1287 ucl_object_pop_key (ucl_object_t *top, const char *key)
1288 {
1289         return ucl_object_pop_keyl (top, key, strlen(key));
1290 }
1291
1292 bool
1293 ucl_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
1299 bool
1300 ucl_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
1306 bool
1307 ucl_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
1313 const ucl_object_t *
1314 ucl_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
1330 const ucl_object_t *
1331 ucl_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
1339 const ucl_object_t*
1340 ucl_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
1389 const ucl_object_t *
1390 ucl_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
1442 ucl_object_t *
1443 ucl_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
1455 ucl_object_t *
1456 ucl_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
1468 ucl_type_t
1469 ucl_object_type (const ucl_object_t *obj)
1470 {
1471         return obj->type;
1472 }
1473
1474 ucl_object_t*
1475 ucl_object_fromstring (const char *str)
1476 {
1477         return ucl_object_fromstring_common (str, 0, UCL_STRING_ESCAPE);
1478 }
1479
1480 ucl_object_t *
1481 ucl_object_fromlstring (const char *str, size_t len)
1482 {
1483         return ucl_object_fromstring_common (str, len, UCL_STRING_ESCAPE);
1484 }
1485
1486 ucl_object_t *
1487 ucl_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
1500 ucl_object_t *
1501 ucl_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
1514 ucl_object_t*
1515 ucl_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
1528 bool
1529 ucl_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
1553 bool
1554 ucl_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
1579 ucl_object_t *
1580 ucl_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
1612 const ucl_object_t *
1613 ucl_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
1621 const ucl_object_t *
1622 ucl_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
1630 ucl_object_t *
1631 ucl_array_pop_last (ucl_object_t *top)
1632 {
1633         return ucl_array_delete (top, __DECONST(ucl_object_t *, ucl_array_tail (top)));
1634 }
1635
1636 ucl_object_t *
1637 ucl_array_pop_first (ucl_object_t *top)
1638 {
1639         return ucl_array_delete (top, __DECONST(ucl_object_t *, ucl_array_head (top)));
1640 }
1641
1642 const ucl_object_t *
1643 ucl_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
1663 ucl_object_t *
1664 ucl_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
1682 bool
1683 ucl_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
1703 double
1704 ucl_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
1712 bool
1713 ucl_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
1733 int64_t
1734 ucl_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
1742 bool
1743 ucl_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
1759 bool
1760 ucl_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
1768 bool
1769 ucl_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
1786 const char *
1787 ucl_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
1795 const char *
1796 ucl_object_tostring_forced (const ucl_object_t *obj)
1797 {
1798         return ucl_copy_value_trash (obj);
1799 }
1800
1801 bool
1802 ucl_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
1821 const char *
1822 ucl_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
1830 const char *
1831 ucl_object_key (const ucl_object_t *obj)
1832 {
1833         return ucl_copy_key_trash (obj);
1834 }
1835
1836 const char *
1837 ucl_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
1846 ucl_object_t *
1847 ucl_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
1862 void
1863 ucl_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
1877 int
1878 ucl_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
1949 void
1950 ucl_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 }