blob: 8871611c7e081b394a835fc77c6459a39778ad0a [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
Radek Krejci998a0b82015-08-17 13:14:36 +020030#include "libyang.h"
31#include "common.h"
32#include "context.h"
33#include "resolve.h"
34#include "xml.h"
35#include "tree_internal.h"
36#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 Vaskoc07187d2015-08-13 15:20:57 +020077 /* so that it's used even in RELEASE target */
78 (void)xml;
Michal Vaskoe7fc19c2015-08-05 16:24:39 +020079 LOGVAL(LYE_OORVAL, LOGLINE(xml), str_val);
Michal Vasko0e60c832015-07-15 15:48:35 +020080 }
Michal Vasko9286afd2015-07-14 15:27:59 +020081 return ret;
82}
83
Michal Vaskofbf7e482015-07-14 14:49:03 +020084static int
Radek Krejci1574a8d2015-08-03 14:16:52 +020085validate_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 +020086{
87 int i;
88 regex_t preq;
89 char *posix_regex;
90
91 assert(type->base == LY_TYPE_STRING);
92
Michal Vasko07471a52015-07-16 11:18:48 +020093 if (type->der && validate_pattern(str, &type->der->type, xml, str_val, log)) {
Michal Vaskof02e3742015-08-05 16:27:02 +020094 return EXIT_FAILURE;
Michal Vaskofbf7e482015-07-14 14:49:03 +020095 }
96
97 for (i = 0; i < type->info.str.pat_count; ++i) {
98 /*
99 * adjust the expression to a POSIX.2 equivalent
100 *
101 * http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#regexs
102 */
103 posix_regex = malloc((strlen(type->info.str.patterns[i].expr)+3) * sizeof(char));
104 posix_regex[0] = '\0';
105
106 if (strncmp(type->info.str.patterns[i].expr, ".*", 2)) {
107 strcat(posix_regex, "^");
108 }
109 strcat(posix_regex, type->info.str.patterns[i].expr);
110 if (strncmp(type->info.str.patterns[i].expr
111 + strlen(type->info.str.patterns[i].expr) - 2, ".*", 2)) {
112 strcat(posix_regex, "$");
113 }
114
115 /* must return 0, already checked during parsing */
Michal Vasko88876dc2015-08-05 09:46:40 +0200116 if (regcomp(&preq, posix_regex, REG_EXTENDED | REG_NOSUB)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200117 LOGINT;
Radek Krejci61ff1a02015-08-13 09:11:34 +0200118 free(posix_regex);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200119 return EXIT_FAILURE;
Michal Vasko88876dc2015-08-05 09:46:40 +0200120 }
Michal Vaskofbf7e482015-07-14 14:49:03 +0200121 free(posix_regex);
122
123 if (regexec(&preq, str, 0, 0, 0)) {
124 regfree(&preq);
Michal Vasko07471a52015-07-16 11:18:48 +0200125 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200126 LOGVAL(LYE_INVAL, LOGLINE(xml), str_val, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200127 }
Michal Vaskof02e3742015-08-05 16:27:02 +0200128 return EXIT_FAILURE;
Michal Vaskofbf7e482015-07-14 14:49:03 +0200129 }
130 regfree(&preq);
131 }
132
Michal Vaskof02e3742015-08-05 16:27:02 +0200133 return EXIT_SUCCESS;
Michal Vaskofbf7e482015-07-14 14:49:03 +0200134}
135
Radek Krejci76512572015-08-04 09:47:08 +0200136static struct lys_node *
137xml_data_search_schemanode(struct lyxml_elem *xml, struct lys_node *start)
Radek Krejci1721c012015-07-08 12:52:33 +0200138{
Radek Krejci76512572015-08-04 09:47:08 +0200139 struct lys_node *result, *aux;
Radek Krejci1721c012015-07-08 12:52:33 +0200140
141 LY_TREE_FOR(start, result) {
142 /* skip groupings */
Radek Krejci76512572015-08-04 09:47:08 +0200143 if (result->nodetype == LYS_GROUPING) {
Radek Krejci1721c012015-07-08 12:52:33 +0200144 continue;
145 }
146
147 /* go into cases, choices, uses */
Radek Krejci76512572015-08-04 09:47:08 +0200148 if (result->nodetype & (LYS_CHOICE | LYS_CASE | LYS_USES)) {
Radek Krejci1721c012015-07-08 12:52:33 +0200149 aux = xml_data_search_schemanode(xml, result->child);
150 if (aux) {
151 /* we have matching result */
152 return aux;
153 }
154 /* else, continue with next schema node */
155 continue;
156 }
157
158 /* match data nodes */
159 if (result->name == xml->name) {
160 /* names matches, what about namespaces? */
161 if (result->module->ns == xml->ns->value) {
162 /* we have matching result */
163 return result;
164 }
165 /* else, continue with next schema node */
166 continue;
167 }
168 }
169
170 /* no match */
171 return NULL;
172}
173
Radek Krejcie4748472015-07-08 18:00:22 +0200174static int
Michal Vasko07471a52015-07-16 11:18:48 +0200175parse_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 +0200176{
177 char *strptr;
178
179 /* convert to 64-bit integer, all the redundant characters are handled */
180 errno = 0;
181 strptr = NULL;
182 *ret = strtoll(str_val, &strptr, base);
183 if (errno || (*ret < min) || (*ret > max)) {
Michal Vasko07471a52015-07-16 11:18:48 +0200184 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200185 LOGVAL(LYE_OORVAL, LOGLINE(xml), str_val, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200186 }
Michal Vaskof02e3742015-08-05 16:27:02 +0200187 return EXIT_FAILURE;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200188 } else if (strptr && *strptr) {
189 while (isspace(*strptr)) {
190 ++strptr;
191 }
192 if (*strptr) {
Michal Vasko07471a52015-07-16 11:18:48 +0200193 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200194 LOGVAL(LYE_INVAL, LOGLINE(xml), str_val, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200195 }
Michal Vaskof02e3742015-08-05 16:27:02 +0200196 return EXIT_FAILURE;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200197 }
198 }
199
Michal Vaskof02e3742015-08-05 16:27:02 +0200200 return EXIT_SUCCESS;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200201}
202
203static int
Michal Vasko07471a52015-07-16 11:18:48 +0200204parse_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 +0200205{
206 char *strptr;
207
208 errno = 0;
209 strptr = NULL;
210 *ret = strtoull(str_val, &strptr, base);
211 if (errno || (*ret > max)) {
Michal Vasko07471a52015-07-16 11:18:48 +0200212 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200213 LOGVAL(LYE_OORVAL, LOGLINE(xml), str_val, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200214 }
Michal Vaskof02e3742015-08-05 16:27:02 +0200215 return EXIT_FAILURE;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200216 } else if (strptr && *strptr) {
217 while (isspace(*strptr)) {
218 ++strptr;
219 }
220 if (*strptr) {
Michal Vasko07471a52015-07-16 11:18:48 +0200221 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200222 LOGVAL(LYE_INVAL, LOGLINE(xml), str_val, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200223 }
Michal Vaskof02e3742015-08-05 16:27:02 +0200224 return EXIT_FAILURE;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200225 }
226 }
227
Michal Vaskof02e3742015-08-05 16:27:02 +0200228 return EXIT_SUCCESS;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200229}
230
Radek Krejci1574a8d2015-08-03 14:16:52 +0200231static struct lys_type *
232get_next_union_type(struct lys_type *type, struct lys_type *prev_type, int *found)
Radek Krejcie4748472015-07-08 18:00:22 +0200233{
Michal Vasko07471a52015-07-16 11:18:48 +0200234 int i;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200235 struct lys_type *ret = NULL;
Michal Vasko07471a52015-07-16 11:18:48 +0200236
Michal Vasko6da1a372015-07-27 11:19:10 +0200237 for (i = 0; i < type->info.uni.count; ++i) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200238 if (type->info.uni.types[i].base == LY_TYPE_UNION) {
239 ret = get_next_union_type(&type->info.uni.types[i], prev_type, found);
Michal Vasko6da1a372015-07-27 11:19:10 +0200240 if (ret) {
Michal Vasko07471a52015-07-16 11:18:48 +0200241 break;;
242 }
243 continue;
244 }
245
246 if (!prev_type || *found) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200247 ret = &type->info.uni.types[i];
Michal Vasko07471a52015-07-16 11:18:48 +0200248 break;
249 }
250
Radek Krejci1574a8d2015-08-03 14:16:52 +0200251 if (&type->info.uni.types[i] == prev_type) {
Michal Vasko07471a52015-07-16 11:18:48 +0200252 *found = 1;
253 }
254 }
255
Michal Vasko6da1a372015-07-27 11:19:10 +0200256 if (!ret && type->der) {
257 ret = get_next_union_type(&type->der->type, prev_type, found);
258 }
259
260 return ret;
Michal Vasko07471a52015-07-16 11:18:48 +0200261}
262
Radek Krejcic5090c32015-08-12 09:46:19 +0200263static const char *
264instid_xml2json(struct ly_ctx *ctx, struct lyxml_elem *xml)
265{
266 const char *in = xml->content;
267 char *out, *aux, *prefix;
268 size_t out_size, len, size, i = 0, o = 0;
269 int start = 1, interior = 1;
270 struct lys_module *mod, *mod_prev = NULL;
271 struct lyxml_ns *ns;
272
273 out_size = strlen(in);
274 out = malloc((out_size + 1) * sizeof *out);
275
276 while (in[i]) {
277
278 /* skip whitespaces */
279 while (isspace(in[i])) {
280 i++;
281 }
282
283 if (start) {
284 /* leading '/' character */
285 if (start == 1 && in[i] != '/') {
286 LOGVAL(LYE_INCHAR, LOGLINE(xml), in[i], &in[i]);
Radek Krejci61ff1a02015-08-13 09:11:34 +0200287 free(out);
Radek Krejcic5090c32015-08-12 09:46:19 +0200288 return NULL;
289 }
290
291 /* check the output buffer size */
292 if (out_size == o) {
293 out_size += 16; /* just add some size */
294 aux = realloc(out, out_size + 1);
295 if (!aux) {
296 free(out);
297 LOGMEM;
298 return NULL;
299 }
300 out = aux;
301 }
302
303 out[o++] = in[i++];
304 start = 0;
305 continue;
306 } else {
307 /* translate the node identifier */
308 /* prefix */
309 aux = strchr(&in[i], ':');
310 if (aux) {
311 /* interior segment */
312 len = aux - &in[i];
313 prefix = strndup(&in[i], len);
314 i += len + 1; /* move after ':' */
315 } else {
316 /* missing prefix -> invalid instance-identifier */
317 LOGVAL(LYE_INVAL, LOGLINE(xml), xml->content, xml->name);
318 free(out);
319 return NULL;
320 }
321 ns = lyxml_get_ns(xml, prefix);
322 free(prefix);
323 mod = ly_ctx_get_module_by_ns(ctx, ns->value, NULL);
324
325 /* node name */
326 aux = strpbrk(&in[i], "/[=");
327 if (aux) {
328 /* interior segment */
329 len = aux - &in[i];
330 } else {
331 /* end segment */
332 interior = 0;
333 len = strlen(&in[i]);
334 }
335
336 /* check the output buffer size */
337 if (!mod_prev || (mod != mod_prev)) {
338 /* prefix + ':' + name to print + '/' */
339 size = o + len + 1 + strlen(mod->name) + interior;
340 } else {
341 /* name to print + '/' */
342 size = o + len + interior;
343 }
344 if (out_size <= size) {
345 /* extend to fit the needed size */
346 out_size = size;
347 aux = realloc(out, out_size + 1);
348 if (!aux) {
349 free(out);
350 LOGMEM;
351 return NULL;
352 }
353 out = aux;
354 }
355
356 if (!mod_prev || (mod != mod_prev)) {
357 mod_prev = mod;
358 size = strlen(mod->name);
359 memcpy(&out[o], mod->name, size);
360 o += size;
361 out[o++] = ':';
362 }
363 memcpy(&out[o], &in[i], len);
364 o += len;
365 i += len;
366
367 if (in[i] == '=') {
368 /* we are in the predicate on the value, so just copy data */
369 aux = strchr(&in[i], ']');
370 if (aux) {
371 len = aux - &in[i] + 1; /* include ] */
372
373 /* check the output buffer size */
374 size = o + len + 1;
375 if (out_size <= size) {
376 out_size = size; /* just add some size */
377 aux = realloc(out, out_size + 1);
378 if (!aux) {
379 free(out);
380 LOGMEM;
381 return NULL;
382 }
383 out = aux;
384 }
385
386 memcpy(&out[o], &in[i], len);
387 o += len;
388 i += len;
389 } else {
390 /* missing closing ] of predicate -> invalid instance-identifier */
391 LOGVAL(LYE_INVAL, LOGLINE(xml), xml->content, xml->name);
392 free(out);
393 return NULL;
394 }
395 }
396 start = 2;
397 }
398 }
399
400 /* terminating NULL byte */
401 /* check the output buffer size */
402 if (out_size < o) {
403 out_size += 1; /* just add some size */
404 aux = realloc(out, out_size + 1);
405 if (!aux) {
406 free(out);
407 LOGMEM;
408 return NULL;
409 }
410 out = aux;
411 }
412 out[o] = '\0';
413
414 return lydict_insert_zc(ctx, out);
415}
416
Michal Vasko07471a52015-07-16 11:18:48 +0200417static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200418_xml_get_value(struct lyd_node *node, struct lys_type *node_type, struct lyxml_elem *xml,
Radek Krejci25b9fd32015-08-10 15:06:07 +0200419 int options, struct unres_data **unres, int log)
Michal Vasko07471a52015-07-16 11:18:48 +0200420{
421 #define DECSIZE 21
Radek Krejci3e3affe2015-07-09 15:38:40 +0200422 struct lyd_node_leaf *leaf = (struct lyd_node_leaf *)node;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200423 struct lys_type *type;
Radek Krejciac8aac62015-07-10 15:36:35 +0200424 struct lyxml_ns *ns;
Radek Krejci7511f402015-07-10 09:56:30 +0200425 char dec[DECSIZE];
Michal Vaskofbf7e482015-07-14 14:49:03 +0200426 char *strptr;
Radek Krejciac8aac62015-07-10 15:36:35 +0200427 const char *name;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200428 int64_t num;
429 uint64_t unum;
Radek Krejci3e3affe2015-07-09 15:38:40 +0200430 int len;
Radek Krejci7511f402015-07-10 09:56:30 +0200431 int c, i, j, d;
Radek Krejci3e3affe2015-07-09 15:38:40 +0200432 int found;
Michal Vaskof02e3742015-08-05 16:27:02 +0200433 struct unres_data *new_unres;
Radek Krejci5a988152015-07-15 11:16:26 +0200434
435 leaf->value_str = xml->content;
436 xml->content = NULL;
Radek Krejcie4748472015-07-08 18:00:22 +0200437
Radek Krejcie3c33142015-08-10 15:04:36 +0200438 /* will be change in case of union */
439 leaf->value_type = node_type->base;
440
Radek Krejcie2cf7c12015-08-12 10:24:05 +0200441 if ((options & LYD_OPT_FILTER) && !leaf->value_str) {
442 /* no value in filter (selection) node -> nothing more is needed */
443 return EXIT_SUCCESS;
444 }
445
Michal Vasko07471a52015-07-16 11:18:48 +0200446 switch (node_type->base) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200447 case LY_TYPE_BINARY:
Radek Krejci5a988152015-07-15 11:16:26 +0200448 leaf->value.binary = leaf->value_str;
Radek Krejci3e3affe2015-07-09 15:38:40 +0200449
Michal Vasko07471a52015-07-16 11:18:48 +0200450 if (node_type->info.binary.length
451 && validate_length_range(0, strlen(leaf->value.binary), 0, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko0e60c832015-07-15 15:48:35 +0200452 return EXIT_FAILURE;
Radek Krejcie4748472015-07-08 18:00:22 +0200453 }
454 break;
455
Radek Krejci3e3affe2015-07-09 15:38:40 +0200456 case LY_TYPE_BITS:
Radek Krejci3e3affe2015-07-09 15:38:40 +0200457 /* locate bits structure with the bits definitions */
Michal Vasko07471a52015-07-16 11:18:48 +0200458 for (type = node_type; type->der->type.der; type = &type->der->type);
Radek Krejci3e3affe2015-07-09 15:38:40 +0200459
460 /* allocate the array of pointers to bits definition */
461 leaf->value.bit = calloc(type->info.bits.count, sizeof *leaf->value.bit);
462
Radek Krejci5a988152015-07-15 11:16:26 +0200463 if (!leaf->value_str) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200464 /* no bits set */
465 break;
466 }
467
468 c = 0;
469 i = 0;
Radek Krejci5a988152015-07-15 11:16:26 +0200470 while (leaf->value_str[c]) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200471 /* skip leading whitespaces */
Radek Krejci5a988152015-07-15 11:16:26 +0200472 while(isspace(leaf->value_str[c])) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200473 c++;
474 }
475
476 /* get the length of the bit identifier */
Radek Krejci5a988152015-07-15 11:16:26 +0200477 for (len = 0; leaf->value_str[c] && !isspace(leaf->value_str[c]); c++, len++);
Radek Krejci3e3affe2015-07-09 15:38:40 +0200478
479 /* go back to the beginning of the identifier */
480 c = c - len;
481
482 /* find bit definition, identifiers appear ordered by their posititon */
483 for (found = 0; i < type->info.bits.count; i++) {
Radek Krejci5a988152015-07-15 11:16:26 +0200484 if (!strncmp(type->info.bits.bit[i].name, &leaf->value_str[c], len)
Radek Krejci3e3affe2015-07-09 15:38:40 +0200485 && !type->info.bits.bit[i].name[len]) {
486 /* we have match, store the pointer */
487 leaf->value.bit[i] = &type->info.bits.bit[i];
488
489 /* stop searching */
490 i++;
491 found = 1;
492 break;
493 }
494 }
495
496 if (!found) {
497 /* referenced bit value does not exists */
Michal Vasko07471a52015-07-16 11:18:48 +0200498 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200499 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200500 }
Radek Krejci3e3affe2015-07-09 15:38:40 +0200501 return EXIT_FAILURE;
502 }
503
504 c = c + len;
505 }
506
507 break;
508
Radek Krejcib7384642015-07-09 16:08:45 +0200509 case LY_TYPE_BOOL:
Radek Krejci5a988152015-07-15 11:16:26 +0200510 if (!strcmp(leaf->value_str, "true")) {
Radek Krejcib7384642015-07-09 16:08:45 +0200511 leaf->value.bool = 1;
512 } /* else false, so keep it zero */
513 break;
514
Radek Krejci7511f402015-07-10 09:56:30 +0200515 case LY_TYPE_DEC64:
516 /* locate dec64 structure with the fraction-digits value */
Michal Vasko07471a52015-07-16 11:18:48 +0200517 for (type = node_type; type->der->type.der; type = &type->der->type);
Radek Krejci7511f402015-07-10 09:56:30 +0200518
Radek Krejci5a988152015-07-15 11:16:26 +0200519 for (c = 0; isspace(leaf->value_str[c]); c++);
520 for (len = 0; leaf->value_str[c] && !isspace(leaf->value_str[c]); c++, len++);
Radek Krejci7511f402015-07-10 09:56:30 +0200521 c = c - len;
522 if (len > DECSIZE) {
523 /* too long */
Michal Vasko07471a52015-07-16 11:18:48 +0200524 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200525 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200526 }
Radek Krejci7511f402015-07-10 09:56:30 +0200527 return EXIT_FAILURE;
528 }
529
530 /* normalize the number */
531 dec[0] = '\0';
532 for (i = j = d = found = 0; i < DECSIZE; i++) {
Radek Krejci5a988152015-07-15 11:16:26 +0200533 if (leaf->value_str[c + i] == '.') {
Radek Krejci7511f402015-07-10 09:56:30 +0200534 found = 1;
535 j = type->info.dec64.dig;
536 i--;
537 c++;
538 continue;
539 }
Radek Krejci5a988152015-07-15 11:16:26 +0200540 if (leaf->value_str[c + i] == '\0') {
Radek Krejci7511f402015-07-10 09:56:30 +0200541 c--;
542 if (!found) {
543 j = type->info.dec64.dig;
544 found = 1;
545 }
546 if (!j) {
547 dec[i] = '\0';
548 break;
549 }
550 d++;
551 if (d > DECSIZE - 2) {
Michal Vasko07471a52015-07-16 11:18:48 +0200552 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200553 LOGVAL(LYE_OORVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200554 }
Radek Krejci7511f402015-07-10 09:56:30 +0200555 return EXIT_FAILURE;
556 }
557 dec[i] = '0';
558 } else {
Radek Krejci5a988152015-07-15 11:16:26 +0200559 if (!isdigit(leaf->value_str[c + i])) {
560 if (i || leaf->value_str[c] != '-') {
Michal Vasko07471a52015-07-16 11:18:48 +0200561 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200562 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200563 }
Radek Krejci7511f402015-07-10 09:56:30 +0200564 return EXIT_FAILURE;
565 }
566 } else {
567 d++;
568 }
569 if (d > DECSIZE - 2 || (found && !j)) {
Michal Vasko07471a52015-07-16 11:18:48 +0200570 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200571 LOGVAL(LYE_OORVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200572 }
Radek Krejci7511f402015-07-10 09:56:30 +0200573 return EXIT_FAILURE;
574 }
Radek Krejci5a988152015-07-15 11:16:26 +0200575 dec[i] = leaf->value_str[c + i];
Radek Krejci7511f402015-07-10 09:56:30 +0200576 }
577 if (j) {
578 j--;
579 }
580 }
581
Michal Vasko07471a52015-07-16 11:18:48 +0200582 if (parse_int(dec, xml, -9223372036854775807L - 1L, 9223372036854775807L, 10, &num, log)
583 || 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 +0200584 return EXIT_FAILURE;
585 }
Michal Vaskobdee69c2015-07-15 15:49:39 +0200586 leaf->value.dec64 = num;
Radek Krejci7511f402015-07-10 09:56:30 +0200587 break;
588
Radek Krejcibce73742015-07-10 12:46:06 +0200589 case LY_TYPE_EMPTY:
590 /* just check that it is empty */
Radek Krejci5a988152015-07-15 11:16:26 +0200591 if (leaf->value_str && leaf->value_str[0]) {
Michal Vasko07471a52015-07-16 11:18:48 +0200592 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200593 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200594 }
Radek Krejcibce73742015-07-10 12:46:06 +0200595 return EXIT_FAILURE;
596 }
597 break;
598
Radek Krejci5b315a92015-07-10 13:18:45 +0200599 case LY_TYPE_ENUM:
Radek Krejci5a988152015-07-15 11:16:26 +0200600 if (!leaf->value_str) {
Michal Vasko07471a52015-07-16 11:18:48 +0200601 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200602 LOGVAL(LYE_INVAL, LOGLINE(xml), "", xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200603 }
Radek Krejci5b315a92015-07-10 13:18:45 +0200604 return EXIT_FAILURE;
605 }
606
607 /* locate enums structure with the enumeration definitions */
Michal Vasko07471a52015-07-16 11:18:48 +0200608 for (type = node_type; type->der->type.der; type = &type->der->type);
Radek Krejci5b315a92015-07-10 13:18:45 +0200609
610 /* find matching enumeration value */
611 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200612 if (!strcmp(leaf->value_str, type->info.enums.enm[i].name)) {
Radek Krejci5b315a92015-07-10 13:18:45 +0200613 /* we have match, store pointer to the definition */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200614 leaf->value.enm = &type->info.enums.enm[i];
Radek Krejci5b315a92015-07-10 13:18:45 +0200615 break;
616 }
617 }
618
619 if (!leaf->value.enm) {
Michal Vasko07471a52015-07-16 11:18:48 +0200620 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200621 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200622 }
Radek Krejci5b315a92015-07-10 13:18:45 +0200623 return EXIT_FAILURE;
624 }
625
626 break;
627
Radek Krejciac8aac62015-07-10 15:36:35 +0200628 case LY_TYPE_IDENT:
Radek Krejci5a988152015-07-15 11:16:26 +0200629 if ((strptr = strchr(leaf->value_str, ':'))) {
630 len = strptr - leaf->value_str;
Radek Krejciac8aac62015-07-10 15:36:35 +0200631 if (!len) {
Michal Vasko07471a52015-07-16 11:18:48 +0200632 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200633 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200634 }
Radek Krejciac8aac62015-07-10 15:36:35 +0200635 return EXIT_FAILURE;
636 }
Radek Krejci5a988152015-07-15 11:16:26 +0200637 strptr = strndup(leaf->value_str, len);
Radek Krejciac8aac62015-07-10 15:36:35 +0200638 }
639 ns = lyxml_get_ns(xml, strptr);
640 if (!ns) {
Michal Vasko07471a52015-07-16 11:18:48 +0200641 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200642 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200643 }
Radek Krejciac8aac62015-07-10 15:36:35 +0200644 return EXIT_FAILURE;
645 }
646 if (strptr) {
647 free(strptr);
Radek Krejci5a988152015-07-15 11:16:26 +0200648 name = leaf->value_str + len + 1;
Radek Krejciac8aac62015-07-10 15:36:35 +0200649 } else {
Radek Krejci5a988152015-07-15 11:16:26 +0200650 name = leaf->value_str;
Radek Krejciac8aac62015-07-10 15:36:35 +0200651 }
652
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200653 leaf->value.ident = resolve_identityref(node_type->info.ident.ref, name, ns->value);
Radek Krejciac8aac62015-07-10 15:36:35 +0200654 if (!leaf->value.ident) {
Michal Vasko07471a52015-07-16 11:18:48 +0200655 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200656 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200657 }
Radek Krejciac8aac62015-07-10 15:36:35 +0200658 return EXIT_FAILURE;
659 }
660 break;
661
Michal Vasko07471a52015-07-16 11:18:48 +0200662 case LY_TYPE_INST:
Michal Vasko493bea72015-07-16 16:08:12 +0200663 if (!leaf->value_str) {
664 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200665 LOGVAL(LYE_INVAL, LOGLINE(xml), "", xml->name);
Michal Vasko493bea72015-07-16 16:08:12 +0200666 }
667 return EXIT_FAILURE;
668 }
669
Radek Krejcic5090c32015-08-12 09:46:19 +0200670 /* convert the path from the XML form using XML namespaces into the JSON format
671 * using module names as namespaces
672 */
673 xml->content = leaf->value_str;
674 leaf->value_str = instid_xml2json(node->schema->module->ctx, xml);
675 lydict_remove(node->schema->module->ctx, xml->content);
676 xml->content = NULL;
677 if (!leaf->value_str) {
678 return EXIT_FAILURE;
679 }
680
Radek Krejcib1c12512015-08-11 11:22:04 +0200681 if (options & (LYD_OPT_EDIT | LYD_OPT_FILTER)) {
682 leaf->value_type |= LY_TYPE_INST_UNRES;
683 } else {
684 /* validity checking is performed later, right now the data tree
685 * is not complete, so many instanceids cannot be resolved
686 */
687 /* remember the leaf for later checking */
688 new_unres = malloc(sizeof *new_unres);
689 new_unres->is_leafref = 0;
690 new_unres->dnode = node;
691 new_unres->next = *unres;
Michal Vaskoc07187d2015-08-13 15:20:57 +0200692#ifndef NDEBUG
Radek Krejcib1c12512015-08-11 11:22:04 +0200693 new_unres->line = LOGLINE(xml);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200694#endif
Radek Krejcib1c12512015-08-11 11:22:04 +0200695 *unres = new_unres;
696 }
Michal Vasko07471a52015-07-16 11:18:48 +0200697 break;
698
Radek Krejci5a988152015-07-15 11:16:26 +0200699 case LY_TYPE_LEAFREF:
700 if (!leaf->value_str) {
Michal Vasko07471a52015-07-16 11:18:48 +0200701 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200702 LOGVAL(LYE_INVAL, LOGLINE(xml), "", xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200703 }
Radek Krejci5a988152015-07-15 11:16:26 +0200704 return EXIT_FAILURE;
705 }
706
Radek Krejcib1c12512015-08-11 11:22:04 +0200707 if (options & (LYD_OPT_EDIT | LYD_OPT_FILTER)) {
708 do {
709 type = &((struct lys_node_leaf *)leaf->schema)->type.info.lref.target->type;
710 } while (type->base == LY_TYPE_LEAFREF);
711 leaf->value_type = type->base | LY_TYPE_LEAFREF_UNRES;
712 } else {
713 /* validity checking is performed later, right now the data tree
714 * is not complete, so many leafrefs cannot be resolved
715 */
716 /* remember the leaf for later checking */
717 new_unres = malloc(sizeof *new_unres);
718 new_unres->is_leafref = 1;
719 new_unres->dnode = node;
720 new_unres->next = *unres;
Michal Vaskoc07187d2015-08-13 15:20:57 +0200721#ifndef NDEBUG
Radek Krejcib1c12512015-08-11 11:22:04 +0200722 new_unres->line = LOGLINE(xml);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200723#endif
Radek Krejcib1c12512015-08-11 11:22:04 +0200724 *unres = new_unres;
725 }
Radek Krejci5a988152015-07-15 11:16:26 +0200726 break;
727
Radek Krejci3e3affe2015-07-09 15:38:40 +0200728 case LY_TYPE_STRING:
Radek Krejci5a988152015-07-15 11:16:26 +0200729 leaf->value.string = leaf->value_str;
Radek Krejci3e3affe2015-07-09 15:38:40 +0200730
Michal Vasko07471a52015-07-16 11:18:48 +0200731 if (node_type->info.str.length
732 && validate_length_range(0, strlen(leaf->value.string), 0, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko0e60c832015-07-15 15:48:35 +0200733 return EXIT_FAILURE;
Radek Krejcie4748472015-07-08 18:00:22 +0200734 }
735
Michal Vasko07471a52015-07-16 11:18:48 +0200736 if (node_type->info.str.patterns
737 && validate_pattern(leaf->value.string, node_type, xml, leaf->value_str, log)) {
Michal Vasko0e60c832015-07-15 15:48:35 +0200738 return EXIT_FAILURE;
Radek Krejcie4748472015-07-08 18:00:22 +0200739 }
740 break;
741
Michal Vasko58110162015-07-15 15:50:16 +0200742 case LY_TYPE_UNION:
Michal Vasko07471a52015-07-16 11:18:48 +0200743 found = 0;
Michal Vasko6da1a372015-07-27 11:19:10 +0200744 type = get_next_union_type(node_type, NULL, &found);
745 for (; type; found = 0, type = get_next_union_type(node_type, type, &found)) {
Michal Vasko07471a52015-07-16 11:18:48 +0200746 xml->content = leaf->value_str;
Radek Krejci25b9fd32015-08-10 15:06:07 +0200747 if (!_xml_get_value(node, type, xml, options, unres, 0)) {
Michal Vasko07471a52015-07-16 11:18:48 +0200748 leaf->value_type = type->base;
749 break;
750 }
751 }
752
753 if (!type) {
754 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200755 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200756 }
757 return EXIT_FAILURE;
758 }
Michal Vasko58110162015-07-15 15:50:16 +0200759 break;
760
761 case LY_TYPE_INT8:
Michal Vasko07471a52015-07-16 11:18:48 +0200762 if (parse_int(leaf->value_str, xml, -128, 127, 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.int8 = num;
767 break;
768
769 case LY_TYPE_INT16:
Michal Vasko07471a52015-07-16 11:18:48 +0200770 if (parse_int(leaf->value_str, xml, -32768, 32767, 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.int16 = num;
775 break;
776
777 case LY_TYPE_INT32:
Michal Vasko07471a52015-07-16 11:18:48 +0200778 if (parse_int(leaf->value_str, xml, -2147483648, 2147483647, 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.int32 = num;
783 break;
784
785 case LY_TYPE_INT64:
Michal Vasko07471a52015-07-16 11:18:48 +0200786 if (parse_int(leaf->value_str, xml, -9223372036854775807L - 1L, 9223372036854775807L, 0, &num, log)
787 || validate_length_range(1, 0, num, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko58110162015-07-15 15:50:16 +0200788 return EXIT_FAILURE;
789 }
790 leaf->value.int64 = num;
791 break;
792
793 case LY_TYPE_UINT8:
Michal Vasko07471a52015-07-16 11:18:48 +0200794 if (parse_uint(leaf->value_str, xml, 255, 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.uint8 = unum;
799 break;
800
801 case LY_TYPE_UINT16:
Michal Vasko07471a52015-07-16 11:18:48 +0200802 if (parse_uint(leaf->value_str, xml, 65535, 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.uint16 = unum;
807 break;
808
809 case LY_TYPE_UINT32:
Michal Vasko07471a52015-07-16 11:18:48 +0200810 if (parse_uint(leaf->value_str, xml, 4294967295, 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.uint32 = unum;
815 break;
816
817 case LY_TYPE_UINT64:
Michal Vasko07471a52015-07-16 11:18:48 +0200818 if (parse_uint(leaf->value_str, xml, 18446744073709551615UL, 0, &unum, log)
819 || validate_length_range(0, unum, 0, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko58110162015-07-15 15:50:16 +0200820 return EXIT_FAILURE;
821 }
822 leaf->value.uint64 = unum;
823 break;
824
Radek Krejcie4748472015-07-08 18:00:22 +0200825 default:
Michal Vasko493bea72015-07-16 16:08:12 +0200826 return EXIT_FAILURE;
Radek Krejcie4748472015-07-08 18:00:22 +0200827 }
828
829 return EXIT_SUCCESS;
830}
831
Michal Vasko07471a52015-07-16 11:18:48 +0200832static int
Radek Krejci25b9fd32015-08-10 15:06:07 +0200833xml_get_value(struct lyd_node *node, struct lyxml_elem *xml, int options, struct unres_data **unres)
Michal Vasko07471a52015-07-16 11:18:48 +0200834{
Radek Krejci25b9fd32015-08-10 15:06:07 +0200835 return _xml_get_value(node, &((struct lys_node_leaf *)node->schema)->type, xml, options, unres, 1);
Michal Vasko07471a52015-07-16 11:18:48 +0200836}
837
Radek Krejci1721c012015-07-08 12:52:33 +0200838struct lyd_node *
Michal Vasko493bea72015-07-16 16:08:12 +0200839xml_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 +0200840 int options, struct unres_data **unres)
Radek Krejci1721c012015-07-08 12:52:33 +0200841{
Radek Krejci7f40ce32015-08-12 20:38:46 +0200842 struct lyd_node *result = NULL, *diter;
843 struct lys_node *schema = NULL, *siter;
Radek Krejcida374342015-08-19 13:33:22 +0200844 struct lys_node *cs, *ch;
Michal Vaskoab8e4402015-07-17 12:54:28 +0200845 int i, havechildren;
Radek Krejci1721c012015-07-08 12:52:33 +0200846
847 if (!xml) {
848 return NULL;
849 }
850 if (!xml->ns || !xml->ns->value) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200851 LOGVAL(LYE_XML_MISS, LOGLINE(xml), "element's", "namespace");
Radek Krejci1721c012015-07-08 12:52:33 +0200852 return NULL;
853 }
854
855 /* find schema node */
856 if (!parent) {
857 /* starting in root */
858 for (i = 0; i < ctx->models.used; i++) {
859 /* match data model based on namespace */
860 if (ctx->models.list[i]->ns == xml->ns->value) {
861 /* get the proper schema node */
862 LY_TREE_FOR(ctx->models.list[i]->data, schema) {
863 if (schema->name == xml->name) {
864 break;
865 }
866 }
867 break;
868 }
869 }
870 } else {
871 /* parsing some internal node, we start with parent's schema pointer */
872 schema = xml_data_search_schemanode(xml, parent->schema->child);
873 }
874 if (!schema) {
Radek Krejci25b9fd32015-08-10 15:06:07 +0200875 if ((options & LYD_OPT_STRICT) || ly_ctx_get_module_by_ns(ctx, xml->ns->value, NULL)) {
876 LOGVAL(LYE_INELEM, LOGLINE(xml), xml->name);
877 return NULL;
878 } else {
879 goto siblings;
880 }
Radek Krejci1721c012015-07-08 12:52:33 +0200881 }
882
Radek Krejci074bf852015-08-19 14:22:16 +0200883 /* check for (non-)presence of status data in edit-config data */
884 if ((options & LYD_OPT_EDIT) && (schema->flags & LYS_CONFIG_R)) {
885 LOGVAL(LYE_INELEM, LOGLINE(xml), schema->name);
886 return NULL;
887 }
888 /* check if the node instance is enabled by if-feature */
889 if (lys_is_disabled(schema, 2)) {
890 LOGVAL(LYE_INELEM, LOGLINE(xml), schema->name);
891 return NULL;
892 }
893
Radek Krejcib9930252015-07-08 15:47:45 +0200894 switch (schema->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +0200895 case LYS_CONTAINER:
Michal Vaskoab8e4402015-07-17 12:54:28 +0200896 result = calloc(1, sizeof *result);
897 havechildren = 1;
Radek Krejcib9930252015-07-08 15:47:45 +0200898 break;
Radek Krejci76512572015-08-04 09:47:08 +0200899 case LYS_LEAF:
Radek Krejcie4748472015-07-08 18:00:22 +0200900 result = calloc(1, sizeof(struct lyd_node_leaf));
901 havechildren = 0;
902 break;
Radek Krejci76512572015-08-04 09:47:08 +0200903 case LYS_LEAFLIST:
Radek Krejcie4748472015-07-08 18:00:22 +0200904 result = calloc(1, sizeof(struct lyd_node_leaflist));
905 havechildren = 0;
906 break;
Radek Krejci76512572015-08-04 09:47:08 +0200907 case LYS_LIST:
Michal Vaskoab8e4402015-07-17 12:54:28 +0200908 result = calloc(1, sizeof(struct lyd_node_list));
909 havechildren = 1;
910 break;
Radek Krejci76512572015-08-04 09:47:08 +0200911 case LYS_ANYXML:
Michal Vaskoab8e4402015-07-17 12:54:28 +0200912 result = calloc(1, sizeof(struct lyd_node_anyxml));
913 havechildren = 0;
914 break;
Radek Krejcib9930252015-07-08 15:47:45 +0200915 default:
Michal Vasko0c888fd2015-08-11 15:54:08 +0200916 LOGINT;
Michal Vaskoab8e4402015-07-17 12:54:28 +0200917 return NULL;
Radek Krejcib9930252015-07-08 15:47:45 +0200918 }
Radek Krejci1721c012015-07-08 12:52:33 +0200919 result->parent = parent;
Radek Krejcib9930252015-07-08 15:47:45 +0200920 result->prev = prev;
Radek Krejci1721c012015-07-08 12:52:33 +0200921 result->schema = schema;
922
Radek Krejci88daf822015-08-10 13:58:16 +0200923 /* check number of instances for non-list nodes */
Radek Krejcib6772142015-08-12 10:16:44 +0200924 if (!(options & LYD_OPT_FILTER) && (schema->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_ANYXML))) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200925 for (diter = result->prev; diter; diter = diter->prev) {
926 if (diter->schema == schema) {
Radek Krejci88daf822015-08-10 13:58:16 +0200927 LOGVAL(LYE_TOOMANY, LOGLINE(xml), xml->name, xml->parent ? xml->parent->name : "data tree");
928 goto error;
929 }
930 }
931 }
932
Radek Krejcib9930252015-07-08 15:47:45 +0200933 /* type specific processing */
Radek Krejci76512572015-08-04 09:47:08 +0200934 if (schema->nodetype == LYS_LIST) {
Radek Krejcib9930252015-07-08 15:47:45 +0200935 /* pointers to next and previous instances of the same list */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200936 for (diter = result->prev; diter; diter = diter->prev) {
937 if (diter->schema == result->schema) {
Radek Krejcib9930252015-07-08 15:47:45 +0200938 /* instances of the same list */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200939 ((struct lyd_node_list *)diter)->lnext = (struct lyd_node_list *)result;
940 ((struct lyd_node_list *)result)->lprev = (struct lyd_node_list *)diter;
Radek Krejcib9930252015-07-08 15:47:45 +0200941 break;
942 }
943 }
Radek Krejci76512572015-08-04 09:47:08 +0200944 } else if (schema->nodetype == LYS_LEAF) {
Radek Krejcie4748472015-07-08 18:00:22 +0200945 /* type detection and assigning the value */
Radek Krejci25b9fd32015-08-10 15:06:07 +0200946 if (xml_get_value(result, xml, options, unres)) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200947 goto error;
948 }
Radek Krejci76512572015-08-04 09:47:08 +0200949 } else if (schema->nodetype == LYS_LEAFLIST) {
Radek Krejcie4748472015-07-08 18:00:22 +0200950 /* type detection and assigning the value */
Radek Krejci25b9fd32015-08-10 15:06:07 +0200951 if (xml_get_value(result, xml, options, unres)) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200952 goto error;
953 }
Radek Krejcie4748472015-07-08 18:00:22 +0200954
955 /* pointers to next and previous instances of the same leaflist */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200956 for (diter = result->prev; diter; diter = diter->prev) {
957 if (diter->schema == result->schema) {
Radek Krejcie4748472015-07-08 18:00:22 +0200958 /* instances of the same list */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200959 ((struct lyd_node_leaflist *)diter)->lnext = (struct lyd_node_leaflist *)result;
960 ((struct lyd_node_leaflist *)result)->lprev = (struct lyd_node_leaflist *)diter;
Radek Krejcie4748472015-07-08 18:00:22 +0200961 break;
962 }
963 }
Radek Krejci76512572015-08-04 09:47:08 +0200964 } else if (schema->nodetype == LYS_ANYXML) {
Michal Vaskoab8e4402015-07-17 12:54:28 +0200965 ((struct lyd_node_anyxml *)result)->value = xml;
966 lyxml_unlink_elem(xml);
Radek Krejcib9930252015-07-08 15:47:45 +0200967 }
968
Radek Krejci1721c012015-07-08 12:52:33 +0200969 /* process children */
Radek Krejcie4748472015-07-08 18:00:22 +0200970 if (havechildren && xml->child) {
Radek Krejci25b9fd32015-08-10 15:06:07 +0200971 result->child = xml_parse_data(ctx, xml->child, result, NULL, options, unres);
972 if (ly_errno) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200973 goto error;
Radek Krejci1721c012015-07-08 12:52:33 +0200974 }
Radek Krejci1721c012015-07-08 12:52:33 +0200975 }
976
Radek Krejcib1c12512015-08-11 11:22:04 +0200977 /* various validation checks */
Radek Krejci1073cc02015-08-12 20:37:39 +0200978
979 /* check presence of all keys in case of list */
Radek Krejcib1c12512015-08-11 11:22:04 +0200980 if (schema->nodetype == LYS_LIST && !(options & LYD_OPT_FILTER)) {
Radek Krejci1073cc02015-08-12 20:37:39 +0200981 siter = (struct lys_node *)lyv_keys_present((struct lyd_node_list *)result);
982 if (siter) {
Radek Krejcib1c12512015-08-11 11:22:04 +0200983 /* key not found in the data */
Radek Krejci1073cc02015-08-12 20:37:39 +0200984 LOGVAL(LYE_MISSELEM, LOGLINE(xml), siter->name, schema->name);
Radek Krejcib1c12512015-08-11 11:22:04 +0200985 goto error;
986 }
987 }
988
Radek Krejci7f40ce32015-08-12 20:38:46 +0200989 /* mandatory children */
990 if (havechildren && !(options & (LYD_OPT_FILTER | LYD_OPT_EDIT))) {
991 siter = ly_check_mandatory(result);
992 if (siter) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200993 if (siter->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
994 LOGVAL(LYE_SPEC, LOGLINE(xml), "Number of \"%s\" instances in \"%s\" does not follow min/max constraints.",
995 siter->name, siter->parent->name);
996 } else {
997 LOGVAL(LYE_MISSELEM, LOGLINE(xml), siter->name, siter->parent->name);
998 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200999 goto error;
1000 }
1001 }
Radek Krejcib1c12512015-08-11 11:22:04 +02001002
Radek Krejci78ce8612015-08-18 14:31:05 +02001003 /* uniqueness of (leaf-)list instances */
1004 if (schema->nodetype == LYS_LEAFLIST) {
1005 /* check uniqueness of the leaf-list instances (compare values) */
1006 for (diter = (struct lyd_node *)((struct lyd_node_leaflist *)result)->lprev;
1007 diter;
1008 diter = (struct lyd_node *)((struct lyd_node_leaflist *)diter)->lprev) {
1009 if (!lyd_compare(diter, result, 0)) {
Radek Krejcib3d6d552015-08-19 11:56:13 +02001010 if (options & LYD_OPT_FILTER) {
1011 /* optimize filter and do not duplicate the same selection node,
1012 * so this is not actually error, but the data are silently removed */
1013 ((struct lyd_node_leaflist *)result)->lprev->lnext = NULL;
1014 result->next = NULL;
1015 result->parent = NULL;
1016 result->prev = result;
1017 lyd_free(result);
1018 result = NULL;
1019 break;
1020 } else {
1021 LOGVAL(LYE_DUPLEAFLIST, LOGLINE(xml), schema->name, ((struct lyd_node_leaflist *)result)->value_str);
1022 goto error;
1023 }
Radek Krejci78ce8612015-08-18 14:31:05 +02001024 }
1025 }
1026 } else if (schema->nodetype == LYS_LIST) {
Radek Krejcib3d6d552015-08-19 11:56:13 +02001027 /* check uniqueness of the list instances */
Radek Krejci78ce8612015-08-18 14:31:05 +02001028 for (diter = (struct lyd_node *)((struct lyd_node_list *)result)->lprev;
1029 diter;
1030 diter = (struct lyd_node *)((struct lyd_node_list *)diter)->lprev) {
Radek Krejcib3d6d552015-08-19 11:56:13 +02001031 if (options & LYD_OPT_FILTER) {
1032 /* compare content match nodes */
1033 if (!lyd_filter_compare(diter, result)) {
1034 /* merge both nodes */
1035 /* add selection and containment nodes from result into the diter,
1036 * but only in case the diter already contains some selection nodes,
1037 * otherwise it already will return all the data */
1038 lyd_filter_merge(diter, result);
1039
1040 /* not the error, just return no data */
1041 ((struct lyd_node_list *)result)->lprev->lnext = NULL;
1042 result->next = NULL;
1043 result->parent = NULL;
1044 result->prev = result;
1045 lyd_free(result);
1046 result = NULL;
1047 break;
1048 }
1049 } else {
1050 /* compare keys and unique combinations */
1051 if (!lyd_compare(diter, result, 1)) {
1052 LOGVAL(LYE_DUPLIST, LOGLINE(xml), schema->name);
1053 goto error;
1054 }
Radek Krejci78ce8612015-08-18 14:31:05 +02001055 }
1056 }
Radek Krejcida374342015-08-19 13:33:22 +02001057 } else if (!(options & LYD_OPT_FILTER) && schema->parent && (schema->parent->nodetype & (LYS_CASE | LYS_CHOICE))) {
1058 /* check that there are no data from different choice case */
1059 if (schema->parent->nodetype == LYS_CHOICE) {
1060 cs = NULL;
1061 ch = schema->parent;
1062 } else { /* schema->parent->nodetype == LYS_CASE */
1063 cs = schema->parent;
1064 ch = schema->parent->parent;
1065 }
1066 if (ch->parent && ch->parent->nodetype == LYS_CASE) {
1067 /* TODO check schemas with a choice inside a case */
1068 LOGWRN("Not checking parent branches of nested choice");
1069 }
1070 for (diter = result->prev; diter; diter = diter->prev) {
1071 if ((diter->schema->parent->nodetype == LYS_CHOICE && diter->schema->parent == ch) ||
1072 (diter->schema->parent->nodetype == LYS_CASE && !cs) ||
1073 (diter->schema->parent->nodetype == LYS_CASE && cs && diter->schema->parent != cs && diter->schema->parent->parent == ch)) {
1074 LOGVAL(LYE_MCASEDATA, LOGLINE(xml), ch->name);
1075 goto error;
1076 }
1077 }
Radek Krejci78ce8612015-08-18 14:31:05 +02001078 }
1079
Radek Krejci25b9fd32015-08-10 15:06:07 +02001080siblings:
Radek Krejci1721c012015-07-08 12:52:33 +02001081 /* process siblings */
1082 if (xml->next) {
Radek Krejci25b9fd32015-08-10 15:06:07 +02001083 if (result) {
1084 result->next = xml_parse_data(ctx, xml->next, parent, result, options, unres);
1085 } else {
1086 result = xml_parse_data(ctx, xml->next, parent, prev, options, unres);
1087 }
1088 if (ly_errno) {
Radek Krejci3e3affe2015-07-09 15:38:40 +02001089 goto error;
Radek Krejci1721c012015-07-08 12:52:33 +02001090 }
Radek Krejci1721c012015-07-08 12:52:33 +02001091 }
1092
Radek Krejcib9930252015-07-08 15:47:45 +02001093 /* fix the "last" pointer */
Radek Krejci25b9fd32015-08-10 15:06:07 +02001094 if (result && !result->prev) {
Radek Krejci7f40ce32015-08-12 20:38:46 +02001095 for (diter = result; diter->next; diter = diter->next);
1096 result->prev = diter;
Radek Krejcib9930252015-07-08 15:47:45 +02001097 }
Radek Krejci1721c012015-07-08 12:52:33 +02001098 return result;
Radek Krejci3e3affe2015-07-09 15:38:40 +02001099
1100error:
1101
Radek Krejci25b9fd32015-08-10 15:06:07 +02001102 if (result) {
1103 result->next = NULL;
1104 result->parent = NULL;
1105 result->prev = result;
1106 lyd_free(result);
Radek Krejci7511f402015-07-10 09:56:30 +02001107 }
Radek Krejci3e3affe2015-07-09 15:38:40 +02001108
1109 return NULL;
Radek Krejci1721c012015-07-08 12:52:33 +02001110}
1111
Radek Krejci5a988152015-07-15 11:16:26 +02001112static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001113check_unres(struct unres_data **list)
Radek Krejci5a988152015-07-15 11:16:26 +02001114{
Radek Krejci5a988152015-07-15 11:16:26 +02001115 struct lyd_node_leaf *leaf;
Radek Krejcib8048692015-08-05 13:36:34 +02001116 struct lys_node_leaf *sleaf;
Michal Vaskof02e3742015-08-05 16:27:02 +02001117 struct unres_data *item, *refset = NULL, *ref;
Radek Krejci5a988152015-07-15 11:16:26 +02001118
Michal Vasko493bea72015-07-16 16:08:12 +02001119 while (*list) {
Michal Vasko8ed75302015-07-17 11:05:14 +02001120 leaf = (struct lyd_node_leaf *)(*list)->dnode;
Radek Krejcib8048692015-08-05 13:36:34 +02001121 sleaf = (struct lys_node_leaf *)(*list)->dnode->schema;
Michal Vasko8ed75302015-07-17 11:05:14 +02001122
Radek Krejci5a988152015-07-15 11:16:26 +02001123 /* resolve path and create a set of possible leafrefs (we need their values) */
Michal Vasko493bea72015-07-16 16:08:12 +02001124 if ((*list)->is_leafref) {
Michal Vasko1f76a282015-08-04 16:16:53 +02001125 if (resolve_path_arg_data(*list, sleaf->type.info.lref.path, &refset)) {
Michal Vasko955abbb2015-07-17 11:31:21 +02001126 LOGERR(LY_EVALID, "Leafref \"%s\" could not be resolved.", sleaf->type.info.lref.path);
Michal Vasko493bea72015-07-16 16:08:12 +02001127 goto error;
Radek Krejci5a988152015-07-15 11:16:26 +02001128 }
Michal Vasko493bea72015-07-16 16:08:12 +02001129
1130 while (refset) {
1131 if (leaf->value_str == ((struct lyd_node_leaf *)refset->dnode)->value_str) {
1132 leaf->value.leafref = refset->dnode;
1133 }
1134 ref = refset->next;
1135 free(refset);
1136 refset = ref;
1137 }
1138
1139 if (!leaf->value.leafref) {
1140 /* reference not found */
Michal Vasko955abbb2015-07-17 11:31:21 +02001141 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 +02001142 goto error;
1143 }
1144
Michal Vasko493bea72015-07-16 16:08:12 +02001145 /* instance-identifier */
1146 } else {
Radek Krejcic5090c32015-08-12 09:46:19 +02001147 ly_errno = 0;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001148 if (!resolve_instid((*list)->dnode, leaf->value_str, LOGLINE(*list))) {
Radek Krejcic5090c32015-08-12 09:46:19 +02001149 if (ly_errno) {
1150 goto error;
1151 } else if (sleaf->type.info.inst.req > -1) {
1152 LOGERR(LY_EVALID, "Instance for the \"%s\" does not exist.", leaf->value_str);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001153 goto error;
1154 } else {
Radek Krejcic5090c32015-08-12 09:46:19 +02001155 LOGVRB("Instance for the \"%s\" does not exist.", leaf->value_str);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001156 }
Michal Vasko493bea72015-07-16 16:08:12 +02001157 }
Radek Krejci5a988152015-07-15 11:16:26 +02001158 }
Michal Vasko8ed75302015-07-17 11:05:14 +02001159
1160 item = (*list)->next;
1161 free(*list);
1162 *list = item;
Radek Krejci5a988152015-07-15 11:16:26 +02001163 }
1164
1165 return EXIT_SUCCESS;
1166
1167error:
1168
1169 while (*list) {
1170 item = (*list)->next;
1171 free(*list);
1172 *list = item;
1173 }
1174
1175 return EXIT_FAILURE;
1176}
1177
Radek Krejci25b9fd32015-08-10 15:06:07 +02001178struct lyd_node *
1179xml_read_data(struct ly_ctx *ctx, const char *data, int options)
Radek Krejci1721c012015-07-08 12:52:33 +02001180{
1181 struct lyxml_elem *xml;
Radek Krejci0e1d1a62015-07-31 11:17:01 +02001182 struct lyd_node *result, *next, *iter;
Michal Vaskof02e3742015-08-05 16:27:02 +02001183 struct unres_data *unres = NULL;
Radek Krejci1721c012015-07-08 12:52:33 +02001184
1185 xml = lyxml_read(ctx, data, 0);
1186 if (!xml) {
1187 return NULL;
1188 }
1189
Radek Krejci25b9fd32015-08-10 15:06:07 +02001190 ly_errno = 0;
1191 result = xml_parse_data(ctx, xml->child, NULL, NULL, options, &unres);
Michal Vasko493bea72015-07-16 16:08:12 +02001192 /* check leafrefs and/or instids if any */
1193 if (check_unres(&unres)) {
1194 /* leafref & instid checking failed */
Radek Krejci0e1d1a62015-07-31 11:17:01 +02001195 LY_TREE_FOR_SAFE(result, next, iter) {
1196 lyd_free(iter);
1197 }
1198 result = NULL;
Radek Krejci5a988152015-07-15 11:16:26 +02001199 }
1200
1201 /* free source XML tree */
Radek Krejci1721c012015-07-08 12:52:33 +02001202 lyxml_free_elem(ctx, xml);
1203
1204 return result;
1205}