From 83986ec38bafcdd27157667e5b3d4a356a29d01a Mon Sep 17 00:00:00 2001 From: Sergey Kitov Date: Wed, 14 Jun 2017 10:41:04 +0300 Subject: [PATCH] lib-imap: added imap_append_nstring_nolf(), which skips CRs and LFs. --- src/lib-imap/imap-quote.c | 27 +++++++++++++++++++++++ src/lib-imap/imap-quote.h | 2 ++ src/lib-imap/test-imap-quote.c | 39 ++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/src/lib-imap/imap-quote.c b/src/lib-imap/imap-quote.c index f4ff853b90..3e751245d3 100644 --- a/src/lib-imap/imap-quote.c +++ b/src/lib-imap/imap-quote.c @@ -90,6 +90,33 @@ void imap_append_nstring(string_t *dest, const char *src) imap_append_quoted(dest, src); } +void imap_append_nstring_nolf(string_t *dest, const char *src) +{ + string_t *src_nolf; + size_t src_len; + if (src == NULL || strpbrk(src, "\r\n") == NULL) + imap_append_nstring(dest, src); + else { + T_BEGIN { + src_len = strlen(src); + src_nolf = t_str_new(src_len + 1); + for (size_t i = 0; i < src_len; ++i) { + if (src[i] != '\r' && src[i] != '\n') { + str_append_c(src_nolf, src[i]); + } else if (src[i+1] != ' ' && + src[i+1] != '\t' && + src[i+1] != '\r' && + src[i+1] != '\n' && + src[i+1] != '\0') { + /* ensure whitespace between lines if new line doesn't start with whitespace */ + str_append_c(src_nolf, ' '); + } + } + imap_append_nstring(dest, str_c(src_nolf)); + } T_END; + } +} + void imap_append_quoted(string_t *dest, const char *src) { str_append_c(dest, '"'); diff --git a/src/lib-imap/imap-quote.h b/src/lib-imap/imap-quote.h index 65fb1b3b3a..a397ec39bc 100644 --- a/src/lib-imap/imap-quote.h +++ b/src/lib-imap/imap-quote.h @@ -7,6 +7,8 @@ void imap_append_string(string_t *dest, const char *src); void imap_append_astring(string_t *dest, const char *src); /* Append NIL, "quoted" or literal. */ void imap_append_nstring(string_t *dest, const char *src); +/* Append NIL, "quoted" or literal, CRs and LFs skipped. */ +void imap_append_nstring_nolf(string_t *dest, const char *src); /* Append "quoted". If src has 8bit chars, skip over them. */ void imap_append_quoted(string_t *dest, const char *src); diff --git a/src/lib-imap/test-imap-quote.c b/src/lib-imap/test-imap-quote.c index 0575d5b117..9b94dd638d 100644 --- a/src/lib-imap/test-imap-quote.c +++ b/src/lib-imap/test-imap-quote.c @@ -112,12 +112,51 @@ static void test_imap_append_nstring(void) test_end(); } +static void test_imap_append_nstring_nolf(void) +{ + static const struct { + const char *input, *output; + } tests[] = { + { "", "\"\"" }, + { NULL, "NIL" }, + { "NIL", "\"NIL\"" }, + { "ni", "\"ni\"" }, + { "\"NIL\n foo", "\"\\\"NIL foo\"" }, + { "\"America N.\", \"America S.\", \"Africa\"", "{36}\r\n\"America N.\", \"America S.\", \"Africa\"" }, + { "foo\nbar", "\"foo bar\"" }, + { "foo\r\nbar", "\"foo bar\"" }, + { "foo\rbar", "\"foo bar\"" }, + { "foo\n bar", "\"foo bar\"" }, + { "foo\r\n bar", "\"foo bar\"" }, + { "foo\r bar", "\"foo bar\"" }, + { "foo\n\tbar", "\"foo\tbar\"" }, + { "foo\r\n\tbar", "\"foo\tbar\"" }, + { "foo\r\tbar", "\"foo\tbar\"" }, + { "foo\n bar", "\"foo bar\"" }, + { "foo\r\n bar", "\"foo bar\"" }, + { "foo\r bar", "\"foo bar\"" }, + { "\nfoo\r bar\r\n", "\" foo bar\"" } + }; + string_t *str = t_str_new(128); + unsigned int i; + + test_begin("test_imap_append_nstring_nolf()"); + + for (i = 0; i < N_ELEMENTS(tests); i++) { + str_truncate(str, 0); + imap_append_nstring_nolf(str, tests[i].input); + test_assert_idx(strcmp(tests[i].output, str_c(str)) == 0, i); + } + test_end(); +} + int main(void) { static void (*test_functions[])(void) = { test_imap_append_string_for_humans, test_imap_append_astring, test_imap_append_nstring, + test_imap_append_nstring_nolf, NULL }; return test_run(test_functions);