* RESTCONF in Clixon used empty key as "wildchar". But according to RFC 8040 it should mean the "empty string".

* Example: `GET restconf/data/x:a=`
  * Previous meaning (wrong): Return all `a` elements.
  * New meaning (correct): Return the `a` instance with empty key string: "".
* [RESTCONF GET request of single-key list with empty string returns all elements #213](https://github.com/clicon/clixon/issues/213)
* [RESTCONF GETof lists with empty string keys does not work #214](https://github.com/clicon/clixon/issues/214)
This commit is contained in:
Olof hagsand 2021-05-05 15:04:22 +02:00
parent af04ec9e9d
commit 17e7b25537
8 changed files with 77 additions and 22 deletions

View file

@ -713,7 +713,7 @@ api_path2xpath_cvv(cvec *api_path,
goto done;
}
/* Check if has value, means '=' */
if (cv2str(cv, NULL, 0) > 0){
if (cv_type_get(cv) == CGV_STRING){
/* val is uri percent encoded, eg x%2Cy,z */
if ((val = cv2str_dup(cv)) == NULL)
goto done;

View file

@ -560,8 +560,9 @@ xml_chardata_cbuf_append(cbuf *cb,
* err;
* @endcode
*
* a=b&c=d -> [[a,"b"][c="d"]
* kalle&c=d -> [[c="d"]] # Discard elements with no delim2
* a=b&c=d -> [[a,"b"][c,"d"]
* a&b= -> [[a,null][b,""]]
* Note difference between empty (CGV_EMPTY) and empty string (CGV_STRING)
* XXX differentiate between error and null cvec.
*/
int
@ -622,12 +623,11 @@ uri_str2cvec(char *string,
}
else{
if (strlen(s)){
if ((cv = cvec_add(cvv, CGV_STRING)) == NULL){
if ((cv = cvec_add(cvv, CGV_EMPTY)) == NULL){
clicon_err(OE_UNIX, errno, "cvec_add");
goto err;
}
cv_name_set(cv, s);
cv_string_set(cv, "");
}
}
s = snext;

View file

@ -251,7 +251,7 @@ xpath_tree2cbuf(xpath_tree *xs,
cprintf(xcb, "/");
break;
case XP_PRIME_STR:
cprintf(xcb, "'%s'", xs->xs_s0);
cprintf(xcb, "'%s'", xs->xs_s0?xs->xs_s0:"");
break;
case XP_PRIME_NR:
cprintf(xcb, "%s", xs->xs_strnr?xs->xs_strnr:"0");

View file

@ -824,8 +824,12 @@ xp_relop(xp_ctx *xc1,
s1 = xml_body(x);
switch(op){
case XO_EQ:
if (s1 == NULL || s2 == NULL)
xr->xc_bool = (s1==NULL && s2 == NULL);
if (s1 == NULL && s2 == NULL)
xr->xc_bool = 1;
else if (s1 == NULL && strlen(s2) == 0)
xr->xc_bool = 1;
else if (strlen(s1) == 0 && s2 == NULL)
xr->xc_bool = 1;
else
xr->xc_bool = (strcmp(s1, s2)==0);
break;

View file

@ -441,9 +441,9 @@ predicates : predicates '[' expr ']' { $$=xp_new(XP_PRED,A_NAN,NULL, NULL, NULL
primaryexpr : '(' expr ')' { $$=xp_new(XP_PRI0,A_NAN,NULL, NULL, NULL, $2, NULL); clicon_debug(3,"primaryexpr-> ( expr )"); }
| NUMBER { $$=xp_new(XP_PRIME_NR,A_NAN, $1, NULL, NULL, NULL, NULL);clicon_debug(3,"primaryexpr-> NUMBER(%s)", $1); /*XXX*/}
| QUOTE string QUOTE { $$=xp_new(XP_PRIME_STR,A_NAN,NULL, $2, NULL, NULL, NULL);clicon_debug(3,"primaryexpr-> \" string \""); }
| QUOTE QUOTE { $$=xp_new(XP_PRIME_STR,A_NAN,NULL, NULL, NULL, NULL, NULL);clicon_debug(3,"primaryexpr-> \" \""); }
| QUOTE QUOTE { $$=xp_new(XP_PRIME_STR,A_NAN,NULL, strdup(""), NULL, NULL, NULL);clicon_debug(3,"primaryexpr-> \" \""); }
| APOST string APOST { $$=xp_new(XP_PRIME_STR,A_NAN,NULL, $2, NULL, NULL, NULL);clicon_debug(3,"primaryexpr-> ' string '"); }
| APOST APOST { $$=xp_new(XP_PRIME_STR,A_NAN,NULL, NULL, NULL, NULL, NULL);clicon_debug(3,"primaryexpr-> ' '"); }
| APOST APOST { $$=xp_new(XP_PRIME_STR,A_NAN,NULL, strdup(""), NULL, NULL, NULL);clicon_debug(3,"primaryexpr-> ' '"); }
| FUNCTIONNAME ')' { if (($$ = xp_primary_function(_XPY, $1, NULL)) == NULL) YYERROR; clicon_debug(3,"primaryexpr-> functionname ()"); }
| FUNCTIONNAME args ')' { if (($$ = xp_primary_function(_XPY, $1, $2)) == NULL) YYERROR; clicon_debug(3,"primaryexpr-> functionname (arguments)"); }
;