mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-03-11 05:48:41 +00:00
BUG/MEDIUM: cli: some err/warn msg dumps add LR into CSV output on stat's CLI
The initial purpose of CSV stats through CLI was to make it easely parsable by scripts. But in some specific cases some error or warning messages strings containing LF were dumped into cells of this CSV. This made some parsing failure on several tools. In addition, if a warning or message contains to successive LF, they will be dumped directly but double LFs tag the end of the response on CLI and the client may consider a truncated response. This patch extends the 'csv_enc_append' and 'csv_enc' functions used to format quoted string content according to RFC with an additionnal parameter to convert multi-lines strings to one line: CRs are skipped, and LFs are replaced with spaces. In addition and optionally, it is also possible to remove resulting trailing spaces. The call of this function to fill strings into stat's CSV output is updated to force this conversion. This patch should be backported on all supported branches (issue was already present in v2.0)
This commit is contained in:
parent
5c88b9fcfb
commit
ef02dba7bc
@ -441,11 +441,19 @@ char *escape_string(char *start, char *stop,
|
|||||||
* It is useful if the escaped string is used between double quotes in the
|
* It is useful if the escaped string is used between double quotes in the
|
||||||
* format.
|
* format.
|
||||||
*
|
*
|
||||||
* printf("..., \"%s\", ...\r\n", csv_enc(str, 0, &trash));
|
* printf("..., \"%s\", ...\r\n", csv_enc(str, 0, 0, &trash));
|
||||||
*
|
*
|
||||||
* If <quote> is 1, the converter puts the quotes only if any character is
|
* If <quote> is 1, the converter puts the quotes only if any character is
|
||||||
* escaped. If <quote> is 2, the converter always puts the quotes.
|
* escaped. If <quote> is 2, the converter always puts the quotes.
|
||||||
*
|
*
|
||||||
|
* If <oneline> is not 0, CRs are skipped and LFs are replaced by spaces.
|
||||||
|
* This re-format multi-lines strings to only one line. The purpose is to
|
||||||
|
* allow a line by line parsing but also to keep the output compliant with
|
||||||
|
* the CLI witch uses LF to defines the end of the response.
|
||||||
|
*
|
||||||
|
* If <oneline> is 2, In addition to previous action, the trailing spaces are
|
||||||
|
* removed.
|
||||||
|
*
|
||||||
* <output> is a struct chunk used for storing the output string.
|
* <output> is a struct chunk used for storing the output string.
|
||||||
*
|
*
|
||||||
* The function returns the converted string on its output. If an error
|
* The function returns the converted string on its output. If an error
|
||||||
@ -458,14 +466,15 @@ char *escape_string(char *start, char *stop,
|
|||||||
* This function appends the encoding to the existing output chunk. Please
|
* This function appends the encoding to the existing output chunk. Please
|
||||||
* use csv_enc() instead if you want to replace the output chunk.
|
* use csv_enc() instead if you want to replace the output chunk.
|
||||||
*/
|
*/
|
||||||
const char *csv_enc_append(const char *str, int quote, struct buffer *output);
|
const char *csv_enc_append(const char *str, int quote, int online,
|
||||||
|
struct buffer *output);
|
||||||
|
|
||||||
/* same as above but the output chunk is reset first */
|
/* same as above but the output chunk is reset first */
|
||||||
static inline const char *csv_enc(const char *str, int quote,
|
static inline const char *csv_enc(const char *str, int quote, int oneline,
|
||||||
struct buffer *output)
|
struct buffer *output)
|
||||||
{
|
{
|
||||||
chunk_reset(output);
|
chunk_reset(output);
|
||||||
return csv_enc_append(str, quote, output);
|
return csv_enc_append(str, quote, oneline, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Decode an URL-encoded string in-place. The resulting string might
|
/* Decode an URL-encoded string in-place. The resulting string might
|
||||||
|
@ -409,7 +409,7 @@ int stats_emit_raw_data_field(struct buffer *out, const struct field *f)
|
|||||||
out->data = flt_trim(out->area, prev_data, chunk_appendf(out, "%f", f->u.flt));
|
out->data = flt_trim(out->area, prev_data, chunk_appendf(out, "%f", f->u.flt));
|
||||||
return out->data;
|
return out->data;
|
||||||
}
|
}
|
||||||
case FF_STR: return csv_enc_append(field_str(f, 0), 1, out) != NULL;
|
case FF_STR: return csv_enc_append(field_str(f, 0), 1, 2, out) != NULL;
|
||||||
default: return chunk_appendf(out, "[INCORRECT_FIELD_TYPE_%08x]", f->type);
|
default: return chunk_appendf(out, "[INCORRECT_FIELD_TYPE_%08x]", f->type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
31
src/tools.c
31
src/tools.c
@ -2065,11 +2065,19 @@ char *escape_string(char *start, char *stop,
|
|||||||
* It is useful if the escaped string is used between double quotes in the
|
* It is useful if the escaped string is used between double quotes in the
|
||||||
* format.
|
* format.
|
||||||
*
|
*
|
||||||
* printf("..., \"%s\", ...\r\n", csv_enc(str, 0, &trash));
|
* printf("..., \"%s\", ...\r\n", csv_enc(str, 0, 0, &trash));
|
||||||
*
|
*
|
||||||
* If <quote> is 1, the converter puts the quotes only if any reserved character
|
* If <quote> is 1, the converter puts the quotes only if any reserved character
|
||||||
* is present. If <quote> is 2, the converter always puts the quotes.
|
* is present. If <quote> is 2, the converter always puts the quotes.
|
||||||
*
|
*
|
||||||
|
* If <oneline> is not 0, CRs are skipped and LFs are replaced by spaces.
|
||||||
|
* This re-format multi-lines strings to only one line. The purpose is to
|
||||||
|
* allow a line by line parsing but also to keep the output compliant with
|
||||||
|
* the CLI witch uses LF to defines the end of the response.
|
||||||
|
*
|
||||||
|
* If <oneline> is 2, In addition to previous action, the trailing spaces are
|
||||||
|
* removed.
|
||||||
|
*
|
||||||
* <output> is a struct buffer used for storing the output string.
|
* <output> is a struct buffer used for storing the output string.
|
||||||
*
|
*
|
||||||
* The function returns the converted string on its output. If an error
|
* The function returns the converted string on its output. If an error
|
||||||
@ -2084,7 +2092,7 @@ char *escape_string(char *start, char *stop,
|
|||||||
* the chunk. Please use csv_enc() instead if you want to replace the output
|
* the chunk. Please use csv_enc() instead if you want to replace the output
|
||||||
* chunk.
|
* chunk.
|
||||||
*/
|
*/
|
||||||
const char *csv_enc_append(const char *str, int quote, struct buffer *output)
|
const char *csv_enc_append(const char *str, int quote, int oneline, struct buffer *output)
|
||||||
{
|
{
|
||||||
char *end = output->area + output->size;
|
char *end = output->area + output->size;
|
||||||
char *out = output->area + output->data;
|
char *out = output->area + output->data;
|
||||||
@ -2100,6 +2108,19 @@ const char *csv_enc_append(const char *str, int quote, struct buffer *output)
|
|||||||
*ptr++ = '"';
|
*ptr++ = '"';
|
||||||
|
|
||||||
while (*str && ptr < end - 2) { /* -2 for reserving space for <"> and \0. */
|
while (*str && ptr < end - 2) { /* -2 for reserving space for <"> and \0. */
|
||||||
|
if (oneline) {
|
||||||
|
if (*str == '\n' ) {
|
||||||
|
/* replace LF by a space */
|
||||||
|
*ptr++ = ' ';
|
||||||
|
str++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (*str == '\r' ) {
|
||||||
|
/* skip CR */
|
||||||
|
str++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
*ptr = *str;
|
*ptr = *str;
|
||||||
if (*str == '"') {
|
if (*str == '"') {
|
||||||
ptr++;
|
ptr++;
|
||||||
@ -2113,6 +2134,12 @@ const char *csv_enc_append(const char *str, int quote, struct buffer *output)
|
|||||||
str++;
|
str++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oneline == 2) {
|
||||||
|
/* remove trailing spaces */
|
||||||
|
while (ptr > out && *(ptr - 1) == ' ')
|
||||||
|
ptr--;
|
||||||
|
}
|
||||||
|
|
||||||
if (quote)
|
if (quote)
|
||||||
*ptr++ = '"';
|
*ptr++ = '"';
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user