Fixed: ["autocli:hide-show" extension cause bug in xmldb_put method #343](https://github.com/clicon/clixon/issues/343)

As a side-effect, added extra "autocliext" parameter to:
- clixon_xml2file()
- clixon_json2file()
- clixon_json2cbuf()
- clixon_txt2file()
This commit is contained in:
Olof hagsand 2022-07-22 15:56:06 +02:00
parent e724dd7f40
commit 4514f2a538
26 changed files with 213 additions and 144 deletions

View file

@ -745,7 +745,7 @@ xmldb_get_nocache(clicon_handle h,
clicon_log(LOG_NOTICE, "%s: sort verify failed #2", __FUNCTION__);
#endif
if (clicon_debug_get()>1)
if (clixon_xml2file(stderr, xt, 0, 1, fprintf, 0) < 0)
if (clixon_xml2file(stderr, xt, 0, 1, fprintf, 0, 0) < 0)
goto done;
*xtop = xt;
xt = NULL;
@ -917,7 +917,7 @@ xmldb_get_cache(clicon_handle h,
* If cache was empty, also update to datastore cache
*/
if (clicon_debug_get()>1)
if (clixon_xml2file(stderr, x1t, 0, 1, fprintf, 0) < 0)
if (clixon_xml2file(stderr, x1t, 0, 1, fprintf, 0, 0) < 0)
goto done;
*xtop = x1t;
retval = 1;
@ -1019,7 +1019,7 @@ xmldb_get_zerocopy(clicon_handle h,
goto done;
}
if (clicon_debug_get() > 1)
if (clixon_xml2file(stderr, x0t, 0, 1, fprintf, 0) < 0)
if (clixon_xml2file(stderr, x0t, 0, 1, fprintf, 0, 0) < 0)
goto done;
*xtop = x0t;
retval = 1;

View file

@ -1244,10 +1244,10 @@ xmldb_put(clicon_handle h,
}
pretty = clicon_option_bool(h, "CLICON_XMLDB_PRETTY");
if (strcmp(format,"json")==0){
if (clixon_json2file(f, x0, pretty, fprintf, 0) < 0)
if (clixon_json2file(f, x0, pretty, fprintf, 0, 0) < 0)
goto done;
}
else if (clixon_xml2file(f, x0, 0, pretty, fprintf, 0) < 0)
else if (clixon_xml2file(f, x0, 0, pretty, fprintf, 0, 0) < 0)
goto done;
/* Remove modules state after writing to file
*/
@ -1302,10 +1302,10 @@ xmldb_dump(clicon_handle h,
}
pretty = clicon_option_bool(h, "CLICON_XMLDB_PRETTY");
if (strcmp(format,"json")==0){
if (clixon_json2file(f, xt, pretty, fprintf, 0) < 0)
if (clixon_json2file(f, xt, pretty, fprintf, 0, 0) < 0)
goto done;
}
else if (clixon_xml2file(f, xt, 0, pretty, fprintf, 0) < 0)
else if (clixon_xml2file(f, xt, 0, pretty, fprintf, 0, 0) < 0)
goto done;
retval = 0;
done:

View file

@ -1043,6 +1043,7 @@ xml2json1_cbuf(cbuf *cb,
* @param[in,out] cb Cligen buffer to write to
* @param[in] x XML tree to translate from
* @param[in] pretty Set if output is pretty-printed
* @param[in] autocliext How to handle autocli extensions: 0: ignore 1: follow
* @retval 0 OK
* @retval -1 Error
*
@ -1052,18 +1053,27 @@ xml2json1_cbuf(cbuf *cb,
static int
xml2json_cbuf1(cbuf *cb,
cxobj *x,
int pretty)
int pretty,
int autocliext)
{
int retval = 1;
int level = 0;
yang_stmt *y;
enum array_element_type arraytype = NO_ARRAY;
int exist = 0;
y = xml_spec(x);
if (autocliext && y != NULL) {
if (yang_extension_value(y, "hide-show", CLIXON_AUTOCLI_NS, &exist, NULL) < 0)
goto done;
if (exist)
goto ok;
}
cprintf(cb, "%*s{%s",
pretty?level*JSON_INDENT:0,"",
pretty?"\n":"");
if ((y = xml_spec(x)) != NULL){
if (y != NULL){
switch (yang_keyword_get(y)){
case Y_LEAF_LIST:
case Y_LIST:
@ -1087,6 +1097,7 @@ xml2json_cbuf1(cbuf *cb,
pretty?"\n":"",
pretty?level*JSON_INDENT:0,"",
pretty?"\n":"");
ok:
retval = 0;
done:
return retval;
@ -1101,6 +1112,7 @@ xml2json_cbuf1(cbuf *cb,
* @param[in] xt Top-level xml object
* @param[in] pretty Set if output is pretty-printed
* @param[in] skiptop 0: Include top object 1: Skip top-object, only children,
* @param[in] autocliext How to handle autocli extensions: 0: ignore 1: follow
* @retval 0 OK
* @retval -1 Error
* @code
@ -1115,7 +1127,8 @@ int
clixon_json2cbuf(cbuf *cb,
cxobj *xt,
int pretty,
int skiptop)
int skiptop,
int autocliext)
{
int retval = -1;
cxobj *xc;
@ -1123,11 +1136,11 @@ clixon_json2cbuf(cbuf *cb,
if (skiptop){
xc = NULL;
while ((xc = xml_child_each(xt, xc, CX_ELMNT)) != NULL)
if (xml2json_cbuf1(cb, xc, pretty) < 0)
if (xml2json_cbuf1(cb, xc, pretty, autocliext) < 0)
goto done;
}
else {
if (xml2json_cbuf1(cb, xt, pretty) < 0)
if (xml2json_cbuf1(cb, xt, pretty, autocliext) < 0)
goto done;
}
retval = 0;
@ -1206,13 +1219,14 @@ xml2json_cbuf_vec(cbuf *cb,
* @param[in] pretty Set if output is pretty-printed
* @param[in] fn File print function (if NULL, use fprintf)
* @param[in] skiptop 0: Include top object 1: Skip top-object, only children,
* @param[in] autocliext How to handle autocli extensions: 0: ignore 1: follow
* @retval 0 OK
* @retval -1 Error
*
* @note yang is necessary to translate to one-member lists,
* eg if a is a yang LIST <a>0</a> -> {"a":["0"]} and not {"a":"0"}
* @code
* if (clixon_json2file(stderr, xn, 0, fprintf, 0) < 0)
* if (clixon_json2file(stderr, xn, 0, fprintf, 0, 0) < 0)
* goto err;
* @endcode
*/
@ -1221,7 +1235,8 @@ clixon_json2file(FILE *f,
cxobj *xn,
int pretty,
clicon_output_cb *fn,
int skiptop)
int skiptop,
int autocliext)
{
int retval = 1;
cbuf *cb = NULL;
@ -1232,7 +1247,7 @@ clixon_json2file(FILE *f,
clicon_err(OE_XML, errno, "cbuf_new");
goto done;
}
if (clixon_json2cbuf(cb, xn, pretty, skiptop) < 0)
if (clixon_json2cbuf(cb, xn, pretty, skiptop, autocliext) < 0)
goto done;
(*fn)(f, "%s", cbuf_get(cb));
retval = 0;
@ -1251,7 +1266,7 @@ int
json_print(FILE *f,
cxobj *x)
{
return clixon_json2file(f, x, 1, fprintf, 0);
return clixon_json2file(f, x, 1, fprintf, 0, 0);
}
/*! Translate a vector of xml objects to JSON File.

View file

@ -1998,7 +1998,7 @@ netconf_output(int s,
if (clicon_debug_get() > 1){ /* XXX: below only works to stderr, clicon_debug may log to syslog */
cxobj *xt = NULL;
if (clixon_xml_parse_string(buf, YB_NONE, NULL, &xt, NULL) == 0){
if (clixon_xml2file(stderr, xml_child_i(xt, 0), 0, 0, fprintf, 0) < 0)
if (clixon_xml2file(stderr, xml_child_i(xt, 0), 0, 0, fprintf, 0, 0) < 0)
goto done;
fprintf(stderr, "\n");
xml_free(xt);

View file

@ -101,6 +101,7 @@ tleaf(cxobj *x)
* @param[in] fn Callback to make print function
* @param[in] f File to print to
* @param[in] level Print 4 spaces per level in front of each line
* @param[in] autocliext How to handle autocli extensions: 0: ignore 1: follow
* @param[in,out] leafl Leaflist state for keeping track of when [] ends
* @param[in,out] leaflname Leaflist state for []
* leaflist state:
@ -112,8 +113,10 @@ xml2txt1(cxobj *xn,
clicon_output_cb *fn,
FILE *f,
int level,
int autocliext,
int *leafl,
char **leaflname)
{
cxobj *xc = NULL;
int children=0;
@ -134,10 +137,12 @@ xml2txt1(cxobj *xn,
goto done;
}
if ((yn = xml_spec(xn)) != NULL){
if (yang_extension_value(yn, "hide-show", CLIXON_AUTOCLI_NS, &exist, NULL) < 0)
goto done;
if (exist)
goto ok;
if (autocliext){
if (yang_extension_value(yn, "hide-show", CLIXON_AUTOCLI_NS, &exist, NULL) < 0)
goto done;
if (exist)
goto ok;
}
/* Find out prefix if needed: topmost or new module a la API-PATH */
if (ys_real_module(yn, &ymod) < 0)
goto done;
@ -230,7 +235,7 @@ xml2txt1(cxobj *xn,
if (xml_type(xc) == CX_ELMNT || xml_type(xc) == CX_BODY){
if (yn && yang_key_match(yn, xml_name(xc), NULL))
continue; /* Skip keys, already printed */
if (xml2txt1(xc, fn, f, level+1, leafl, leaflname) < 0)
if (xml2txt1(xc, fn, f, level+1, autocliext, leafl, leaflname) < 0)
break;
}
}
@ -256,6 +261,7 @@ xml2txt1(cxobj *xn,
* @param[in] level Print 4 spaces per level in front of each line
* @param[in] fn File print function (if NULL, use fprintf)
* @param[in] skiptop 0: Include top object 1: Skip top-object, only children,
* @param[in] autocliext How to handle autocli extensions: 0: ignore 1: follow
* @retval 0 OK
* @retval -1 Error
*/
@ -264,7 +270,8 @@ clixon_txt2file(FILE *f,
cxobj *xn,
int level,
clicon_output_cb *fn,
int skiptop)
int skiptop,
int autocliext)
{
int retval = 1;
cxobj *xc;
@ -276,11 +283,11 @@ clixon_txt2file(FILE *f,
if (skiptop){
xc = NULL;
while ((xc = xml_child_each(xn, xc, CX_ELMNT)) != NULL)
if (xml2txt1(xc, fn, f, level, &leafl, &leaflname) < 0)
if (xml2txt1(xc, fn, f, level, autocliext, &leafl, &leaflname) < 0)
goto done;
}
else {
if (xml2txt1(xn, fn, f, level, &leafl, &leaflname) < 0)
if (xml2txt1(xn, fn, f, level, autocliext, &leafl, &leaflname) < 0)
goto done;
}
retval = 0;

View file

@ -89,21 +89,26 @@
/*! Print an XML tree structure to an output stream and encode chars "<>&"
*
* @param[in] f UNIX output stream
* @param[in] xn Clicon xml tree
* @param[in] level How many spaces to insert before each line
* @param[in] pretty Insert \n and spaces to make the xml more readable.
* @param[in] fn Callback to make print function
* @param[in] f UNIX output stream
* @param[in] xn Clicon xml tree
* @param[in] level How many spaces to insert before each line
* @param[in] pretty Insert \n and spaces to make the xml more readable.
* @param[in] fn Callback to make print function
* @param[in] autocliext How to handle autocli extensions: 0: ignore 1: follow
* @retval 0 OK
* @retval -1 Error
* @see clixon_xml2cbuf
* One can use clixon_xml2cbuf to get common code, but using fprintf is
* much faster than using cbuf and then printing that,...
*
*/
int
static int
xml2file_recurse(FILE *f,
cxobj *x,
int level,
int pretty,
clicon_output_cb *fn)
clicon_output_cb *fn,
int autocliext)
{
int retval = -1;
char *name;
@ -114,13 +119,17 @@ xml2file_recurse(FILE *f,
char *val;
char *encstr = NULL; /* xml encoded string */
int exist = 0;
yang_stmt *y;
if (x == NULL)
goto ok;
if (yang_extension_value(xml_spec(x), "hide-show", CLIXON_AUTOCLI_NS, &exist, NULL) < 0)
goto done;
if (exist)
goto ok;
if (autocliext &&
(y = xml_spec(x)) != NULL){
if (yang_extension_value(y, "hide-show", CLIXON_AUTOCLI_NS, &exist, NULL) < 0)
goto done;
if (exist)
goto ok;
}
name = xml_name(x);
namespace = xml_prefix(x);
switch(xml_type(x)){
@ -149,7 +158,7 @@ xml2file_recurse(FILE *f,
while ((xc = xml_child_each(x, xc, -1)) != NULL) {
switch (xml_type(xc)){
case CX_ATTR:
if (xml2file_recurse(f, xc, level+1, pretty, fn) <0)
if (xml2file_recurse(f, xc, level+1, pretty, fn, autocliext) <0)
goto done;
break;
case CX_BODY:
@ -174,7 +183,7 @@ xml2file_recurse(FILE *f,
xc = NULL;
while ((xc = xml_child_each(x, xc, -1)) != NULL) {
if (xml_type(xc) != CX_ATTR)
if (xml2file_recurse(f, xc, level+1, pretty, fn) <0)
if (xml2file_recurse(f, xc, level+1, pretty, fn, autocliext) <0)
goto done;
}
if (pretty && hasbody==0)
@ -206,9 +215,12 @@ xml2file_recurse(FILE *f,
* @param[in] pretty Insert \n and spaces to make the xml more readable.
* @param[in] fn File print function (if NULL, use fprintf)
* @param[in] skiptop 0: Include top object 1: Skip top-object, only children,
* @param[in] autocliext How to handle autocli extensions: 0: ignore 1: follow
* @retval 0 OK
* @retval -1 Error
* @see clixon_xml2cbuf print to a cbuf string
* @note There is a slight "layer violation" with the autocli parameter: it should normally be set
* for CLI calls, but not for others.
*/
int
clixon_xml2file(FILE *f,
@ -216,7 +228,8 @@ clixon_xml2file(FILE *f,
int level,
int pretty,
clicon_output_cb *fn,
int skiptop)
int skiptop,
int autocliext)
{
int retval = 1;
cxobj *xc;
@ -226,11 +239,11 @@ clixon_xml2file(FILE *f,
if (skiptop){
xc = NULL;
while ((xc = xml_child_each(xn, xc, CX_ELMNT)) != NULL)
if (xml2file_recurse(f, xc, level, pretty, fn) < 0)
if (xml2file_recurse(f, xc, level, pretty, fn, autocliext) < 0)
goto done;
}
else {
if (xml2file_recurse(f, xn, level, pretty, fn) < 0)
if (xml2file_recurse(f, xn, level, pretty, fn, autocliext) < 0)
goto done;
}
retval = 0;
@ -241,8 +254,7 @@ clixon_xml2file(FILE *f,
/*! Print an XML tree structure to an output stream
*
* Uses clixon_xml2file internally
*
* Utility function eg in gdb. For code, use clixon_xml2file
* @param[in] f UNIX output stream
* @param[in] xn clicon xml tree
* @see clixon_xml2cbuf
@ -252,7 +264,7 @@ int
xml_print(FILE *f,
cxobj *x)
{
return xml2file_recurse(f, x, 0, 1, fprintf);
return xml2file_recurse(f, x, 0, 1, fprintf, 0);
}
/*! Dump cxobj structure with pointers and flags for debugging, internal function

View file

@ -377,7 +377,7 @@ clixon_xvec_print(FILE *f,
int i;
for (i=0; i<xv->xv_len; i++)
if (clixon_xml2file(f, xv->xv_vec[i], 0, 1, fprintf, 0) < 0)
if (clixon_xml2file(f, xv->xv_vec[i], 0, 1, fprintf, 0, 0) < 0)
return -1;
return 0;
}