blob: 564e0079103fc9b350b625f4b84389a1d9488fd2 [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>
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +020029#include <pcre.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/**
Michal Vaskofb0873c2015-08-21 09:00:07 +020042 * @brief Transform data from XML format (prefixes and separate NS definitions) to
43 * JSON format (prefixes are module names instead).
Michal Vasko249e6b52015-08-19 11:08:52 +020044 * Logs directly.
45 *
46 * @param[in] ctx Main context with the dictionary.
Michal Vaskofb0873c2015-08-21 09:00:07 +020047 * @param[in] xml XML data value.
Michal Vasko249e6b52015-08-19 11:08:52 +020048 *
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020049 * @return Transformed data in the dictionary or NULL on error.
Michal Vasko249e6b52015-08-19 11:08:52 +020050 */
51static const char *
Michal Vaskofb0873c2015-08-21 09:00:07 +020052transform_data_xml2json(struct ly_ctx *ctx, struct lyxml_elem *xml, int log)
Michal Vasko249e6b52015-08-19 11:08:52 +020053{
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);
Michal Vaskofb0873c2015-08-21 09:00:07 +020075 if ((id[0] == '/') || (id[0] == ' ') || (id[0] == '[')) {
76 ++id;
77 }
Michal Vasko249e6b52015-08-19 11:08:52 +020078 id_len = col-id;
79 rc = parse_identifier(id);
80 if (rc < id_len) {
Michal Vaskofb0873c2015-08-21 09:00:07 +020081 if (log) {
82 LOGVAL(LYE_INCHAR, LOGLINE(xml), id[rc], &id[rc]);
83 }
Michal Vasko249e6b52015-08-19 11:08:52 +020084 free(out);
85 return NULL;
86 }
87
88 /* get the module */
89 prefix = strndup(id, id_len);
90 ns = lyxml_get_ns(xml, prefix);
91 free(prefix);
92 if (!ns) {
Michal Vaskofb0873c2015-08-21 09:00:07 +020093 if (log) {
94 LOGVAL(LYE_SPEC, LOGLINE(xml), "XML namespace with prefix \"%.*s\" not defined.", id_len, id);
95 }
Michal Vasko249e6b52015-08-19 11:08:52 +020096 free(out);
97 return NULL;
98 }
99 mod = ly_ctx_get_module_by_ns(ctx, ns->value, NULL);
100 if (!mod) {
Michal Vaskofb0873c2015-08-21 09:00:07 +0200101 if (log) {
102 LOGVAL(LYE_SPEC, LOGLINE(xml), "Module with the namespace \"%s\" could not be found.", ns->value);
103 }
Michal Vasko249e6b52015-08-19 11:08:52 +0200104 free(out);
105 return NULL;
106 }
107
108 /* adjust out size (it can even decrease in some strange cases) */
109 out_size += strlen(mod->name)-id_len;
110 out = realloc(out, out_size);
111
112 /* copy the data before prefix */
113 strncpy(&out[out_used], in, id-in);
114 out_used += id-in;
115
116 /* copy the model name */
117 strcpy(&out[out_used], mod->name);
118 out_used += strlen(mod->name);
119
120 /* copy ':' */
121 out[out_used] = ':';
122 ++out_used;
123
124 /* finally adjust in pointer for next round */
125 in = col+1;
126 }
127
128 /* unreachable */
129 assert(0);
130 return NULL;
131}
132
Michal Vasko0d343d12015-08-24 14:57:36 +0200133/* logs directly
134 *
135 * kind == 0 - unsigned (unum used), 1 - signed (snum used), 2 - floating point (fnum used)
136 */
Michal Vasko9286afd2015-07-14 15:27:59 +0200137static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200138validate_length_range(uint8_t kind, uint64_t unum, int64_t snum, long double fnum, struct lys_type *type,
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200139 const char *val_str, uint32_t line)
Michal Vasko9286afd2015-07-14 15:27:59 +0200140{
Michal Vasko020404f2015-07-15 15:45:42 +0200141 struct len_ran_intv *intv = NULL, *tmp_intv;
Michal Vaskof02e3742015-08-05 16:27:02 +0200142 int ret = EXIT_FAILURE;
Michal Vasko9286afd2015-07-14 15:27:59 +0200143
Michal Vasko9c1bc642015-08-05 16:25:53 +0200144 if (resolve_len_ran_interval(NULL, type, 0, &intv)) {
Michal Vasko0d343d12015-08-24 14:57:36 +0200145 /* already done during schema parsing */
146 LOGINT;
Michal Vasko9c1bc642015-08-05 16:25:53 +0200147 return EXIT_FAILURE;
148 }
Michal Vasko020404f2015-07-15 15:45:42 +0200149 if (!intv) {
Michal Vaskof02e3742015-08-05 16:27:02 +0200150 return EXIT_SUCCESS;
Michal Vasko020404f2015-07-15 15:45:42 +0200151 }
152
Michal Vasko9286afd2015-07-14 15:27:59 +0200153 for (tmp_intv = intv; tmp_intv; tmp_intv = tmp_intv->next) {
154 if (((kind == 0) && (unum < tmp_intv->value.uval.min))
155 || ((kind == 1) && (snum < tmp_intv->value.sval.min))
156 || ((kind == 2) && (fnum < tmp_intv->value.fval.min))) {
157 break;
158 }
159
160 if (((kind == 0) && (unum >= tmp_intv->value.uval.min) && (unum <= tmp_intv->value.uval.max))
161 || ((kind == 1) && (snum >= tmp_intv->value.sval.min) && (snum <= tmp_intv->value.sval.max))
162 || ((kind == 2) && (fnum >= tmp_intv->value.fval.min) && (fnum <= tmp_intv->value.fval.max))) {
Michal Vaskof02e3742015-08-05 16:27:02 +0200163 ret = EXIT_SUCCESS;
Michal Vasko9286afd2015-07-14 15:27:59 +0200164 break;
165 }
166 }
167
168 while (intv) {
169 tmp_intv = intv->next;
170 free(intv);
171 intv = tmp_intv;
172 }
173
Michal Vaskof2f45df2015-08-21 09:03:14 +0200174 if (ret) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200175 LOGVAL(LYE_OORVAL, line, (val_str ? val_str : ""));
Michal Vasko0e60c832015-07-15 15:48:35 +0200176 }
Michal Vasko9286afd2015-07-14 15:27:59 +0200177 return ret;
178}
179
Michal Vasko0d343d12015-08-24 14:57:36 +0200180/* logs directly */
Michal Vaskofbf7e482015-07-14 14:49:03 +0200181static int
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200182validate_pattern(const char *val_str, struct lys_type *type, const char *node_name, uint32_t line)
Michal Vaskofbf7e482015-07-14 14:49:03 +0200183{
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200184 int i, err_offset;
185 pcre *precomp;
186 char *perl_regex;
187 const char *err_ptr;
Michal Vaskofbf7e482015-07-14 14:49:03 +0200188
189 assert(type->base == LY_TYPE_STRING);
190
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200191 if (!val_str) {
192 val_str = "";
Michal Vasko24bfc632015-08-24 15:01:21 +0200193 }
194
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200195 if (type->der && validate_pattern(val_str, &type->der->type, node_name, line)) {
Michal Vaskof02e3742015-08-05 16:27:02 +0200196 return EXIT_FAILURE;
Michal Vaskofbf7e482015-07-14 14:49:03 +0200197 }
198
199 for (i = 0; i < type->info.str.pat_count; ++i) {
200 /*
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200201 * adjust the expression to a Perl equivalent
Michal Vaskofbf7e482015-07-14 14:49:03 +0200202 *
203 * http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#regexs
204 */
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200205 perl_regex = malloc((strlen(type->info.str.patterns[i].expr)+2) * sizeof(char));
206 perl_regex[0] = '\0';
207 strcat(perl_regex, type->info.str.patterns[i].expr);
Michal Vaskofbf7e482015-07-14 14:49:03 +0200208 if (strncmp(type->info.str.patterns[i].expr
209 + strlen(type->info.str.patterns[i].expr) - 2, ".*", 2)) {
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200210 strcat(perl_regex, "$");
Michal Vaskofbf7e482015-07-14 14:49:03 +0200211 }
212
213 /* must return 0, already checked during parsing */
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200214 precomp = pcre_compile(perl_regex, PCRE_ANCHORED | PCRE_DOLLAR_ENDONLY | PCRE_NO_AUTO_CAPTURE,
215 &err_ptr, &err_offset, NULL);
216 if (!precomp) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200217 LOGINT;
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200218 free(perl_regex);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200219 return EXIT_FAILURE;
Michal Vasko88876dc2015-08-05 09:46:40 +0200220 }
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200221 free(perl_regex);
Michal Vaskofbf7e482015-07-14 14:49:03 +0200222
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200223 if (pcre_exec(precomp, NULL, val_str, strlen(val_str), 0, 0, NULL, 0)) {
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200224 free(precomp);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200225 LOGVAL(LYE_INVAL, line, val_str, node_name);
Michal Vaskof02e3742015-08-05 16:27:02 +0200226 return EXIT_FAILURE;
Michal Vaskofbf7e482015-07-14 14:49:03 +0200227 }
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200228 free(precomp);
Michal Vaskofbf7e482015-07-14 14:49:03 +0200229 }
230
Michal Vaskof02e3742015-08-05 16:27:02 +0200231 return EXIT_SUCCESS;
Michal Vaskofbf7e482015-07-14 14:49:03 +0200232}
233
Michal Vasko0d343d12015-08-24 14:57:36 +0200234/* does not log */
Radek Krejci76512572015-08-04 09:47:08 +0200235static struct lys_node *
236xml_data_search_schemanode(struct lyxml_elem *xml, struct lys_node *start)
Radek Krejci1721c012015-07-08 12:52:33 +0200237{
Radek Krejci76512572015-08-04 09:47:08 +0200238 struct lys_node *result, *aux;
Radek Krejci1721c012015-07-08 12:52:33 +0200239
240 LY_TREE_FOR(start, result) {
241 /* skip groupings */
Radek Krejci76512572015-08-04 09:47:08 +0200242 if (result->nodetype == LYS_GROUPING) {
Radek Krejci1721c012015-07-08 12:52:33 +0200243 continue;
244 }
245
246 /* go into cases, choices, uses */
Radek Krejci76512572015-08-04 09:47:08 +0200247 if (result->nodetype & (LYS_CHOICE | LYS_CASE | LYS_USES)) {
Radek Krejci1721c012015-07-08 12:52:33 +0200248 aux = xml_data_search_schemanode(xml, result->child);
249 if (aux) {
250 /* we have matching result */
251 return aux;
252 }
253 /* else, continue with next schema node */
254 continue;
255 }
256
257 /* match data nodes */
258 if (result->name == xml->name) {
259 /* names matches, what about namespaces? */
260 if (result->module->ns == xml->ns->value) {
261 /* we have matching result */
262 return result;
263 }
264 /* else, continue with next schema node */
265 continue;
266 }
267 }
268
269 /* no match */
270 return NULL;
271}
272
Michal Vasko0d343d12015-08-24 14:57:36 +0200273/* logs directly */
Radek Krejcie4748472015-07-08 18:00:22 +0200274static int
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200275parse_int(const char *val_str, int64_t min, int64_t max, int base, int64_t *ret, const char *node_name, uint32_t line)
Michal Vaskobdee69c2015-07-15 15:49:39 +0200276{
277 char *strptr;
278
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200279 if (!val_str) {
280 LOGVAL(LYE_INVAL, line, "", node_name);
Michal Vasko24bfc632015-08-24 15:01:21 +0200281 return EXIT_FAILURE;
282 }
283
Michal Vaskobdee69c2015-07-15 15:49:39 +0200284 /* convert to 64-bit integer, all the redundant characters are handled */
285 errno = 0;
286 strptr = NULL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200287 *ret = strtoll(val_str, &strptr, base);
Michal Vaskobdee69c2015-07-15 15:49:39 +0200288 if (errno || (*ret < min) || (*ret > max)) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200289 LOGVAL(LYE_OORVAL, line, val_str, node_name);
Michal Vaskof02e3742015-08-05 16:27:02 +0200290 return EXIT_FAILURE;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200291 } else if (strptr && *strptr) {
292 while (isspace(*strptr)) {
293 ++strptr;
294 }
295 if (*strptr) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200296 LOGVAL(LYE_INVAL, line, val_str, node_name);
Michal Vaskof02e3742015-08-05 16:27:02 +0200297 return EXIT_FAILURE;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200298 }
299 }
300
Michal Vaskof02e3742015-08-05 16:27:02 +0200301 return EXIT_SUCCESS;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200302}
303
Michal Vasko0d343d12015-08-24 14:57:36 +0200304/* logs directly */
Michal Vaskobdee69c2015-07-15 15:49:39 +0200305static int
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200306parse_uint(const char *val_str, uint64_t max, int base, uint64_t *ret, const char *node_name, uint32_t line)
Michal Vaskobdee69c2015-07-15 15:49:39 +0200307{
308 char *strptr;
309
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200310 if (!val_str) {
311 LOGVAL(LYE_INVAL, line, "", node_name);
Michal Vasko24bfc632015-08-24 15:01:21 +0200312 return EXIT_FAILURE;
313 }
314
Michal Vaskobdee69c2015-07-15 15:49:39 +0200315 errno = 0;
316 strptr = NULL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200317 *ret = strtoull(val_str, &strptr, base);
Michal Vaskobdee69c2015-07-15 15:49:39 +0200318 if (errno || (*ret > max)) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200319 LOGVAL(LYE_OORVAL, line, val_str, node_name);
Michal Vaskof02e3742015-08-05 16:27:02 +0200320 return EXIT_FAILURE;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200321 } else if (strptr && *strptr) {
322 while (isspace(*strptr)) {
323 ++strptr;
324 }
325 if (*strptr) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200326 LOGVAL(LYE_INVAL, line, val_str, node_name);
Michal Vaskof02e3742015-08-05 16:27:02 +0200327 return EXIT_FAILURE;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200328 }
329 }
330
Michal Vaskof02e3742015-08-05 16:27:02 +0200331 return EXIT_SUCCESS;
Michal Vaskobdee69c2015-07-15 15:49:39 +0200332}
333
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200334/*
335 * logs directly
336 *
337 * resolve - whether resolve identityrefs and leafrefs (which must be in JSON form)
338 * unres - whether to try to resolve and on failure store it as unres or fail if resolving fails
339 */
340int
341lyp_parse_value(struct lyd_node_leaf_list *node, struct lys_type *stype, int resolve, struct unres_data *unres, uint32_t line)
342{
343 #define DECSIZE 21
344 struct lys_type *type;
345 char dec[DECSIZE];
346 int64_t num;
347 uint64_t unum;
348 int len;
349 int c, i, j, d;
350 int found;
351
352 assert(node && node->value_type && (node->value_type == stype->base));
353
354 switch (node->value_type) {
355 case LY_TYPE_BINARY:
356 if (validate_length_range(0, (node->value_str ? strlen(node->value_str) : 0), 0, 0, stype,
357 node->value_str, line)) {
358 return EXIT_FAILURE;
359 }
360
Radek Krejci0bfdbfd2015-10-02 14:11:14 +0200361 node->value.binary = node->value_str;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200362 break;
363
364 case LY_TYPE_BITS:
365 /* locate bits structure with the bits definitions */
366 for (type = stype; type->der->type.der; type = &type->der->type);
367
368 /* allocate the array of pointers to bits definition */
369 node->value.bit = calloc(type->info.bits.count, sizeof *node->value.bit);
370
371 if (!node->value_str) {
372 /* no bits set */
373 break;
374 }
375
376 c = 0;
377 i = 0;
378 while (node->value_str[c]) {
379 /* skip leading whitespaces */
380 while (isspace(node->value_str[c])) {
381 c++;
382 }
383
384 /* get the length of the bit identifier */
385 for (len = 0; node->value_str[c] && !isspace(node->value_str[c]); c++, len++);
386
387 /* go back to the beginning of the identifier */
388 c = c - len;
389
390 /* find bit definition, identifiers appear ordered by their posititon */
391 for (found = 0; i < type->info.bits.count; i++) {
392 if (!strncmp(type->info.bits.bit[i].name, &node->value_str[c], len)
393 && !type->info.bits.bit[i].name[len]) {
394 /* we have match, store the pointer */
395 node->value.bit[i] = &type->info.bits.bit[i];
396
397 /* stop searching */
398 i++;
399 found = 1;
400 break;
401 }
402 }
403
404 if (!found) {
405 /* referenced bit value does not exists */
406 LOGVAL(LYE_INVAL, line, node->value_str, node->schema->name);
407 return EXIT_FAILURE;
408 }
409
410 c = c + len;
411 }
412
413 break;
414
415 case LY_TYPE_BOOL:
416 if (!node->value_str) {
417 LOGVAL(LYE_INVAL, line, "", node->schema->name);
418 return EXIT_FAILURE;
419 }
420
421 if (!strcmp(node->value_str, "true")) {
422 node->value.bool = 1;
423 } /* else false, so keep it zero */
424 break;
425
426 case LY_TYPE_DEC64:
427 if (!node->value_str) {
428 LOGVAL(LYE_INVAL, line, "", node->schema->name);
429 return EXIT_FAILURE;
430 }
431
432 /* locate dec64 structure with the fraction-digits value */
433 for (type = stype; type->der->type.der; type = &type->der->type);
434
435 for (c = 0; isspace(node->value_str[c]); c++);
436 for (len = 0; node->value_str[c] && !isspace(node->value_str[c]); c++, len++);
437 c = c - len;
438 if (len > DECSIZE) {
439 /* too long */
440 LOGVAL(LYE_INVAL, line, node->value_str, node->schema->name);
441 return EXIT_FAILURE;
442 }
443
444 /* normalize the number */
445 dec[0] = '\0';
446 for (i = j = d = found = 0; i < DECSIZE; i++) {
447 if (node->value_str[c + i] == '.') {
448 found = 1;
449 j = type->info.dec64.dig;
450 i--;
451 c++;
452 continue;
453 }
454 if (node->value_str[c + i] == '\0') {
455 c--;
456 if (!found) {
457 j = type->info.dec64.dig;
458 found = 1;
459 }
460 if (!j) {
461 dec[i] = '\0';
462 break;
463 }
464 d++;
465 if (d > DECSIZE - 2) {
466 LOGVAL(LYE_OORVAL, line, node->value_str, node->schema->name);
467 return EXIT_FAILURE;
468 }
469 dec[i] = '0';
470 } else {
471 if (!isdigit(node->value_str[c + i])) {
472 if (i || node->value_str[c] != '-') {
473 LOGVAL(LYE_INVAL, line, node->value_str, node->schema->name);
474 return EXIT_FAILURE;
475 }
476 } else {
477 d++;
478 }
479 if (d > DECSIZE - 2 || (found && !j)) {
480 LOGVAL(LYE_OORVAL, line, node->value_str, node->schema->name);
481 return EXIT_FAILURE;
482 }
483 dec[i] = node->value_str[c + i];
484 }
485 if (j) {
486 j--;
487 }
488 }
489
490 if (parse_int(dec, -9223372036854775807L - 1L, 9223372036854775807L, 10, &num, node->schema->name, line)
491 || validate_length_range(2, 0, 0, ((long double)num)/(1 << type->info.dec64.dig), stype,
492 node->value_str, line)) {
493 return EXIT_FAILURE;
494 }
495 node->value.dec64 = num;
496 break;
497
498 case LY_TYPE_EMPTY:
499 /* just check that it is empty */
500 if (node->value_str && node->value_str[0]) {
501 LOGVAL(LYE_INVAL, line, node->value_str, node->schema->name);
502 return EXIT_FAILURE;
503 }
504 break;
505
506 case LY_TYPE_ENUM:
507 if (!node->value_str) {
508 LOGVAL(LYE_INVAL, line, "", node->schema->name);
509 return EXIT_FAILURE;
510 }
511
512 /* locate enums structure with the enumeration definitions */
513 for (type = stype; type->der->type.der; type = &type->der->type);
514
515 /* find matching enumeration value */
516 for (i = 0; i < type->info.enums.count; i++) {
517 if (!strcmp(node->value_str, type->info.enums.enm[i].name)) {
518 /* we have match, store pointer to the definition */
519 node->value.enm = &type->info.enums.enm[i];
520 break;
521 }
522 }
523
524 if (!node->value.enm) {
525 LOGVAL(LYE_INVAL, line, node->value_str, node->schema->name);
526 return EXIT_FAILURE;
527 }
528
529 break;
530
531 case LY_TYPE_IDENT:
532 if (!node->value_str) {
533 LOGVAL(LYE_INVAL, line, "", node->schema->name);
534 return EXIT_FAILURE;
535 }
536
537 node->value.ident = resolve_identref_json(stype->info.ident.ref, node->value_str, line);
538 if (!node->value.ident) {
539 return EXIT_FAILURE;
540 }
541 break;
542
543 case LY_TYPE_INST:
544 if (!node->value_str) {
545 LOGVAL(LYE_INVAL, line, "", node->schema->name);
546 return EXIT_FAILURE;
547 }
548
549 if (!resolve) {
550 node->value_type |= LY_TYPE_INST_UNRES;
551 } else {
552 /* validity checking is performed later, right now the data tree
553 * is not complete, so many instanceids cannot be resolved
554 */
555 if (unres) {
556 if (unres_data_add(unres, (struct lyd_node *)node, line)) {
557 return EXIT_FAILURE;
558 }
559 } else {
560 if (resolve_unres_data_item((struct lyd_node *)node, 0, line)) {
561 return EXIT_FAILURE;
562 }
563 }
564 }
565 break;
566
567 case LY_TYPE_LEAFREF:
568 if (!node->value_str) {
569 LOGVAL(LYE_INVAL, line, "", node->schema->name);
570 return EXIT_FAILURE;
571 }
572
573 if (!resolve) {
574 do {
575 type = &((struct lys_node_leaf *)node->schema)->type.info.lref.target->type;
576 } while (type->base == LY_TYPE_LEAFREF);
577 node->value_type = type->base | LY_TYPE_LEAFREF_UNRES;
578 } else {
579 /* validity checking is performed later, right now the data tree
580 * is not complete, so many noderefs cannot be resolved
581 */
582 if (unres) {
583 if (unres_data_add(unres, (struct lyd_node *)node, line)) {
584 return EXIT_FAILURE;
585 }
586 } else {
587 if (resolve_unres_data_item((struct lyd_node *)node, 0, line)) {
588 return EXIT_FAILURE;
589 }
590 }
591 }
592 break;
593
594 case LY_TYPE_STRING:
595 if (validate_length_range(0, (node->value_str ? strlen(node->value_str) : 0), 0, 0, stype,
Radek Krejci0bfdbfd2015-10-02 14:11:14 +0200596 node->value_str, line)) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200597 return EXIT_FAILURE;
598 }
599
600 if (validate_pattern(node->value_str, stype, node->schema->name, line)) {
601 return EXIT_FAILURE;
602 }
603
Radek Krejci0bfdbfd2015-10-02 14:11:14 +0200604 node->value.string = node->value_str;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200605 break;
606
607 case LY_TYPE_INT8:
608 if (parse_int(node->value_str, -128, 127, 0, &num, node->schema->name, line)
609 || validate_length_range(1, 0, num, 0, stype, node->value_str, line)) {
610 return EXIT_FAILURE;
611 }
612 node->value.int8 = num;
613 break;
614
615 case LY_TYPE_INT16:
616 if (parse_int(node->value_str, -32768, 32767, 0, &num, node->schema->name, line)
617 || validate_length_range(1, 0, num, 0, stype, node->value_str, line)) {
618 return EXIT_FAILURE;
619 }
620 node->value.int16 = num;
621 break;
622
623 case LY_TYPE_INT32:
624 if (parse_int(node->value_str, -2147483648, 2147483647, 0, &num, node->schema->name, line)
625 || validate_length_range(1, 0, num, 0, stype, node->value_str, line)) {
626 return EXIT_FAILURE;
627 }
628 node->value.int32 = num;
629 break;
630
631 case LY_TYPE_INT64:
632 if (parse_int(node->value_str, -9223372036854775807L - 1L, 9223372036854775807L, 0, &num,
633 node->schema->name, line)
634 || validate_length_range(1, 0, num, 0, stype, node->value_str, line)) {
635 return EXIT_FAILURE;
636 }
637 node->value.int64 = num;
638 break;
639
640 case LY_TYPE_UINT8:
641 if (parse_uint(node->value_str, 255, 0, &unum, node->schema->name, line)
642 || validate_length_range(0, unum, 0, 0, stype, node->value_str, line)) {
643 return EXIT_FAILURE;
644 }
645 node->value.uint8 = unum;
646 break;
647
648 case LY_TYPE_UINT16:
649 if (parse_uint(node->value_str, 65535, 0, &unum, node->schema->name, line)
650 || validate_length_range(0, unum, 0, 0, stype, node->value_str, line)) {
651 return EXIT_FAILURE;
652 }
653 node->value.uint16 = unum;
654 break;
655
656 case LY_TYPE_UINT32:
657 if (parse_uint(node->value_str, 4294967295, 0, &unum, node->schema->name, line)
658 || validate_length_range(0, unum, 0, 0, stype, node->value_str, line)) {
659 return EXIT_FAILURE;
660 }
661 node->value.uint32 = unum;
662 break;
663
664 case LY_TYPE_UINT64:
665 if (parse_uint(node->value_str, 18446744073709551615UL, 0, &unum, node->schema->name, line)
666 || validate_length_range(0, unum, 0, 0, stype, node->value_str, line)) {
667 return EXIT_FAILURE;
668 }
669 node->value.uint64 = unum;
670 break;
671
672 default:
673 return EXIT_FAILURE;
674 }
675
676 return EXIT_SUCCESS;
677}
678
Michal Vasko0d343d12015-08-24 14:57:36 +0200679/* does not log, cannot fail */
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200680struct lys_type *
681lyp_get_next_union_type(struct lys_type *type, struct lys_type *prev_type, int *found)
Radek Krejcie4748472015-07-08 18:00:22 +0200682{
Michal Vasko07471a52015-07-16 11:18:48 +0200683 int i;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200684 struct lys_type *ret = NULL;
Michal Vasko07471a52015-07-16 11:18:48 +0200685
Michal Vasko6da1a372015-07-27 11:19:10 +0200686 for (i = 0; i < type->info.uni.count; ++i) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200687 if (type->info.uni.types[i].base == LY_TYPE_UNION) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200688 ret = lyp_get_next_union_type(&type->info.uni.types[i], prev_type, found);
Michal Vasko6da1a372015-07-27 11:19:10 +0200689 if (ret) {
Michal Vasko07471a52015-07-16 11:18:48 +0200690 break;;
691 }
692 continue;
693 }
694
695 if (!prev_type || *found) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200696 ret = &type->info.uni.types[i];
Michal Vasko07471a52015-07-16 11:18:48 +0200697 break;
698 }
699
Radek Krejci1574a8d2015-08-03 14:16:52 +0200700 if (&type->info.uni.types[i] == prev_type) {
Michal Vasko07471a52015-07-16 11:18:48 +0200701 *found = 1;
702 }
703 }
704
Michal Vasko6da1a372015-07-27 11:19:10 +0200705 if (!ret && type->der) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200706 ret = lyp_get_next_union_type(&type->der->type, prev_type, found);
Michal Vasko6da1a372015-07-27 11:19:10 +0200707 }
708
709 return ret;
Michal Vasko07471a52015-07-16 11:18:48 +0200710}
711
Michal Vasko0d343d12015-08-24 14:57:36 +0200712/* logs directly */
Michal Vasko07471a52015-07-16 11:18:48 +0200713static int
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200714xml_get_value(struct lyd_node *node, struct lyxml_elem *xml, int options, struct unres_data *unres)
Michal Vasko07471a52015-07-16 11:18:48 +0200715{
Michal Vasko4c183312015-09-25 10:41:47 +0200716 struct lyd_node_leaf_list *leaf = (struct lyd_node_leaf_list *)node;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200717 struct lys_type *type, *stype;
718 int resolve, found;
Michal Vasko23b61ec2015-08-19 11:19:50 +0200719
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200720 assert(node && (node->schema->nodetype & (LYS_LEAFLIST | LYS_LEAF)) && xml && unres);
Radek Krejci5a988152015-07-15 11:16:26 +0200721
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200722 stype = &((struct lys_node_leaf *)node->schema)->type;
Radek Krejci5a988152015-07-15 11:16:26 +0200723 leaf->value_str = xml->content;
724 xml->content = NULL;
Radek Krejcie4748472015-07-08 18:00:22 +0200725
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200726 /* will be changed in case of union */
727 leaf->value_type = stype->base;
Radek Krejcie3c33142015-08-10 15:04:36 +0200728
Radek Krejcie2cf7c12015-08-12 10:24:05 +0200729 if ((options & LYD_OPT_FILTER) && !leaf->value_str) {
730 /* no value in filter (selection) node -> nothing more is needed */
731 return EXIT_SUCCESS;
732 }
733
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200734 if (options & (LYD_OPT_FILTER | LYD_OPT_EDIT)) {
735 resolve = 0;
736 } else {
737 resolve = 1;
738 }
Radek Krejci3e3affe2015-07-09 15:38:40 +0200739
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200740 if ((stype->base == LY_TYPE_IDENT) || (stype->base == LY_TYPE_INST)) {
Michal Vaskofb0873c2015-08-21 09:00:07 +0200741 /* convert the path from the XML form using XML namespaces into the JSON format
742 * using module names as namespaces
743 */
744 xml->content = leaf->value_str;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200745 leaf->value_str = transform_data_xml2json(leaf->schema->module->ctx, xml, 1);
746 lydict_remove(leaf->schema->module->ctx, xml->content);
Michal Vaskofb0873c2015-08-21 09:00:07 +0200747 xml->content = NULL;
748 if (!leaf->value_str) {
749 return EXIT_FAILURE;
Radek Krejciac8aac62015-07-10 15:36:35 +0200750 }
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200751 }
Radek Krejciac8aac62015-07-10 15:36:35 +0200752
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200753 if (stype->base == LY_TYPE_UNION) {
Michal Vasko07471a52015-07-16 11:18:48 +0200754 found = 0;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200755 /* TODO if type is IDENT | INST temporarily convert to JSON, convert back on fail */
756 type = lyp_get_next_union_type(stype, NULL, &found);
757 while (type) {
758 leaf->value_type = type->base;
759 if (!lyp_parse_value(leaf, type, resolve, unres, UINT_MAX)) {
Michal Vasko07471a52015-07-16 11:18:48 +0200760 break;
761 }
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200762
763 found = 0;
764 type = lyp_get_next_union_type(stype, type, &found);
Michal Vasko07471a52015-07-16 11:18:48 +0200765 }
766
767 if (!type) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200768 LOGVAL(LYE_INVAL, LOGLINE(xml), (leaf->value_str ? leaf->value_str : ""), xml->name);
Michal Vasko07471a52015-07-16 11:18:48 +0200769 return EXIT_FAILURE;
770 }
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200771 } else if (lyp_parse_value(leaf, stype, resolve, unres, LOGLINE(xml))) {
Michal Vasko493bea72015-07-16 16:08:12 +0200772 return EXIT_FAILURE;
Radek Krejcie4748472015-07-08 18:00:22 +0200773 }
774
775 return EXIT_SUCCESS;
776}
777
Michal Vasko0d343d12015-08-24 14:57:36 +0200778/* logs directly */
Radek Krejci1721c012015-07-08 12:52:33 +0200779struct lyd_node *
Michal Vasko493bea72015-07-16 16:08:12 +0200780xml_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 +0200781 int options, struct unres_data *unres)
Radek Krejci1721c012015-07-08 12:52:33 +0200782{
Radek Krejci7f40ce32015-08-12 20:38:46 +0200783 struct lyd_node *result = NULL, *diter;
Radek Krejcieab784a2015-08-27 09:56:53 +0200784 struct lys_node *schema = NULL;
Radek Krejcia5241e52015-08-19 15:09:31 +0200785 struct lyxml_attr *attr;
Michal Vasko9f1ef592015-09-29 14:57:51 +0200786 struct lyxml_elem *first_child, *last_child, *child;
Michal Vaskoab8e4402015-07-17 12:54:28 +0200787 int i, havechildren;
Radek Krejci1721c012015-07-08 12:52:33 +0200788
789 if (!xml) {
Michal Vasko0d343d12015-08-24 14:57:36 +0200790 LOGINT;
Radek Krejci1721c012015-07-08 12:52:33 +0200791 return NULL;
792 }
793 if (!xml->ns || !xml->ns->value) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200794 LOGVAL(LYE_XML_MISS, LOGLINE(xml), "element's", "namespace");
Radek Krejci1721c012015-07-08 12:52:33 +0200795 return NULL;
796 }
797
798 /* find schema node */
799 if (!parent) {
800 /* starting in root */
801 for (i = 0; i < ctx->models.used; i++) {
802 /* match data model based on namespace */
803 if (ctx->models.list[i]->ns == xml->ns->value) {
804 /* get the proper schema node */
805 LY_TREE_FOR(ctx->models.list[i]->data, schema) {
806 if (schema->name == xml->name) {
807 break;
808 }
809 }
810 break;
811 }
812 }
813 } else {
814 /* parsing some internal node, we start with parent's schema pointer */
815 schema = xml_data_search_schemanode(xml, parent->schema->child);
816 }
817 if (!schema) {
Radek Krejci25b9fd32015-08-10 15:06:07 +0200818 if ((options & LYD_OPT_STRICT) || ly_ctx_get_module_by_ns(ctx, xml->ns->value, NULL)) {
819 LOGVAL(LYE_INELEM, LOGLINE(xml), xml->name);
820 return NULL;
821 } else {
822 goto siblings;
823 }
Radek Krejci1721c012015-07-08 12:52:33 +0200824 }
825
Radek Krejcieab784a2015-08-27 09:56:53 +0200826 if (lyv_data_context(schema, LOGLINE(xml), options)) {
Radek Krejci074bf852015-08-19 14:22:16 +0200827 return NULL;
828 }
Radek Krejcia5241e52015-08-19 15:09:31 +0200829
830 /* check insert attribute and its values */
831 if (options & LYD_OPT_EDIT) {
832 i = 0;
833 for (attr = xml->attr; attr; attr = attr->next) {
834 if (attr->type != LYXML_ATTR_STD || !attr->ns ||
835 strcmp(attr->name, "insert") || strcmp(attr->ns->value, LY_NSYANG)) {
836 continue;
837 }
838
839 /* insert attribute present */
840 if (!(schema->flags & LYS_USERORDERED)) {
841 /* ... but it is not expected */
842 LOGVAL(LYE_INATTR, LOGLINE(xml), "insert", schema->name);
843 return NULL;
844 }
845
846 if (i) {
847 LOGVAL(LYE_TOOMANY, LOGLINE(xml), "insert attributes", xml->name);
848 return NULL;
849 }
850 if (!strcmp(attr->value, "first") || !strcmp(attr->value, "last")) {
851 i = 1;
852 } else if (!strcmp(attr->value, "before") || !strcmp(attr->value, "after")) {
853 i = 2;
854 } else {
855 LOGVAL(LYE_INARG, LOGLINE(xml), attr->value, attr->name);
856 return NULL;
857 }
858 }
859
860 for (attr = xml->attr; attr; attr = attr->next) {
861 if (attr->type != LYXML_ATTR_STD || !attr->ns ||
862 strcmp(attr->name, "value") || strcmp(attr->ns->value, LY_NSYANG)) {
863 continue;
864 }
865
866 /* the value attribute is present */
867 if (i < 2) {
868 /* but it shouldn't */
869 LOGVAL(LYE_INATTR, LOGLINE(xml), "value", schema->name);
870 return NULL;
871 }
872 i++;
873 }
874 if (i == 2) {
875 /* missing value attribute for "before" or "after" */
876 LOGVAL(LYE_MISSATTR, LOGLINE(xml), "value", xml->name);
877 return NULL;
878 } else if (i > 3) {
879 /* more than one instance of the value attribute */
880 LOGVAL(LYE_TOOMANY, LOGLINE(xml), "value attributes", xml->name);
881 return NULL;
882 }
Radek Krejci074bf852015-08-19 14:22:16 +0200883 }
884
Radek Krejcib9930252015-07-08 15:47:45 +0200885 switch (schema->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +0200886 case LYS_CONTAINER:
Radek Krejci27aaa732015-09-04 15:24:04 +0200887 case LYS_LIST:
Michal Vaskoab8e4402015-07-17 12:54:28 +0200888 result = calloc(1, sizeof *result);
889 havechildren = 1;
Radek Krejcib9930252015-07-08 15:47:45 +0200890 break;
Radek Krejci76512572015-08-04 09:47:08 +0200891 case LYS_LEAF:
Radek Krejci76512572015-08-04 09:47:08 +0200892 case LYS_LEAFLIST:
Michal Vasko4c183312015-09-25 10:41:47 +0200893 result = calloc(1, sizeof(struct lyd_node_leaf_list));
Radek Krejcie4748472015-07-08 18:00:22 +0200894 havechildren = 0;
895 break;
Radek Krejci76512572015-08-04 09:47:08 +0200896 case LYS_ANYXML:
Michal Vaskoab8e4402015-07-17 12:54:28 +0200897 result = calloc(1, sizeof(struct lyd_node_anyxml));
898 havechildren = 0;
899 break;
Radek Krejcib9930252015-07-08 15:47:45 +0200900 default:
Michal Vasko0c888fd2015-08-11 15:54:08 +0200901 LOGINT;
Michal Vaskoab8e4402015-07-17 12:54:28 +0200902 return NULL;
Radek Krejcib9930252015-07-08 15:47:45 +0200903 }
Radek Krejci1721c012015-07-08 12:52:33 +0200904 result->parent = parent;
Radek Krejcic41bf8a2015-08-21 10:28:48 +0200905 if (parent && !parent->child) {
906 parent->child = result;
907 }
908 if (prev) {
909 result->prev = prev;
910 prev->next = result;
911
912 /* fix the "last" pointer */
913 for (diter = prev; diter->prev != prev; diter = diter->prev);
914 diter->prev = result;
915 } else {
916 result->prev = result;
917 }
Radek Krejci1721c012015-07-08 12:52:33 +0200918 result->schema = schema;
919
Radek Krejcib9930252015-07-08 15:47:45 +0200920 /* type specific processing */
Radek Krejci27aaa732015-09-04 15:24:04 +0200921 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
Radek Krejcie4748472015-07-08 18:00:22 +0200922 /* type detection and assigning the value */
Radek Krejci25b9fd32015-08-10 15:06:07 +0200923 if (xml_get_value(result, xml, options, unres)) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200924 goto error;
925 }
Radek Krejci1b0d01a2015-08-19 17:00:35 +0200926 } else if (schema->nodetype == LYS_ANYXML && !(options & LYD_OPT_FILTER)) {
Michal Vasko9f1ef592015-09-29 14:57:51 +0200927 /* unlink xml children, they will be the anyxml value */
928 first_child = NULL;
929 LY_TREE_FOR(xml->child, child) {
930 lyxml_unlink_elem(ctx, child, 1);
931 if (!first_child) {
932 first_child = child;
933 last_child = child;
934 } else {
935 last_child->next = child;
936 child->prev = last_child;
937 last_child = child;
938 }
Michal Vasko60beecb2015-09-03 14:24:09 +0200939 }
Michal Vasko9f1ef592015-09-29 14:57:51 +0200940 first_child->prev = last_child;
Michal Vasko60beecb2015-09-03 14:24:09 +0200941
Michal Vasko9f1ef592015-09-29 14:57:51 +0200942 ((struct lyd_node_anyxml *)result)->value = first_child;
Michal Vasko60beecb2015-09-03 14:24:09 +0200943 /* we can safely continue with xml, it's like it was, only without children */
Radek Krejcib9930252015-07-08 15:47:45 +0200944 }
945
Radek Krejci1721c012015-07-08 12:52:33 +0200946 /* process children */
Radek Krejcie4748472015-07-08 18:00:22 +0200947 if (havechildren && xml->child) {
Radek Krejcic41bf8a2015-08-21 10:28:48 +0200948 xml_parse_data(ctx, xml->child, result, NULL, options, unres);
Radek Krejci25b9fd32015-08-10 15:06:07 +0200949 if (ly_errno) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200950 goto error;
Radek Krejci1721c012015-07-08 12:52:33 +0200951 }
Radek Krejci1721c012015-07-08 12:52:33 +0200952 }
953
Michal Vasko4ff7b072015-08-21 09:05:03 +0200954 result->attr = (struct lyd_attr *)xml->attr;
955 xml->attr = NULL;
956
Radek Krejcib1c12512015-08-11 11:22:04 +0200957 /* various validation checks */
Radek Krejcieab784a2015-08-27 09:56:53 +0200958 ly_errno = 0;
959 if (lyv_data_content(result, LOGLINE(xml), options)) {
960 if (ly_errno) {
Radek Krejcib1c12512015-08-11 11:22:04 +0200961 goto error;
Radek Krejci1b0d01a2015-08-19 17:00:35 +0200962 } else {
Radek Krejcieab784a2015-08-27 09:56:53 +0200963 goto cleargotosiblings;
Radek Krejcida374342015-08-19 13:33:22 +0200964 }
Radek Krejci78ce8612015-08-18 14:31:05 +0200965 }
966
Radek Krejci25b9fd32015-08-10 15:06:07 +0200967siblings:
Radek Krejci1721c012015-07-08 12:52:33 +0200968 /* process siblings */
969 if (xml->next) {
Radek Krejci25b9fd32015-08-10 15:06:07 +0200970 if (result) {
Radek Krejcic41bf8a2015-08-21 10:28:48 +0200971 xml_parse_data(ctx, xml->next, parent, result, options, unres);
Radek Krejci25b9fd32015-08-10 15:06:07 +0200972 } else {
Radek Krejcic41bf8a2015-08-21 10:28:48 +0200973 xml_parse_data(ctx, xml->next, parent, prev, options, unres);
Radek Krejci25b9fd32015-08-10 15:06:07 +0200974 }
975 if (ly_errno) {
Radek Krejci3e3affe2015-07-09 15:38:40 +0200976 goto error;
Radek Krejci1721c012015-07-08 12:52:33 +0200977 }
Radek Krejci1721c012015-07-08 12:52:33 +0200978 }
979
980 return result;
Radek Krejci3e3affe2015-07-09 15:38:40 +0200981
982error:
983
Radek Krejcieab784a2015-08-27 09:56:53 +0200984 /* cleanup */
985 lyd_free(result);
Radek Krejci3e3affe2015-07-09 15:38:40 +0200986
987 return NULL;
Radek Krejci1b0d01a2015-08-19 17:00:35 +0200988
989cleargotosiblings:
990
Radek Krejcieab784a2015-08-27 09:56:53 +0200991 /* remove the result ... */
Radek Krejci1b0d01a2015-08-19 17:00:35 +0200992 lyd_free(result);
993 result = NULL;
994
995 /* ... and then go to siblings label */
996 goto siblings;
Radek Krejci1721c012015-07-08 12:52:33 +0200997}
998
Michal Vasko0d343d12015-08-24 14:57:36 +0200999/* logs indirectly */
Radek Krejci25b9fd32015-08-10 15:06:07 +02001000struct lyd_node *
1001xml_read_data(struct ly_ctx *ctx, const char *data, int options)
Radek Krejci1721c012015-07-08 12:52:33 +02001002{
1003 struct lyxml_elem *xml;
Radek Krejci0e1d1a62015-07-31 11:17:01 +02001004 struct lyd_node *result, *next, *iter;
Michal Vaskof02e3742015-08-05 16:27:02 +02001005 struct unres_data *unres = NULL;
Radek Krejci1721c012015-07-08 12:52:33 +02001006
1007 xml = lyxml_read(ctx, data, 0);
1008 if (!xml) {
1009 return NULL;
1010 }
1011
Michal Vasko23b61ec2015-08-19 11:19:50 +02001012 unres = calloc(1, sizeof *unres);
1013
Radek Krejci25b9fd32015-08-10 15:06:07 +02001014 ly_errno = 0;
Michal Vasko23b61ec2015-08-19 11:19:50 +02001015 result = xml_parse_data(ctx, xml->child, NULL, NULL, options, unres);
Michal Vasko23d926a2015-08-21 09:05:36 +02001016
Michal Vasko493bea72015-07-16 16:08:12 +02001017 /* check leafrefs and/or instids if any */
Michal Vasko0bb747c2015-08-21 09:39:10 +02001018 if (result && resolve_unres_data(unres)) {
Michal Vasko493bea72015-07-16 16:08:12 +02001019 /* leafref & instid checking failed */
Radek Krejci0e1d1a62015-07-31 11:17:01 +02001020 LY_TREE_FOR_SAFE(result, next, iter) {
1021 lyd_free(iter);
1022 }
1023 result = NULL;
Radek Krejci5a988152015-07-15 11:16:26 +02001024 }
1025
Michal Vasko23b61ec2015-08-19 11:19:50 +02001026 free(unres->dnode);
1027#ifndef NDEBUG
1028 free(unres->line);
1029#endif
1030 free(unres);
1031
Radek Krejci5a988152015-07-15 11:16:26 +02001032 /* free source XML tree */
Radek Krejci1721c012015-07-08 12:52:33 +02001033 lyxml_free_elem(ctx, xml);
1034
1035 return result;
1036}