Enhanced for client-side functionality:
- parse of yang from string, not only file - Decode of xml encoding, not only decoding
This commit is contained in:
parent
0df023c70e
commit
99c6f61637
7 changed files with 158 additions and 7 deletions
|
|
@ -95,6 +95,7 @@ int uri_str2cvec(char *string, char delim1, char delim2, int decode, cvec **c
|
||||||
int uri_percent_encode(char **encp, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
|
int uri_percent_encode(char **encp, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
|
||||||
int xml_chardata_encode(char **escp, const char *fmt, ... ) __attribute__ ((format (printf, 2, 3)));
|
int xml_chardata_encode(char **escp, const char *fmt, ... ) __attribute__ ((format (printf, 2, 3)));
|
||||||
int xml_chardata_cbuf_append(cbuf *cb, char *str);
|
int xml_chardata_cbuf_append(cbuf *cb, char *str);
|
||||||
|
int xml_chardata_decode(char **escp, const char *fmt,...);
|
||||||
int uri_percent_decode(char *enc, char **str);
|
int uri_percent_decode(char *enc, char **str);
|
||||||
|
|
||||||
const char *clicon_int2str(const map_str2int *mstab, int i);
|
const char *clicon_int2str(const map_str2int *mstab, int i);
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ yang_stmt *yang_parse_file(FILE *fp, const char *name, yang_stmt *ysp);
|
||||||
yang_stmt *yang_parse_filename(const char *filename, yang_stmt *ysp);
|
yang_stmt *yang_parse_filename(const char *filename, yang_stmt *ysp);
|
||||||
int yang_spec_parse_module(clicon_handle h, const char *module,
|
int yang_spec_parse_module(clicon_handle h, const char *module,
|
||||||
const char *revision, yang_stmt *yspec);
|
const char *revision, yang_stmt *yspec);
|
||||||
|
yang_stmt *yang_parse_str(char *str, const char *name, yang_stmt *yspec);
|
||||||
int yang_spec_parse_file(clicon_handle h, char *filename, yang_stmt *yspec);
|
int yang_spec_parse_file(clicon_handle h, char *filename, yang_stmt *yspec);
|
||||||
int yang_spec_load_dir(clicon_handle h, char *dir, yang_stmt *yspec);
|
int yang_spec_load_dir(clicon_handle h, char *dir, yang_stmt *yspec);
|
||||||
int ys_parse_date_arg(char *datearg, uint32_t *dateint);
|
int ys_parse_date_arg(char *datearg, uint32_t *dateint);
|
||||||
|
|
|
||||||
|
|
@ -1270,7 +1270,7 @@ clicon_rpc_validate(clicon_handle h,
|
||||||
/*! Commit changes send a commit request to backend daemon
|
/*! Commit changes send a commit request to backend daemon
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
* @param[in] confirmed If set, send commit/confirmed
|
* @param[in] confirmed If set, send commit/confirmed
|
||||||
* @param[in] cancel If set, send cancle-commit
|
* @param[in] cancel If set, send cancel-commit
|
||||||
* @param[in] timeout For confirmed, a timeout in seconds (default 600s)
|
* @param[in] timeout For confirmed, a timeout in seconds (default 600s)
|
||||||
* @param[in] persist A persist identifier to use
|
* @param[in] persist A persist identifier to use
|
||||||
* @param[in] persist_id If cancel or confirmed, the persist id
|
* @param[in] persist_id If cancel or confirmed, the persist id
|
||||||
|
|
|
||||||
|
|
@ -387,7 +387,7 @@ uri_percent_decode(char *enc,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Escape characters according to XML definition
|
/*! Encode escape characters according to XML definition
|
||||||
* @param[out] encp Encoded malloced output string
|
* @param[out] encp Encoded malloced output string
|
||||||
* @param[in] fmt Not-encoded input string (stdarg format string)
|
* @param[in] fmt Not-encoded input string (stdarg format string)
|
||||||
* @param[in] ... stdarg variable parameters
|
* @param[in] ... stdarg variable parameters
|
||||||
|
|
@ -410,6 +410,7 @@ uri_percent_decode(char *enc,
|
||||||
* @see uri_percent_encode
|
* @see uri_percent_encode
|
||||||
* @see AMPERSAND mode in clixon_xml_parse.l, implicit decoding
|
* @see AMPERSAND mode in clixon_xml_parse.l, implicit decoding
|
||||||
* @see xml_chardata_cbuf_append for a specialized version
|
* @see xml_chardata_cbuf_append for a specialized version
|
||||||
|
* @see xml_chardata_decode for decoding
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xml_chardata_encode(char **escp,
|
xml_chardata_encode(char **escp,
|
||||||
|
|
@ -587,6 +588,147 @@ xml_chardata_cbuf_append(cbuf *cb,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! xml decode &...;
|
||||||
|
*
|
||||||
|
* @param[in] str Input string on the form &..; with & stripped
|
||||||
|
* @param[out] ch Decoded character
|
||||||
|
* @param[in,out] ip
|
||||||
|
* @retval 1 OK and identified a decoding
|
||||||
|
* @retval 0 OK No identified decoding
|
||||||
|
* @retval -1 Error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
xml_chardata_decode_ampersand(char *str,
|
||||||
|
char *ch,
|
||||||
|
int *ip)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char *semi;
|
||||||
|
char *p;
|
||||||
|
size_t len;
|
||||||
|
uint32_t code;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((semi = index(str, ';')) == NULL)
|
||||||
|
goto fail;
|
||||||
|
*semi = '\0';
|
||||||
|
len = strlen(str);
|
||||||
|
p = str;
|
||||||
|
if (strcmp(p, "amp") == 0)
|
||||||
|
*ch = '&';
|
||||||
|
else if (strcmp(p, "lt") == 0)
|
||||||
|
*ch = '<';
|
||||||
|
else if (strcmp(p, "gt") == 0)
|
||||||
|
*ch = '>';
|
||||||
|
else if (strcmp(p, "apos") == 0)
|
||||||
|
*ch = '\'';
|
||||||
|
else if (strcmp(p, "quot") == 0)
|
||||||
|
*ch = '"';
|
||||||
|
else if (len > 0 && *p == '#'){
|
||||||
|
p++;
|
||||||
|
if ((cb = cbuf_new()) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "parse_uint32");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (len > 1 && *p == 'x'){
|
||||||
|
cprintf(cb, "0x");
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
cprintf(cb, "%s", p);
|
||||||
|
if ((ret = parse_uint32(cbuf_get(cb), &code, NULL)) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "parse_uint32");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (ret == 0){
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
*ch = code;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto fail;
|
||||||
|
*ip += len+1;
|
||||||
|
retval = 1;
|
||||||
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
|
return retval;
|
||||||
|
fail:
|
||||||
|
retval = 0;
|
||||||
|
if (semi)
|
||||||
|
*semi = ';';
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Decode escape characters according to XML definition
|
||||||
|
* @param[out] decp Decoded malloced output string
|
||||||
|
* @param[in] fmt Encoded input string (stdarg format string)
|
||||||
|
* @see xml_chardata_encode for encoding
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xml_chardata_decode(char **decp,
|
||||||
|
const char *fmt,...)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char *str = NULL; /* Expanded encoded format string w stdarg */
|
||||||
|
char *dec = NULL;
|
||||||
|
int fmtlen;
|
||||||
|
va_list args;
|
||||||
|
size_t slen;
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
char ch;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Two steps: (1) read in the complete format string */
|
||||||
|
va_start(args, fmt); /* dryrun */
|
||||||
|
fmtlen = vsnprintf(NULL, 0, fmt, args) + 1;
|
||||||
|
va_end(args);
|
||||||
|
if ((str = malloc(fmtlen)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "malloc");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
memset(str, 0, fmtlen);
|
||||||
|
va_start(args, fmt); /* real */
|
||||||
|
fmtlen = vsnprintf(str, fmtlen, fmt, args) + 1;
|
||||||
|
va_end(args);
|
||||||
|
/* Now str is the combined fmt + ... */
|
||||||
|
|
||||||
|
/* Step (2) decode str --> dec
|
||||||
|
* First allocate decoded string, encoded is always >= larger */
|
||||||
|
slen = strlen(str);
|
||||||
|
if ((dec = malloc(slen+1)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "malloc");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
j = 0;
|
||||||
|
memset(dec, 0, slen+1);
|
||||||
|
for (i=0; i<slen; i++){
|
||||||
|
ch = str[i];
|
||||||
|
switch (ch){
|
||||||
|
case '&':
|
||||||
|
if ((ret = xml_chardata_decode_ampersand(&str[i+1], &ch, &i)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ret == 0)
|
||||||
|
dec[j++] = str[i];
|
||||||
|
else
|
||||||
|
dec[j++] = ch;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dec[j++] = str[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*decp = dec;
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (str)
|
||||||
|
free(str);
|
||||||
|
if (retval < 0 && dec)
|
||||||
|
free(dec);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Split a string into a cligen variable vector using 1st and 2nd delimiter
|
/*! Split a string into a cligen variable vector using 1st and 2nd delimiter
|
||||||
*
|
*
|
||||||
* (1) Split a string into elements delimited by delim1,
|
* (1) Split a string into elements delimited by delim1,
|
||||||
|
|
|
||||||
|
|
@ -146,8 +146,8 @@ ncname {namestart}{namechar}*
|
||||||
<AMPERSAND>"gt;" { BEGIN(_XY->xy_lex_state); clixon_xml_parselval.string = ">"; return CHARDATA;}
|
<AMPERSAND>"gt;" { BEGIN(_XY->xy_lex_state); clixon_xml_parselval.string = ">"; return CHARDATA;}
|
||||||
<AMPERSAND>"apos;" { BEGIN(_XY->xy_lex_state); clixon_xml_parselval.string = "'"; return CHARDATA;}
|
<AMPERSAND>"apos;" { BEGIN(_XY->xy_lex_state); clixon_xml_parselval.string = "'"; return CHARDATA;}
|
||||||
<AMPERSAND>"quot;" { BEGIN(_XY->xy_lex_state); clixon_xml_parselval.string = "\""; return CHARDATA;}
|
<AMPERSAND>"quot;" { BEGIN(_XY->xy_lex_state); clixon_xml_parselval.string = "\""; return CHARDATA;}
|
||||||
<AMPERSAND>"#"[0-9]+";" { BEGIN(_XY->xy_lex_state); clixon_xml_parselval.string = "\""; return CHARDATA; /* ISO/IEC 10646 */ }
|
<AMPERSAND>"#"[0-9]+";" { BEGIN(_XY->xy_lex_state); clixon_xml_parselval.string = yytext; return ENCODED; /* ISO/IEC 10646 */ }
|
||||||
<AMPERSAND>"#x"[0-9a-fA-F]+";" { BEGIN(_XY->xy_lex_state); clixon_xml_parselval.string = "\""; return CHARDATA;}
|
<AMPERSAND>"#x"[0-9a-fA-F]+";" { BEGIN(_XY->xy_lex_state); clixon_xml_parselval.string = yytext; return ENCODED;}
|
||||||
|
|
||||||
<CDATA>\n { clixon_xml_parselval.string = yytext;_XY->xy_linenum++; return (CHARDATA);}
|
<CDATA>\n { clixon_xml_parselval.string = yytext;_XY->xy_linenum++; return (CHARDATA);}
|
||||||
<CDATA>"]]>" { BEGIN(_XY->xy_lex_state); clixon_xml_parselval.string = yytext; return CHARDATA;}
|
<CDATA>"]]>" { BEGIN(_XY->xy_lex_state); clixon_xml_parselval.string = yytext; return CHARDATA;}
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@
|
||||||
|
|
||||||
%start document
|
%start document
|
||||||
|
|
||||||
%token <string> NAME CHARDATA WHITESPACE STRING
|
%token <string> NAME CHARDATA ENCODED WHITESPACE STRING
|
||||||
%token MY_EOF
|
%token MY_EOF
|
||||||
%token VER ENC SD
|
%token VER ENC SD
|
||||||
%token BSLASH ESLASH
|
%token BSLASH ESLASH
|
||||||
|
|
@ -104,12 +104,14 @@ clixon_xml_parseerror(void *_xy,
|
||||||
|
|
||||||
/*! Parse XML content, eg chars between >...<
|
/*! Parse XML content, eg chars between >...<
|
||||||
* @param[in] xy
|
* @param[in] xy
|
||||||
|
* @param[in] encoded set if ampersand encoded
|
||||||
* @param[in] str Body string, direct pointer (copy before use, dont free)
|
* @param[in] str Body string, direct pointer (copy before use, dont free)
|
||||||
* Note that we dont handle escaped characters correctly
|
* Note that we dont handle escaped characters correctly
|
||||||
* there may also be some leakage here on NULL return
|
* there may also be some leakage here on NULL return
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
xml_parse_content(clixon_xml_yacc *xy,
|
xml_parse_content(clixon_xml_yacc *xy,
|
||||||
|
int encoded,
|
||||||
char *str)
|
char *str)
|
||||||
{
|
{
|
||||||
cxobj *xn = xy->xy_xelement;
|
cxobj *xn = xy->xy_xelement;
|
||||||
|
|
@ -121,6 +123,9 @@ xml_parse_content(clixon_xml_yacc *xy,
|
||||||
if ((xn = xml_new("body", xp, CX_BODY)) == NULL)
|
if ((xn = xml_new("body", xp, CX_BODY)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (encoded)
|
||||||
|
if (xml_value_append(xn, "&") < 0)
|
||||||
|
goto done;
|
||||||
if (xml_value_append(xn, str) < 0)
|
if (xml_value_append(xn, str) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
xy->xy_xelement = xn;
|
xy->xy_xelement = xn;
|
||||||
|
|
@ -446,8 +451,10 @@ elist : elist content { _PARSE_DEBUG("elist -> elist content"); }
|
||||||
content : element { _PARSE_DEBUG("content -> element"); }
|
content : element { _PARSE_DEBUG("content -> element"); }
|
||||||
| comment { _PARSE_DEBUG("content -> comment"); }
|
| comment { _PARSE_DEBUG("content -> comment"); }
|
||||||
| pi { _PARSE_DEBUG("content -> pi"); }
|
| pi { _PARSE_DEBUG("content -> pi"); }
|
||||||
| CHARDATA { if (xml_parse_content(_XY, $1) < 0) YYABORT;
|
| CHARDATA { if (xml_parse_content(_XY, 0, $1) < 0) YYABORT;
|
||||||
_PARSE_DEBUG("content -> CHARDATA"); }
|
_PARSE_DEBUG("content -> CHARDATA"); }
|
||||||
|
| ENCODED { if (xml_parse_content(_XY, 1, $1) < 0) YYABORT;
|
||||||
|
_PARSE_DEBUG("content -> ENCODED"); }
|
||||||
| WHITESPACE { if (xml_parse_whitespace(_XY, $1) < 0) YYABORT;
|
| WHITESPACE { if (xml_parse_whitespace(_XY, $1) < 0) YYABORT;
|
||||||
_PARSE_DEBUG("content -> WHITESPACE"); }
|
_PARSE_DEBUG("content -> WHITESPACE"); }
|
||||||
| { _PARSE_DEBUG("content -> "); }
|
| { _PARSE_DEBUG("content -> "); }
|
||||||
|
|
|
||||||
|
|
@ -759,7 +759,7 @@ yang_expand_grouping(yang_stmt *yn)
|
||||||
* @retval NULL Error encountered
|
* @retval NULL Error encountered
|
||||||
* See top of file for diagram of calling order
|
* See top of file for diagram of calling order
|
||||||
*/
|
*/
|
||||||
static yang_stmt *
|
yang_stmt *
|
||||||
yang_parse_str(char *str,
|
yang_parse_str(char *str,
|
||||||
const char *name, /* just for errs */
|
const char *name, /* just for errs */
|
||||||
yang_stmt *yspec)
|
yang_stmt *yspec)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue