]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-smtp: smtp-server-reply - Support changing the reply status and enhanced code.
authorStephan Bosch <stephan.bosch@dovecot.fi>
Sat, 16 Mar 2019 16:13:28 +0000 (17:13 +0100)
committerStephan Bosch <stephan.bosch@dovecot.fi>
Tue, 19 Mar 2019 12:31:21 +0000 (13:31 +0100)
src/lib-smtp/smtp-server-reply.c
src/lib-smtp/smtp-server.h

index d67a443a55e23ccd79d1f156a3ea96ec928ee8fb..7cbc271ec028648f5bdae8e780977391952e54a8 100644 (file)
@@ -81,8 +81,67 @@ smtp_server_reply_alloc(struct smtp_server_command *cmd, unsigned int index)
 }
 
 static void
-smtp_server_reply_set_status(struct smtp_server_reply *reply,
-                            unsigned int status, const char *enh_code)
+smtp_server_reply_update_prefix(struct smtp_server_reply *reply,
+                               unsigned int status, const char *enh_code)
+{
+       pool_t pool = reply->command->context.pool;
+       string_t *textbuf, *new_text;
+       const char *new_prefix, *text, *p;
+       size_t text_len, prefix_len, line_len;
+
+       if (enh_code == NULL || *enh_code == '\0') {
+               new_prefix = p_strdup_printf(pool, "%03u-", status);
+       } else {
+               new_prefix = p_strdup_printf(pool, "%03u-%s ",
+                                            status, enh_code);
+       }
+
+       i_assert(reply->content != NULL);
+       textbuf = reply->content->text;
+
+       if (textbuf == NULL || str_len(textbuf) == 0) {
+               reply->content->status_prefix = new_prefix;
+               return;
+       }
+       new_text = str_new(default_pool, 256);
+
+       prefix_len = strlen(reply->content->status_prefix);
+       text = str_c(textbuf);
+       text_len = str_len(textbuf);
+
+       i_assert(text_len > prefix_len);
+       text_len -= prefix_len;
+       text += prefix_len;
+
+       for (;;) {
+               reply->content->last_line = str_len(new_text);
+
+               p = strchr(text, '\n');
+               i_assert(p != NULL && p > text && *(p-1) == '\r');
+               p++;
+
+               str_append(new_text, new_prefix);
+               str_append_data(new_text, text, p - text);
+
+               line_len = (size_t)(p - text);
+               i_assert(text_len >= line_len);
+               text_len -= line_len;
+               text = p;
+
+               if (text_len <= prefix_len)
+                       break;
+
+               text_len -= prefix_len;
+               text += prefix_len;
+       }
+
+       str_free(&textbuf);
+       reply->content->text = new_text;
+       reply->content->status_prefix = new_prefix;
+}
+
+void smtp_server_reply_set_status(struct smtp_server_reply *reply,
+                                 unsigned int status, const char *enh_code)
 {
        pool_t pool = reply->command->context.pool;
 
@@ -106,15 +165,13 @@ smtp_server_reply_set_status(struct smtp_server_reply *reply,
                ((unsigned int)(enh_code[0] - '0') == (status / 100)
                        && enh_code[1] == '.'));
 
+       if (reply->content->status == status &&
+           null_strcmp(reply->content->enhanced_code, enh_code) == 0)
+               return;
+
+       smtp_server_reply_update_prefix(reply, status, enh_code);
        reply->content->status = status;
        reply->content->enhanced_code = p_strdup(pool, enh_code);
-       if (enh_code == NULL || *enh_code == '\0') {
-               reply->content->status_prefix =
-                       p_strdup_printf(pool, "%03u-", status);
-       } else {
-               reply->content->status_prefix =
-                       p_strdup_printf(pool, "%03u-%s ", status, enh_code);
-       }
 }
 
 struct smtp_server_reply *
index 57ecf9a4e0e63671ac9968563ec0f290eacb1040..c698316d85a0f9575018a8d8fa0c66642deb8459 100644 (file)
@@ -634,6 +634,10 @@ struct smtp_server_reply *
 smtp_server_reply_create_forward(struct smtp_server_command *cmd,
        unsigned int index, const struct smtp_reply *from);
 
+void smtp_server_reply_set_status(struct smtp_server_reply *reply,
+                                 unsigned int status, const char *enh_code)
+                                 ATTR_NULL(3);
+
 void smtp_server_reply_add_text(struct smtp_server_reply *reply,
        const char *line);
 void smtp_server_reply_submit(struct smtp_server_reply *reply);