blob: a0f1b5eb3ffff12a5052f9dcd2863775624d659a [file] [log] [blame]
Radek Krejci1721c012015-07-08 12:52:33 +02001/**
2 * @file xml.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief XML data parser for libyang
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of the Company nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 */
21
22#include <assert.h>
Radek Krejci3e3affe2015-07-09 15:38:40 +020023#include <ctype.h>
Radek Krejci1721c012015-07-08 12:52:33 +020024#include <errno.h>
25#include <stdlib.h>
26#include <string.h>
Michal Vaskobe190a62015-07-13 16:14:20 +020027#include <sys/types.h>
28#include <regex.h>
Radek Krejci1721c012015-07-08 12:52:33 +020029
30#include "../libyang.h"
31#include "../common.h"
32#include "../context.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020033#include "../resolve.h"
Radek Krejci1721c012015-07-08 12:52:33 +020034#include "../xml.h"
Radek Krejciac8aac62015-07-10 15:36:35 +020035#include "../tree_internal.h"
Radek Krejcib1c12512015-08-11 11:22:04 +020036#include "../validation.h"
Radek Krejci1721c012015-07-08 12:52:33 +020037
38#define LY_NSNC "urn:ietf:params:xml:ns:netconf:base:1.0"
39
Michal Vasko9286afd2015-07-14 15:27:59 +020040/* kind == 0 - unsigned (unum used), 1 - signed (snum used), 2 - floating point (fnum used) */
41static int
Radek Krejci1574a8d2015-08-03 14:16:52 +020042validate_length_range(uint8_t kind, uint64_t unum, int64_t snum, long double fnum, struct lys_type *type,
Michal Vasko07471a52015-07-16 11:18:48 +020043 struct lyxml_elem *xml, const char *str_val, int log)
Michal Vasko9286afd2015-07-14 15:27:59 +020044{
Michal Vasko020404f2015-07-15 15:45:42 +020045 struct len_ran_intv *intv = NULL, *tmp_intv;
Michal Vaskof02e3742015-08-05 16:27:02 +020046 int ret = EXIT_FAILURE;
Michal Vasko9286afd2015-07-14 15:27:59 +020047
Michal Vasko9c1bc642015-08-05 16:25:53 +020048 if (resolve_len_ran_interval(NULL, type, 0, &intv)) {
49 return EXIT_FAILURE;
50 }
Michal Vasko020404f2015-07-15 15:45:42 +020051 if (!intv) {
Michal Vaskof02e3742015-08-05 16:27:02 +020052 return EXIT_SUCCESS;
Michal Vasko020404f2015-07-15 15:45:42 +020053 }
54
Michal Vasko9286afd2015-07-14 15:27:59 +020055 for (tmp_intv = intv; tmp_intv; tmp_intv = tmp_intv->next) {
56 if (((kind == 0) && (unum < tmp_intv->value.uval.min))
57 || ((kind == 1) && (snum < tmp_intv->value.sval.min))
58 || ((kind == 2) && (fnum < tmp_intv->value.fval.min))) {
59 break;
60 }
61
62 if (((kind == 0) && (unum >= tmp_intv->value.uval.min) && (unum <= tmp_intv->value.uval.max))
63 || ((kind == 1) && (snum >= tmp_intv->value.sval.min) && (snum <= tmp_intv->value.sval.max))
64 || ((kind == 2) && (fnum >= tmp_intv->value.fval.min) && (fnum <= tmp_intv->value.fval.max))) {
Michal Vaskof02e3742015-08-05 16:27:02 +020065 ret = EXIT_SUCCESS;
Michal Vasko9286afd2015-07-14 15:27:59 +020066 break;
67 }
68 }
69
70 while (intv) {
71 tmp_intv = intv->next;
72 free(intv);
73 intv = tmp_intv;
74 }
75
Michal Vasko07471a52015-07-16 11:18:48 +020076 if (ret && log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +020077 LOGVAL(LYE_OORVAL, LOGLINE(xml), str_val);
Michal Vasko0e60c832015-07-15 15:48:35 +020078 }
Michal Vasko9286afd2015-07-14 15:27:59 +020079 return ret;
80}
81
Michal Vaskofbf7e482015-07-14 14:49:03 +020082static int
Radek Krejci1574a8d2015-08-03 14:16:52 +020083validate_pattern(const char *str, struct lys_type *type, struct lyxml_elem *xml, const char *str_val, int log)
Michal Vaskofbf7e482015-07-14 14:49:03 +020084{
85 int i;
86 regex_t preq;
87 char *posix_regex;
88
89 assert(type->base == LY_TYPE_STRING);
90
Michal Vasko07471a52015-07-16 11:18:48 +020091 if (type->der && validate_pattern(str, &type->der->type, xml, str_val, log)) {
Michal Vaskof02e3742015-08-05 16:27:02 +020092 return EXIT_FAILURE;
Michal Vaskofbf7e482015-07-14 14:49:03 +020093 }
94
95 for (i = 0; i < type->info.str.pat_count; ++i) {
96 /*
97 * adjust the expression to a POSIX.2 equivalent
98 *
99 * http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#regexs
100 */
101 posix_regex = malloc((strlen(type->info.str.patterns[i].expr)+3) * sizeof(char));
102 posix_regex[0] = '\0';
103
104 if (strncmp(type->info.str.patterns[i].expr, ".*", 2)) {
105 strcat(posix_regex, "^");
106 }
107 strcat(posix_regex, type->info.str.patterns[i].expr);
108 if (strncmp(type->info.str.patterns[i].expr
109 + strlen(type->info.str.patterns[i].expr) - 2, ".*", 2)) {
110 strcat(posix_regex, "$");
111 }
112
113 /* must return 0, already checked during parsing */
Michal Vasko88876dc2015-08-05 09:46:40 +0200114 if (regcomp(&preq, posix_regex, REG_EXTENDED | REG_NOSUB)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200115 LOGINT;
116 return EXIT_FAILURE;
Michal Vasko88876dc2015-08-05 09:46:40 +0200117 }
Michal Vaskofbf7e482015-07-14 14:49:03 +0200118 free(posix_regex);
119
120 if (regexec(&preq, str, 0, 0, 0)) {
121 regfree(&preq);
Michal Vasko07471a52015-07-16 11:18:48 +0200122 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200123 LOGVAL(LYE_INVAL, LOGLINE(xml), str_val, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200124 }
Michal Vaskof02e3742015-08-05 16:27:02 +0200125 return EXIT_FAILURE;
Michal Vaskofbf7e482015-07-14 14:49:03 +0200126 }
127 regfree(&preq);
128 }
129
Michal Vaskof02e3742015-08-05 16:27:02 +0200130 return EXIT_SUCCESS;
Michal Vaskofbf7e482015-07-14 14:49:03 +0200131}
132
Radek Krejci76512572015-08-04 09:47:08 +0200133static struct lys_node *
134xml_data_search_schemanode(struct lyxml_elem *xml, struct lys_node *start)
Radek Krejci1721c012015-07-08 12:52:33 +0200135{
Radek Krejci76512572015-08-04 09:47:08 +0200136 struct lys_node *result, *aux;
Radek Krejci1721c012015-07-08 12:52:33 +0200137
138 LY_TREE_FOR(start, result) {
139 /* skip groupings */
Radek Krejci76512572015-08-04 09:47:08 +0200140 if (result->nodetype == LYS_GROUPING) {
Radek Krejci1721c012015-07-08 12:52:33 +0200141 continue;
142 }
143
144 /* go into cases, choices, uses */
Radek Krejci76512572015-08-04 09:47:08 +0200145 if (result->nodetype & (LYS_CHOICE | LYS_CASE | LYS_USES)) {
Radek Krejci1721c012015-07-08 12:52:33 +0200146 aux = xml_data_search_schemanode(xml, result->child);
147 if (aux) {
148 /* we have matching result */
149 return aux;
150 }
151 /* else, continue with next schema node */
152 continue;
153 }
154
155 /* match data nodes */
156 if (result->name == xml->name) {
157 /* names matches, what about namespaces? */
158 if (result->module->ns == xml->ns->value) {
159 /* we have matching result */
160 return result;
161 }
162 /* else, continue with next schema node */
163 continue;
164 }
165 }
166
167 /* no match */
168 return NULL;
169}
170
Radek Krejcie4748472015-07-08 18:00:22 +0200171static int
Michal Vasko07471a52015-07-16 11:18:48 +0200172parse_int(const char *str_val, struct lyxml_elem *xml, int64_t min, int64_t max, int base, int64_t *ret, int log)
Michal Vaskobdee69c2015-07-15 15:49:39 +0200173{
174 char *strptr;
175
176 /* convert to 64-bit integer, all the redundant characters are handled */
177 errno = 0;
178 strptr = NULL;
179 *ret = strtoll(str_val, &strptr, base);
180 if (errno || (*ret < min) || (*ret > max)) {
Michal Vasko07471a52015-07-16 11:18:48 +0200181 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200182 LOGVAL(LYE_OORVAL, LOGLINE(xml), str_val, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200183 }
Michal Vaskof02e3742015-08-05 16:27:02 +0200184 return EXIT_FAILURE;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200185 } else if (strptr && *strptr) {
186 while (isspace(*strptr)) {
187 ++strptr;
188 }
189 if (*strptr) {
Michal Vasko07471a52015-07-16 11:18:48 +0200190 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200191 LOGVAL(LYE_INVAL, LOGLINE(xml), str_val, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200192 }
Michal Vaskof02e3742015-08-05 16:27:02 +0200193 return EXIT_FAILURE;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200194 }
195 }
196
Michal Vaskof02e3742015-08-05 16:27:02 +0200197 return EXIT_SUCCESS;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200198}
199
200static int
Michal Vasko07471a52015-07-16 11:18:48 +0200201parse_uint(const char *str_val, struct lyxml_elem *xml, uint64_t max, int base, uint64_t *ret, int log)
Michal Vaskobdee69c2015-07-15 15:49:39 +0200202{
203 char *strptr;
204
205 errno = 0;
206 strptr = NULL;
207 *ret = strtoull(str_val, &strptr, base);
208 if (errno || (*ret > max)) {
Michal Vasko07471a52015-07-16 11:18:48 +0200209 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200210 LOGVAL(LYE_OORVAL, LOGLINE(xml), str_val, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200211 }
Michal Vaskof02e3742015-08-05 16:27:02 +0200212 return EXIT_FAILURE;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200213 } else if (strptr && *strptr) {
214 while (isspace(*strptr)) {
215 ++strptr;
216 }
217 if (*strptr) {
Michal Vasko07471a52015-07-16 11:18:48 +0200218 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200219 LOGVAL(LYE_INVAL, LOGLINE(xml), str_val, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200220 }
Michal Vaskof02e3742015-08-05 16:27:02 +0200221 return EXIT_FAILURE;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200222 }
223 }
224
Michal Vaskof02e3742015-08-05 16:27:02 +0200225 return EXIT_SUCCESS;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200226}
227
Radek Krejci1574a8d2015-08-03 14:16:52 +0200228static struct lys_type *
229get_next_union_type(struct lys_type *type, struct lys_type *prev_type, int *found)
Radek Krejcie4748472015-07-08 18:00:22 +0200230{
Michal Vasko07471a52015-07-16 11:18:48 +0200231 int i;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200232 struct lys_type *ret = NULL;
Michal Vasko07471a52015-07-16 11:18:48 +0200233
Michal Vasko6da1a372015-07-27 11:19:10 +0200234 for (i = 0; i < type->info.uni.count; ++i) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200235 if (type->info.uni.types[i].base == LY_TYPE_UNION) {
236 ret = get_next_union_type(&type->info.uni.types[i], prev_type, found);
Michal Vasko6da1a372015-07-27 11:19:10 +0200237 if (ret) {
Michal Vasko07471a52015-07-16 11:18:48 +0200238 break;;
239 }
240 continue;
241 }
242
243 if (!prev_type || *found) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200244 ret = &type->info.uni.types[i];
Michal Vasko07471a52015-07-16 11:18:48 +0200245 break;
246 }
247
Radek Krejci1574a8d2015-08-03 14:16:52 +0200248 if (&type->info.uni.types[i] == prev_type) {
Michal Vasko07471a52015-07-16 11:18:48 +0200249 *found = 1;
250 }
251 }
252
Michal Vasko6da1a372015-07-27 11:19:10 +0200253 if (!ret && type->der) {
254 ret = get_next_union_type(&type->der->type, prev_type, found);
255 }
256
257 return ret;
Michal Vasko07471a52015-07-16 11:18:48 +0200258}
259
Radek Krejcic5090c32015-08-12 09:46:19 +0200260static const char *
261instid_xml2json(struct ly_ctx *ctx, struct lyxml_elem *xml)
262{
263 const char *in = xml->content;
264 char *out, *aux, *prefix;
265 size_t out_size, len, size, i = 0, o = 0;
266 int start = 1, interior = 1;
267 struct lys_module *mod, *mod_prev = NULL;
268 struct lyxml_ns *ns;
269
270 out_size = strlen(in);
271 out = malloc((out_size + 1) * sizeof *out);
272
273 while (in[i]) {
274
275 /* skip whitespaces */
276 while (isspace(in[i])) {
277 i++;
278 }
279
280 if (start) {
281 /* leading '/' character */
282 if (start == 1 && in[i] != '/') {
283 LOGVAL(LYE_INCHAR, LOGLINE(xml), in[i], &in[i]);
284 return NULL;
285 }
286
287 /* check the output buffer size */
288 if (out_size == o) {
289 out_size += 16; /* just add some size */
290 aux = realloc(out, out_size + 1);
291 if (!aux) {
292 free(out);
293 LOGMEM;
294 return NULL;
295 }
296 out = aux;
297 }
298
299 out[o++] = in[i++];
300 start = 0;
301 continue;
302 } else {
303 /* translate the node identifier */
304 /* prefix */
305 aux = strchr(&in[i], ':');
306 if (aux) {
307 /* interior segment */
308 len = aux - &in[i];
309 prefix = strndup(&in[i], len);
310 i += len + 1; /* move after ':' */
311 } else {
312 /* missing prefix -> invalid instance-identifier */
313 LOGVAL(LYE_INVAL, LOGLINE(xml), xml->content, xml->name);
314 free(out);
315 return NULL;
316 }
317 ns = lyxml_get_ns(xml, prefix);
318 free(prefix);
319 mod = ly_ctx_get_module_by_ns(ctx, ns->value, NULL);
320
321 /* node name */
322 aux = strpbrk(&in[i], "/[=");
323 if (aux) {
324 /* interior segment */
325 len = aux - &in[i];
326 } else {
327 /* end segment */
328 interior = 0;
329 len = strlen(&in[i]);
330 }
331
332 /* check the output buffer size */
333 if (!mod_prev || (mod != mod_prev)) {
334 /* prefix + ':' + name to print + '/' */
335 size = o + len + 1 + strlen(mod->name) + interior;
336 } else {
337 /* name to print + '/' */
338 size = o + len + interior;
339 }
340 if (out_size <= size) {
341 /* extend to fit the needed size */
342 out_size = size;
343 aux = realloc(out, out_size + 1);
344 if (!aux) {
345 free(out);
346 LOGMEM;
347 return NULL;
348 }
349 out = aux;
350 }
351
352 if (!mod_prev || (mod != mod_prev)) {
353 mod_prev = mod;
354 size = strlen(mod->name);
355 memcpy(&out[o], mod->name, size);
356 o += size;
357 out[o++] = ':';
358 }
359 memcpy(&out[o], &in[i], len);
360 o += len;
361 i += len;
362
363 if (in[i] == '=') {
364 /* we are in the predicate on the value, so just copy data */
365 aux = strchr(&in[i], ']');
366 if (aux) {
367 len = aux - &in[i] + 1; /* include ] */
368
369 /* check the output buffer size */
370 size = o + len + 1;
371 if (out_size <= size) {
372 out_size = size; /* just add some size */
373 aux = realloc(out, out_size + 1);
374 if (!aux) {
375 free(out);
376 LOGMEM;
377 return NULL;
378 }
379 out = aux;
380 }
381
382 memcpy(&out[o], &in[i], len);
383 o += len;
384 i += len;
385 } else {
386 /* missing closing ] of predicate -> invalid instance-identifier */
387 LOGVAL(LYE_INVAL, LOGLINE(xml), xml->content, xml->name);
388 free(out);
389 return NULL;
390 }
391 }
392 start = 2;
393 }
394 }
395
396 /* terminating NULL byte */
397 /* check the output buffer size */
398 if (out_size < o) {
399 out_size += 1; /* just add some size */
400 aux = realloc(out, out_size + 1);
401 if (!aux) {
402 free(out);
403 LOGMEM;
404 return NULL;
405 }
406 out = aux;
407 }
408 out[o] = '\0';
409
410 return lydict_insert_zc(ctx, out);
411}
412
Michal Vasko07471a52015-07-16 11:18:48 +0200413static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200414_xml_get_value(struct lyd_node *node, struct lys_type *node_type, struct lyxml_elem *xml,
Radek Krejci25b9fd32015-08-10 15:06:07 +0200415 int options, struct unres_data **unres, int log)
Michal Vasko07471a52015-07-16 11:18:48 +0200416{
417 #define DECSIZE 21
Radek Krejci3e3affe2015-07-09 15:38:40 +0200418 struct lyd_node_leaf *leaf = (struct lyd_node_leaf *)node;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200419 struct lys_type *type;
Radek Krejciac8aac62015-07-10 15:36:35 +0200420 struct lyxml_ns *ns;
Radek Krejci7511f402015-07-10 09:56:30 +0200421 char dec[DECSIZE];
Michal Vaskofbf7e482015-07-14 14:49:03 +0200422 char *strptr;
Radek Krejciac8aac62015-07-10 15:36:35 +0200423 const char *name;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200424 int64_t num;
425 uint64_t unum;
Radek Krejci3e3affe2015-07-09 15:38:40 +0200426 int len;
Radek Krejci7511f402015-07-10 09:56:30 +0200427 int c, i, j, d;
Radek Krejci3e3affe2015-07-09 15:38:40 +0200428 int found;
Michal Vaskof02e3742015-08-05 16:27:02 +0200429 struct unres_data *new_unres;
Radek Krejci5a988152015-07-15 11:16:26 +0200430
431 leaf->value_str = xml->content;
432 xml->content = NULL;
Radek Krejcie4748472015-07-08 18:00:22 +0200433
Radek Krejcie3c33142015-08-10 15:04:36 +0200434 /* will be change in case of union */
435 leaf->value_type = node_type->base;
436
Radek Krejcie2cf7c12015-08-12 10:24:05 +0200437 if ((options & LYD_OPT_FILTER) && !leaf->value_str) {
438 /* no value in filter (selection) node -> nothing more is needed */
439 return EXIT_SUCCESS;
440 }
441
Michal Vasko07471a52015-07-16 11:18:48 +0200442 switch (node_type->base) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200443 case LY_TYPE_BINARY:
Radek Krejci5a988152015-07-15 11:16:26 +0200444 leaf->value.binary = leaf->value_str;
Radek Krejci3e3affe2015-07-09 15:38:40 +0200445
Michal Vasko07471a52015-07-16 11:18:48 +0200446 if (node_type->info.binary.length
447 && validate_length_range(0, strlen(leaf->value.binary), 0, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko0e60c832015-07-15 15:48:35 +0200448 return EXIT_FAILURE;
Radek Krejcie4748472015-07-08 18:00:22 +0200449 }
450 break;
451
Radek Krejci3e3affe2015-07-09 15:38:40 +0200452 case LY_TYPE_BITS:
Radek Krejci3e3affe2015-07-09 15:38:40 +0200453 /* locate bits structure with the bits definitions */
Michal Vasko07471a52015-07-16 11:18:48 +0200454 for (type = node_type; type->der->type.der; type = &type->der->type);
Radek Krejci3e3affe2015-07-09 15:38:40 +0200455
456 /* allocate the array of pointers to bits definition */
457 leaf->value.bit = calloc(type->info.bits.count, sizeof *leaf->value.bit);
458
Radek Krejci5a988152015-07-15 11:16:26 +0200459 if (!leaf->value_str) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200460 /* no bits set */
461 break;
462 }
463
464 c = 0;
465 i = 0;
Radek Krejci5a988152015-07-15 11:16:26 +0200466 while (leaf->value_str[c]) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200467 /* skip leading whitespaces */
Radek Krejci5a988152015-07-15 11:16:26 +0200468 while(isspace(leaf->value_str[c])) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200469 c++;
470 }
471
472 /* get the length of the bit identifier */
Radek Krejci5a988152015-07-15 11:16:26 +0200473 for (len = 0; leaf->value_str[c] && !isspace(leaf->value_str[c]); c++, len++);
Radek Krejci3e3affe2015-07-09 15:38:40 +0200474
475 /* go back to the beginning of the identifier */
476 c = c - len;
477
478 /* find bit definition, identifiers appear ordered by their posititon */
479 for (found = 0; i < type->info.bits.count; i++) {
Radek Krejci5a988152015-07-15 11:16:26 +0200480 if (!strncmp(type->info.bits.bit[i].name, &leaf->value_str[c], len)
Radek Krejci3e3affe2015-07-09 15:38:40 +0200481 && !type->info.bits.bit[i].name[len]) {
482 /* we have match, store the pointer */
483 leaf->value.bit[i] = &type->info.bits.bit[i];
484
485 /* stop searching */
486 i++;
487 found = 1;
488 break;
489 }
490 }
491
492 if (!found) {
493 /* referenced bit value does not exists */
Michal Vasko07471a52015-07-16 11:18:48 +0200494 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200495 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200496 }
Radek Krejci3e3affe2015-07-09 15:38:40 +0200497 return EXIT_FAILURE;
498 }
499
500 c = c + len;
501 }
502
503 break;
504
Radek Krejcib7384642015-07-09 16:08:45 +0200505 case LY_TYPE_BOOL:
Radek Krejci5a988152015-07-15 11:16:26 +0200506 if (!strcmp(leaf->value_str, "true")) {
Radek Krejcib7384642015-07-09 16:08:45 +0200507 leaf->value.bool = 1;
508 } /* else false, so keep it zero */
509 break;
510
Radek Krejci7511f402015-07-10 09:56:30 +0200511 case LY_TYPE_DEC64:
512 /* locate dec64 structure with the fraction-digits value */
Michal Vasko07471a52015-07-16 11:18:48 +0200513 for (type = node_type; type->der->type.der; type = &type->der->type);
Radek Krejci7511f402015-07-10 09:56:30 +0200514
Radek Krejci5a988152015-07-15 11:16:26 +0200515 for (c = 0; isspace(leaf->value_str[c]); c++);
516 for (len = 0; leaf->value_str[c] && !isspace(leaf->value_str[c]); c++, len++);
Radek Krejci7511f402015-07-10 09:56:30 +0200517 c = c - len;
518 if (len > DECSIZE) {
519 /* too long */
Michal Vasko07471a52015-07-16 11:18:48 +0200520 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200521 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200522 }
Radek Krejci7511f402015-07-10 09:56:30 +0200523 return EXIT_FAILURE;
524 }
525
526 /* normalize the number */
527 dec[0] = '\0';
528 for (i = j = d = found = 0; i < DECSIZE; i++) {
Radek Krejci5a988152015-07-15 11:16:26 +0200529 if (leaf->value_str[c + i] == '.') {
Radek Krejci7511f402015-07-10 09:56:30 +0200530 found = 1;
531 j = type->info.dec64.dig;
532 i--;
533 c++;
534 continue;
535 }
Radek Krejci5a988152015-07-15 11:16:26 +0200536 if (leaf->value_str[c + i] == '\0') {
Radek Krejci7511f402015-07-10 09:56:30 +0200537 c--;
538 if (!found) {
539 j = type->info.dec64.dig;
540 found = 1;
541 }
542 if (!j) {
543 dec[i] = '\0';
544 break;
545 }
546 d++;
547 if (d > DECSIZE - 2) {
Michal Vasko07471a52015-07-16 11:18:48 +0200548 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200549 LOGVAL(LYE_OORVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200550 }
Radek Krejci7511f402015-07-10 09:56:30 +0200551 return EXIT_FAILURE;
552 }
553 dec[i] = '0';
554 } else {
Radek Krejci5a988152015-07-15 11:16:26 +0200555 if (!isdigit(leaf->value_str[c + i])) {
556 if (i || leaf->value_str[c] != '-') {
Michal Vasko07471a52015-07-16 11:18:48 +0200557 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200558 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200559 }
Radek Krejci7511f402015-07-10 09:56:30 +0200560 return EXIT_FAILURE;
561 }
562 } else {
563 d++;
564 }
565 if (d > DECSIZE - 2 || (found && !j)) {
Michal Vasko07471a52015-07-16 11:18:48 +0200566 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200567 LOGVAL(LYE_OORVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200568 }
Radek Krejci7511f402015-07-10 09:56:30 +0200569 return EXIT_FAILURE;
570 }
Radek Krejci5a988152015-07-15 11:16:26 +0200571 dec[i] = leaf->value_str[c + i];
Radek Krejci7511f402015-07-10 09:56:30 +0200572 }
573 if (j) {
574 j--;
575 }
576 }
577
Michal Vasko07471a52015-07-16 11:18:48 +0200578 if (parse_int(dec, xml, -9223372036854775807L - 1L, 9223372036854775807L, 10, &num, log)
579 || validate_length_range(2, 0, 0, ((long double)num)/(1 << type->info.dec64.dig), node_type, xml, leaf->value_str, log)) {
Radek Krejci7511f402015-07-10 09:56:30 +0200580 return EXIT_FAILURE;
581 }
Michal Vaskobdee69c2015-07-15 15:49:39 +0200582 leaf->value.dec64 = num;
Radek Krejci7511f402015-07-10 09:56:30 +0200583 break;
584
Radek Krejcibce73742015-07-10 12:46:06 +0200585 case LY_TYPE_EMPTY:
586 /* just check that it is empty */
Radek Krejci5a988152015-07-15 11:16:26 +0200587 if (leaf->value_str && leaf->value_str[0]) {
Michal Vasko07471a52015-07-16 11:18:48 +0200588 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200589 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200590 }
Radek Krejcibce73742015-07-10 12:46:06 +0200591 return EXIT_FAILURE;
592 }
593 break;
594
Radek Krejci5b315a92015-07-10 13:18:45 +0200595 case LY_TYPE_ENUM:
Radek Krejci5a988152015-07-15 11:16:26 +0200596 if (!leaf->value_str) {
Michal Vasko07471a52015-07-16 11:18:48 +0200597 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200598 LOGVAL(LYE_INVAL, LOGLINE(xml), "", xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200599 }
Radek Krejci5b315a92015-07-10 13:18:45 +0200600 return EXIT_FAILURE;
601 }
602
603 /* locate enums structure with the enumeration definitions */
Michal Vasko07471a52015-07-16 11:18:48 +0200604 for (type = node_type; type->der->type.der; type = &type->der->type);
Radek Krejci5b315a92015-07-10 13:18:45 +0200605
606 /* find matching enumeration value */
607 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200608 if (!strcmp(leaf->value_str, type->info.enums.enm[i].name)) {
Radek Krejci5b315a92015-07-10 13:18:45 +0200609 /* we have match, store pointer to the definition */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200610 leaf->value.enm = &type->info.enums.enm[i];
Radek Krejci5b315a92015-07-10 13:18:45 +0200611 break;
612 }
613 }
614
615 if (!leaf->value.enm) {
Michal Vasko07471a52015-07-16 11:18:48 +0200616 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200617 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200618 }
Radek Krejci5b315a92015-07-10 13:18:45 +0200619 return EXIT_FAILURE;
620 }
621
622 break;
623
Radek Krejciac8aac62015-07-10 15:36:35 +0200624 case LY_TYPE_IDENT:
Radek Krejci5a988152015-07-15 11:16:26 +0200625 if ((strptr = strchr(leaf->value_str, ':'))) {
626 len = strptr - leaf->value_str;
Radek Krejciac8aac62015-07-10 15:36:35 +0200627 if (!len) {
Michal Vasko07471a52015-07-16 11:18:48 +0200628 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200629 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200630 }
Radek Krejciac8aac62015-07-10 15:36:35 +0200631 return EXIT_FAILURE;
632 }
Radek Krejci5a988152015-07-15 11:16:26 +0200633 strptr = strndup(leaf->value_str, len);
Radek Krejciac8aac62015-07-10 15:36:35 +0200634 }
635 ns = lyxml_get_ns(xml, strptr);
636 if (!ns) {
Michal Vasko07471a52015-07-16 11:18:48 +0200637 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200638 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200639 }
Radek Krejciac8aac62015-07-10 15:36:35 +0200640 return EXIT_FAILURE;
641 }
642 if (strptr) {
643 free(strptr);
Radek Krejci5a988152015-07-15 11:16:26 +0200644 name = leaf->value_str + len + 1;
Radek Krejciac8aac62015-07-10 15:36:35 +0200645 } else {
Radek Krejci5a988152015-07-15 11:16:26 +0200646 name = leaf->value_str;
Radek Krejciac8aac62015-07-10 15:36:35 +0200647 }
648
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200649 leaf->value.ident = resolve_identityref(node_type->info.ident.ref, name, ns->value);
Radek Krejciac8aac62015-07-10 15:36:35 +0200650 if (!leaf->value.ident) {
Michal Vasko07471a52015-07-16 11:18:48 +0200651 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200652 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200653 }
Radek Krejciac8aac62015-07-10 15:36:35 +0200654 return EXIT_FAILURE;
655 }
656 break;
657
Michal Vasko07471a52015-07-16 11:18:48 +0200658 case LY_TYPE_INST:
Michal Vasko493bea72015-07-16 16:08:12 +0200659 if (!leaf->value_str) {
660 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200661 LOGVAL(LYE_INVAL, LOGLINE(xml), "", xml->name);
Michal Vasko493bea72015-07-16 16:08:12 +0200662 }
663 return EXIT_FAILURE;
664 }
665
Radek Krejcic5090c32015-08-12 09:46:19 +0200666 /* convert the path from the XML form using XML namespaces into the JSON format
667 * using module names as namespaces
668 */
669 xml->content = leaf->value_str;
670 leaf->value_str = instid_xml2json(node->schema->module->ctx, xml);
671 lydict_remove(node->schema->module->ctx, xml->content);
672 xml->content = NULL;
673 if (!leaf->value_str) {
674 return EXIT_FAILURE;
675 }
676
Radek Krejcib1c12512015-08-11 11:22:04 +0200677 if (options & (LYD_OPT_EDIT | LYD_OPT_FILTER)) {
678 leaf->value_type |= LY_TYPE_INST_UNRES;
679 } else {
680 /* validity checking is performed later, right now the data tree
681 * is not complete, so many instanceids cannot be resolved
682 */
683 /* remember the leaf for later checking */
684 new_unres = malloc(sizeof *new_unres);
685 new_unres->is_leafref = 0;
686 new_unres->dnode = node;
687 new_unres->next = *unres;
688 new_unres->line = LOGLINE(xml);
689 *unres = new_unres;
690 }
Michal Vasko07471a52015-07-16 11:18:48 +0200691 break;
692
Radek Krejci5a988152015-07-15 11:16:26 +0200693 case LY_TYPE_LEAFREF:
694 if (!leaf->value_str) {
Michal Vasko07471a52015-07-16 11:18:48 +0200695 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200696 LOGVAL(LYE_INVAL, LOGLINE(xml), "", xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200697 }
Radek Krejci5a988152015-07-15 11:16:26 +0200698 return EXIT_FAILURE;
699 }
700
Radek Krejcib1c12512015-08-11 11:22:04 +0200701 if (options & (LYD_OPT_EDIT | LYD_OPT_FILTER)) {
702 do {
703 type = &((struct lys_node_leaf *)leaf->schema)->type.info.lref.target->type;
704 } while (type->base == LY_TYPE_LEAFREF);
705 leaf->value_type = type->base | LY_TYPE_LEAFREF_UNRES;
706 } else {
707 /* validity checking is performed later, right now the data tree
708 * is not complete, so many leafrefs cannot be resolved
709 */
710 /* remember the leaf for later checking */
711 new_unres = malloc(sizeof *new_unres);
712 new_unres->is_leafref = 1;
713 new_unres->dnode = node;
714 new_unres->next = *unres;
715 new_unres->line = LOGLINE(xml);
716 *unres = new_unres;
717 }
Radek Krejci5a988152015-07-15 11:16:26 +0200718 break;
719
Radek Krejci3e3affe2015-07-09 15:38:40 +0200720 case LY_TYPE_STRING:
Radek Krejci5a988152015-07-15 11:16:26 +0200721 leaf->value.string = leaf->value_str;
Radek Krejci3e3affe2015-07-09 15:38:40 +0200722
Michal Vasko07471a52015-07-16 11:18:48 +0200723 if (node_type->info.str.length
724 && validate_length_range(0, strlen(leaf->value.string), 0, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko0e60c832015-07-15 15:48:35 +0200725 return EXIT_FAILURE;
Radek Krejcie4748472015-07-08 18:00:22 +0200726 }
727
Michal Vasko07471a52015-07-16 11:18:48 +0200728 if (node_type->info.str.patterns
729 && validate_pattern(leaf->value.string, node_type, xml, leaf->value_str, log)) {
Michal Vasko0e60c832015-07-15 15:48:35 +0200730 return EXIT_FAILURE;
Radek Krejcie4748472015-07-08 18:00:22 +0200731 }
732 break;
733
Michal Vasko58110162015-07-15 15:50:16 +0200734 case LY_TYPE_UNION:
Michal Vasko07471a52015-07-16 11:18:48 +0200735 found = 0;
Michal Vasko6da1a372015-07-27 11:19:10 +0200736 type = get_next_union_type(node_type, NULL, &found);
737 for (; type; found = 0, type = get_next_union_type(node_type, type, &found)) {
Michal Vasko07471a52015-07-16 11:18:48 +0200738 xml->content = leaf->value_str;
Radek Krejci25b9fd32015-08-10 15:06:07 +0200739 if (!_xml_get_value(node, type, xml, options, unres, 0)) {
Michal Vasko07471a52015-07-16 11:18:48 +0200740 leaf->value_type = type->base;
741 break;
742 }
743 }
744
745 if (!type) {
746 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200747 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200748 }
749 return EXIT_FAILURE;
750 }
Michal Vasko58110162015-07-15 15:50:16 +0200751 break;
752
753 case LY_TYPE_INT8:
Michal Vasko07471a52015-07-16 11:18:48 +0200754 if (parse_int(leaf->value_str, xml, -128, 127, 0, &num, log)
755 || validate_length_range(1, 0, num, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko58110162015-07-15 15:50:16 +0200756 return EXIT_FAILURE;
757 }
758 leaf->value.int8 = num;
759 break;
760
761 case LY_TYPE_INT16:
Michal Vasko07471a52015-07-16 11:18:48 +0200762 if (parse_int(leaf->value_str, xml, -32768, 32767, 0, &num, log)
763 || validate_length_range(1, 0, num, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko58110162015-07-15 15:50:16 +0200764 return EXIT_FAILURE;
765 }
766 leaf->value.int16 = num;
767 break;
768
769 case LY_TYPE_INT32:
Michal Vasko07471a52015-07-16 11:18:48 +0200770 if (parse_int(leaf->value_str, xml, -2147483648, 2147483647, 0, &num, log)
771 || validate_length_range(1, 0, num, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko58110162015-07-15 15:50:16 +0200772 return EXIT_FAILURE;
773 }
774 leaf->value.int32 = num;
775 break;
776
777 case LY_TYPE_INT64:
Michal Vasko07471a52015-07-16 11:18:48 +0200778 if (parse_int(leaf->value_str, xml, -9223372036854775807L - 1L, 9223372036854775807L, 0, &num, log)
779 || validate_length_range(1, 0, num, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko58110162015-07-15 15:50:16 +0200780 return EXIT_FAILURE;
781 }
782 leaf->value.int64 = num;
783 break;
784
785 case LY_TYPE_UINT8:
Michal Vasko07471a52015-07-16 11:18:48 +0200786 if (parse_uint(leaf->value_str, xml, 255, 0, &unum, log)
787 || validate_length_range(0, unum, 0, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko58110162015-07-15 15:50:16 +0200788 return EXIT_FAILURE;
789 }
790 leaf->value.uint8 = unum;
791 break;
792
793 case LY_TYPE_UINT16:
Michal Vasko07471a52015-07-16 11:18:48 +0200794 if (parse_uint(leaf->value_str, xml, 65535, 0, &unum, log)
795 || validate_length_range(0, unum, 0, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko58110162015-07-15 15:50:16 +0200796 return EXIT_FAILURE;
797 }
798 leaf->value.uint16 = unum;
799 break;
800
801 case LY_TYPE_UINT32:
Michal Vasko07471a52015-07-16 11:18:48 +0200802 if (parse_uint(leaf->value_str, xml, 4294967295, 0, &unum, log)
803 || validate_length_range(0, unum, 0, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko58110162015-07-15 15:50:16 +0200804 return EXIT_FAILURE;
805 }
806 leaf->value.uint32 = unum;
807 break;
808
809 case LY_TYPE_UINT64:
Michal Vasko07471a52015-07-16 11:18:48 +0200810 if (parse_uint(leaf->value_str, xml, 18446744073709551615UL, 0, &unum, log)
811 || validate_length_range(0, unum, 0, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko58110162015-07-15 15:50:16 +0200812 return EXIT_FAILURE;
813 }
814 leaf->value.uint64 = unum;
815 break;
816
Radek Krejcie4748472015-07-08 18:00:22 +0200817 default:
Michal Vasko493bea72015-07-16 16:08:12 +0200818 return EXIT_FAILURE;
Radek Krejcie4748472015-07-08 18:00:22 +0200819 }
820
821 return EXIT_SUCCESS;
822}
823
Michal Vasko07471a52015-07-16 11:18:48 +0200824static int
Radek Krejci25b9fd32015-08-10 15:06:07 +0200825xml_get_value(struct lyd_node *node, struct lyxml_elem *xml, int options, struct unres_data **unres)
Michal Vasko07471a52015-07-16 11:18:48 +0200826{
Radek Krejci25b9fd32015-08-10 15:06:07 +0200827 return _xml_get_value(node, &((struct lys_node_leaf *)node->schema)->type, xml, options, unres, 1);
Michal Vasko07471a52015-07-16 11:18:48 +0200828}
829
Radek Krejci1721c012015-07-08 12:52:33 +0200830struct lyd_node *
Michal Vasko493bea72015-07-16 16:08:12 +0200831xml_parse_data(struct ly_ctx *ctx, struct lyxml_elem *xml, struct lyd_node *parent, struct lyd_node *prev,
Radek Krejci25b9fd32015-08-10 15:06:07 +0200832 int options, struct unres_data **unres)
Radek Krejci1721c012015-07-08 12:52:33 +0200833{
Radek Krejci25b9fd32015-08-10 15:06:07 +0200834 struct lyd_node *result = NULL, *aux;
Radek Krejci76512572015-08-04 09:47:08 +0200835 struct lys_node *schema = NULL;
Michal Vaskoab8e4402015-07-17 12:54:28 +0200836 int i, havechildren;
Radek Krejci1721c012015-07-08 12:52:33 +0200837
838 if (!xml) {
839 return NULL;
840 }
841 if (!xml->ns || !xml->ns->value) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200842 LOGVAL(LYE_XML_MISS, LOGLINE(xml), "element's", "namespace");
Radek Krejci1721c012015-07-08 12:52:33 +0200843 return NULL;
844 }
845
846 /* find schema node */
847 if (!parent) {
848 /* starting in root */
849 for (i = 0; i < ctx->models.used; i++) {
850 /* match data model based on namespace */
851 if (ctx->models.list[i]->ns == xml->ns->value) {
852 /* get the proper schema node */
853 LY_TREE_FOR(ctx->models.list[i]->data, schema) {
854 if (schema->name == xml->name) {
855 break;
856 }
857 }
858 break;
859 }
860 }
861 } else {
862 /* parsing some internal node, we start with parent's schema pointer */
863 schema = xml_data_search_schemanode(xml, parent->schema->child);
864 }
865 if (!schema) {
Radek Krejci25b9fd32015-08-10 15:06:07 +0200866 if ((options & LYD_OPT_STRICT) || ly_ctx_get_module_by_ns(ctx, xml->ns->value, NULL)) {
867 LOGVAL(LYE_INELEM, LOGLINE(xml), xml->name);
868 return NULL;
869 } else {
870 goto siblings;
871 }
Radek Krejci1721c012015-07-08 12:52:33 +0200872 }
873
Radek Krejcib9930252015-07-08 15:47:45 +0200874 switch (schema->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +0200875 case LYS_CONTAINER:
Michal Vaskoab8e4402015-07-17 12:54:28 +0200876 result = calloc(1, sizeof *result);
877 havechildren = 1;
Radek Krejcib9930252015-07-08 15:47:45 +0200878 break;
Radek Krejci76512572015-08-04 09:47:08 +0200879 case LYS_LEAF:
Radek Krejcie4748472015-07-08 18:00:22 +0200880 result = calloc(1, sizeof(struct lyd_node_leaf));
881 havechildren = 0;
882 break;
Radek Krejci76512572015-08-04 09:47:08 +0200883 case LYS_LEAFLIST:
Radek Krejcie4748472015-07-08 18:00:22 +0200884 result = calloc(1, sizeof(struct lyd_node_leaflist));
885 havechildren = 0;
886 break;
Radek Krejci76512572015-08-04 09:47:08 +0200887 case LYS_LIST:
Michal Vaskoab8e4402015-07-17 12:54:28 +0200888 result = calloc(1, sizeof(struct lyd_node_list));
889 havechildren = 1;
890 break;
Radek Krejci76512572015-08-04 09:47:08 +0200891 case LYS_ANYXML:
Michal Vaskoab8e4402015-07-17 12:54:28 +0200892 result = calloc(1, sizeof(struct lyd_node_anyxml));
893 havechildren = 0;
894 break;
Radek Krejcib9930252015-07-08 15:47:45 +0200895 default:
Michal Vasko0c888fd2015-08-11 15:54:08 +0200896 LOGINT;
Michal Vaskoab8e4402015-07-17 12:54:28 +0200897 return NULL;
Radek Krejcib9930252015-07-08 15:47:45 +0200898 }
Radek Krejci1721c012015-07-08 12:52:33 +0200899 result->parent = parent;
Radek Krejcib9930252015-07-08 15:47:45 +0200900 result->prev = prev;
Radek Krejci1721c012015-07-08 12:52:33 +0200901 result->schema = schema;
902
Radek Krejci88daf822015-08-10 13:58:16 +0200903 /* check number of instances for non-list nodes */
Radek Krejcib6772142015-08-12 10:16:44 +0200904 if (!(options & LYD_OPT_FILTER) && (schema->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_ANYXML))) {
Radek Krejci88daf822015-08-10 13:58:16 +0200905 for (aux = result->prev; aux; aux = aux->prev) {
906 if (aux->schema == schema) {
907 LOGVAL(LYE_TOOMANY, LOGLINE(xml), xml->name, xml->parent ? xml->parent->name : "data tree");
908 goto error;
909 }
910 }
911 }
912
Radek Krejcib9930252015-07-08 15:47:45 +0200913 /* type specific processing */
Radek Krejci76512572015-08-04 09:47:08 +0200914 if (schema->nodetype == LYS_LIST) {
Radek Krejcib9930252015-07-08 15:47:45 +0200915 /* pointers to next and previous instances of the same list */
916 for (aux = result->prev; aux; aux = aux->prev) {
917 if (aux->schema == result->schema) {
918 /* instances of the same list */
919 ((struct lyd_node_list *)aux)->lnext = (struct lyd_node_list *)result;
920 ((struct lyd_node_list *)result)->lprev = (struct lyd_node_list *)aux;
921 break;
922 }
923 }
Radek Krejci76512572015-08-04 09:47:08 +0200924 } else if (schema->nodetype == LYS_LEAF) {
Radek Krejcie4748472015-07-08 18:00:22 +0200925 /* type detection and assigning the value */
Radek Krejci25b9fd32015-08-10 15:06:07 +0200926 if (xml_get_value(result, xml, options, unres)) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200927 goto error;
928 }
Radek Krejci76512572015-08-04 09:47:08 +0200929 } else if (schema->nodetype == LYS_LEAFLIST) {
Radek Krejcie4748472015-07-08 18:00:22 +0200930 /* type detection and assigning the value */
Radek Krejci25b9fd32015-08-10 15:06:07 +0200931 if (xml_get_value(result, xml, options, unres)) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200932 goto error;
933 }
Radek Krejcie4748472015-07-08 18:00:22 +0200934
935 /* pointers to next and previous instances of the same leaflist */
936 for (aux = result->prev; aux; aux = aux->prev) {
937 if (aux->schema == result->schema) {
938 /* instances of the same list */
939 ((struct lyd_node_leaflist *)aux)->lnext = (struct lyd_node_leaflist *)result;
940 ((struct lyd_node_leaflist *)result)->lprev = (struct lyd_node_leaflist *)aux;
941 break;
942 }
943 }
Radek Krejci76512572015-08-04 09:47:08 +0200944 } else if (schema->nodetype == LYS_ANYXML) {
Michal Vaskoab8e4402015-07-17 12:54:28 +0200945 ((struct lyd_node_anyxml *)result)->value = xml;
946 lyxml_unlink_elem(xml);
Radek Krejcib9930252015-07-08 15:47:45 +0200947 }
948
Radek Krejci1721c012015-07-08 12:52:33 +0200949 /* process children */
Radek Krejcie4748472015-07-08 18:00:22 +0200950 if (havechildren && xml->child) {
Radek Krejci25b9fd32015-08-10 15:06:07 +0200951 result->child = xml_parse_data(ctx, xml->child, result, NULL, options, unres);
952 if (ly_errno) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200953 goto error;
Radek Krejci1721c012015-07-08 12:52:33 +0200954 }
Radek Krejci1721c012015-07-08 12:52:33 +0200955 }
956
Radek Krejcib1c12512015-08-11 11:22:04 +0200957 /* various validation checks */
958 if (schema->nodetype == LYS_LIST && !(options & LYD_OPT_FILTER)) {
959 /* check presence of all keys in case of list */
960 if (lyv_keys_present((struct lyd_node_list *)result)) {
961 /* key not found in the data */
962 LOGVAL(LYE_MISSELEM, LOGLINE(xml), ((struct lys_node_list * )schema)->keys[i]->name, schema->name);
963 goto error;
964 }
965 }
966
967
Radek Krejci25b9fd32015-08-10 15:06:07 +0200968siblings:
Radek Krejci1721c012015-07-08 12:52:33 +0200969 /* process siblings */
970 if (xml->next) {
Radek Krejci25b9fd32015-08-10 15:06:07 +0200971 if (result) {
972 result->next = xml_parse_data(ctx, xml->next, parent, result, options, unres);
973 } else {
974 result = xml_parse_data(ctx, xml->next, parent, prev, options, unres);
975 }
976 if (ly_errno) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200977 goto error;
Radek Krejci1721c012015-07-08 12:52:33 +0200978 }
Radek Krejci1721c012015-07-08 12:52:33 +0200979 }
980
Radek Krejcib9930252015-07-08 15:47:45 +0200981 /* fix the "last" pointer */
Radek Krejci25b9fd32015-08-10 15:06:07 +0200982 if (result && !result->prev) {
Radek Krejcib9930252015-07-08 15:47:45 +0200983 for (aux = result; aux->next; aux = aux->next);
984 result->prev = aux;
985 }
Radek Krejci1721c012015-07-08 12:52:33 +0200986 return result;
Radek Krejci3e3affe2015-07-09 15:38:40 +0200987
988error:
989
Radek Krejci25b9fd32015-08-10 15:06:07 +0200990 if (result) {
991 result->next = NULL;
992 result->parent = NULL;
993 result->prev = result;
994 lyd_free(result);
Radek Krejci7511f402015-07-10 09:56:30 +0200995 }
Radek Krejci3e3affe2015-07-09 15:38:40 +0200996
997 return NULL;
Radek Krejci1721c012015-07-08 12:52:33 +0200998}
999
Radek Krejci5a988152015-07-15 11:16:26 +02001000static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001001check_unres(struct unres_data **list)
Radek Krejci5a988152015-07-15 11:16:26 +02001002{
Radek Krejci5a988152015-07-15 11:16:26 +02001003 struct lyd_node_leaf *leaf;
Radek Krejcib8048692015-08-05 13:36:34 +02001004 struct lys_node_leaf *sleaf;
Michal Vaskof02e3742015-08-05 16:27:02 +02001005 struct unres_data *item, *refset = NULL, *ref;
Radek Krejci5a988152015-07-15 11:16:26 +02001006
Michal Vasko493bea72015-07-16 16:08:12 +02001007 while (*list) {
Michal Vasko8ed75302015-07-17 11:05:14 +02001008 leaf = (struct lyd_node_leaf *)(*list)->dnode;
Radek Krejcib8048692015-08-05 13:36:34 +02001009 sleaf = (struct lys_node_leaf *)(*list)->dnode->schema;
Michal Vasko8ed75302015-07-17 11:05:14 +02001010
Radek Krejci5a988152015-07-15 11:16:26 +02001011 /* resolve path and create a set of possible leafrefs (we need their values) */
Michal Vasko493bea72015-07-16 16:08:12 +02001012 if ((*list)->is_leafref) {
Michal Vasko1f76a282015-08-04 16:16:53 +02001013 if (resolve_path_arg_data(*list, sleaf->type.info.lref.path, &refset)) {
Michal Vasko955abbb2015-07-17 11:31:21 +02001014 LOGERR(LY_EVALID, "Leafref \"%s\" could not be resolved.", sleaf->type.info.lref.path);
Michal Vasko493bea72015-07-16 16:08:12 +02001015 goto error;
Radek Krejci5a988152015-07-15 11:16:26 +02001016 }
Michal Vasko493bea72015-07-16 16:08:12 +02001017
1018 while (refset) {
1019 if (leaf->value_str == ((struct lyd_node_leaf *)refset->dnode)->value_str) {
1020 leaf->value.leafref = refset->dnode;
1021 }
1022 ref = refset->next;
1023 free(refset);
1024 refset = ref;
1025 }
1026
1027 if (!leaf->value.leafref) {
1028 /* reference not found */
Michal Vasko955abbb2015-07-17 11:31:21 +02001029 LOGERR(LY_EVALID, "Leafref \"%s\" value \"%s\" did not match any node value.", sleaf->type.info.lref.path, leaf->value_str);
Michal Vasko493bea72015-07-16 16:08:12 +02001030 goto error;
1031 }
1032
Michal Vasko493bea72015-07-16 16:08:12 +02001033 /* instance-identifier */
1034 } else {
Radek Krejcic5090c32015-08-12 09:46:19 +02001035 ly_errno = 0;
1036 if (!resolve_instid((*list)->dnode, leaf->value_str, (*list)->line)) {
1037 if (ly_errno) {
1038 goto error;
1039 } else if (sleaf->type.info.inst.req > -1) {
1040 LOGERR(LY_EVALID, "Instance for the \"%s\" does not exist.", leaf->value_str);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001041 goto error;
1042 } else {
Radek Krejcic5090c32015-08-12 09:46:19 +02001043 LOGVRB("Instance for the \"%s\" does not exist.", leaf->value_str);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001044 }
Michal Vasko493bea72015-07-16 16:08:12 +02001045 }
1046
Michal Vasko3f1098b2015-07-20 15:16:43 +02001047 while (refset) {
1048 ref = refset->next;
1049 free(refset);
1050 refset = ref;
1051 }
Radek Krejci5a988152015-07-15 11:16:26 +02001052 }
Michal Vasko8ed75302015-07-17 11:05:14 +02001053
1054 item = (*list)->next;
1055 free(*list);
1056 *list = item;
Radek Krejci5a988152015-07-15 11:16:26 +02001057 }
1058
1059 return EXIT_SUCCESS;
1060
1061error:
1062
1063 while (*list) {
1064 item = (*list)->next;
1065 free(*list);
1066 *list = item;
1067 }
1068
Michal Vasko3f1098b2015-07-20 15:16:43 +02001069 while (refset) {
1070 ref = refset->next;
1071 free(refset);
1072 refset = ref;
1073 }
1074
Radek Krejci5a988152015-07-15 11:16:26 +02001075 return EXIT_FAILURE;
1076}
1077
Radek Krejci25b9fd32015-08-10 15:06:07 +02001078struct lyd_node *
1079xml_read_data(struct ly_ctx *ctx, const char *data, int options)
Radek Krejci1721c012015-07-08 12:52:33 +02001080{
1081 struct lyxml_elem *xml;
Radek Krejci0e1d1a62015-07-31 11:17:01 +02001082 struct lyd_node *result, *next, *iter;
Michal Vaskof02e3742015-08-05 16:27:02 +02001083 struct unres_data *unres = NULL;
Radek Krejci1721c012015-07-08 12:52:33 +02001084
1085 xml = lyxml_read(ctx, data, 0);
1086 if (!xml) {
1087 return NULL;
1088 }
1089
Radek Krejci25b9fd32015-08-10 15:06:07 +02001090 ly_errno = 0;
1091 result = xml_parse_data(ctx, xml->child, NULL, NULL, options, &unres);
Michal Vasko493bea72015-07-16 16:08:12 +02001092 /* check leafrefs and/or instids if any */
1093 if (check_unres(&unres)) {
1094 /* leafref & instid checking failed */
Radek Krejci0e1d1a62015-07-31 11:17:01 +02001095 LY_TREE_FOR_SAFE(result, next, iter) {
1096 lyd_free(iter);
1097 }
1098 result = NULL;
Radek Krejci5a988152015-07-15 11:16:26 +02001099 }
1100
1101 /* free source XML tree */
Radek Krejci1721c012015-07-08 12:52:33 +02001102 lyxml_free_elem(ctx, xml);
1103
1104 return result;
1105}