if ((url_flags & IMAP_URLAUTH_FETCH_FLAG_BINARY) != 0)
imap_msgpart_url_set_decode_to_binary(client->url);
if ((url_flags & IMAP_URLAUTH_FETCH_FLAG_BODYPARTSTRUCTURE) != 0) {
+ /* FIXME: Implement UTF-8 support for quoted strings in
+ generated BODYSTRUCTURE element. */
ret = imap_msgpart_url_get_bodypartstructure(client->url, 0,
bpstruct_r, &error);
if (ret <= 0) {
bool cmd_genurlauth(struct client_command_context *cmd)
{
const struct imap_arg *args;
+ enum imap_quote_flags qflags = (cmd->utf8 ? IMAP_QUOTE_FLAG_UTF8 : 0);
string_t *response;
int ret;
}
str_append_c(response, ' ');
- imap_append_astring(response, url, 0);
+ imap_append_astring(response, url, qflags);
}
client_send_line(cmd->client, str_c(response));
static string_t *
metadata_add_entry(struct imap_getmetadata_context *ctx, const char *entry)
{
+ enum imap_quote_flags qflags = (ctx->cmd->utf8 ?
+ IMAP_QUOTE_FLAG_UTF8 : 0);
string_t *str;
str = t_str_new(64);
/* server metadata reply */
str_append(str, "\"\"");
} else if (ctx->cmd->utf8) {
- imap_append_astring(str, mailbox_get_vname(ctx->box), FALSE);
+ imap_append_astring(str, mailbox_get_vname(ctx->box), qflags);
} else {
if (imap_utf8_to_utf7(mailbox_get_vname(ctx->box), mailbox_mutf7) < 0)
i_unreached();
} else {
str_append_c(str, ' ');
}
- imap_append_astring(str, entry, 0);
+ imap_append_astring(str, entry, qflags);
return str;
}
bool cmd_id(struct client_command_context *cmd)
{
const struct imap_settings *set = cmd->client->set;
+ enum imap_quote_flags qflags = (cmd->utf8 ? IMAP_QUOTE_FLAG_UTF8 : 0);
const struct imap_arg *args;
if (!client_read_args(cmd, 0, 0, &args))
str_free(&log_reply);
}
- client_send_line(cmd->client, t_strdup_printf(
- "* ID %s", imap_id_reply_generate(&set->imap_id_send, 0)));
+ client_send_line(cmd->client,
+ t_strdup_printf("* ID %s",
+ imap_id_reply_generate(&set->imap_id_send, qflags)));
client_send_tagline(cmd, "OK ID completed.");
return TRUE;
}
timeout_remove(&ctx->to_hibernate);
ctx->sync_pending = FALSE;
- ctx->sync_ctx = imap_sync_init(ctx->client, box, 0, 0);
+ ctx->sync_ctx = imap_sync_init(ctx->client, box, 0, 0, ctx->cmd->utf8);
return cmd_idle_continue(ctx->cmd);
}
static bool cmd_list_continue(struct client_command_context *cmd)
{
struct cmd_list_context *ctx = cmd->context;
+ enum imap_quote_flags qflags = (cmd->utf8 ? IMAP_QUOTE_FLAG_UTF8 : 0);
const struct mailbox_info *info;
enum mailbox_info_flags flags;
string_t *str, *mutf7_name;
list_reply_append_ns_sep_param(str,
mail_namespace_get_sep(info->ns));
str_append_c(str, ' ');
- imap_append_astring(str, name, 0);
+ imap_append_astring(str, name, qflags);
mailbox_childinfo2str(ctx, str, flags);
/* send LIST/LSUB response */
static void cmd_list_ref_root(struct client *client, const char *ref, bool utf8)
{
+ enum imap_quote_flags qflags = (utf8 ? IMAP_QUOTE_FLAG_UTF8 : 0);
struct mail_namespace *ns;
const char *ns_prefix;
char ns_sep;
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, 0);
+ imap_append_astring(str, ns_prefix, qflags);
} else {
/* Hidden namespace or empty namespace prefix. We could just
return an empty root name, but it's safer to emulate what
if (p == NULL)
str_append(str, "\"\"");
- else
- imap_append_astring(str, t_strdup_until(ref, p + 1), 0);
+ else {
+ imap_append_astring(str, t_strdup_until(ref, p + 1),
+ qflags);
+ }
}
client_send_line(client, str_c(str));
}
list_namespaces(struct mail_namespace *ns, enum mail_namespace_type type,
string_t *str, bool utf8)
{
+ enum imap_quote_flags qflags = (utf8 ? IMAP_QUOTE_FLAG_UTF8 : 0);
ARRAY(struct namespace_order) ns_order;
struct namespace_order *no;
unsigned int count = 0;
prefix = str_c(mutf7_prefix);
}
- imap_append_string(str, prefix, 0);
+ imap_append_string(str, prefix, qflags);
str_append(str, " \"");
if (ns_sep == '\\')
str_append_c(str, '\\');
static void
imap_notify_box_list_noperm(struct client *client, struct mailbox *box)
{
+ bool utf8 = client_has_enabled(client, imap_feature_utf8accept);
+ enum imap_quote_flags qflags = (utf8 ? IMAP_QUOTE_FLAG_UTF8 : 0);
string_t *str = t_str_new(128);
char ns_sep = mail_namespace_get_sep(mailbox_get_namespace(box));
enum mailbox_info_flags mailbox_flags;
mailbox_flags = 0;
vname = mailbox_get_vname(box);
- string_t *mutf7_name = t_str_new(128);
- if (imap_utf8_to_utf7(vname, mutf7_name) < 0)
- i_panic("LIST: Mailbox name not UTF-8: %s", vname);
- vname = str_c(mutf7_name);
+ if (!utf8) {
+ string_t *mutf7_name = t_str_new(128);
+ if (imap_utf8_to_utf7(vname, mutf7_name) < 0)
+ i_panic("LIST: Mailbox name not UTF-8: %s", vname);
+ vname = str_c(mutf7_name);
+ }
str_append(str, "* LIST (");
if (imap_mailbox_flags2str(str, mailbox_flags))
str_append_c(str, ns_sep);
str_append(str, "\" ");
- imap_append_astring(str, vname, 0);
+ imap_append_astring(str, vname, qflags);
client_send_line(client, str_c(str));
}
const struct imap_arg *params;
const char *url_text;
+ if (cmd->utf8)
+ url_flags |= IMAP_URLAUTH_FETCH_FLAG_UTF8;
if (imap_arg_get_list(arg, ¶ms))
url_flags |= IMAP_URLAUTH_FETCH_FLAG_EXTENDED;
else
struct imap_fetch_body_data *body, const char *prefix,
const struct imap_arg *args, unsigned int args_count)
{
+ enum imap_quote_flags qflags = (ctx->fetch_ctx->utf8 ?
+ IMAP_QUOTE_FLAG_UTF8 : 0);
string_t *str;
const char *value;
size_t i;
if (args[i].type == IMAP_ARG_ATOM)
str_append(str, value);
else
- imap_append_quoted(str, value, 0);
+ imap_append_quoted(str, value, qflags);
}
str_append_c(str, ')');
body->section = str_c(str);
fetch_snippet(struct imap_fetch_context *ctx, struct mail *mail,
struct imap_fetch_preview_data *preview)
{
+ enum imap_quote_flags qflags = (ctx->utf8 ? IMAP_QUOTE_FLAG_UTF8 : 0);
enum mail_lookup_abort temp_lookup_abort = preview->lazy ? MAIL_LOOKUP_ABORT_NOT_IN_CACHE_START_CACHING : mail->lookup_abort;
enum mail_lookup_abort orig_lookup_abort = mail->lookup_abort;
const char *resp, *snippet;
else
str_append(ctx->state.cur_str, " ");
if (ret == 0)
- imap_append_string(ctx->state.cur_str, snippet, 0);
+ imap_append_string(ctx->state.cur_str, snippet, qflags);
else
str_append(ctx->state.cur_str, "NIL");
if (preview->old_standard)
static int fetch_x_mailbox(struct imap_fetch_context *ctx, struct mail *mail,
void *context ATTR_UNUSED)
{
+ enum imap_quote_flags qflags = (ctx->utf8 ? IMAP_QUOTE_FLAG_UTF8 : 0);
const char *name;
if (mail_get_special(mail, MAIL_FETCH_MAILBOX_NAME, &name) < 0) {
}
str_append(ctx->state.cur_str, "X-MAILBOX ");
- imap_append_astring(ctx->state.cur_str, name, 0);
+ imap_append_astring(ctx->state.cur_str, name, qflags);
str_append_c(ctx->state.cur_str, ' ');
return 1;
}
enum mailbox_info_flags flags)
{
struct client *client = notify_ns->ctx->client;
+ bool utf8 = client_has_enabled(client, imap_feature_utf8accept);
+ enum imap_quote_flags qflags = (utf8 ? IMAP_QUOTE_FLAG_UTF8 : 0);
string_t *str = t_str_new(128), *mutf7_vname;
char ns_sep = mail_namespace_get_sep(notify_ns->ns);
const char *vname, *old_vname;
str_append(str, "\" ");
vname = rec->vname;
- mutf7_vname = t_str_new(128);
- 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, 0);
+ if (!utf8) {
+ mutf7_vname = t_str_new(128);
+ 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, qflags);
if (rec->old_vname != NULL) {
old_vname = rec->old_vname;
- str_truncate(mutf7_vname, 0);
- if (imap_utf8_to_utf7(old_vname, mutf7_vname) < 0) {
- i_panic("Mailbox name not UTF-8: %s",
- old_vname);
+ if (!utf8) {
+ str_truncate(mutf7_vname, 0);
+ if (imap_utf8_to_utf7(old_vname, mutf7_vname) < 0) {
+ i_panic("Mailbox name not UTF-8: %s",
+ old_vname);
+ }
+ old_vname = str_c(mutf7_vname);
}
- old_vname = str_c(mutf7_vname);
str_append(str, " (\"OLDNAME\" (");
- imap_append_astring(str, old_vname, 0);
+ imap_append_astring(str, old_vname, qflags);
str_append(str, "))");
}
return client_send_line_next(client, str_c(str));
const struct imap_status_items *items,
const struct imap_status_result *result)
{
+ bool utf8 = client_has_enabled(client, imap_feature_utf8accept);
+ enum imap_quote_flags qflags = (utf8 ? IMAP_QUOTE_FLAG_UTF8 : 0);
const struct mailbox_status *status = &result->status;
string_t *str;
size_t prefix_len;
str = t_str_new(128);
str_append(str, "* STATUS ");
- imap_append_astring(str, mailbox_mutf7, 0);
+ imap_append_astring(str, mailbox_mutf7, qflags);
str_append(str, " (");
prefix_len = str_len(str);
bool no_newmail:1;
bool have_new_mails:1;
bool search_update_notifying:1;
+ bool utf8:1;
};
#endif
const struct imap_search_update *update,
bool removes_only)
{
+ enum imap_quote_flags qflags = (ctx->utf8 ? IMAP_QUOTE_FLAG_UTF8 : 0);
string_t *cmd;
int ret = 1;
cmd = t_str_new(256);
str_append(cmd, "* ESEARCH (TAG ");
- imap_append_string(cmd, update->tag, 0);
+ imap_append_string(cmd, update->tag, qflags);
str_append_c(cmd, ')');
if (update->return_uids)
str_append(cmd, " UID");
struct imap_sync_context *
imap_sync_init(struct client *client, struct mailbox *box,
- enum imap_sync_flags imap_flags, enum mailbox_sync_flags flags)
+ enum imap_sync_flags imap_flags, enum mailbox_sync_flags flags,
+ bool utf8)
{
struct imap_sync_context *ctx;
ctx->client = client;
ctx->box = box;
ctx->imap_flags = imap_flags;
+ ctx->utf8 = utf8;
i_array_init(&ctx->module_contexts, 5);
/* make sure user can't DoS the system by causing Dovecot to create
client->syncing = TRUE;
- ctx = imap_sync_init(client, client->mailbox, imap_flags, flags);
+ ctx = imap_sync_init(client, client->mailbox, imap_flags, flags,
+ sync_cmd->utf8);
ctx->no_newmail = no_newmail;
/* handle the syncing using sync_cmd. it doesn't actually matter which
struct imap_sync_context *
imap_sync_init(struct client *client, struct mailbox *box,
- enum imap_sync_flags imap_flags, enum mailbox_sync_flags flags);
+ enum imap_sync_flags imap_flags, enum mailbox_sync_flags flags,
+ bool utf8);
int imap_sync_deinit(struct imap_sync_context *ctx,
struct client_command_context *sync_cmd);
int imap_sync_more(struct imap_sync_context *ctx);
string_t *str;
str = str_new(mail->mail.data_pool, 256);
+ /* FIXME: Implement UTF-8 support for quoted strings in generated
+ ENVELOPE element. */
imap_envelope_write(mail->data.envelope_data, str, 0);
mail->data.envelope = str_c(str);
mail->data.save_envelope = FALSE;
{
const char *error;
- if (imap_bodystructure_write(mail->data.parts, str, extended, FALSE,
+ /* FIXME: Implement UTF-8 support for quoted strings in generated
+ BODYSTRUCTURE element. */
+ if (imap_bodystructure_write(mail->data.parts, str, extended, 0,
&error) < 0) {
mail_set_cache_corrupted(&mail->mail.mail,
MAIL_FETCH_MESSAGE_PARTS, error);
static void
imap_acl_write_right(string_t *dest, string_t *tmp,
- const struct acl_rights *right, bool neg)
+ const struct acl_rights *right, bool neg, bool utf8)
{
+ enum imap_quote_flags qflags = (utf8 ? IMAP_QUOTE_FLAG_UTF8 : 0);
const char *const *rights = neg ? right->neg_rights : right->rights;
str_truncate(tmp, 0);
i_unreached();
}
- imap_append_astring(dest, str_c(tmp), 0);
+ imap_append_astring(dest, str_c(tmp), qflags);
str_append_c(dest, ' ');
imap_acl_write_rights_list(dest, rights);
}
static int
imap_acl_write_aclobj(string_t *dest, struct acl_backend *backend,
struct acl_object *aclobj, bool convert_owner,
- bool add_default)
+ bool add_default, bool utf8)
{
struct acl_object_list_iter *iter;
struct acl_rights rights;
str_truncate(dest, orig_len);
return imap_acl_write_aclobj(dest, backend,
aclobj, FALSE,
- add_default);
+ add_default, utf8);
}
seen_owner = TRUE;
if (rights.rights != NULL)
if (rights.rights != NULL) {
str_append_c(dest, ' ');
- imap_acl_write_right(dest, tmp, &rights, FALSE);
+ imap_acl_write_right(dest, tmp, &rights, FALSE, utf8);
}
if (rights.neg_rights != NULL) {
str_append_c(dest, ' ');
- imap_acl_write_right(dest, tmp, &rights, TRUE);
+ imap_acl_write_right(dest, tmp, &rights, TRUE, utf8);
}
}
ret = acl_object_list_deinit(&iter);
rights.rights = acl_object_get_default_rights(aclobj);
if (rights.rights != NULL) {
str_append_c(dest, ' ');
- imap_acl_write_right(dest, tmp, &rights, FALSE);
+ imap_acl_write_right(dest, tmp, &rights, FALSE, utf8);
}
}
return ret;
imap_acl_send_myrights(struct client_command_context *cmd,
struct mailbox *box, const char *mutf7_mailbox)
{
+ enum imap_quote_flags qflags = (cmd->utf8 ? IMAP_QUOTE_FLAG_UTF8 : 0);
const char *const *rights;
string_t *str;
str = t_str_new(128);
str_append(str, "* MYRIGHTS ");
- imap_append_astring(str, mutf7_mailbox, 0);
+ imap_append_astring(str, mutf7_mailbox, qflags);
str_append_c(str, ' ');
imap_acl_write_rights_list(str, rights);
const char *mailbox,
struct client_command_context *cmd)
{
+ enum imap_quote_flags qflags = (cmd->utf8 ? IMAP_QUOTE_FLAG_UTF8 : 0);
struct acl_backend *backend;
string_t *str;
int ret;
str = t_str_new(128);
str_append(str, "* ACL ");
- imap_append_astring(str, mailbox, 0);
+ imap_append_astring(str, mailbox, qflags);
ret = imap_acl_write_aclobj(str, backend,
acl_mailbox_get_aclobj(box), TRUE,
- ns->type == MAIL_NAMESPACE_TYPE_PRIVATE);
+ ns->type == MAIL_NAMESPACE_TYPE_PRIVATE,
+ cmd->utf8);
if (ret > -1) {
client_send_line(cmd->client, str_c(str));
client_send_tagline(cmd, "OK Getacl completed.");
static bool cmd_listrights(struct client_command_context *cmd)
{
+ enum imap_quote_flags qflags = (cmd->utf8 ? IMAP_QUOTE_FLAG_UTF8 : 0);
struct mailbox *box;
struct mail_namespace *ns;
const char *mailbox, *orig_mailbox, *identifier;
str = t_str_new(128);
str_append(str, "* LISTRIGHTS ");
- imap_append_astring(str, orig_mailbox, 0);
+ imap_append_astring(str, orig_mailbox, qflags);
str_append_c(str, ' ');
- imap_append_astring(str, identifier, 0);
+ imap_append_astring(str, identifier, qflags);
str_append_c(str, ' ');
str_append(str, "\"\" l r w s t p i e k x a c d");
static bool cmd_setacl(struct client_command_context *cmd)
{
+ enum imap_quote_flags qflags = (cmd->utf8 ? IMAP_QUOTE_FLAG_UTF8 : 0);
struct mail_namespace *ns;
struct mailbox *box;
const char *mailbox, *orig_mailbox, *identifier, *rights;
}
/* Keep original identifer for proxy_cmd_args */
- imap_append_astring(proxy_cmd_args, identifier, 0);
+ imap_append_astring(proxy_cmd_args, identifier, qflags);
str_append_c(proxy_cmd_args, ' ');
/* Append original rights for proxy_cmd_args */
imap_append_astring(proxy_cmd_args, rights, 0);
static bool cmd_deleteacl(struct client_command_context *cmd)
{
+ enum imap_quote_flags qflags = (cmd->utf8 ? IMAP_QUOTE_FLAG_UTF8 : 0);
struct mailbox *box;
struct mail_namespace *ns;
const char *mailbox, *orig_mailbox, *identifier;
return TRUE;
/* Escaped identifer for proxy_cmd_args */
- imap_append_astring(proxy_cmd_args, identifier, 0);
+ imap_append_astring(proxy_cmd_args, identifier, qflags);
box = mailbox_alloc(ns->list, mailbox,
MAILBOX_FLAG_READONLY | MAILBOX_FLAG_IGNORE_ACLS);
static int
quota_reply_write(string_t *str, struct mail_user *user,
- struct mail_user *owner, struct quota_root *root)
+ struct mail_user *owner, struct quota_root *root, bool utf8)
{
+ enum imap_quote_flags qflags = (utf8 ? IMAP_QUOTE_FLAG_UTF8 : 0);
const char *name, *const *list, *error;
unsigned int i;
uint64_t value, limit;
str_append(str, "* QUOTA ");
name = imap_quota_root_get_name(user, owner, root);
- imap_append_astring(str, name, 0);
+ imap_append_astring(str, name, qflags);
str_append(str, " (");
prefix_len = str_len(str);
static bool cmd_getquotaroot(struct client_command_context *cmd)
{
struct client *client = cmd->client;
+ enum imap_quote_flags qflags = (cmd->utf8 ? IMAP_QUOTE_FLAG_UTF8 : 0);
struct quota_user *quser = QUOTA_USER_CONTEXT(client->user);
struct mail_namespace *ns;
struct mailbox *box;
quotaroot_reply = t_str_new(128);
quota_reply = t_str_new(256);
str_append(quotaroot_reply, "* QUOTAROOT ");
- imap_append_astring(quotaroot_reply, orig_mailbox, 0);
+ imap_append_astring(quotaroot_reply, orig_mailbox, qflags);
ret = 0;
iter = quota_root_iter_init(box);
continue;
str_append_c(quotaroot_reply, ' ');
name = imap_quota_root_get_name(client->user, ns->owner, root);
- imap_append_astring(quotaroot_reply, name, 0);
+ imap_append_astring(quotaroot_reply, name, qflags);
- if (quota_reply_write(quota_reply, client->user, ns->owner, root) < 0)
+ if (quota_reply_write(quota_reply, client->user, ns->owner,
+ root, cmd->utf8) < 0)
ret = -1;
}
quota_root_iter_deinit(&iter);
}
quota_reply = t_str_new(128);
- if (quota_reply_write(quota_reply, cmd->client->user, owner, root) < 0)
+ if (quota_reply_write(quota_reply, cmd->client->user, owner,
+ root, cmd->utf8) < 0)
client_send_tagline(cmd, "NO Internal quota calculation error.");
else {
o_stream_nsend(cmd->client->output, str_data(quota_reply),