]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-imap: imap-quote - Add UTF8 support for IMAP string encoding
authorStephan Bosch <stephan.bosch@open-xchange.com>
Tue, 26 Aug 2025 00:54:57 +0000 (02:54 +0200)
committerStephan Bosch <stephan.bosch@open-xchange.com>
Mon, 26 Jan 2026 01:35:25 +0000 (02:35 +0100)
30 files changed:
src/imap-login/imap-login-cmd-id.c
src/imap-login/imap-proxy.c
src/imap/cmd-genurlauth.c
src/imap/cmd-getmetadata.c
src/imap/cmd-list.c
src/imap/cmd-namespace.c
src/imap/cmd-notify.c
src/imap/cmd-urlfetch.c
src/imap/imap-fetch-body.c
src/imap/imap-fetch.c
src/imap/imap-notify.c
src/imap/imap-progress.c
src/imap/imap-search.c
src/imap/imap-status.c
src/imap/imap-sync.c
src/lib-imap-client/imapc-connection.c
src/lib-imap/imap-bodystructure.c
src/lib-imap/imap-envelope.c
src/lib-imap/imap-id.c
src/lib-imap/imap-quote.c
src/lib-imap/imap-quote.h
src/lib-imap/test-imap-quote.c
src/lib-storage/index/imapc/imapc-attribute.c
src/lib-storage/index/imapc/imapc-mail-fetch.c
src/lib-storage/index/imapc/imapc-save.c
src/lib-storage/mail-search-args-cmdline.c
src/lib-storage/mail-search-args-imap.c
src/lib-storage/mail-search-mime.c
src/plugins/imap-acl/imap-acl-plugin.c
src/plugins/imap-quota/imap-quota-plugin.c

index 572f933da64d5b3b99baa40f6f420c7afb39aa7e..513e085e541ed7bed76c912c5e3e51609a492b15 100644 (file)
@@ -200,12 +200,12 @@ static bool cmd_id_handle_keyvalue(struct imap_client *client,
                } else {
                        str_append_c(client->common.client_id, ' ');
                }
-               imap_append_quoted(client->common.client_id, key);
+               imap_append_quoted(client->common.client_id, key, 0);
                str_append_c(client->common.client_id, ' ');
                if (value == NULL)
                        str_append(client->common.client_id, "NIL");
                else
-                       imap_append_quoted(client->common.client_id, value);
+                       imap_append_quoted(client->common.client_id, value, 0);
        }
 
        if (!is_login_id_param)
index 3156a4bbf4ebe5c7f646609c9d9b622377cb850b..7eaa4ed57baf7afe715a3279c5d7d6b1c86e7e37 100644 (file)
@@ -62,7 +62,7 @@ static void proxy_write_id(struct imap_client *client, string_t *str)
 
        if (client->common.local_name != NULL) {
                str_append(str, " \"x-connected-name\" ");
-               imap_append_nstring(str, client->common.local_name);
+               imap_append_nstring(str, client->common.local_name, 0);
        }
 
        /* append any forward_ variables to request */
@@ -74,9 +74,9 @@ static void proxy_write_id(struct imap_client *client, string_t *str)
                                                      NULL);
                        const char *val = i_strchr_to_next(suffix, '=');
                        str_append_c(str, ' ');
-                       imap_append_string(str, key);
+                       imap_append_string(str, key, 0);
                        str_append_c(str, ' ');
-                       imap_append_nstring(str, val);
+                       imap_append_nstring(str, val, 0);
                }
        }
 
@@ -139,9 +139,9 @@ static int proxy_write_login(struct imap_client *client, string_t *str)
                        return -1;
                }
                str_append(str, "L LOGIN ");
-               imap_append_string(str, client->common.proxy_user);
+               imap_append_string(str, client->common.proxy_user, 0);
                str_append_c(str, ' ');
-               imap_append_string(str, client->common.proxy_password);
+               imap_append_string(str, client->common.proxy_password, 0);
                str_append(str, "\r\n");
 
                client->proxy_sent_state |= IMAP_PROXY_SENT_STATE_LOGIN;
index 2cdbdd134094af6629c579263992a3e0f343f134..2beb56eb0dda4ae0ebca6608b192081615cb9c57 100644 (file)
@@ -45,7 +45,7 @@ bool cmd_genurlauth(struct client_command_context *cmd)
                }
 
                str_append_c(response, ' ');
-               imap_append_astring(response, url);
+               imap_append_astring(response, url, 0);
        }
 
        client_send_line(cmd->client, str_c(response));
index 36e5da00a9477cc5c97f7bc488e497a874a12121..0b34be3a6554509c09eb7891b5bf482b7943f038 100644 (file)
@@ -123,7 +123,7 @@ metadata_add_entry(struct imap_getmetadata_context *ctx, const char *entry)
                } else {
                        if (imap_utf8_to_utf7(mailbox_get_vname(ctx->box), mailbox_mutf7) < 0)
                                i_unreached();
-                       imap_append_astring(str, str_c(mailbox_mutf7));
+                       imap_append_astring(str, str_c(mailbox_mutf7), 0);
                }
                str_append(str, " (");
 
@@ -132,7 +132,7 @@ metadata_add_entry(struct imap_getmetadata_context *ctx, const char *entry)
        } else {
                str_append_c(str, ' ');
        }
-       imap_append_astring(str, entry);
+       imap_append_astring(str, entry, 0);
        return str;
 }
 
index 86d4c3b855e50928f37d2463ba7fa5bd99f79063..993740b31ddf151606d27ce874498b9cabeae78a 100644 (file)
@@ -309,7 +309,7 @@ static bool cmd_list_continue(struct client_command_context *cmd)
                list_reply_append_ns_sep_param(str,
                        mail_namespace_get_sep(info->ns));
                str_append_c(str, ' ');
-               imap_append_astring(str, str_c(mutf7_name));
+               imap_append_astring(str, str_c(mutf7_name), 0);
                mailbox_childinfo2str(ctx, str, flags);
 
                /* send LIST/LSUB response */
