diff --git a/CHANGELOG b/CHANGELOG index 1e036111..df6b8045 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -29,6 +29,7 @@ # # ***** END LICENSE BLOCK ***** +- List keys with special characters are RFC 3986 encoded. - Added cli multiple callback and expand support. Use options CLICON_CLIGEN_CALLBACK_SINGLE_ARG and CLICON_CLIGEN_EXPAND_SINGLE_ARG to control these. diff --git a/lib/src/clixon_xml_db.c b/lib/src/clixon_xml_db.c index 78b62835..fc33f866 100644 --- a/lib/src/clixon_xml_db.c +++ b/lib/src/clixon_xml_db.c @@ -51,6 +51,7 @@ #include #include #include +#include /* cligen */ #include @@ -95,14 +96,16 @@ * +-----------------+ +-----------------+ * | yang-stmt | yang2xmlkeyfmt | xmlkeyfmt | * | list aa,leaf k | ----------------->| /aa/%s | + * | | | XXX: /aa=%s | * +-----------------+ +-----------------+ * | * | xmlkeyfmt2key * | k=17 * v * +-------------------+ +-----------------+ - * | xml-tree/cxobj | xmlkey2xml | xmlkey | + * | xml-tree/cxobj | xmlkey2xml | xmlkey RFC3986| * | 17| <------------- | /aa/17 | + * | | | XXX: /aa=17 | * +-------------------+ +-----------------+ * * Alternative for xmlkeyfmt would be xpath: eg @@ -235,6 +238,8 @@ xmlkeyfmt2key(char *xkfmt, int i; int j; char *str; + char *strenc=NULL; + /* Sanity check */ #if 1 @@ -266,7 +271,12 @@ xmlkeyfmt2key(char *xkfmt, clicon_err(OE_UNIX, errno, "strdup"); goto done; } - cprintf(cb, "%s", str); + if ((strenc = curl_easy_escape(NULL, str, 0)) == NULL){ + clicon_err(OE_UNIX, errno, "curl_easy_escape"); + goto done; + } + cprintf(cb, "%s", strenc); + curl_free(strenc); free(str); } else @@ -493,6 +503,7 @@ append_listkeys(cbuf *ckey, cg_var *cvi; cvec *cvk = NULL; /* vector of index keys */ char *keyname; + char *bodyenc; if ((ykey = yang_find((yang_node*)ys, Y_KEY, NULL)) == NULL){ clicon_err(OE_XML, errno, "%s: List statement \"%s\" has no key", @@ -511,7 +522,12 @@ append_listkeys(cbuf *ckey, xml_name(xt), keyname); goto done; } - cprintf(ckey, "/%s", xml_body(xkey)); + if ((bodyenc = curl_easy_escape(NULL, xml_body(xkey), 0)) == NULL){ + clicon_err(OE_UNIX, errno, "curl_easy_escape"); + goto done; + } + cprintf(ckey, "/%s", bodyenc); + free(bodyenc); bodyenc = NULL; } retval = 0; done: @@ -617,6 +633,7 @@ get(char *dbname, cvec *cvk = NULL; /* vector of index keys */ char *keyname; char *arg; + char *argdec; cbuf *cb; // clicon_debug(1, "%s xkey:%s val:%s", __FUNCTION__, xk, val); @@ -700,7 +717,13 @@ get(char *dbname, goto done; } arg = vec[i]; - cprintf(cb, "[%s=%s]", cv_string_get(cvi), arg); + if ((argdec = curl_easy_unescape(NULL, arg, 0, NULL)) == NULL){ + clicon_err(OE_UNIX, errno, "curl_easy_escape"); + goto done; + } + cprintf(cb, "[%s=%s]", cv_string_get(cvi), argdec); + free(argdec); + argdec=NULL; } if ((xc = xpath_first(x, cbuf_get(cb))) == NULL){ if ((xc = xml_new_spec(name, x, y)) == NULL) @@ -712,11 +735,16 @@ get(char *dbname, keyname = cv_string_get(cvi); i++; arg = vec[i]; + if ((argdec = curl_easy_unescape(NULL, arg, 0, NULL)) == NULL){ + clicon_err(OE_UNIX, errno, "curl_easy_escape"); + goto done; + } if (create_keyvalues(xc, ykey, - arg, + argdec, keyname) < 0) goto done; + free(argdec); argdec = NULL; } /* while */ } if (cb){ @@ -1570,7 +1598,7 @@ xmldb_put_xkey_local(clicon_handle h, char *name; cg_var *cvi; cvec *cvk = NULL; /* vector of index keys */ - char *val2; + char *val2 = NULL; cbuf *ckey=NULL; /* partial keys */ cbuf *csubkey=NULL; /* partial keys */ cbuf *crx=NULL; /* partial keys */ diff --git a/lib/src/clixon_xsl.c b/lib/src/clixon_xsl.c index 3a84bead..698a53d4 100644 --- a/lib/src/clixon_xsl.c +++ b/lib/src/clixon_xsl.c @@ -312,12 +312,12 @@ xpath_parse(char *xpath, { int retval = -1; int nvec = 0; - char *p; char *s; char *s0; int i; struct xpath_element *xplist = NULL; struct xpath_element **xpnext = &xplist; + int esc = 0; if ((s0 = strdup(xpath)) == NULL){ clicon_err(OE_XML, errno, "%s: strdup", __FUNCTION__); @@ -326,10 +326,28 @@ xpath_parse(char *xpath, s = s0; if (strlen(s)) nvec = 1; - while ((p = index(s, '/')) != NULL){ - nvec++; - *p = '\0'; - s = p+1; + /* Chop up LocatoinPath in Steps delimited by '/' (unless [] predicate) + * Eg, "/a/b[/c]/d" -> "a" "b[/c]" "d" + */ + esc = 0; + while (*s != '\0'){ + switch (*s){ + case '/': + if (esc) + break; + nvec++; + *s = '\0'; + break; + case '[': + esc++; + break; + case ']': + esc--; + break; + default: + break; + } + s++; } s = s0; for (i=0; i= * - - * - = + * - = # RelationalExpr '=' RelationalExpr * @see https://www.w3.org/TR/xpath/#predicates */ static int