blob: 94780c20a802b08e0ac5870e8f5be2ad86aa50cf [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 Vasko8bcdf292015-08-19 14:04:43 +020027#include <limits.h>
Michal Vaskobe190a62015-07-13 16:14:20 +020028#include <sys/types.h>
29#include <regex.h>
Radek Krejci1721c012015-07-08 12:52:33 +020030
Radek Krejci998a0b82015-08-17 13:14:36 +020031#include "libyang.h"
32#include "common.h"
33#include "context.h"
34#include "resolve.h"
35#include "xml.h"
36#include "tree_internal.h"
37#include "validation.h"
Radek Krejci1721c012015-07-08 12:52:33 +020038
39#define LY_NSNC "urn:ietf:params:xml:ns:netconf:base:1.0"
40
Michal Vasko249e6b52015-08-19 11:08:52 +020041/**
42 * @brief Transform instance-identifier from XML data format to
43 * JSON data format (replace prefixes with module names).
44 * Logs directly.
45 *
46 * @param[in] ctx Main context with the dictionary.
47 * @param[in] xml Instance-identifier XML element.
48 *
49 * @return Transformed instance-identifier or NULL on error.
50 */
51static const char *
52transform_instid_xml2json(struct ly_ctx *ctx, struct lyxml_elem *xml)
53{
54 const char *in, *id;
55 char *out, *col, *prefix;
56 size_t out_size, out_used, id_len, rc;
57 struct lys_module *mod;
58 struct lyxml_ns *ns;
59
60 in = xml->content;
61 out_size = strlen(in)+1;
62 out = malloc(out_size);
63 out_used = 0;
64
65 while (1) {
66 col = strchr(in, ':');
67 /* we're finished, copy the remaining part */
68 if (!col) {
69 strcpy(&out[out_used], in);
70 out_used += strlen(in)+1;
71 assert(out_size == out_used);
72 return lydict_insert_zc(ctx, out);
73 }
74 id = strpbrk_backwards(col-1, "/ [", (col-in)-1);
75 ++id;
76 id_len = col-id;
77 rc = parse_identifier(id);
78 if (rc < id_len) {
79 LOGVAL(LYE_INCHAR, LOGLINE(xml), id[rc], &id[rc]);
80 free(out);
81 return NULL;
82 }
83
84 /* get the module */
85 prefix = strndup(id, id_len);
86 ns = lyxml_get_ns(xml, prefix);
87 free(prefix);
88 if (!ns) {
89 LOGVAL(LYE_SPEC, LOGLINE(xml), "XML namespace with prefix \"%.*s\" not defined.", id_len, id);
90 free(out);
91 return NULL;
92 }
93 mod = ly_ctx_get_module_by_ns(ctx, ns->value, NULL);
94 if (!mod) {
95 LOGVAL(LYE_SPEC, LOGLINE(xml), "Module with the namespace \"%s\" could not be found.", ns->value);
96 free(out);
97 return NULL;
98 }
99
100 /* adjust out size (it can even decrease in some strange cases) */
101 out_size += strlen(mod->name)-id_len;
102 out = realloc(out, out_size);
103
104 /* copy the data before prefix */
105 strncpy(&out[out_used], in, id-in);
106 out_used += id-in;
107
108 /* copy the model name */
109 strcpy(&out[out_used], mod->name);
110 out_used += strlen(mod->name);
111
112 /* copy ':' */
113 out[out_used] = ':';
114 ++out_used;
115
116 /* finally adjust in pointer for next round */
117 in = col+1;
118 }
119
120 /* unreachable */
121 assert(0);
122 return NULL;
123}
124
Michal Vasko9286afd2015-07-14 15:27:59 +0200125/* kind == 0 - unsigned (unum used), 1 - signed (snum used), 2 - floating point (fnum used) */
126static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200127validate_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 +0200128 struct lyxml_elem *xml, const char *str_val, int log)
Michal Vasko9286afd2015-07-14 15:27:59 +0200129{
Michal Vasko020404f2015-07-15 15:45:42 +0200130 struct len_ran_intv *intv = NULL, *tmp_intv;
Michal Vaskof02e3742015-08-05 16:27:02 +0200131 int ret = EXIT_FAILURE;
Michal Vasko9286afd2015-07-14 15:27:59 +0200132
Michal Vasko9c1bc642015-08-05 16:25:53 +0200133 if (resolve_len_ran_interval(NULL, type, 0, &intv)) {
134 return EXIT_FAILURE;
135 }
Michal Vasko020404f2015-07-15 15:45:42 +0200136 if (!intv) {
Michal Vaskof02e3742015-08-05 16:27:02 +0200137 return EXIT_SUCCESS;
Michal Vasko020404f2015-07-15 15:45:42 +0200138 }
139
Michal Vasko9286afd2015-07-14 15:27:59 +0200140 for (tmp_intv = intv; tmp_intv; tmp_intv = tmp_intv->next) {
141 if (((kind == 0) && (unum < tmp_intv->value.uval.min))
142 || ((kind == 1) && (snum < tmp_intv->value.sval.min))
143 || ((kind == 2) && (fnum < tmp_intv->value.fval.min))) {
144 break;
145 }
146
147 if (((kind == 0) && (unum >= tmp_intv->value.uval.min) && (unum <= tmp_intv->value.uval.max))
148 || ((kind == 1) && (snum >= tmp_intv->value.sval.min) && (snum <= tmp_intv->value.sval.max))
149 || ((kind == 2) && (fnum >= tmp_intv->value.fval.min) && (fnum <= tmp_intv->value.fval.max))) {
Michal Vaskof02e3742015-08-05 16:27:02 +0200150 ret = EXIT_SUCCESS;
Michal Vasko9286afd2015-07-14 15:27:59 +0200151 break;
152 }
153 }
154
155 while (intv) {
156 tmp_intv = intv->next;
157 free(intv);
158 intv = tmp_intv;
159 }
160
Michal Vasko07471a52015-07-16 11:18:48 +0200161 if (ret && log) {
Michal Vaskoc07187d2015-08-13 15:20:57 +0200162 /* so that it's used even in RELEASE target */
163 (void)xml;
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200164 LOGVAL(LYE_OORVAL, LOGLINE(xml), str_val);
Michal Vasko0e60c832015-07-15 15:48:35 +0200165 }
Michal Vasko9286afd2015-07-14 15:27:59 +0200166 return ret;
167}
168
Michal Vaskofbf7e482015-07-14 14:49:03 +0200169static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200170validate_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 +0200171{
172 int i;
173 regex_t preq;
174 char *posix_regex;
175
176 assert(type->base == LY_TYPE_STRING);
177
Michal Vasko07471a52015-07-16 11:18:48 +0200178 if (type->der && validate_pattern(str, &type->der->type, xml, str_val, log)) {
Michal Vaskof02e3742015-08-05 16:27:02 +0200179 return EXIT_FAILURE;
Michal Vaskofbf7e482015-07-14 14:49:03 +0200180 }
181
182 for (i = 0; i < type->info.str.pat_count; ++i) {
183 /*
184 * adjust the expression to a POSIX.2 equivalent
185 *
186 * http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#regexs
187 */
188 posix_regex = malloc((strlen(type->info.str.patterns[i].expr)+3) * sizeof(char));
189 posix_regex[0] = '\0';
190
191 if (strncmp(type->info.str.patterns[i].expr, ".*", 2)) {
192 strcat(posix_regex, "^");
193 }
194 strcat(posix_regex, type->info.str.patterns[i].expr);
195 if (strncmp(type->info.str.patterns[i].expr
196 + strlen(type->info.str.patterns[i].expr) - 2, ".*", 2)) {
197 strcat(posix_regex, "$");
198 }
199
200 /* must return 0, already checked during parsing */
Michal Vasko88876dc2015-08-05 09:46:40 +0200201 if (regcomp(&preq, posix_regex, REG_EXTENDED | REG_NOSUB)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200202 LOGINT;
Radek Krejci61ff1a02015-08-13 09:11:34 +0200203 free(posix_regex);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200204 return EXIT_FAILURE;
Michal Vasko88876dc2015-08-05 09:46:40 +0200205 }
Michal Vaskofbf7e482015-07-14 14:49:03 +0200206 free(posix_regex);
207
208 if (regexec(&preq, str, 0, 0, 0)) {
209 regfree(&preq);
Michal Vasko07471a52015-07-16 11:18:48 +0200210 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200211 LOGVAL(LYE_INVAL, LOGLINE(xml), str_val, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200212 }
Michal Vaskof02e3742015-08-05 16:27:02 +0200213 return EXIT_FAILURE;
Michal Vaskofbf7e482015-07-14 14:49:03 +0200214 }
215 regfree(&preq);
216 }
217
Michal Vaskof02e3742015-08-05 16:27:02 +0200218 return EXIT_SUCCESS;
Michal Vaskofbf7e482015-07-14 14:49:03 +0200219}
220
Radek Krejci76512572015-08-04 09:47:08 +0200221static struct lys_node *
222xml_data_search_schemanode(struct lyxml_elem *xml, struct lys_node *start)
Radek Krejci1721c012015-07-08 12:52:33 +0200223{
Radek Krejci76512572015-08-04 09:47:08 +0200224 struct lys_node *result, *aux;
Radek Krejci1721c012015-07-08 12:52:33 +0200225
226 LY_TREE_FOR(start, result) {
227 /* skip groupings */
Radek Krejci76512572015-08-04 09:47:08 +0200228 if (result->nodetype == LYS_GROUPING) {
Radek Krejci1721c012015-07-08 12:52:33 +0200229 continue;
230 }
231
232 /* go into cases, choices, uses */
Radek Krejci76512572015-08-04 09:47:08 +0200233 if (result->nodetype & (LYS_CHOICE | LYS_CASE | LYS_USES)) {
Radek Krejci1721c012015-07-08 12:52:33 +0200234 aux = xml_data_search_schemanode(xml, result->child);
235 if (aux) {
236 /* we have matching result */
237 return aux;
238 }
239 /* else, continue with next schema node */
240 continue;
241 }
242
243 /* match data nodes */
244 if (result->name == xml->name) {
245 /* names matches, what about namespaces? */
246 if (result->module->ns == xml->ns->value) {
247 /* we have matching result */
248 return result;
249 }
250 /* else, continue with next schema node */
251 continue;
252 }
253 }
254
255 /* no match */
256 return NULL;
257}
258
Radek Krejcie4748472015-07-08 18:00:22 +0200259static int
Michal Vasko07471a52015-07-16 11:18:48 +0200260parse_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 +0200261{
262 char *strptr;
263
264 /* convert to 64-bit integer, all the redundant characters are handled */
265 errno = 0;
266 strptr = NULL;
267 *ret = strtoll(str_val, &strptr, base);
268 if (errno || (*ret < min) || (*ret > max)) {
Michal Vasko07471a52015-07-16 11:18:48 +0200269 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200270 LOGVAL(LYE_OORVAL, LOGLINE(xml), str_val, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200271 }
Michal Vaskof02e3742015-08-05 16:27:02 +0200272 return EXIT_FAILURE;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200273 } else if (strptr && *strptr) {
274 while (isspace(*strptr)) {
275 ++strptr;
276 }
277 if (*strptr) {
Michal Vasko07471a52015-07-16 11:18:48 +0200278 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200279 LOGVAL(LYE_INVAL, LOGLINE(xml), str_val, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200280 }
Michal Vaskof02e3742015-08-05 16:27:02 +0200281 return EXIT_FAILURE;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200282 }
283 }
284
Michal Vaskof02e3742015-08-05 16:27:02 +0200285 return EXIT_SUCCESS;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200286}
287
288static int
Michal Vasko07471a52015-07-16 11:18:48 +0200289parse_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 +0200290{
291 char *strptr;
292
293 errno = 0;
294 strptr = NULL;
295 *ret = strtoull(str_val, &strptr, base);
296 if (errno || (*ret > max)) {
Michal Vasko07471a52015-07-16 11:18:48 +0200297 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200298 LOGVAL(LYE_OORVAL, LOGLINE(xml), str_val, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200299 }
Michal Vaskof02e3742015-08-05 16:27:02 +0200300 return EXIT_FAILURE;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200301 } else if (strptr && *strptr) {
302 while (isspace(*strptr)) {
303 ++strptr;
304 }
305 if (*strptr) {
Michal Vasko07471a52015-07-16 11:18:48 +0200306 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200307 LOGVAL(LYE_INVAL, LOGLINE(xml), str_val, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200308 }
Michal Vaskof02e3742015-08-05 16:27:02 +0200309 return EXIT_FAILURE;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200310 }
311 }
312
Michal Vaskof02e3742015-08-05 16:27:02 +0200313 return EXIT_SUCCESS;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200314}
315
Radek Krejci1574a8d2015-08-03 14:16:52 +0200316static struct lys_type *
317get_next_union_type(struct lys_type *type, struct lys_type *prev_type, int *found)
Radek Krejcie4748472015-07-08 18:00:22 +0200318{
Michal Vasko07471a52015-07-16 11:18:48 +0200319 int i;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200320 struct lys_type *ret = NULL;
Michal Vasko07471a52015-07-16 11:18:48 +0200321
Michal Vasko6da1a372015-07-27 11:19:10 +0200322 for (i = 0; i < type->info.uni.count; ++i) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200323 if (type->info.uni.types[i].base == LY_TYPE_UNION) {
324 ret = get_next_union_type(&type->info.uni.types[i], prev_type, found);
Michal Vasko6da1a372015-07-27 11:19:10 +0200325 if (ret) {
Michal Vasko07471a52015-07-16 11:18:48 +0200326 break;;
327 }
328 continue;
329 }
330
331 if (!prev_type || *found) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200332 ret = &type->info.uni.types[i];
Michal Vasko07471a52015-07-16 11:18:48 +0200333 break;
334 }
335
Radek Krejci1574a8d2015-08-03 14:16:52 +0200336 if (&type->info.uni.types[i] == prev_type) {
Michal Vasko07471a52015-07-16 11:18:48 +0200337 *found = 1;
338 }
339 }
340
Michal Vasko6da1a372015-07-27 11:19:10 +0200341 if (!ret && type->der) {
342 ret = get_next_union_type(&type->der->type, prev_type, found);
343 }
344
345 return ret;
Michal Vasko07471a52015-07-16 11:18:48 +0200346}
347
348static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200349_xml_get_value(struct lyd_node *node, struct lys_type *node_type, struct lyxml_elem *xml,
Michal Vasko23b61ec2015-08-19 11:19:50 +0200350 int options, struct unres_data *unres, int log)
Michal Vasko07471a52015-07-16 11:18:48 +0200351{
352 #define DECSIZE 21
Radek Krejci3e3affe2015-07-09 15:38:40 +0200353 struct lyd_node_leaf *leaf = (struct lyd_node_leaf *)node;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200354 struct lys_type *type;
Radek Krejciac8aac62015-07-10 15:36:35 +0200355 struct lyxml_ns *ns;
Radek Krejci7511f402015-07-10 09:56:30 +0200356 char dec[DECSIZE];
Michal Vaskofbf7e482015-07-14 14:49:03 +0200357 char *strptr;
Radek Krejciac8aac62015-07-10 15:36:35 +0200358 const char *name;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200359 int64_t num;
360 uint64_t unum;
Radek Krejci3e3affe2015-07-09 15:38:40 +0200361 int len;
Radek Krejci7511f402015-07-10 09:56:30 +0200362 int c, i, j, d;
Radek Krejci3e3affe2015-07-09 15:38:40 +0200363 int found;
Michal Vasko23b61ec2015-08-19 11:19:50 +0200364
365 assert(node && node_type && xml && unres);
Radek Krejci5a988152015-07-15 11:16:26 +0200366
367 leaf->value_str = xml->content;
368 xml->content = NULL;
Radek Krejcie4748472015-07-08 18:00:22 +0200369
Radek Krejcie3c33142015-08-10 15:04:36 +0200370 /* will be change in case of union */
371 leaf->value_type = node_type->base;
372
Radek Krejcie2cf7c12015-08-12 10:24:05 +0200373 if ((options & LYD_OPT_FILTER) && !leaf->value_str) {
374 /* no value in filter (selection) node -> nothing more is needed */
375 return EXIT_SUCCESS;
376 }
377
Michal Vasko07471a52015-07-16 11:18:48 +0200378 switch (node_type->base) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200379 case LY_TYPE_BINARY:
Radek Krejci5a988152015-07-15 11:16:26 +0200380 leaf->value.binary = leaf->value_str;
Radek Krejci3e3affe2015-07-09 15:38:40 +0200381
Michal Vasko07471a52015-07-16 11:18:48 +0200382 if (node_type->info.binary.length
383 && validate_length_range(0, strlen(leaf->value.binary), 0, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko0e60c832015-07-15 15:48:35 +0200384 return EXIT_FAILURE;
Radek Krejcie4748472015-07-08 18:00:22 +0200385 }
386 break;
387
Radek Krejci3e3affe2015-07-09 15:38:40 +0200388 case LY_TYPE_BITS:
Radek Krejci3e3affe2015-07-09 15:38:40 +0200389 /* locate bits structure with the bits definitions */
Michal Vasko07471a52015-07-16 11:18:48 +0200390 for (type = node_type; type->der->type.der; type = &type->der->type);
Radek Krejci3e3affe2015-07-09 15:38:40 +0200391
392 /* allocate the array of pointers to bits definition */
393 leaf->value.bit = calloc(type->info.bits.count, sizeof *leaf->value.bit);
394
Radek Krejci5a988152015-07-15 11:16:26 +0200395 if (!leaf->value_str) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200396 /* no bits set */
397 break;
398 }
399
400 c = 0;
401 i = 0;
Radek Krejci5a988152015-07-15 11:16:26 +0200402 while (leaf->value_str[c]) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200403 /* skip leading whitespaces */
Radek Krejci5a988152015-07-15 11:16:26 +0200404 while(isspace(leaf->value_str[c])) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200405 c++;
406 }
407
408 /* get the length of the bit identifier */
Radek Krejci5a988152015-07-15 11:16:26 +0200409 for (len = 0; leaf->value_str[c] && !isspace(leaf->value_str[c]); c++, len++);
Radek Krejci3e3affe2015-07-09 15:38:40 +0200410
411 /* go back to the beginning of the identifier */
412 c = c - len;
413
414 /* find bit definition, identifiers appear ordered by their posititon */
415 for (found = 0; i < type->info.bits.count; i++) {
Radek Krejci5a988152015-07-15 11:16:26 +0200416 if (!strncmp(type->info.bits.bit[i].name, &leaf->value_str[c], len)
Radek Krejci3e3affe2015-07-09 15:38:40 +0200417 && !type->info.bits.bit[i].name[len]) {
418 /* we have match, store the pointer */
419 leaf->value.bit[i] = &type->info.bits.bit[i];
420
421 /* stop searching */
422 i++;
423 found = 1;
424 break;
425 }
426 }
427
428 if (!found) {
429 /* referenced bit value does not exists */
Michal Vasko07471a52015-07-16 11:18:48 +0200430 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200431 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200432 }
Radek Krejci3e3affe2015-07-09 15:38:40 +0200433 return EXIT_FAILURE;
434 }
435
436 c = c + len;
437 }
438
439 break;
440
Radek Krejcib7384642015-07-09 16:08:45 +0200441 case LY_TYPE_BOOL:
Radek Krejci5a988152015-07-15 11:16:26 +0200442 if (!strcmp(leaf->value_str, "true")) {
Radek Krejcib7384642015-07-09 16:08:45 +0200443 leaf->value.bool = 1;
444 } /* else false, so keep it zero */
445 break;
446
Radek Krejci7511f402015-07-10 09:56:30 +0200447 case LY_TYPE_DEC64:
448 /* locate dec64 structure with the fraction-digits value */
Michal Vasko07471a52015-07-16 11:18:48 +0200449 for (type = node_type; type->der->type.der; type = &type->der->type);
Radek Krejci7511f402015-07-10 09:56:30 +0200450
Radek Krejci5a988152015-07-15 11:16:26 +0200451 for (c = 0; isspace(leaf->value_str[c]); c++);
452 for (len = 0; leaf->value_str[c] && !isspace(leaf->value_str[c]); c++, len++);
Radek Krejci7511f402015-07-10 09:56:30 +0200453 c = c - len;
454 if (len > DECSIZE) {
455 /* too long */
Michal Vasko07471a52015-07-16 11:18:48 +0200456 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200457 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200458 }
Radek Krejci7511f402015-07-10 09:56:30 +0200459 return EXIT_FAILURE;
460 }
461
462 /* normalize the number */
463 dec[0] = '\0';
464 for (i = j = d = found = 0; i < DECSIZE; i++) {
Radek Krejci5a988152015-07-15 11:16:26 +0200465 if (leaf->value_str[c + i] == '.') {
Radek Krejci7511f402015-07-10 09:56:30 +0200466 found = 1;
467 j = type->info.dec64.dig;
468 i--;
469 c++;
470 continue;
471 }
Radek Krejci5a988152015-07-15 11:16:26 +0200472 if (leaf->value_str[c + i] == '\0') {
Radek Krejci7511f402015-07-10 09:56:30 +0200473 c--;
474 if (!found) {
475 j = type->info.dec64.dig;
476 found = 1;
477 }
478 if (!j) {
479 dec[i] = '\0';
480 break;
481 }
482 d++;
483 if (d > DECSIZE - 2) {
Michal Vasko07471a52015-07-16 11:18:48 +0200484 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200485 LOGVAL(LYE_OORVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200486 }
Radek Krejci7511f402015-07-10 09:56:30 +0200487 return EXIT_FAILURE;
488 }
489 dec[i] = '0';
490 } else {
Radek Krejci5a988152015-07-15 11:16:26 +0200491 if (!isdigit(leaf->value_str[c + i])) {
492 if (i || leaf->value_str[c] != '-') {
Michal Vasko07471a52015-07-16 11:18:48 +0200493 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200494 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200495 }
Radek Krejci7511f402015-07-10 09:56:30 +0200496 return EXIT_FAILURE;
497 }
498 } else {
499 d++;
500 }
501 if (d > DECSIZE - 2 || (found && !j)) {
Michal Vasko07471a52015-07-16 11:18:48 +0200502 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200503 LOGVAL(LYE_OORVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200504 }
Radek Krejci7511f402015-07-10 09:56:30 +0200505 return EXIT_FAILURE;
506 }
Radek Krejci5a988152015-07-15 11:16:26 +0200507 dec[i] = leaf->value_str[c + i];
Radek Krejci7511f402015-07-10 09:56:30 +0200508 }
509 if (j) {
510 j--;
511 }
512 }
513
Michal Vasko07471a52015-07-16 11:18:48 +0200514 if (parse_int(dec, xml, -9223372036854775807L - 1L, 9223372036854775807L, 10, &num, log)
515 || 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 +0200516 return EXIT_FAILURE;
517 }
Michal Vaskobdee69c2015-07-15 15:49:39 +0200518 leaf->value.dec64 = num;
Radek Krejci7511f402015-07-10 09:56:30 +0200519 break;
520
Radek Krejcibce73742015-07-10 12:46:06 +0200521 case LY_TYPE_EMPTY:
522 /* just check that it is empty */
Radek Krejci5a988152015-07-15 11:16:26 +0200523 if (leaf->value_str && leaf->value_str[0]) {
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 Krejcibce73742015-07-10 12:46:06 +0200527 return EXIT_FAILURE;
528 }
529 break;
530
Radek Krejci5b315a92015-07-10 13:18:45 +0200531 case LY_TYPE_ENUM:
Radek Krejci5a988152015-07-15 11:16:26 +0200532 if (!leaf->value_str) {
Michal Vasko07471a52015-07-16 11:18:48 +0200533 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200534 LOGVAL(LYE_INVAL, LOGLINE(xml), "", xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200535 }
Radek Krejci5b315a92015-07-10 13:18:45 +0200536 return EXIT_FAILURE;
537 }
538
539 /* locate enums structure with the enumeration definitions */
Michal Vasko07471a52015-07-16 11:18:48 +0200540 for (type = node_type; type->der->type.der; type = &type->der->type);
Radek Krejci5b315a92015-07-10 13:18:45 +0200541
542 /* find matching enumeration value */
543 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200544 if (!strcmp(leaf->value_str, type->info.enums.enm[i].name)) {
Radek Krejci5b315a92015-07-10 13:18:45 +0200545 /* we have match, store pointer to the definition */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200546 leaf->value.enm = &type->info.enums.enm[i];
Radek Krejci5b315a92015-07-10 13:18:45 +0200547 break;
548 }
549 }
550
551 if (!leaf->value.enm) {
Michal Vasko07471a52015-07-16 11:18:48 +0200552 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200553 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200554 }
Radek Krejci5b315a92015-07-10 13:18:45 +0200555 return EXIT_FAILURE;
556 }
557
558 break;
559
Radek Krejciac8aac62015-07-10 15:36:35 +0200560 case LY_TYPE_IDENT:
Radek Krejci5a988152015-07-15 11:16:26 +0200561 if ((strptr = strchr(leaf->value_str, ':'))) {
562 len = strptr - leaf->value_str;
Radek Krejciac8aac62015-07-10 15:36:35 +0200563 if (!len) {
Michal Vasko07471a52015-07-16 11:18:48 +0200564 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200565 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200566 }
Radek Krejciac8aac62015-07-10 15:36:35 +0200567 return EXIT_FAILURE;
568 }
Radek Krejci5a988152015-07-15 11:16:26 +0200569 strptr = strndup(leaf->value_str, len);
Radek Krejciac8aac62015-07-10 15:36:35 +0200570 }
571 ns = lyxml_get_ns(xml, strptr);
572 if (!ns) {
Michal Vasko07471a52015-07-16 11:18:48 +0200573 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200574 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200575 }
Radek Krejciac8aac62015-07-10 15:36:35 +0200576 return EXIT_FAILURE;
577 }
578 if (strptr) {
579 free(strptr);
Radek Krejci5a988152015-07-15 11:16:26 +0200580 name = leaf->value_str + len + 1;
Radek Krejciac8aac62015-07-10 15:36:35 +0200581 } else {
Radek Krejci5a988152015-07-15 11:16:26 +0200582 name = leaf->value_str;
Radek Krejciac8aac62015-07-10 15:36:35 +0200583 }
584
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200585 leaf->value.ident = resolve_identityref(node_type->info.ident.ref, name, ns->value);
Radek Krejciac8aac62015-07-10 15:36:35 +0200586 if (!leaf->value.ident) {
Michal Vasko07471a52015-07-16 11:18:48 +0200587 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200588 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200589 }
Radek Krejciac8aac62015-07-10 15:36:35 +0200590 return EXIT_FAILURE;
591 }
592 break;
593
Michal Vasko07471a52015-07-16 11:18:48 +0200594 case LY_TYPE_INST:
Michal Vasko493bea72015-07-16 16:08:12 +0200595 if (!leaf->value_str) {
596 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200597 LOGVAL(LYE_INVAL, LOGLINE(xml), "", xml->name);
Michal Vasko493bea72015-07-16 16:08:12 +0200598 }
599 return EXIT_FAILURE;
600 }
601
Radek Krejcic5090c32015-08-12 09:46:19 +0200602 /* convert the path from the XML form using XML namespaces into the JSON format
603 * using module names as namespaces
604 */
605 xml->content = leaf->value_str;
Michal Vasko083a4332015-08-19 11:11:43 +0200606 leaf->value_str = transform_instid_xml2json(node->schema->module->ctx, xml);
Radek Krejcic5090c32015-08-12 09:46:19 +0200607 lydict_remove(node->schema->module->ctx, xml->content);
608 xml->content = NULL;
609 if (!leaf->value_str) {
610 return EXIT_FAILURE;
611 }
612
Radek Krejcib1c12512015-08-11 11:22:04 +0200613 if (options & (LYD_OPT_EDIT | LYD_OPT_FILTER)) {
614 leaf->value_type |= LY_TYPE_INST_UNRES;
615 } else {
616 /* validity checking is performed later, right now the data tree
617 * is not complete, so many instanceids cannot be resolved
618 */
619 /* remember the leaf for later checking */
Michal Vasko8bcdf292015-08-19 14:04:43 +0200620 if (unres_data_add(unres, node, (log ? LOGLINE(xml) : UINT_MAX))) {
621 return EXIT_FAILURE;
622 }
Radek Krejcib1c12512015-08-11 11:22:04 +0200623 }
Michal Vasko07471a52015-07-16 11:18:48 +0200624 break;
625
Radek Krejci5a988152015-07-15 11:16:26 +0200626 case LY_TYPE_LEAFREF:
627 if (!leaf->value_str) {
Michal Vasko07471a52015-07-16 11:18:48 +0200628 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200629 LOGVAL(LYE_INVAL, LOGLINE(xml), "", xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200630 }
Radek Krejci5a988152015-07-15 11:16:26 +0200631 return EXIT_FAILURE;
632 }
633
Radek Krejcib1c12512015-08-11 11:22:04 +0200634 if (options & (LYD_OPT_EDIT | LYD_OPT_FILTER)) {
635 do {
636 type = &((struct lys_node_leaf *)leaf->schema)->type.info.lref.target->type;
637 } while (type->base == LY_TYPE_LEAFREF);
638 leaf->value_type = type->base | LY_TYPE_LEAFREF_UNRES;
639 } else {
640 /* validity checking is performed later, right now the data tree
641 * is not complete, so many leafrefs cannot be resolved
642 */
643 /* remember the leaf for later checking */
Michal Vasko8bcdf292015-08-19 14:04:43 +0200644 if (unres_data_add(unres, node, (log ? LOGLINE(xml) : UINT_MAX))) {
645 return EXIT_FAILURE;
646 }
Radek Krejcib1c12512015-08-11 11:22:04 +0200647 }
Radek Krejci5a988152015-07-15 11:16:26 +0200648 break;
649
Radek Krejci3e3affe2015-07-09 15:38:40 +0200650 case LY_TYPE_STRING:
Radek Krejci5a988152015-07-15 11:16:26 +0200651 leaf->value.string = leaf->value_str;
Radek Krejci3e3affe2015-07-09 15:38:40 +0200652
Michal Vasko07471a52015-07-16 11:18:48 +0200653 if (node_type->info.str.length
654 && validate_length_range(0, strlen(leaf->value.string), 0, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko0e60c832015-07-15 15:48:35 +0200655 return EXIT_FAILURE;
Radek Krejcie4748472015-07-08 18:00:22 +0200656 }
657
Michal Vasko07471a52015-07-16 11:18:48 +0200658 if (node_type->info.str.patterns
659 && validate_pattern(leaf->value.string, node_type, xml, leaf->value_str, log)) {
Michal Vasko0e60c832015-07-15 15:48:35 +0200660 return EXIT_FAILURE;
Radek Krejcie4748472015-07-08 18:00:22 +0200661 }
662 break;
663
Michal Vasko58110162015-07-15 15:50:16 +0200664 case LY_TYPE_UNION:
Michal Vasko07471a52015-07-16 11:18:48 +0200665 found = 0;
Michal Vasko6da1a372015-07-27 11:19:10 +0200666 type = get_next_union_type(node_type, NULL, &found);
667 for (; type; found = 0, type = get_next_union_type(node_type, type, &found)) {
Michal Vasko07471a52015-07-16 11:18:48 +0200668 xml->content = leaf->value_str;
Radek Krejci25b9fd32015-08-10 15:06:07 +0200669 if (!_xml_get_value(node, type, xml, options, unres, 0)) {
Michal Vasko07471a52015-07-16 11:18:48 +0200670 leaf->value_type = type->base;
671 break;
672 }
673 }
674
675 if (!type) {
676 if (log) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200677 LOGVAL(LYE_INVAL, LOGLINE(xml), leaf->value_str, xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200678 }
679 return EXIT_FAILURE;
680 }
Michal Vasko58110162015-07-15 15:50:16 +0200681 break;
682
683 case LY_TYPE_INT8:
Michal Vasko07471a52015-07-16 11:18:48 +0200684 if (parse_int(leaf->value_str, xml, -128, 127, 0, &num, log)
685 || validate_length_range(1, 0, num, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko58110162015-07-15 15:50:16 +0200686 return EXIT_FAILURE;
687 }
688 leaf->value.int8 = num;
689 break;
690
691 case LY_TYPE_INT16:
Michal Vasko07471a52015-07-16 11:18:48 +0200692 if (parse_int(leaf->value_str, xml, -32768, 32767, 0, &num, log)
693 || validate_length_range(1, 0, num, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko58110162015-07-15 15:50:16 +0200694 return EXIT_FAILURE;
695 }
696 leaf->value.int16 = num;
697 break;
698
699 case LY_TYPE_INT32:
Michal Vasko07471a52015-07-16 11:18:48 +0200700 if (parse_int(leaf->value_str, xml, -2147483648, 2147483647, 0, &num, log)
701 || validate_length_range(1, 0, num, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko58110162015-07-15 15:50:16 +0200702 return EXIT_FAILURE;
703 }
704 leaf->value.int32 = num;
705 break;
706
707 case LY_TYPE_INT64:
Michal Vasko07471a52015-07-16 11:18:48 +0200708 if (parse_int(leaf->value_str, xml, -9223372036854775807L - 1L, 9223372036854775807L, 0, &num, log)
709 || validate_length_range(1, 0, num, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko58110162015-07-15 15:50:16 +0200710 return EXIT_FAILURE;
711 }
712 leaf->value.int64 = num;
713 break;
714
715 case LY_TYPE_UINT8:
Michal Vasko07471a52015-07-16 11:18:48 +0200716 if (parse_uint(leaf->value_str, xml, 255, 0, &unum, log)
717 || validate_length_range(0, unum, 0, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko58110162015-07-15 15:50:16 +0200718 return EXIT_FAILURE;
719 }
720 leaf->value.uint8 = unum;
721 break;
722
723 case LY_TYPE_UINT16:
Michal Vasko07471a52015-07-16 11:18:48 +0200724 if (parse_uint(leaf->value_str, xml, 65535, 0, &unum, log)
725 || validate_length_range(0, unum, 0, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko58110162015-07-15 15:50:16 +0200726 return EXIT_FAILURE;
727 }
728 leaf->value.uint16 = unum;
729 break;
730
731 case LY_TYPE_UINT32:
Michal Vasko07471a52015-07-16 11:18:48 +0200732 if (parse_uint(leaf->value_str, xml, 4294967295, 0, &unum, log)
733 || validate_length_range(0, unum, 0, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko58110162015-07-15 15:50:16 +0200734 return EXIT_FAILURE;
735 }
736 leaf->value.uint32 = unum;
737 break;
738
739 case LY_TYPE_UINT64:
Michal Vasko07471a52015-07-16 11:18:48 +0200740 if (parse_uint(leaf->value_str, xml, 18446744073709551615UL, 0, &unum, log)
741 || validate_length_range(0, unum, 0, 0, node_type, xml, leaf->value_str, log)) {
Michal Vasko58110162015-07-15 15:50:16 +0200742 return EXIT_FAILURE;
743 }
744 leaf->value.uint64 = unum;
745 break;
746
Radek Krejcie4748472015-07-08 18:00:22 +0200747 default:
Michal Vasko493bea72015-07-16 16:08:12 +0200748 return EXIT_FAILURE;
Radek Krejcie4748472015-07-08 18:00:22 +0200749 }
750
751 return EXIT_SUCCESS;
752}
753
Michal Vasko07471a52015-07-16 11:18:48 +0200754static int
Michal Vasko23b61ec2015-08-19 11:19:50 +0200755xml_get_value(struct lyd_node *node, struct lyxml_elem *xml, int options, struct unres_data *unres)
Michal Vasko07471a52015-07-16 11:18:48 +0200756{
Radek Krejci25b9fd32015-08-10 15:06:07 +0200757 return _xml_get_value(node, &((struct lys_node_leaf *)node->schema)->type, xml, options, unres, 1);
Michal Vasko07471a52015-07-16 11:18:48 +0200758}
759
Radek Krejci1721c012015-07-08 12:52:33 +0200760struct lyd_node *
Michal Vasko493bea72015-07-16 16:08:12 +0200761xml_parse_data(struct ly_ctx *ctx, struct lyxml_elem *xml, struct lyd_node *parent, struct lyd_node *prev,
Michal Vasko23b61ec2015-08-19 11:19:50 +0200762 int options, struct unres_data *unres)
Radek Krejci1721c012015-07-08 12:52:33 +0200763{
Radek Krejci7f40ce32015-08-12 20:38:46 +0200764 struct lyd_node *result = NULL, *diter;
765 struct lys_node *schema = NULL, *siter;
Michal Vaskoab8e4402015-07-17 12:54:28 +0200766 int i, havechildren;
Radek Krejci1721c012015-07-08 12:52:33 +0200767
768 if (!xml) {
769 return NULL;
770 }
771 if (!xml->ns || !xml->ns->value) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200772 LOGVAL(LYE_XML_MISS, LOGLINE(xml), "element's", "namespace");
Radek Krejci1721c012015-07-08 12:52:33 +0200773 return NULL;
774 }
775
776 /* find schema node */
777 if (!parent) {
778 /* starting in root */
779 for (i = 0; i < ctx->models.used; i++) {
780 /* match data model based on namespace */
781 if (ctx->models.list[i]->ns == xml->ns->value) {
782 /* get the proper schema node */
783 LY_TREE_FOR(ctx->models.list[i]->data, schema) {
784 if (schema->name == xml->name) {
785 break;
786 }
787 }
788 break;
789 }
790 }
791 } else {
792 /* parsing some internal node, we start with parent's schema pointer */
793 schema = xml_data_search_schemanode(xml, parent->schema->child);
794 }
795 if (!schema) {
Radek Krejci25b9fd32015-08-10 15:06:07 +0200796 if ((options & LYD_OPT_STRICT) || ly_ctx_get_module_by_ns(ctx, xml->ns->value, NULL)) {
797 LOGVAL(LYE_INELEM, LOGLINE(xml), xml->name);
798 return NULL;
799 } else {
800 goto siblings;
801 }
Radek Krejci1721c012015-07-08 12:52:33 +0200802 }
803
Radek Krejcib9930252015-07-08 15:47:45 +0200804 switch (schema->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +0200805 case LYS_CONTAINER:
Michal Vaskoab8e4402015-07-17 12:54:28 +0200806 result = calloc(1, sizeof *result);
807 havechildren = 1;
Radek Krejcib9930252015-07-08 15:47:45 +0200808 break;
Radek Krejci76512572015-08-04 09:47:08 +0200809 case LYS_LEAF:
Radek Krejcie4748472015-07-08 18:00:22 +0200810 result = calloc(1, sizeof(struct lyd_node_leaf));
811 havechildren = 0;
812 break;
Radek Krejci76512572015-08-04 09:47:08 +0200813 case LYS_LEAFLIST:
Radek Krejcie4748472015-07-08 18:00:22 +0200814 result = calloc(1, sizeof(struct lyd_node_leaflist));
815 havechildren = 0;
816 break;
Radek Krejci76512572015-08-04 09:47:08 +0200817 case LYS_LIST:
Michal Vaskoab8e4402015-07-17 12:54:28 +0200818 result = calloc(1, sizeof(struct lyd_node_list));
819 havechildren = 1;
820 break;
Radek Krejci76512572015-08-04 09:47:08 +0200821 case LYS_ANYXML:
Michal Vaskoab8e4402015-07-17 12:54:28 +0200822 result = calloc(1, sizeof(struct lyd_node_anyxml));
823 havechildren = 0;
824 break;
Radek Krejcib9930252015-07-08 15:47:45 +0200825 default:
Michal Vasko0c888fd2015-08-11 15:54:08 +0200826 LOGINT;
Michal Vaskoab8e4402015-07-17 12:54:28 +0200827 return NULL;
Radek Krejcib9930252015-07-08 15:47:45 +0200828 }
Radek Krejci1721c012015-07-08 12:52:33 +0200829 result->parent = parent;
Radek Krejcib9930252015-07-08 15:47:45 +0200830 result->prev = prev;
Radek Krejci1721c012015-07-08 12:52:33 +0200831 result->schema = schema;
832
Radek Krejci88daf822015-08-10 13:58:16 +0200833 /* check number of instances for non-list nodes */
Radek Krejcib6772142015-08-12 10:16:44 +0200834 if (!(options & LYD_OPT_FILTER) && (schema->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_ANYXML))) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200835 for (diter = result->prev; diter; diter = diter->prev) {
836 if (diter->schema == schema) {
Radek Krejci88daf822015-08-10 13:58:16 +0200837 LOGVAL(LYE_TOOMANY, LOGLINE(xml), xml->name, xml->parent ? xml->parent->name : "data tree");
838 goto error;
839 }
840 }
841 }
842
Radek Krejcib9930252015-07-08 15:47:45 +0200843 /* type specific processing */
Radek Krejci76512572015-08-04 09:47:08 +0200844 if (schema->nodetype == LYS_LIST) {
Radek Krejcib9930252015-07-08 15:47:45 +0200845 /* pointers to next and previous instances of the same list */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200846 for (diter = result->prev; diter; diter = diter->prev) {
847 if (diter->schema == result->schema) {
Radek Krejcib9930252015-07-08 15:47:45 +0200848 /* instances of the same list */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200849 ((struct lyd_node_list *)diter)->lnext = (struct lyd_node_list *)result;
850 ((struct lyd_node_list *)result)->lprev = (struct lyd_node_list *)diter;
Radek Krejcib9930252015-07-08 15:47:45 +0200851 break;
852 }
853 }
Radek Krejci76512572015-08-04 09:47:08 +0200854 } else if (schema->nodetype == LYS_LEAF) {
Radek Krejcie4748472015-07-08 18:00:22 +0200855 /* type detection and assigning the value */
Radek Krejci25b9fd32015-08-10 15:06:07 +0200856 if (xml_get_value(result, xml, options, unres)) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200857 goto error;
858 }
Radek Krejci76512572015-08-04 09:47:08 +0200859 } else if (schema->nodetype == LYS_LEAFLIST) {
Radek Krejcie4748472015-07-08 18:00:22 +0200860 /* type detection and assigning the value */
Radek Krejci25b9fd32015-08-10 15:06:07 +0200861 if (xml_get_value(result, xml, options, unres)) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200862 goto error;
863 }
Radek Krejcie4748472015-07-08 18:00:22 +0200864
865 /* pointers to next and previous instances of the same leaflist */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200866 for (diter = result->prev; diter; diter = diter->prev) {
867 if (diter->schema == result->schema) {
Radek Krejcie4748472015-07-08 18:00:22 +0200868 /* instances of the same list */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200869 ((struct lyd_node_leaflist *)diter)->lnext = (struct lyd_node_leaflist *)result;
870 ((struct lyd_node_leaflist *)result)->lprev = (struct lyd_node_leaflist *)diter;
Radek Krejcie4748472015-07-08 18:00:22 +0200871 break;
872 }
873 }
Radek Krejci76512572015-08-04 09:47:08 +0200874 } else if (schema->nodetype == LYS_ANYXML) {
Michal Vaskoab8e4402015-07-17 12:54:28 +0200875 ((struct lyd_node_anyxml *)result)->value = xml;
876 lyxml_unlink_elem(xml);
Radek Krejcib9930252015-07-08 15:47:45 +0200877 }
878
Radek Krejci1721c012015-07-08 12:52:33 +0200879 /* process children */
Radek Krejcie4748472015-07-08 18:00:22 +0200880 if (havechildren && xml->child) {
Radek Krejci25b9fd32015-08-10 15:06:07 +0200881 result->child = xml_parse_data(ctx, xml->child, result, NULL, options, unres);
882 if (ly_errno) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200883 goto error;
Radek Krejci1721c012015-07-08 12:52:33 +0200884 }
Radek Krejci1721c012015-07-08 12:52:33 +0200885 }
886
Radek Krejcib1c12512015-08-11 11:22:04 +0200887 /* various validation checks */
Radek Krejci1073cc02015-08-12 20:37:39 +0200888
889 /* check presence of all keys in case of list */
Radek Krejcib1c12512015-08-11 11:22:04 +0200890 if (schema->nodetype == LYS_LIST && !(options & LYD_OPT_FILTER)) {
Radek Krejci1073cc02015-08-12 20:37:39 +0200891 siter = (struct lys_node *)lyv_keys_present((struct lyd_node_list *)result);
892 if (siter) {
Radek Krejcib1c12512015-08-11 11:22:04 +0200893 /* key not found in the data */
Radek Krejci1073cc02015-08-12 20:37:39 +0200894 LOGVAL(LYE_MISSELEM, LOGLINE(xml), siter->name, schema->name);
Radek Krejcib1c12512015-08-11 11:22:04 +0200895 goto error;
896 }
897 }
898
Radek Krejci7f40ce32015-08-12 20:38:46 +0200899 /* mandatory children */
900 if (havechildren && !(options & (LYD_OPT_FILTER | LYD_OPT_EDIT))) {
901 siter = ly_check_mandatory(result);
902 if (siter) {
903 LOGVAL(LYE_MISSELEM, LOGLINE(xml), siter->name, siter->parent->name);
904 goto error;
905 }
906 }
Radek Krejcib1c12512015-08-11 11:22:04 +0200907
Radek Krejci25b9fd32015-08-10 15:06:07 +0200908siblings:
Radek Krejci1721c012015-07-08 12:52:33 +0200909 /* process siblings */
910 if (xml->next) {
Radek Krejci25b9fd32015-08-10 15:06:07 +0200911 if (result) {
912 result->next = xml_parse_data(ctx, xml->next, parent, result, options, unres);
913 } else {
914 result = xml_parse_data(ctx, xml->next, parent, prev, options, unres);
915 }
916 if (ly_errno) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200917 goto error;
Radek Krejci1721c012015-07-08 12:52:33 +0200918 }
Radek Krejci1721c012015-07-08 12:52:33 +0200919 }
920
Radek Krejcib9930252015-07-08 15:47:45 +0200921 /* fix the "last" pointer */
Radek Krejci25b9fd32015-08-10 15:06:07 +0200922 if (result && !result->prev) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200923 for (diter = result; diter->next; diter = diter->next);
924 result->prev = diter;
Radek Krejcib9930252015-07-08 15:47:45 +0200925 }
Radek Krejci1721c012015-07-08 12:52:33 +0200926 return result;
Radek Krejci3e3affe2015-07-09 15:38:40 +0200927
928error:
929
Radek Krejci25b9fd32015-08-10 15:06:07 +0200930 if (result) {
931 result->next = NULL;
932 result->parent = NULL;
933 result->prev = result;
934 lyd_free(result);
Radek Krejci7511f402015-07-10 09:56:30 +0200935 }
Radek Krejci3e3affe2015-07-09 15:38:40 +0200936
937 return NULL;
Radek Krejci1721c012015-07-08 12:52:33 +0200938}
939
Radek Krejci25b9fd32015-08-10 15:06:07 +0200940struct lyd_node *
941xml_read_data(struct ly_ctx *ctx, const char *data, int options)
Radek Krejci1721c012015-07-08 12:52:33 +0200942{
943 struct lyxml_elem *xml;
Radek Krejci0e1d1a62015-07-31 11:17:01 +0200944 struct lyd_node *result, *next, *iter;
Michal Vaskof02e3742015-08-05 16:27:02 +0200945 struct unres_data *unres = NULL;
Radek Krejci1721c012015-07-08 12:52:33 +0200946
947 xml = lyxml_read(ctx, data, 0);
948 if (!xml) {
949 return NULL;
950 }
951
Michal Vasko23b61ec2015-08-19 11:19:50 +0200952 unres = calloc(1, sizeof *unres);
953
Radek Krejci25b9fd32015-08-10 15:06:07 +0200954 ly_errno = 0;
Michal Vasko23b61ec2015-08-19 11:19:50 +0200955 result = xml_parse_data(ctx, xml->child, NULL, NULL, options, unres);
Michal Vasko493bea72015-07-16 16:08:12 +0200956 /* check leafrefs and/or instids if any */
Michal Vasko8bcdf292015-08-19 14:04:43 +0200957 if (resolve_unres_data(unres)) {
Michal Vasko493bea72015-07-16 16:08:12 +0200958 /* leafref & instid checking failed */
Radek Krejci0e1d1a62015-07-31 11:17:01 +0200959 LY_TREE_FOR_SAFE(result, next, iter) {
960 lyd_free(iter);
961 }
962 result = NULL;
Radek Krejci5a988152015-07-15 11:16:26 +0200963 }
964
Michal Vasko23b61ec2015-08-19 11:19:50 +0200965 free(unres->dnode);
966#ifndef NDEBUG
967 free(unres->line);
968#endif
969 free(unres);
970
Radek Krejci5a988152015-07-15 11:16:26 +0200971 /* free source XML tree */
Radek Krejci1721c012015-07-08 12:52:33 +0200972 lyxml_free_elem(ctx, xml);
973
974 return result;
975}