]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-mail: Use quoted text as snippet if there is nothing else
authorAki Tuomi <aki.tuomi@open-xchange.com>
Tue, 29 Oct 2019 10:40:31 +0000 (12:40 +0200)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Tue, 5 Nov 2019 11:54:01 +0000 (13:54 +0200)
src/lib-mail/message-snippet.c
src/lib-mail/test-message-snippet.c

index 26cb39512646b38e1da876a196db119bbeead12d..b33bbae60a95f75a8391d5925e980debfebb21a3 100644 (file)
@@ -9,6 +9,8 @@
 #include "message-decoder.h"
 #include "message-snippet.h"
 
+#include <ctype.h>
+
 enum snippet_state {
        /* beginning of the line */
        SNIPPET_STATE_NEWLINE = 0,
@@ -25,6 +27,7 @@ struct snippet_data {
 
 struct snippet_context {
        struct snippet_data snippet;
+       struct snippet_data quoted_snippet;
        enum snippet_state state;
        bool add_whitespace;
        struct mail_html2text *html2text;
@@ -74,6 +77,7 @@ static bool snippet_generate(struct snippet_context *ctx,
                             const unsigned char *data, size_t size)
 {
        size_t i, count;
+       struct snippet_data *target = &ctx->snippet;
 
        if (ctx->html2text != NULL) {
                buffer_set_used_size(ctx->plain_output, 0);
@@ -92,24 +96,34 @@ static bool snippet_generate(struct snippet_context *ctx,
                case SNIPPET_STATE_NEWLINE:
                        if (data[i] == '>' && ctx->html2text == NULL) {
                                ctx->state = SNIPPET_STATE_QUOTED;
-                               break;
+                               i++;
+                               target = &ctx->quoted_snippet;
+                       } else {
+                               ctx->state = SNIPPET_STATE_NORMAL;
+                               target = &ctx->snippet;
                        }
-                       ctx->state = SNIPPET_STATE_NORMAL;
                        /* fallthrough */
                case SNIPPET_STATE_NORMAL:
-                       snippet_add_content(ctx, &ctx->snippet,
-                                           CONST_PTR_OFFSET(data, i), size-i,
-                                           &count);
-                       break;
                case SNIPPET_STATE_QUOTED:
-                       if (data[i] == '\n')
-                               ctx->state = SNIPPET_STATE_NEWLINE;
+                       snippet_add_content(ctx, target, CONST_PTR_OFFSET(data, i),
+                                           size-i, &count);
+                       /* break here if we have enough non-quoted data,
+                          quoted data does not need to break here as it's
+                          only used if the actual snippet is left empty. */
+                       if (ctx->snippet.chars_left == 0)
+                               return FALSE;
                        break;
                }
        }
        return TRUE;
 }
 
+static void snippet_copy(const char *src, string_t *dst)
+{
+       while (*src != '\0' && i_isspace(*src)) src++;
+       str_append(dst, src);
+}
+
 int message_snippet_generate(struct istream *input,
                             unsigned int max_snippet_chars,
                             string_t *snippet)
@@ -123,10 +137,11 @@ int message_snippet_generate(struct istream *input,
        int ret;
 
        i_zero(&ctx);
-       pool = pool_alloconly_create("message snippet", 1024);
-       ctx.snippet.snippet = snippet;
+       pool = pool_alloconly_create("message snippet", 2048);
+       ctx.snippet.snippet = str_new(pool, max_snippet_chars);
        ctx.snippet.chars_left = max_snippet_chars;
-
+       ctx.quoted_snippet.snippet = str_new(pool, max_snippet_chars);
+       ctx.quoted_snippet.chars_left = max_snippet_chars;
        parser = message_parser_init(pool_datastack_create(), input, 0, 0);
        decoder = message_decoder_init(NULL, 0);
        while ((ret = message_parser_parse_next_block(parser, &raw_block)) > 0) {
@@ -158,6 +173,12 @@ int message_snippet_generate(struct istream *input,
        message_decoder_deinit(&decoder);
        message_parser_deinit(&parser, &parts);
        mail_html2text_deinit(&ctx.html2text);
+       if (ctx.snippet.snippet->used != 0)
+               snippet_copy(str_c(ctx.snippet.snippet), snippet);
+       else if (ctx.quoted_snippet.snippet->used != 0) {
+               str_append_c(snippet, '>');
+               snippet_copy(str_c(ctx.quoted_snippet.snippet), snippet);
+       }
        pool_unref(&pool);
        return input->stream_errno == 0 ? 0 : -1;
 }
index 1401b8fc41980839a8229f79b0b059c503682f41..623afabb83541d6ad3d6a7e160d4851d1e4a9c87 100644 (file)
@@ -65,6 +65,32 @@ static const struct {
          "</div><br =class=3D\"\"></body></html>=\n",
          100,
          "Hi, How is it going? > -foo" },
+       { "Content-Type: text/plain\n"
+         "\n"
+         ">quote1\n>quote2\n",
+         100,
+         ">quote1 quote2" },
+       { "Content-Type: text/plain\n"
+         "\n"
+         ">quote1\n>quote2\nbottom\nposter\n",
+         100,
+         "bottom poster" },
+       { "Content-Type: text/plain\n"
+         "\n"
+         "top\nposter\n>quote1\n>quote2\n",
+         100,
+         "top poster" },
+        { "Content-Transfer-Encoding: quoted-printable\n"
+          "Content-Type: text/html;\n"
+          "      charset=utf-8\n"
+          "\n"
+          "<html><head><meta http-equiv=3D\"Content-Type\" content=3D\"text/html =\n"
+          "charset=3Dutf-8\"></head><body style=3D\"word-wrap: break-word; =\n"
+          "-webkit-nbsp-mode: space; -webkit-line-break: after-white-space;\" =\n"
+          "class=3D\"\"><div><blockquote>quoted text is included</blockquote>\n"
+          "</div><br =class=3D\"\"></body></html>=\n",
+          100,
+          "" },
 };
 
 static void test_message_snippet(void)