* NACM extension (RFC8341)
* NACM module support (RFC8341 A1+A2)
* Recovery user "_nacm_recovery" added.
* Example use is restconf PUT when NACM edit-config is permitted, then automatic commit and discard are permitted using recovery user.
* Example user changed adm1 to andy to comply with RFC8341 example
* Yang code upgrade (RFC7950)
* RPC method input parameters validated
* see https://github.com/clicon/clixon/issues/4
* Correct XML namespace handling
* XML multiple modules was based on "loose" semantics so that yang modules were found by iterating thorugh namespaces until a match was made. This did not adhere to proper [XML namespace handling](https://www.w3.org/TR/2009/REC-xml-names-20091208), and causes problems with overlapping names and false positives. Below see XML accepted (but wrong), and correct namespace declaration:
```
<rpc><my-own-method></rpc> # Wrong but accepted
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> # Correct
<my-own-method xmlns="http://example.net/me/my-own/1.0">
</rpc>
```
* To keep old loose semantics set config option CLICON_XML_NS_ITERATE (true by default)
* XML to JSON translator support for mapping xmlns attribute to module name prefix.
* Default namespace is still "urn:ietf:params:xml:ns:netconf:base:1.0"
* See https://github.com/clicon/clixon/issues/49
* Changed all make tags --> make TAGS
* Keyvalue datastore removed (it has been disabled since 3.3.3)
* debug rpc added in example application (should be in clixon-config).
This commit is contained in:
parent
e5c0b06cf9
commit
ae1af8da9e
63 changed files with 1852 additions and 3492 deletions
|
|
@ -90,22 +90,43 @@ enum childtype{
|
|||
ANY_CHILD, /* eg <a><b/></a> or <a><b/><c/></a> */
|
||||
};
|
||||
|
||||
/*! Number of children EXCEPT attributes
|
||||
* @param[in] xn xml node
|
||||
* @retval number of children in XML tree (except children of type CX_ATTR)
|
||||
* @see xml_child_nr
|
||||
*/
|
||||
static int
|
||||
xml_child_nr_noattr(cxobj *xn)
|
||||
{
|
||||
cxobj *x = NULL;
|
||||
int nr = 0;
|
||||
|
||||
while ((x = xml_child_each(xn, x, -1)) != NULL) {
|
||||
if (xml_type(x) != CX_ATTR)
|
||||
nr++;
|
||||
}
|
||||
return nr;
|
||||
}
|
||||
|
||||
/*! x is element and has exactly one child which in turn has none
|
||||
* remove attributes from x
|
||||
* Clone from clixon_xml_map.c
|
||||
*/
|
||||
static enum childtype
|
||||
childtype(cxobj *x)
|
||||
{
|
||||
cxobj *xc1; /* the only child of x */
|
||||
int clen; /* nr of children */
|
||||
|
||||
clen = xml_child_nr_noattr(x);
|
||||
if (xml_type(x) != CX_ELMNT)
|
||||
return -1; /* n/a */
|
||||
if (xml_child_nr(x) == 0)
|
||||
if (clen == 0)
|
||||
return NULL_CHILD;
|
||||
if (xml_child_nr(x) > 1)
|
||||
if (clen > 1)
|
||||
return ANY_CHILD;
|
||||
xc1 = xml_child_i(x, 0); /* From here exactly one child */
|
||||
if (xml_child_nr(xc1) == 0 && xml_type(xc1)==CX_BODY)
|
||||
if (xml_child_nr_noattr(xc1) == 0 && xml_type(xc1)==CX_BODY)
|
||||
return BODY_CHILD;
|
||||
else
|
||||
return ANY_CHILD;
|
||||
|
|
@ -267,13 +288,13 @@ json_str_escape(char *str)
|
|||
+----------+--------------+--------------+--------------+
|
||||
*/
|
||||
static int
|
||||
xml2json1_cbuf(cbuf *cb,
|
||||
cxobj *x,
|
||||
xml2json1_cbuf(cbuf *cb,
|
||||
cxobj *x,
|
||||
enum array_element_type arraytype,
|
||||
int level,
|
||||
int pretty,
|
||||
int flat,
|
||||
int bodystr)
|
||||
int level,
|
||||
int pretty,
|
||||
int flat,
|
||||
int bodystr)
|
||||
{
|
||||
int retval = -1;
|
||||
int i;
|
||||
|
|
@ -281,10 +302,30 @@ xml2json1_cbuf(cbuf *cb,
|
|||
enum childtype childt;
|
||||
enum array_element_type xc_arraytype;
|
||||
yang_stmt *ys;
|
||||
yang_stmt *ymod; /* yang module */
|
||||
yang_spec *yspec = NULL; /* yang spec */
|
||||
int bodystr0=1;
|
||||
char *str;
|
||||
char *prefix=NULL; /* prefix / local namespace name */
|
||||
char *namespace=NULL; /* namespace uri */
|
||||
char *modname=NULL; /* Module name */
|
||||
|
||||
/* If x is labelled with a default namespace, it should be translated
|
||||
* to a module name.
|
||||
* Harder if x has a prefix, then that should also be translated to associated
|
||||
* module name
|
||||
*/
|
||||
prefix = xml_namespace(x);
|
||||
if (xml2ns(x, prefix, &namespace) < 0)
|
||||
goto done;
|
||||
if ((ys = xml_spec(x)) != NULL) /* yang spec associated with x */
|
||||
yspec = ys_spec(ys);
|
||||
/* Find module name associated with namspace URI */
|
||||
if (namespace && yspec &&
|
||||
(ymod = yang_find_module_by_namespace(yspec, namespace)) != NULL){
|
||||
modname = ymod->ys_argument;
|
||||
}
|
||||
childt = childtype(x);
|
||||
ys = xml_spec(x);
|
||||
if (pretty==2)
|
||||
cprintf(cb, "#%s_array, %s_child ",
|
||||
arraytype2str(arraytype),
|
||||
|
|
@ -292,7 +333,6 @@ xml2json1_cbuf(cbuf *cb,
|
|||
switch(arraytype){
|
||||
case BODY_ARRAY:{
|
||||
if (bodystr){
|
||||
char *str;
|
||||
if ((str = json_str_escape(xml_value(x))) == NULL)
|
||||
goto done;
|
||||
cprintf(cb, "\"%s\"", str);
|
||||
|
|
@ -300,14 +340,13 @@ xml2json1_cbuf(cbuf *cb,
|
|||
}
|
||||
else
|
||||
cprintf(cb, "%s", xml_value(x));
|
||||
|
||||
break;
|
||||
}
|
||||
case NO_ARRAY:
|
||||
if (!flat){
|
||||
cprintf(cb, "%*s\"", pretty?(level*JSON_INDENT):0, "");
|
||||
if (xml_namespace(x))
|
||||
cprintf(cb, "%s:", xml_namespace(x));
|
||||
if (modname) /* XXX should remove this? */
|
||||
cprintf(cb, "%s:", modname);
|
||||
cprintf(cb, "%s\": ", xml_name(x));
|
||||
}
|
||||
switch (childt){
|
||||
|
|
@ -326,8 +365,8 @@ xml2json1_cbuf(cbuf *cb,
|
|||
case FIRST_ARRAY:
|
||||
case SINGLE_ARRAY:
|
||||
cprintf(cb, "%*s\"", pretty?(level*JSON_INDENT):0, "");
|
||||
if (xml_namespace(x))
|
||||
cprintf(cb, "%s:", xml_namespace(x));
|
||||
if (modname)
|
||||
cprintf(cb, "%s:", modname);
|
||||
cprintf(cb, "%s\": ", xml_name(x));
|
||||
level++;
|
||||
cprintf(cb, "[%s%*s",
|
||||
|
|
@ -368,7 +407,7 @@ xml2json1_cbuf(cbuf *cb,
|
|||
break;
|
||||
}
|
||||
/* Check for typed sub-body if:
|
||||
* arracytype=* but chilt-type is BODY_CHILD
|
||||
* arraytype=* but child-type is BODY_CHILD
|
||||
* This is code for writing <a>42</a> as "a":42 and not "a":"42"
|
||||
*/
|
||||
if (childt == BODY_CHILD && ys!=NULL &&
|
||||
|
|
@ -393,6 +432,8 @@ xml2json1_cbuf(cbuf *cb,
|
|||
|
||||
for (i=0; i<xml_child_nr(x); i++){
|
||||
xc = xml_child_i(x, i);
|
||||
if (xml_type(xc) == CX_ATTR)
|
||||
continue; /* XXX Only xmlns attributes mapped */
|
||||
xc_arraytype = array_eval(i?xml_child_i(x,i-1):NULL,
|
||||
xc,
|
||||
xml_child_i(x, i+1));
|
||||
|
|
@ -401,7 +442,7 @@ xml2json1_cbuf(cbuf *cb,
|
|||
xc_arraytype,
|
||||
level+1, pretty, 0, bodystr0) < 0)
|
||||
goto done;
|
||||
if (i<xml_child_nr(x)-1)
|
||||
if (i<xml_child_nr_noattr(x)-1)
|
||||
cprintf(cb, ",%s", pretty?"\n":"");
|
||||
}
|
||||
switch (arraytype){
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue