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 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_decode(char **escp, const char *fmt,...);
|
||||
int uri_percent_decode(char *enc, char **str);
|
||||
|
||||
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);
|
||||
int yang_spec_parse_module(clicon_handle h, const char *module,
|
||||
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_load_dir(clicon_handle h, char *dir, yang_stmt *yspec);
|
||||
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
|
||||
* @param[in] h CLICON handle
|
||||
* @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] persist A persist identifier to use
|
||||
* @param[in] persist_id If cancel or confirmed, the persist id
|
||||
|
|
|
|||
|
|
@ -387,7 +387,7 @@ uri_percent_decode(char *enc,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Escape characters according to XML definition
|
||||
/*! Encode escape characters according to XML definition
|
||||
* @param[out] encp Encoded malloced output string
|
||||
* @param[in] fmt Not-encoded input string (stdarg format string)
|
||||
* @param[in] ... stdarg variable parameters
|
||||
|
|
@ -410,6 +410,7 @@ uri_percent_decode(char *enc,
|
|||
* @see uri_percent_encode
|
||||
* @see AMPERSAND mode in clixon_xml_parse.l, implicit decoding
|
||||
* @see xml_chardata_cbuf_append for a specialized version
|
||||
* @see xml_chardata_decode for decoding
|
||||
*/
|
||||
int
|
||||
xml_chardata_encode(char **escp,
|
||||
|
|
@ -587,6 +588,147 @@ xml_chardata_cbuf_append(cbuf *cb,
|
|||
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
|
||||
*
|
||||
* (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>"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>"#"[0-9]+";" { BEGIN(_XY->xy_lex_state); clixon_xml_parselval.string = "\""; return CHARDATA; /* ISO/IEC 10646 */ }
|
||||
<AMPERSAND>"#x"[0-9a-fA-F]+";" { BEGIN(_XY->xy_lex_state); clixon_xml_parselval.string = "\""; return CHARDATA;}
|
||||
<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 = yytext; return ENCODED;}
|
||||
|
||||
<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;}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
%start document
|
||||
|
||||
%token <string> NAME CHARDATA WHITESPACE STRING
|
||||
%token <string> NAME CHARDATA ENCODED WHITESPACE STRING
|
||||
%token MY_EOF
|
||||
%token VER ENC SD
|
||||
%token BSLASH ESLASH
|
||||
|
|
@ -104,12 +104,14 @@ clixon_xml_parseerror(void *_xy,
|
|||
|
||||
/*! Parse XML content, eg chars between >...<
|
||||
* @param[in] xy
|
||||
* @param[in] encoded set if ampersand encoded
|
||||
* @param[in] str Body string, direct pointer (copy before use, dont free)
|
||||
* Note that we dont handle escaped characters correctly
|
||||
* there may also be some leakage here on NULL return
|
||||
*/
|
||||
static int
|
||||
xml_parse_content(clixon_xml_yacc *xy,
|
||||
int encoded,
|
||||
char *str)
|
||||
{
|
||||
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)
|
||||
goto done;
|
||||
}
|
||||
if (encoded)
|
||||
if (xml_value_append(xn, "&") < 0)
|
||||
goto done;
|
||||
if (xml_value_append(xn, str) < 0)
|
||||
goto done;
|
||||
xy->xy_xelement = xn;
|
||||
|
|
@ -446,8 +451,10 @@ elist : elist content { _PARSE_DEBUG("elist -> elist content"); }
|
|||
content : element { _PARSE_DEBUG("content -> element"); }
|
||||
| comment { _PARSE_DEBUG("content -> comment"); }
|
||||
| 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"); }
|
||||
| ENCODED { if (xml_parse_content(_XY, 1, $1) < 0) YYABORT;
|
||||
_PARSE_DEBUG("content -> ENCODED"); }
|
||||
| WHITESPACE { if (xml_parse_whitespace(_XY, $1) < 0) YYABORT;
|
||||
_PARSE_DEBUG("content -> WHITESPACE"); }
|
||||
| { _PARSE_DEBUG("content -> "); }
|
||||
|
|
|
|||
|
|
@ -759,7 +759,7 @@ yang_expand_grouping(yang_stmt *yn)
|
|||
* @retval NULL Error encountered
|
||||
* See top of file for diagram of calling order
|
||||
*/
|
||||
static yang_stmt *
|
||||
yang_stmt *
|
||||
yang_parse_str(char *str,
|
||||
const char *name, /* just for errs */
|
||||
yang_stmt *yspec)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue