* Much better support for XPATH 1.0 according to https://www.w3.org/TR/xpath-10 using yacc/lex

* NOTE: Due to an error in the previous implementation, all XPATH calls on the form `x[a=str]` where `str` is a string (not a number or XML symbol), must be changed to: `x[a='str'] or x[a="str"]`
    * This includes all calls to `xpath_vec, xpath_first`, etc.
    * All calls to cli_copy_config in CLI spec files must replace 2nd argument from `x[%s=%s]` to `x[%s='%s']`
  * The old API is stillenabled. To define the new, define XPATH_USE_NEW in include/clixon_custom.h and recompile
This commit is contained in:
Olof hagsand 2018-07-17 16:59:32 +02:00
parent 5d7c4a8d18
commit ba7f84afee
29 changed files with 395 additions and 79 deletions

View file

@ -985,7 +985,13 @@ nacm_access(clicon_handle h,
if (username == NULL)
goto step10;
/* User's group */
if (xpath_vec(xacm, "groups/group[user-name=%s]", &gvec, &glen, username) < 0)
if (xpath_vec(xacm,
#ifdef XPATH_USE_NEW
"groups/group[user-name='%s']",
#else
"groups/group[user-name=%s]",
#endif
&gvec, &glen, username) < 0)
goto done;
/* 5. If no groups are found, continue with step 10. */
if (glen == 0)
@ -1002,7 +1008,13 @@ nacm_access(clicon_handle h,
for (j=0; j<glen; j++){
char *gname;
gname = xml_find_body(gvec[j], "name");
if (xpath_first(xrlist,".[group=%s]", gname)!=NULL)
if (xpath_first(xrlist,
#ifdef XPATH_USE_NEW
".[group='%s']",
#else
".[group=%s]",
#endif
gname)!=NULL)
break; /* found */
}
if (j==glen) /* not found */

View file

@ -78,7 +78,7 @@
/*! Register log notification stream
* @param[in] h Clicon handle
* @param[in] stream Event stream. CLICON is predefined, others are application-defined
* @param[in] filter Filter. For xml notification ie xpath: .[name=kalle]
* @param[in] filter Filter. For xml notification ie xpath: .[name="kalle"]
* @param[in] status 0 for stop, 1 to start
* @param[in] fn Callback function called when notification occurs
* @param[in] arg Argument to function note
@ -1189,7 +1189,7 @@ cli_unlock(clicon_handle h,
* tovar: Name of variable containing name of object to copy to.
* @code
* cli spec:
* copy snd <n1:string> to <n2:string>, cli_copy_config("candidate", "/sender[%s=%s]", "from", "n1", "n2");
* copy snd <n1:string> to <n2:string>, cli_copy_config("candidate", "/sender[%s='%s']", "from", "n1", "n2");
* cli command:
* copy snd from to to
* @endcode
@ -1244,17 +1244,34 @@ cli_copy_config(clicon_handle h,
clicon_err(OE_PLUGIN, errno, "cbuf_new");
goto done;
}
/* Sanity check that xpath contains exactly one %s */
/* Sanity check that xpath contains exactly two %s, ie [%s='%s'] */
j = 0;
for (i=0; i<strlen(xpath); i++)
for (i=0; i<strlen(xpath); i++){
if (xpath[i] == '%')
j++;
#ifndef XPATH_USE_NEW
/* This is a horrible kludge due to:
* (1) old xpath implementation wrongly did: a[b=x] instead of a[b='x']
* (2) cli_copy_config has as 2nd argument such an xpath provided by user.
*/
if (j==2){
int k;
if ((xpath[i-1] == '\'' || xpath[i-1] == '\"') &&
(xpath[i+2] == '\'' || xpath[i+2] == '\"')){
for (k=i-1;k<i+2;k++)
xpath[k] = xpath[k+1];
for (k=i+1;k<strlen(xpath)+1;k++)
xpath[k] = xpath[k+2];
i-=1;
}
}
#endif
}
if (j != 2){
clicon_err(OE_PLUGIN, 0, "xpath '%s' does not have two '%%'", xpath);
goto done;
}
cprintf(cb, xpath, keyname, fromname);
/* Get from object configuration and store in x1 */
if (clicon_rpc_get_config(h, db, cbuf_get(cb), &x1) < 0)
goto done;

View file

@ -285,7 +285,7 @@ yang2cli_var_sub(clicon_handle h,
goto done;
}
}
cprintf(cb, "%s]", r);
cprintf(cb, "%s]", r); /* range */
free(r);
r = NULL;
}

View file

@ -148,7 +148,7 @@ expand_dbvar(void *h,
api_path_fmt = cv_string_get(cv);
/* api_path_fmt = /interface/%s/address/%s
--> ^/interface/eth0/address/.*$
--> /interface/[name=eth0]/address
--> /interface/[name="eth0"]/address
*/
if (api_path_fmt2xpath(api_path_fmt, cvv, &xpath) < 0)
goto done;
@ -417,10 +417,10 @@ show_yang(clicon_handle h,
* Format of argv:
* <dbname> "running"|"candidate"|"startup"
* <format> "text"|"xml"|"json"|"cli"|"netconf" (see format_enum)
* <xpath> xpath expression, that may contain one %, eg "/sender[name=%s]"
* <xpath> xpath expression, that may contain one %, eg "/sender[name="%s"]"
* <varname> optional name of variable in cvv. If set, xpath must have a '%s'
* @code
* show config id <n:string>, cli_show_config("running","xml","iface[name=%s]","n");
* show config id <n:string>, cli_show_config("running","xml","iface[name="%s"]","n");
* @endcode
*/
int

View file

@ -82,12 +82,15 @@
static int
netconf_hello(cxobj *xn)
{
#ifdef nyi
cxobj *x;
x = NULL;
while ((x = xpath_each(xn, "//capability", x)) != NULL) {
//fprintf(stderr, "cap: %s\n", xml_body(x));
}
#endif
return 0;
}

View file

@ -95,6 +95,9 @@ Mapping netconf error-tag -> status code
*/
#ifdef HAVE_CONFIG_H
#include "clixon_config.h" /* generated by config & autoconf */
#endif
#include <stdlib.h>
#include <string.h>
#include <unistd.h>