@@ -411,7 +411,7 @@ static void cmd_list_ref_root(struct client *client, const char *ref)
        str_printfa(str, "%c\" ", ns_sep);
        if (*ns_prefix != '\0') {
                /* non-hidden namespace, use it as the root name */
-               imap_append_astring(str, ns_prefix);
+               imap_append_astring(str, ns_prefix, 0);
        } else {
                /* Hidden namespace or empty namespace prefix. We could just
                   return an empty root name, but it's safer to emulate what
@@ -422,7 +422,7 @@ static void cmd_list_ref_root(struct client *client, const char *ref)
                if (p == NULL)
                        str_append(str, "\"\"");
                else
-                       imap_append_astring(str, t_strdup_until(ref, p + 1));
+                       imap_append_astring(str, t_strdup_until(ref, p + 1), 0);
        }
        client_send_line(client, str_c(str));
 }
index 23d22863bb826c54e9a449ab38fc7a0a438c9bff..0ae67fff1e56f3c45b24fcbf023c8eeb3e530d34 100644 (file)
@@ -66,7 +66,7 @@ static void list_namespaces(struct mail_namespace *ns,
                                no->ns->prefix);
                }
 
-               imap_append_string(str, str_c(mutf7_prefix));
+               imap_append_string(str, str_c(mutf7_prefix), 0);
                str_append(str, " \"");
                if (ns_sep == '\\')
                        str_append_c(str, '\\');
index 9d3a62370d43702cce83d06114c3a40735733b6d..caabf62d2ba6578ce0b5e0d2d566d50c7579564f 100644 (file)
@@ -426,7 +426,7 @@ imap_notify_box_list_noperm(struct client *client, struct mailbox *box)
        str_append_c(str, ns_sep);
        str_append(str, "\" ");
 
-       imap_append_astring(str, vname);
+       imap_append_astring(str, vname, 0);
        client_send_line(client, str_c(str));
 }
 
index f371510a4c4922a9ef8d42756c84967dc688f959..0cba2f5bf34d2a0a8fc3ffa7c5d50a91fc15d78c 100644 (file)
@@ -175,7 +175,7 @@ static int cmd_urlfetch_url_success(struct client_command_context *cmd,
        int ret;
 
        str_append(response, "* URLFETCH ");
-       imap_append_astring(response, reply->url);
+       imap_append_astring(response, reply->url, 0);
 
        if ((reply->flags & IMAP_URLAUTH_FETCH_FLAG_EXTENDED) == 0) {
                /* simple */
@@ -256,7 +256,7 @@ cmd_urlfetch_url_callback(struct imap_urlauth_fetch_reply *reply,
                string_t *response = t_str_new(128);
 
                str_append(response, "* URLFETCH ");
-               imap_append_astring(response, reply->url);
+               imap_append_astring(response, reply->url, 0);
                str_append(response, " NIL");
                client_send_line(client, str_c(response));
                if (reply->error != NULL) {
index c5d433308a0005f4550c311dbe5d52a4c638e6cc..ddc9f3511d155c2ff0acddb05fed20835e57f5e9 100644 (file)
@@ -271,7 +271,7 @@ body_header_fields_parse(struct imap_fetch_init_context *ctx,
                if (args[i].type == IMAP_ARG_ATOM)
                        str_append(str, value);
                else
-                       imap_append_quoted(str, value);
+                       imap_append_quoted(str, value, 0);
        }
        str_append_c(str, ')');
        body->section = str_c(str);
@@ -640,7 +640,7 @@ fetch_snippet(struct imap_fetch_context *ctx, struct mail *mail,
        else
                str_append(ctx->state.cur_str, " ");
        if (ret == 0)
-               imap_append_string(ctx->state.cur_str, snippet);
+               imap_append_string(ctx->state.cur_str, snippet, 0);
        else
                str_append(ctx->state.cur_str, "NIL");
        if (preview->old_standard)
index ca4b3216cef8aedf798a1a032b4538bfe88900b1..fb8a0bb60ae0fae7ab2b27e29f393827dcb5ace0 100644 (file)
@@ -925,7 +925,7 @@ static int fetch_guid(struct imap_fetch_context *ctx, struct mail *mail,
                return -1;
 
        str_append(ctx->state.cur_str, "X-GUID ");
-       imap_append_astring(ctx->state.cur_str, value);
+       imap_append_astring(ctx->state.cur_str, value, 0);
        str_append_c(ctx->state.cur_str, ' ');
        return 1;
 }
@@ -955,7 +955,7 @@ static int fetch_x_mailbox(struct imap_fetch_context *ctx, struct mail *mail,
                i_panic("FETCH: Mailbox name not UTF-8: %s", name);
 
        str_append(ctx->state.cur_str, "X-MAILBOX ");
-       imap_append_astring(ctx->state.cur_str, str_c(mutf7_name));
+       imap_append_astring(ctx->state.cur_str, str_c(mutf7_name), 0);
        str_append_c(ctx->state.cur_str, ' ');
        return 1;
 }
index 3ada855281ed1eb589f6ce9d76e317ad93b47168..a8928667ca51a1f65283054a73048686e616aef0 100644 (file)
@@ -39,7 +39,7 @@ static int imap_notify_list(struct imap_notify_namespace *notify_ns,
        if (imap_utf8_to_utf7(vname, mutf7_vname) < 0)
                i_panic("Mailbox name not UTF-8: %s", vname);
        vname = str_c(mutf7_vname);
-       imap_append_astring(str, vname);
+       imap_append_astring(str, vname, 0);
        if (rec->old_vname != NULL) {
                old_vname = rec->old_vname;
                str_truncate(mutf7_vname, 0);
@@ -49,7 +49,7 @@ static int imap_notify_list(struct imap_notify_namespace *notify_ns,
                }
                old_vname = str_c(mutf7_vname);
                str_append(str, " (\"OLDNAME\" (");
-               imap_append_astring(str, old_vname);
+               imap_append_astring(str, old_vname, 0);
                str_append(str, "))");
        }
        return client_send_line_next(client, str_c(str));
index 0e1c17468e4fa2807b5d8debfb2301074f0dfca9..7184ab513e88e368193a6d4d09e66366c90b5be2 100644 (file)
@@ -31,7 +31,7 @@ imap_progress_line(const struct mail_storage_progress_details *dtl,
        if (has_tag || processed > 0 || total > 0) {
                str_append(str, " (");
                if (has_tag)
-                       imap_append_quoted(str, tag);
+                       imap_append_quoted(str, tag, 0);
                else
                        str_append(str, "NIL");
 
index e62ddd9ce9f310b35d6a764e2437003c9e966484..efcf4a53a4071c04896b0f57109e4f73d069176e 100644 (file)
@@ -178,7 +178,7 @@ static void imap_search_result_save(struct imap_search_context *ctx)
                /* too many updates */
                string_t *str = t_str_new(256);
                str_append(str, "* NO [NOUPDATE ");
-               imap_append_quoted(str, ctx->cmd->tag);
+               imap_append_quoted(str, ctx->cmd->tag, 0);
                str_append_c(str, ']');
                client_send_line(client, str_c(str));
                ctx->return_options &= ENUM_NEGATE(SEARCH_RETURN_UPDATE);
@@ -285,7 +285,7 @@ static void imap_search_send_result(struct imap_search_context *ctx)
 
        str = str_new(default_pool, 1024);
        str_append(str, "* ESEARCH (TAG ");
-       imap_append_string(str, ctx->cmd->tag);
+       imap_append_string(str, ctx->cmd->tag, 0);
        str_append_c(str, ')');
 
        if (ctx->cmd->uid)
index c5b44a56d6fead3cb9942a127f50f7ab34a820b4..360361ce9b629152b2346e8ae160dc14eb5049fa 100644 (file)
@@ -138,7 +138,7 @@ int imap_status_send(struct client *client, const char *mailbox_mutf7,
 
        str = t_str_new(128);
        str_append(str, "* STATUS ");
-        imap_append_astring(str, mailbox_mutf7);
+        imap_append_astring(str, mailbox_mutf7, 0);
        str_append(str, " (");
 
        prefix_len = str_len(str);
index 5a138f6e85973731ff51decca4ea1ec7cfe2c904..8865bba4af325c08102c6f85661f587b388cabcf 100644 (file)
@@ -113,7 +113,7 @@ imap_sync_send_search_update(struct imap_sync_context *ctx,
 
        cmd = t_str_new(256);
        str_append(cmd, "* ESEARCH (TAG ");
-       imap_append_string(cmd, update->tag);
+       imap_append_string(cmd, update->tag, 0);
        str_append_c(cmd, ')');
        if (update->return_uids)
                str_append(cmd, " UID");
index d17ead5c38cb4846c5b456da744c998c293309c6..17aa54c3b0d1a13884b8244dc07e82c1c1346f5f 100644 (file)
@@ -2527,7 +2527,7 @@ void imapc_command_sendvf(struct imapc_command *cmd,
                        const char *arg = va_arg(args, const char *);
 
                        if (!need_literal(arg))
-                               imap_append_quoted(cmd->data, arg);
+                               imap_append_quoted(cmd->data, arg, 0);
                        else if ((cmd->conn->capabilities &
                                  IMAPC_CAPABILITY_LITERALPLUS) != 0) {
                                str_printfa(cmd->data, "{%zu+}\r\n%s",
index 4bacb495c92199316629760072654531f65dada6..74a8f651a77b54dda9ad3c753fda4dd4f26fdc68 100644 (file)
@@ -54,9 +54,9 @@ params_write(const struct message_part_param *params,
                if (default_charset &&
                        strcasecmp(params[i].name, "charset") == 0)
                        seen_charset = TRUE;
-               imap_append_string(str, params[i].name);
+               imap_append_string(str, params[i].name, 0);
                str_append_c(str, ' ');
-               imap_append_string(str, params[i].value);
+               imap_append_string(str, params[i].value, 0);
        }
        if (default_charset && !seen_charset) {
                if (i > 0)
@@ -90,7 +90,7 @@ part_write_bodystructure_common(const struct message_part_data *data,
                str_append(str, "NIL");
        else {
                str_append_c(str, '(');
-               imap_append_string(str, data->content_disposition);
+               imap_append_string(str, data->content_disposition, 0);
 
                str_append_c(str, ' ');
                params_write(data->content_disposition_params,
@@ -107,18 +107,18 @@ part_write_bodystructure_common(const struct message_part_data *data,
 
                i_assert(*lang != NULL);
                str_append_c(str, '(');
-               imap_append_string(str, *lang);
+               imap_append_string(str, *lang, 0);
                lang++;
                while (*lang != NULL) {
                        str_append_c(str, ' ');
-                       imap_append_string(str, *lang);
+                       imap_append_string(str, *lang, 0);
                        lang++;
                }
                str_append_c(str, ')');
        }
 
        str_append_c(str, ' ');
-       imap_append_nstring_nolf(str, data->content_location);
+       imap_append_nstring_nolf(str, data->content_location, 0);
 }
 
 static int part_write_body_multipart(const struct message_part *part,
@@ -144,7 +144,7 @@ static int part_write_body_multipart(const struct message_part *part,
        }
 
        str_append_c(str, ' ');
-       imap_append_string(str, data->content_subtype);
+       imap_append_string(str, data->content_subtype, 0);
 
        if (!extended)
                return 0;
@@ -216,9 +216,9 @@ static int part_write_body(const struct message_part *part,
                        str_append(str, "\"text\" \"plain\"");
                } else {
                        text = (strcasecmp(data->content_type, "text") == 0);
-                       imap_append_string(str, data->content_type);
+                       imap_append_string(str, data->content_type, 0);
                        str_append_c(str, ' ');
-                       imap_append_string(str, data->content_subtype);
+                       imap_append_string(str, data->content_subtype, 0);
                }
                bool part_is_text = (part->flags & MESSAGE_PART_FLAG_TEXT) != 0;
                if (text != part_is_text) {
@@ -233,12 +233,12 @@ static int part_write_body(const struct message_part *part,
                data->content_type_params_count, str, text);
 
        str_append_c(str, ' ');
-       imap_append_nstring_nolf(str, data->content_id);
+       imap_append_nstring_nolf(str, data->content_id, 0);
        str_append_c(str, ' ');
-       imap_append_nstring_nolf(str, data->content_description);
+       imap_append_nstring_nolf(str, data->content_description, 0);
        str_append_c(str, ' ');
        if (data->content_transfer_encoding != NULL)
-               imap_append_string(str, data->content_transfer_encoding);
+               imap_append_string(str, data->content_transfer_encoding, 0);
        else
                str_append(str, "\"7bit\"");
        str_printfa(str, " %"PRIuUOFF_T, part->body_size.virtual_size);
@@ -273,7 +273,7 @@ static int part_write_body(const struct message_part *part,
        /* "md5" ("content disposition" ("disposition" "params"))
           ("body" "language" "params") "location" */
        str_append_c(str, ' ');
-       imap_append_nstring_nolf(str, data->content_md5);
+       imap_append_nstring_nolf(str, data->content_md5, 0);
        part_write_bodystructure_common(data, str);
        return 0;
 }
index da3177025a5e832e8841be6e64d9a898e692f186..9211cd9ce9e256a4430898633ac3d074d707bc87 100644 (file)
@@ -29,14 +29,15 @@ static void imap_write_address(string_t *str, struct message_address *addr)
                        str_append(str, "NIL");
                else {
                        imap_append_string_for_humans(str,
-                               (const void *)addr->name, strlen(addr->name));
+                               (const void *)addr->name, strlen(addr->name),
+                               0);
                }
                str_append_c(str, ' ');
-               imap_append_nstring(str, addr->route);
+               imap_append_nstring(str, addr->route, 0);
                str_append_c(str, ' ');
-               imap_append_nstring(str, addr->mailbox);
+               imap_append_nstring(str, addr->mailbox, 0);
                str_append_c(str, ' ');
-               imap_append_nstring(str, addr->domain);
+               imap_append_nstring(str, addr->domain, 0);
                str_append_c(str, ')');
 
                addr = addr->next;
@@ -56,14 +57,14 @@ void imap_envelope_write(struct message_part_envelope *data,
                return;
        }
 
-       imap_append_nstring_nolf(str, data->date);
+       imap_append_nstring_nolf(str, data->date, 0);
        str_append_c(str, ' ');
        if (data->subject == NULL)
                str_append(str, "NIL");
        else {
                imap_append_string_for_humans(str,
                        (const unsigned char *)data->subject,
-                       strlen(data->subject));
+                       strlen(data->subject), 0);
        }
 
        str_append_c(str, ' ');
@@ -80,9 +81,9 @@ void imap_envelope_write(struct message_part_envelope *data,
        imap_write_address(str, data->bcc.head);
 
        str_append_c(str, ' ');
-       imap_append_nstring_nolf(str, data->in_reply_to);
+       imap_append_nstring_nolf(str, data->in_reply_to, 0);
        str_append_c(str, ' ');
-       imap_append_nstring_nolf(str, data->message_id);
+       imap_append_nstring_nolf(str, data->message_id, 0);
 }
 
 /*
index 5685a17ca34a09df87a2fc683fc6946250164e9e..6b0f2077ed9d495079a717f25f5ecedcfed8f789 100644 (file)
@@ -24,7 +24,7 @@ const char *imap_id_reply_generate(const ARRAY_TYPE(const_string) *args)
        for (unsigned int i = 0; i < count; i += 2) {
                if (i > 0)
                        str_append_c(str, ' ');
-               imap_append_quoted(str, kv[i]);
+               imap_append_quoted(str, kv[i], 0);
                str_append_c(str, ' ');
                const char *value = kv[i + 1];
 #if defined(DOVECOT_EDITION)
@@ -32,7 +32,7 @@ const char *imap_id_reply_generate(const ARRAY_TYPE(const_string) *args)
                    strcmp(DOVECOT_EDITION, "Pro") == 0)
                        value = DOVECOT_NAME;
 #endif
-               imap_append_nstring(str, value);
+               imap_append_nstring(str, value, 0);
        }
        str_append_c(str, ')');
        return str_c(str);
index ba7f05c16a2922aab7e35c0f074a074482678041..e90b2c0a06e2133f739ca377959a9093ef473786 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "str.h"
+#include "unichar.h"
 #include "imap-arg.h"
 #include "imap-quote.h"
 
    quoted-specials. */
 #define QUOTED_MAX_ESCAPE_CHARS 4
 
-void imap_append_string(string_t *dest, const char *src)
+void imap_append_string(string_t *dest, const char *src,
+                       enum imap_quote_flags flags)
 {
        i_assert(src != NULL);
 
-       imap_append_nstring(dest, src);
+       imap_append_nstring(dest, src, flags);
 }
 
-void imap_append_astring(string_t *dest, const char *src)
+void imap_append_astring(string_t *dest, const char *src,
+                        enum imap_quote_flags flags)
 {
        unsigned int i;
 
@@ -30,13 +33,13 @@ void imap_append_astring(string_t *dest, const char *src)
 
        for (i = 0; src[i] != '\0'; i++) {
                if (!IS_ASTRING_CHAR(src[i])) {
-                       imap_append_string(dest, src);
+                       imap_append_string(dest, src, flags);
                        return;
                }
        }
        /* don't mix up NIL and "NIL"! */
        if (i == 0 || strcasecmp(src, "NIL") == 0)
-               imap_append_string(dest, src);
+               imap_append_string(dest, src, flags);
        else
                str_append(dest, src);
 }
@@ -50,7 +53,8 @@ imap_append_literal(string_t *dest, const char *src, unsigned int pos)
        buffer_append(dest, src, full_len);
 }
 
-void imap_append_nstring(string_t *dest, const char *src)
+void imap_append_nstring(string_t *dest, const char *src,
+                        enum imap_quote_flags flags)
 {
        unsigned int escape_count = 0;
        size_t i;
@@ -80,17 +84,31 @@ void imap_append_nstring(string_t *dest, const char *src)
                        imap_append_literal(dest, src, i);
                        return;
                default:
-                       if ((unsigned char)src[i] >= 0x80) {
-                               imap_append_literal(dest, src, i);
-                               return;
+                       if (HAS_NO_BITS(flags, IMAP_QUOTE_FLAG_UTF8)) {
+                               if ((unsigned char)src[i] >= 0x80) {
+                                       imap_append_literal(dest, src, i);
+                                       return;
+                               }
+                       } else {
+                               unichar_t chr;
+                               int ret;
+
+                               ret = uni_utf8_get_char(&src[i], &chr);
+                               if (ret <= 0) {
+                                       imap_append_literal(dest, src, i);
+                                       return;
+                               }
+                               i += ret - 1;
                        }
                        break;
                }
        }
-       imap_append_quoted(dest, src);
+       imap_append_quoted(dest, src, flags);
 }
 
-static void remove_newlines_and_append(string_t *dest, const char *src)
+static void
+remove_newlines_and_append(string_t *dest, const char *src,
+                          enum imap_quote_flags flags)
 {
        size_t src_len;
        string_t *src_nolf;
@@ -113,21 +131,23 @@ static void remove_newlines_and_append(string_t *dest, const char *src)
                           OR at the end of the string are discarded */
                }
        }
-       imap_append_nstring(dest, str_c(src_nolf));
+       imap_append_nstring(dest, str_c(src_nolf), flags);
 }
 
-void imap_append_nstring_nolf(string_t *dest, const char *src)
+void imap_append_nstring_nolf(string_t *dest, const char *src,
+                             enum imap_quote_flags flags)
 {
        if (src == NULL || strpbrk(src, "\r\n") == NULL)
-               imap_append_nstring(dest, src);
+               imap_append_nstring(dest, src, flags);
        else if (buffer_get_pool(dest)->datastack_pool)
-               remove_newlines_and_append(dest, src);
+               remove_newlines_and_append(dest, src, flags);
        else T_BEGIN {
-               remove_newlines_and_append(dest, src);
+               remove_newlines_and_append(dest, src, flags);
        } T_END;
 }
 
-void imap_append_quoted(string_t *dest, const char *src)
+void imap_append_quoted(string_t *dest, const char *src,
+                       enum imap_quote_flags flags)
 {
        str_append_c(dest, '"');
        for (; *src != '\0'; src++) {
@@ -142,12 +162,22 @@ void imap_append_quoted(string_t *dest, const char *src)
                        str_append_c(dest, *src);
                        break;
                default:
-                       if ((unsigned char)*src >= 0x80) {
-                               /* 8bit input not allowed in dquotes */
-                               break;
-                       }
+                       if (HAS_NO_BITS(flags, IMAP_QUOTE_FLAG_UTF8)) {
+                               if ((unsigned char)*src >= 0x80) {
+                                       /* 8bit input not allowed in dquotes */
+                                       break;
+                               }
+                               str_append_c(dest, *src);
+                       } else {
+                               unichar_t chr;
+                               int ret;
 
-                       str_append_c(dest, *src);
+                               ret = uni_utf8_get_char(src, &chr);
+                               if (ret <= 0)
+                                       break;
+                               str_append_data(dest, src, ret);
+                               src += ret - 1;
+                       }
                        break;
                }
        }
@@ -155,7 +185,8 @@ void imap_append_quoted(string_t *dest, const char *src)
 }
 
 void imap_append_string_for_humans(string_t *dest,
-                                  const unsigned char *src, size_t size)
+                                  const unsigned char *src, size_t size,
+                                  enum imap_quote_flags flags)
 {
        size_t i, pos, remove_count = 0;
        bool whitespace_prefix = TRUE, last_lwsp = TRUE, modify = FALSE;
@@ -186,8 +217,19 @@ void imap_append_string_for_humans(string_t *dest,
                        last_lwsp = FALSE;
                        break;
                default:
-                       if ((src[i] & 0x80) != 0)
-                               modify = TRUE;
+                       if (HAS_NO_BITS(flags, IMAP_QUOTE_FLAG_UTF8)) {
+                               if ((src[i] & 0x80) != 0)
+                                       modify = TRUE;
+                       } else {
+                               unichar_t chr;
+                               int ret;
+
+                               ret = uni_utf8_get_char_n(&src[i], size - i, &chr);
+                               if (ret <= 0)
+                                       modify = TRUE;
+                               else
+                                       i += ret - 1;
+                       }
                        last_lwsp = FALSE;
                        break;
                }
index a397ec39bc372e1ac9b0803ab39178579da4aef9..c3b3c00bdcc1ace31599ca71e8511836743aeae8 100644 (file)
@@ -1,21 +1,38 @@
 #ifndef IMAP_QUOTE_H
 #define IMAP_QUOTE_H
 
+enum imap_quote_flags {
+       /* This flag indicates that UTF-8 is allowed in quoted strings. When
+          generating IMAP string values with the functions below, the
+          production of quoted strings is preferred, unless characters need to
+          be represented that are not allowed therein. In that case, a literal
+          will be produced. This flag extends the allowed characters with valid
+          UTF-8 sequences. In case of invalid UTF-8, a literal will still be
+          emitted instead. */
+       IMAP_QUOTE_FLAG_UTF8 = BIT(0),
+};
+
 /* Append "quoted" or literal. */
-void imap_append_string(string_t *dest, const char *src);
+void imap_append_string(string_t *dest, const char *src,
+                       enum imap_quote_flags flags);
 /* Append atom, "quoted" or literal. */
-void imap_append_astring(string_t *dest, const char *src);
+void imap_append_astring(string_t *dest, const char *src,
+                        enum imap_quote_flags flags);
 /* Append NIL, "quoted" or literal. */
-void imap_append_nstring(string_t *dest, const char *src);
+void imap_append_nstring(string_t *dest, const char *src,
+                        enum imap_quote_flags flags);
 /* Append NIL, "quoted" or literal, CRs and LFs skipped. */
-void imap_append_nstring_nolf(string_t *dest, const char *src);
+void imap_append_nstring_nolf(string_t *dest, const char *src,
+                             enum imap_quote_flags flags);
 /* Append "quoted". If src has 8bit chars, skip over them. */
-void imap_append_quoted(string_t *dest, const char *src);
+void imap_append_quoted(string_t *dest, const char *src,
+                       enum imap_quote_flags flags);
 
 /* Otherwise the same as imap_append_string(), but cleanup the input data
    so that it's more readable by humans. This includes converting TABs to
    spaces, multiple spaces into a single space and NULs to #0x80. */
 void imap_append_string_for_humans(string_t *dest,
-                                  const unsigned char *src, size_t size);
+                                  const unsigned char *src, size_t size,
+                                  enum imap_quote_flags flags);
 
 #endif
index 77b46b3b0d22a29f537e6eabc2a5d972e08afb0c..9165a2d61f0a79235db1dd4eb996dc0a7439ff2a 100644 (file)
@@ -38,7 +38,7 @@ static void test_imap_append_string_for_humans(void)
        for (i = 0; i < N_ELEMENTS(tests); i++) {
                str_truncate(str, 0);
                imap_append_string_for_humans(str, (const void *)tests[i].input,
-                                             strlen(tests[i].input));
+                                             strlen(tests[i].input), 0);
                test_assert_idx(strcmp(tests[i].output, str_c(str)) == 0, i);
        }
        test_end();
@@ -71,6 +71,7 @@ static void test_imap_append_astring(void)
                { "\x7f", "\"\x7f\"" },
                { "\x80", "{1}\r\n\x80" },
                { "\xff", "{1}\r\n\xff" },
+               { "außergewöhnlich", "{17}\r\naußergewöhnlich" },
        };
        string_t *str = t_str_new(128);
        unsigned int i;
@@ -79,7 +80,7 @@ static void test_imap_append_astring(void)
 
        for (i = 0; i < N_ELEMENTS(tests); i++) {
                str_truncate(str, 0);
-               imap_append_astring(str, tests[i].input);
+               imap_append_astring(str, tests[i].input, 0);
                test_assert_idx(strcmp(tests[i].output, str_c(str)) == 0, i);
        }
        test_end();
@@ -106,7 +107,7 @@ static void test_imap_append_nstring(void)
 
        for (i = 0; i < N_ELEMENTS(tests); i++) {
                str_truncate(str, 0);
-               imap_append_nstring(str, tests[i].input);
+               imap_append_nstring(str, tests[i].input, 0);
                test_assert_idx(strcmp(tests[i].output, str_c(str)) == 0, i);
        }
        test_end();
@@ -146,11 +147,11 @@ static void test_imap_append_nstring_nolf(void)
                string_t *str2 = str_new(default_pool, 1);
 
                str_truncate(str, 0);
-               imap_append_nstring_nolf(str, tests[i].input);
+               imap_append_nstring_nolf(str, tests[i].input, 0);
                test_assert_idx(strcmp(tests[i].output, str_c(str)) == 0, i);
 
                str_truncate(str2, 0);
-               imap_append_nstring_nolf(str2, tests[i].input);
+               imap_append_nstring_nolf(str2, tests[i].input, 0);
                test_assert_idx(strcmp(tests[i].output, str_c(str2)) == 0, i);
 
                str_free(&str2);
@@ -158,6 +159,38 @@ static void test_imap_append_nstring_nolf(void)
        test_end();
 }
 
+static void test_imap_append_string_utf8(void)
+{
+       static const struct {
+               const char *input, *output;
+       } tests[] = {
+               { "", "\"\"" },
+               { "\"\"", "\"\\\"\\\"\"" },
+               { "\"\"\"", "\"\\\"\\\"\\\"\"" },
+               { "\"\"\"\"", "\"\\\"\\\"\\\"\\\"\"" },
+               { "\"\"\"\"\"", "{5}\r\n\"\"\"\"\"" },
+               { "\"\"\"\"\"\"", "{6}\r\n\"\"\"\"\"\"" },
+               { "\r", "{1}\r\n\r" },
+               { "\n", "{1}\r\n\n" },
+               { "\r\n", "{2}\r\n\r\n" },
+               { "\x7f", "\"\x7f\"" },
+               { "\x80", "{1}\r\n\x80" },
+               { "\xff", "{1}\r\n\xff" },
+               { "außergewöhnlich", "\"außergewöhnlich\"" }
+       };
+       string_t *str = t_str_new(128);
+       unsigned int i;
+
+       test_begin("test_imap_append_string_utf8()");
+
+       for (i = 0; i < N_ELEMENTS(tests); i++) {
+               str_truncate(str, 0);
+               imap_append_string(str, tests[i].input, IMAP_QUOTE_FLAG_UTF8);
+               test_assert_idx(strcmp(tests[i].output, str_c(str)) == 0, i);
+       }
+       test_end();
+}
+
 int main(void)
 {
        static void (*const test_functions[])(void) = {
@@ -165,6 +198,7 @@ int main(void)
                test_imap_append_astring,
                test_imap_append_nstring,
                test_imap_append_nstring_nolf,
+               test_imap_append_string_utf8,
                NULL
        };
        return test_run(test_functions);
index cc625124701b2981303f55b4340b3f5f82ed95ba..ba8c81bcb6a6192eb518cf3ad3c640e221f4bd5c 100644 (file)
@@ -145,16 +145,16 @@ imapc_storage_attribute_build_cmd(struct imapc_mailbox *mbox,
        }
 
        str_append_c(text, ' ');
-       imap_append_astring(text, mbname);
+       imap_append_astring(text, mbname, 0);
 
        str_append_c(text, ' ');
        if (command == GETMETADATA) {
-               imap_append_astring(text, fkey);
+               imap_append_astring(text, fkey, 0);
        } else {
                str_append_c(text, '(');
-               imap_append_astring(text, fkey);
+               imap_append_astring(text, fkey, 0);
                str_append_c(text, ' ');
-               imap_append_nstring(text, value);
+               imap_append_nstring(text, value, 0);
                str_append_c(text, ')');
        }
        return str_c(text);
index 4e6447a97bf730f9d275f9417cca4fbc5530baf4..dc9e5ffcf9ca22ad0451138ed3a929e1e88e392e 100644 (file)
@@ -289,7 +289,7 @@ imapc_mail_send_fetch(struct mail *_mail, enum mail_fetch_field fields,
                for (i = 0; mail->fetching_headers[i] != NULL; i++) {
                        if (i > 0)
                                str_append_c(str, ' ');
-                       imap_append_astring(str, mail->fetching_headers[i]);
+                       imap_append_astring(str, mail->fetching_headers[i], 0);
                }
                str_append(str, ")] ");
                mail->header_list_fetched = FALSE;
index b44ceaf23214bdde661077a92df3032370ba2098..e6fdab9e969c1a18bafa2f52e6e2aadc89b15c9e 100644 (file)
@@ -699,7 +699,7 @@ static void imapc_mail_copy_bulk_flush(struct imapc_mailbox *mbox)
        seqset_builder_deinit(&mbox->pending_copy_request->uidset_builder);
 
        str_append(mbox->pending_copy_cmd, " ");
-       imap_append_astring(mbox->pending_copy_cmd, mbox->copy_dest_box);
+       imap_append_astring(mbox->pending_copy_cmd, mbox->copy_dest_box, 0);
 
        imapc_command_send(cmd, str_c(mbox->pending_copy_cmd));
 
index 5b1c47fbaeb82d76437d9cba352ed4a419d156bc..18bbc171299ceb1deb6b62fc67d20a6db1d421fe 100644 (file)
@@ -54,18 +54,20 @@ mail_search_arg_to_cmdline(string_t *dest, const struct mail_search_arg *arg)
        }
        case SEARCH_INTHREAD:
                str_append(dest, "INTHREAD ");
-               imap_append_astring(dest, mail_thread_type_to_str(arg->value.thread_type));
+               imap_append_astring(
+                       dest, mail_thread_type_to_str(arg->value.thread_type),
+                       0);
                str_append_c(dest, ' ');
                mail_search_subargs_to_cmdline(dest, arg->value.subargs, " ");
                break;
        case SEARCH_MAILBOX:
        case SEARCH_MAILBOX_GLOB:
                str_append(dest, "MAILBOX ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                return;
        case SEARCH_MAILBOX_GUID:
                str_append(dest, "MAILBOX-GUID ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                return;
        case SEARCH_ALL:
        case SEARCH_SEQSET:
index e89e11940a08149c8ff1536150bf5801a54b6215..60f0064284b94e2ab3aa3002a42b8de067c49ad0 100644 (file)
@@ -226,19 +226,19 @@ bool mail_search_arg_to_imap(string_t *dest, const struct mail_search_arg *arg,
                        str_append(dest, t_str_ucase(arg->hdr_field_name));
                else {
                        str_append(dest, "HEADER ");
-                       imap_append_astring(dest, arg->hdr_field_name);
+                       imap_append_astring(dest, arg->hdr_field_name, 0);
                }
                str_append_c(dest, ' ');
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
 
        case SEARCH_BODY:
                str_append(dest, "BODY ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_TEXT:
                str_append(dest, "TEXT ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
 
        /* extensions */
@@ -277,7 +277,9 @@ bool mail_search_arg_to_imap(string_t *dest, const struct mail_search_arg *arg,
                break;
        case SEARCH_INTHREAD:
                str_append(dest, "INTHREAD ");
-               imap_append_astring(dest, mail_thread_type_to_str(arg->value.thread_type));
+               imap_append_astring(
+                       dest, mail_thread_type_to_str(arg->value.thread_type),
+                       0);
                str_append_c(dest, ' ');
                if (!mail_search_subargs_to_imap(dest, arg->value.subargs,
                                                 "", error_r))
@@ -285,7 +287,7 @@ bool mail_search_arg_to_imap(string_t *dest, const struct mail_search_arg *arg,
                break;
        case SEARCH_GUID:
                str_append(dest, "X-GUID ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MAILBOX:
                *error_r = "SEARCH_MAILBOX can't be written as IMAP";
@@ -295,7 +297,7 @@ bool mail_search_arg_to_imap(string_t *dest, const struct mail_search_arg *arg,
                return FALSE;
        case SEARCH_MAILBOX_GLOB:
                str_append(dest, "X-MAILBOX ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_REAL_UID:
                str_append(dest, "X-REAL-UID ");
index 660ab4c0106f5dd14f8295060bc9327e94023dde..08ddcb9a916dbf280f75ca8be9b8a37b15ee4e40 100644 (file)
@@ -414,93 +414,93 @@ bool mail_search_mime_arg_to_imap(string_t *dest,
                break;
        case SEARCH_MIME_DESCRIPTION:
                str_append(dest, "DESCRIPTION ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_DISPOSITION_TYPE:
                str_append(dest, "DISPOSITION TYPE ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_DISPOSITION_PARAM:
                str_append(dest, "DISPOSITION PARAM ");
-               imap_append_astring(dest, arg->field_name);
+               imap_append_astring(dest, arg->field_name, 0);
                str_append_c(dest, ' ');
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_ENCODING:
                str_append(dest, "ENCODING ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_ID:
                str_append(dest, "ID ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_LANGUAGE:
                str_append(dest, "LANGUAGE ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_LOCATION:
                str_append(dest, "LOCATION ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_MD5:
                str_append(dest, "MD5 ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_TYPE:
                str_append(dest, "TYPE ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_SUBTYPE:
                str_append(dest, "SUBTYPE ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_PARAM:
                str_append(dest, "PARAM ");
-               imap_append_astring(dest, arg->field_name);
+               imap_append_astring(dest, arg->field_name, 0);
                str_append_c(dest, ' ');
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_HEADER:
                str_append(dest, "HEADER ");
-               imap_append_astring(dest, arg->field_name);
+               imap_append_astring(dest, arg->field_name, 0);
                str_append_c(dest, ' ');
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_BODY:
                str_append(dest, "BODY ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_TEXT:
                str_append(dest, "TEXT ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_CC:
                str_append(dest, "CC ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_BCC:
                str_append(dest, "BCC ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_FROM:
                str_append(dest, "FROM ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_IN_REPLY_TO:
                str_append(dest, "IN-REPLY-TO ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_MESSAGE_ID:
                str_append(dest, "MESSAGE-ID ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_REPLY_TO:
                str_append(dest, "REPLY-TO ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_SENDER:
                str_append(dest, "SENDER ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_SENTBEFORE:
                str_append(dest, "SENTBEFORE");
@@ -531,11 +531,11 @@ bool mail_search_mime_arg_to_imap(string_t *dest,
                break;
        case SEARCH_MIME_SUBJECT:
                str_append(dest, "SUBJECT ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_TO:
                str_append(dest, "TO ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_DEPTH_EQUAL:
                str_printfa(dest, "DEPTH %u", arg->value.number);
@@ -567,19 +567,19 @@ bool mail_search_mime_arg_to_imap(string_t *dest,
                break;
        case SEARCH_MIME_FILENAME_IS:
                str_append(dest, "FILENAME IS ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_FILENAME_CONTAINS:
                str_append(dest, "FILENAME CONTAINS ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_FILENAME_BEGINS:
                str_append(dest, "FILENAME BEGINS ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        case SEARCH_MIME_FILENAME_ENDS:
                str_append(dest, "FILENAME ENDS ");
-               imap_append_astring(dest, arg->value.str);
+               imap_append_astring(dest, arg->value.str, 0);
                break;
        }
        return TRUE;
index df403d0d9744aa8ed9b634893e16c9a651b797ce..e2c0e5f01c07799a73d386b7c0ce76bb0c901856 100644 (file)
@@ -208,7 +208,7 @@ imap_acl_write_right(string_t *dest, string_t *tmp,
                i_unreached();
        }
 
-       imap_append_astring(dest, str_c(tmp));
+       imap_append_astring(dest, str_c(tmp), 0);
        str_append_c(dest, ' ');
        imap_acl_write_rights_list(dest, rights);
 }
@@ -479,29 +479,32 @@ imapc_acl_prepare_cmd(string_t *reply_r, const char *mailbox,
        case IMAP_ACL_CMD_MYRIGHTS:
                /* Prepare client untagged reply. */
                str_append(reply_r, "* MYRIGHTS ");
-               imap_append_astring(reply_r, mailbox);
+               imap_append_astring(reply_r, mailbox, 0);
                str_append_c(reply_r, ' ');
 
                str_append(proxy_cmd_str, "MYRIGHTS ");
                /* Strip namespace prefix. */
                imap_append_astring(proxy_cmd_str,
-                                   imap_acl_get_mailbox_name(ns, mailbox));
+                                   imap_acl_get_mailbox_name(ns, mailbox),
+                                   0);
                break;
        case IMAP_ACL_CMD_GETACL:
                /* Prepare client untagged reply. */
                str_append(reply_r, "* ACL ");
-               imap_append_astring(reply_r, mailbox);
+               imap_append_astring(reply_r, mailbox, 0);
                str_append_c(reply_r, ' ');
 
                str_append(proxy_cmd_str, "GETACL ");
                imap_append_astring(proxy_cmd_str,
-                                   imap_acl_get_mailbox_name(ns, mailbox));
+                                   imap_acl_get_mailbox_name(ns, mailbox),
+                                   0);
                break;
        case IMAP_ACL_CMD_SETACL:
                /* No contents in untagged replies for SETACL */
                str_append(proxy_cmd_str, "SETACL ");
                imap_append_astring(proxy_cmd_str,
-                                   imap_acl_get_mailbox_name(ns, mailbox));
+                                   imap_acl_get_mailbox_name(ns, mailbox),
+                                   0);
 
                str_append_c(proxy_cmd_str, ' ');
                str_append(proxy_cmd_str, cmd_args);
@@ -510,7 +513,8 @@ imapc_acl_prepare_cmd(string_t *reply_r, const char *mailbox,
                /* No contents in untagged replies for DELETEACL */
                str_append(proxy_cmd_str, "DELETEACL ");
                imap_append_astring(proxy_cmd_str,
-                                   imap_acl_get_mailbox_name(ns, mailbox));
+                                   imap_acl_get_mailbox_name(ns, mailbox),
+                                   0);
 
                str_append_c(proxy_cmd_str, ' ');
                str_append(proxy_cmd_str, cmd_args);
@@ -640,7 +644,7 @@ imap_acl_send_myrights(struct client_command_context *cmd,
 
        str = t_str_new(128);
        str_append(str, "* MYRIGHTS ");
-       imap_append_astring(str, mutf7_mailbox);
+       imap_append_astring(str, mutf7_mailbox, 0);
        str_append_c(str, ' ');
        imap_acl_write_rights_list(str, rights);
 
@@ -663,7 +667,7 @@ static void imap_acl_cmd_getacl(struct mailbox *box, struct mail_namespace *ns,
 
        str = t_str_new(128);
        str_append(str, "* ACL ");
-       imap_append_astring(str, mailbox);
+       imap_append_astring(str, mailbox, 0);
 
        ret = imap_acl_write_aclobj(str, backend,
                                    acl_mailbox_get_aclobj(box), TRUE,
@@ -798,9 +802,9 @@ static bool cmd_listrights(struct client_command_context *cmd)
 
        str = t_str_new(128);
        str_append(str, "* LISTRIGHTS ");
-       imap_append_astring(str, orig_mailbox);
+       imap_append_astring(str, orig_mailbox, 0);
        str_append_c(str, ' ');
-       imap_append_astring(str, identifier);
+       imap_append_astring(str, identifier, 0);
        str_append_c(str, ' ');
        str_append(str, "\"\" l r w s t p i e k x a c d");
 
@@ -1076,10 +1080,10 @@ static bool cmd_setacl(struct client_command_context *cmd)
        }
 
        /* Keep original identifer for proxy_cmd_args */
-       imap_append_astring(proxy_cmd_args, identifier);
+       imap_append_astring(proxy_cmd_args, identifier, 0);
        str_append_c(proxy_cmd_args, ' ');
        /* Append original rights for proxy_cmd_args */
-       imap_append_astring(proxy_cmd_args, rights);
+       imap_append_astring(proxy_cmd_args, rights, 0);
 
        ns = imap_acl_find_namespace(cmd, &mailbox);
        if (ns == NULL)
@@ -1154,7 +1158,7 @@ static bool cmd_deleteacl(struct client_command_context *cmd)
                return TRUE;
 
        /* Escaped identifer for proxy_cmd_args */
-       imap_append_astring(proxy_cmd_args, identifier);
+       imap_append_astring(proxy_cmd_args, identifier, 0);
 
        box = mailbox_alloc(ns->list, mailbox,
                            MAILBOX_FLAG_READONLY | MAILBOX_FLAG_IGNORE_ACLS);
index 601fdbc2c38d2e66464c39241d2dd287ee2024ad..9344a4f567986d7e2840fc3b772236e765cf69a6 100644 (file)
@@ -44,7 +44,7 @@ quota_reply_write(string_t *str, struct mail_user *user,
 
        str_append(str, "* QUOTA ");
        name = imap_quota_root_get_name(user, owner, root);
-       imap_append_astring(str, name);
+       imap_append_astring(str, name, 0);
 
        str_append(str, " (");
        prefix_len = str_len(str);
@@ -110,7 +110,7 @@ static bool cmd_getquotaroot(struct client_command_context *cmd)
        quotaroot_reply = t_str_new(128);
        quota_reply = t_str_new(256);
        str_append(quotaroot_reply, "* QUOTAROOT ");
-       imap_append_astring(quotaroot_reply, orig_mailbox);
+       imap_append_astring(quotaroot_reply, orig_mailbox, 0);
 
        ret = 0;
        iter = quota_root_iter_init(box);
@@ -119,7 +119,7 @@ static bool cmd_getquotaroot(struct client_command_context *cmd)
                        continue;
                str_append_c(quotaroot_reply, ' ');
                name = imap_quota_root_get_name(client->user, ns->owner, root);
-               imap_append_astring(quotaroot_reply, name);
+               imap_append_astring(quotaroot_reply, name, 0);
 
                if (quota_reply_write(quota_reply, client->user, ns->owner, root) < 0)
                        ret = -1;