diff --git a/include/haproxy/tools.h b/include/haproxy/tools.h index 9fa431eb3..3726f6353 100644 --- a/include/haproxy/tools.h +++ b/include/haproxy/tools.h @@ -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 * format. * - * printf("..., \"%s\", ...\r\n", csv_enc(str, 0, &trash)); + * printf("..., \"%s\", ...\r\n", csv_enc(str, 0, 0, &trash)); * * If is 1, the converter puts the quotes only if any character is * escaped. If is 2, the converter always puts the quotes. * + * If 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 is 2, In addition to previous action, the trailing spaces are + * removed. + * * is a struct chunk used for storing the output string. * * 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 * 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 */ -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) { 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 diff --git a/src/stats.c b/src/stats.c index b4c35b370..95f40fef8 100644 --- a/src/stats.c +++ b/src/stats.c @@ -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)); 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); } } diff --git a/src/tools.c b/src/tools.c index 89302eb10..b2814b5af 100644 --- a/src/tools.c +++ b/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 * format. * - * printf("..., \"%s\", ...\r\n", csv_enc(str, 0, &trash)); + * printf("..., \"%s\", ...\r\n", csv_enc(str, 0, 0, &trash)); * * If is 1, the converter puts the quotes only if any reserved character * is present. If is 2, the converter always puts the quotes. * + * If 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 is 2, In addition to previous action, the trailing spaces are + * removed. + * * is a struct buffer used for storing the output string. * * 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 * 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 *out = output->area + output->data; @@ -2100,6 +2108,19 @@ const char *csv_enc_append(const char *str, int quote, struct buffer *output) *ptr++ = '"'; 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; if (*str == '"') { ptr++; @@ -2113,6 +2134,12 @@ const char *csv_enc_append(const char *str, int quote, struct buffer *output) str++; } + if (oneline == 2) { + /* remove trailing spaces */ + while (ptr > out && *(ptr - 1) == ' ') + ptr--; + } + if (quote) *ptr++ = '"';