From 81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Fri, 7 Oct 2011 20:10:11 +0300 Subject: [PATCH] imapc: Command sending API changed to be more extensible. --- src/lib-imap-client/imapc-client-private.h | 3 + src/lib-imap-client/imapc-client.c | 124 +++------------- src/lib-imap-client/imapc-client.h | 21 +-- src/lib-imap-client/imapc-connection.c | 140 ++++++++++-------- src/lib-imap-client/imapc-connection.h | 14 +- src/lib-storage/index/imapc/imapc-list.c | 48 +++--- .../index/imapc/imapc-mail-fetch.c | 7 +- src/lib-storage/index/imapc/imapc-mail.c | 6 +- src/lib-storage/index/imapc/imapc-save.c | 17 ++- src/lib-storage/index/imapc/imapc-storage.c | 31 ++-- src/lib-storage/index/imapc/imapc-sync.c | 17 ++- 11 files changed, 197 insertions(+), 231 deletions(-) diff --git a/src/lib-imap-client/imapc-client-private.h b/src/lib-imap-client/imapc-client-private.h index 419565f9fd..1a40270f88 100644 --- a/src/lib-imap-client/imapc-client-private.h +++ b/src/lib-imap-client/imapc-client-private.h @@ -37,4 +37,7 @@ struct imapc_client_mailbox { void imapc_client_ref(struct imapc_client *client); void imapc_client_unref(struct imapc_client **client); +void imapc_command_set_mailbox(struct imapc_command *cmd, + struct imapc_client_mailbox *box); + #endif diff --git a/src/lib-imap-client/imapc-client.c b/src/lib-imap-client/imapc-client.c index b9246b0705..a1144b1186 100644 --- a/src/lib-imap-client/imapc-client.c +++ b/src/lib-imap-client/imapc-client.c @@ -12,13 +12,6 @@ #include -struct imapc_client_command_context { - struct imapc_client_mailbox *box; - - imapc_command_callback_t *callback; - void *context; -}; - const struct imapc_capability_name imapc_capability_names[] = { { "SASL-IR", IMAPC_CAPABILITY_SASL_IR }, { "LITERAL+", IMAPC_CAPABILITY_LITERALPLUS }, @@ -203,18 +196,14 @@ imapc_client_find_connection(struct imapc_client *client) return (*connp)->conn; } -void imapc_client_cmdf(struct imapc_client *client, - imapc_command_callback_t *callback, void *context, - const char *cmd_fmt, ...) +struct imapc_command * +imapc_client_cmd(struct imapc_client *client, + imapc_command_callback_t *callback, void *context) { struct imapc_connection *conn; - va_list args; conn = imapc_client_find_connection(client); - - va_start(args, cmd_fmt); - imapc_connection_cmdvf(conn, FALSE, callback, context, cmd_fmt, args); - va_end(args); + return imapc_connection_cmd(conn, callback, context); } static struct imapc_client_connection * @@ -292,36 +281,30 @@ void imapc_client_mailbox_close(struct imapc_client_mailbox **_box) *_box = NULL; } -static void imapc_client_mailbox_cmd_cb(const struct imapc_command_reply *reply, - void *context) +struct imapc_command * +imapc_client_mailbox_cmd(struct imapc_client_mailbox *box, + imapc_command_callback_t *callback, void *context) { - struct imapc_client_command_context *ctx = context; - - ctx->box->pending_box_command_count--; + struct imapc_command *cmd; - ctx->callback(reply, ctx->context); - i_free(ctx); + cmd = imapc_connection_cmd(box->conn, callback, context); + imapc_command_set_mailbox(cmd, box); + return cmd; } -static struct imapc_client_command_context * -imapc_client_mailbox_cmd_common(struct imapc_client_mailbox *box, - imapc_command_callback_t *callback, - void *context) +struct imapc_msgmap * +imapc_client_mailbox_get_msgmap(struct imapc_client_mailbox *box) { - struct imapc_client_command_context *ctx; - - ctx = i_new(struct imapc_client_command_context, 1); - ctx->box = box; - ctx->callback = callback; - ctx->context = context; + return box->msgmap; +} - box->pending_box_command_count++; - return ctx; +void imapc_client_mailbox_idle(struct imapc_client_mailbox *box) +{ + if (imapc_client_mailbox_is_connected(box)) + imapc_connection_idle(box->conn); } -static bool -imapc_client_mailbox_is_selected(struct imapc_client_mailbox *box, - struct imapc_command_reply *reply_r) +bool imapc_client_mailbox_is_connected(struct imapc_client_mailbox *box) { struct imapc_client_mailbox *selected_box; @@ -330,78 +313,13 @@ imapc_client_mailbox_is_selected(struct imapc_client_mailbox *box, if (selected_box == box) return TRUE; - memset(reply_r, 0, sizeof(*reply_r)); - reply_r->state = IMAPC_COMMAND_STATE_DISCONNECTED; - if (selected_box == NULL) { - reply_r->text_full = "Disconnected from server"; - } else { + if (selected_box != NULL) i_error("imapc: Selected mailbox changed unexpectedly"); - reply_r->text_full = "Internal error"; - } - reply_r->text_without_resp = reply_r->text_full; box->conn = NULL; return FALSE; } -void imapc_client_mailbox_cmd(struct imapc_client_mailbox *box, - imapc_command_callback_t *callback, - void *context, const char *cmd) -{ - struct imapc_client_command_context *ctx; - struct imapc_command_reply reply; - - if (!imapc_client_mailbox_is_selected(box, &reply)) { - callback(&reply, context); - return; - } - - ctx = imapc_client_mailbox_cmd_common(box, callback, context); - imapc_connection_cmd(box->conn, TRUE, cmd, - imapc_client_mailbox_cmd_cb, ctx); -} - -void imapc_client_mailbox_cmdf(struct imapc_client_mailbox *box, - imapc_command_callback_t *callback, - void *context, const char *cmd_fmt, ...) -{ - struct imapc_client_command_context *ctx; - va_list args; - struct imapc_command_reply reply; - - if (!imapc_client_mailbox_is_selected(box, &reply)) { - callback(&reply, context); - return; - } - - ctx = imapc_client_mailbox_cmd_common(box, callback, context); - va_start(args, cmd_fmt); - imapc_connection_cmdvf(box->conn, TRUE, imapc_client_mailbox_cmd_cb, - ctx, cmd_fmt, args); - va_end(args); -} - -struct imapc_msgmap * -imapc_client_mailbox_get_msgmap(struct imapc_client_mailbox *box) -{ - return box->msgmap; -} - -void imapc_client_mailbox_idle(struct imapc_client_mailbox *box) -{ - struct imapc_command_reply reply; - - if (imapc_client_mailbox_is_selected(box, &reply)) - imapc_connection_idle(box->conn); -} - -bool imapc_client_mailbox_is_connected(struct imapc_client_mailbox *box) -{ - struct imapc_command_reply reply; - - return imapc_client_mailbox_is_selected(box, &reply); -} - enum imapc_capability imapc_client_get_capabilities(struct imapc_client *client) { diff --git a/src/lib-imap-client/imapc-client.h b/src/lib-imap-client/imapc-client.h index d23aacedd4..5e9afa7395 100644 --- a/src/lib-imap-client/imapc-client.h +++ b/src/lib-imap-client/imapc-client.h @@ -109,9 +109,14 @@ void imapc_client_deinit(struct imapc_client **client); void imapc_client_login(struct imapc_client *client, imapc_command_callback_t *callback, void *context); -void imapc_client_cmdf(struct imapc_client *client, - imapc_command_callback_t *callback, void *context, - const char *cmd_fmt, ...) ATTR_FORMAT(4, 5); +struct imapc_command * +imapc_client_cmd(struct imapc_client *client, + imapc_command_callback_t *callback, void *context); +void imapc_command_send(struct imapc_command *cmd, const char *cmd_str); +void imapc_command_sendf(struct imapc_command *cmd, const char *cmd_fmt, ...) + ATTR_FORMAT(2, 3); +void imapc_command_sendvf(struct imapc_command *cmd, + const char *cmd_fmt, va_list args) ATTR_FORMAT(2, 0); void imapc_client_register_untagged(struct imapc_client *client, imapc_untagged_callback_t *callback, @@ -132,13 +137,9 @@ imapc_client_mailbox_open(struct imapc_client *client, void *untagged_box_context); void imapc_client_mailbox_close(struct imapc_client_mailbox **box); void imapc_client_mailbox_disconnect(struct imapc_client_mailbox *box); -void imapc_client_mailbox_cmd(struct imapc_client_mailbox *box, - imapc_command_callback_t *callback, - void *context, const char *cmd); -void imapc_client_mailbox_cmdf(struct imapc_client_mailbox *box, - imapc_command_callback_t *callback, - void *context, const char *cmd_fmt, ...) - ATTR_FORMAT(4, 5); +struct imapc_command * +imapc_client_mailbox_cmd(struct imapc_client_mailbox *box, + imapc_command_callback_t *callback, void *context); struct imapc_msgmap * imapc_client_mailbox_get_msgmap(struct imapc_client_mailbox *box); diff --git a/src/lib-imap-client/imapc-connection.c b/src/lib-imap-client/imapc-connection.c index a50c34ee91..dd0b208b81 100644 --- a/src/lib-imap-client/imapc-connection.c +++ b/src/lib-imap-client/imapc-connection.c @@ -47,13 +47,19 @@ struct imapc_command { unsigned int send_pos; unsigned int tag; + struct imapc_connection *conn; + /* If non-NULL, points to the mailbox where this command should be + executed */ + struct imapc_client_mailbox *box; + ARRAY_DEFINE(streams, struct imapc_command_stream); imapc_command_callback_t *callback; void *context; + /* This is the IDLE command */ unsigned int idle:1; - unsigned int mailboxcmd:1; + /* Waiting for '+' literal reply before we can continue */ unsigned int wait_for_literal:1; }; @@ -657,7 +663,7 @@ imapc_connection_get_sasl_plain_request(struct imapc_connection *conn) static void imapc_connection_authenticate(struct imapc_connection *conn) { const struct imapc_client_settings *set = &conn->client->set; - const char *cmd; + struct imapc_command *cmd; if (conn->client->set.debug) { if (set->master_user == NULL) { @@ -669,23 +675,21 @@ static void imapc_connection_authenticate(struct imapc_connection *conn) } } + cmd = imapc_connection_cmd(conn, imapc_connection_login_cb, + conn); + if ((set->master_user == NULL && need_literal(set->username) && need_literal(set->password)) || (conn->capabilities & IMAPC_CAPABILITY_AUTH_PLAIN) == 0) { /* We can use LOGIN command */ - imapc_connection_cmdf(conn, FALSE, imapc_connection_login_cb, - conn, "LOGIN %s %s", - set->username, set->password); + imapc_command_sendf(cmd, "LOGIN %s %s", + set->username, set->password); } else if ((conn->capabilities & IMAPC_CAPABILITY_SASL_IR) != 0) { - cmd = t_strdup_printf("AUTHENTICATE PLAIN %s", + imapc_command_sendf(cmd, "AUTHENTICATE PLAIN %1s", imapc_connection_get_sasl_plain_request(conn)); - imapc_connection_cmd(conn, FALSE, cmd, - imapc_connection_login_cb, conn); } else { - cmd = t_strdup_printf("AUTHENTICATE PLAIN\r\n%s", + imapc_command_sendf(cmd, "AUTHENTICATE PLAIN\r\n%1s", imapc_connection_get_sasl_plain_request(conn)); - imapc_connection_cmd(conn, FALSE, cmd, - imapc_connection_login_cb, conn); } } @@ -709,6 +713,8 @@ imapc_connection_starttls_cb(const struct imapc_command_reply *reply, static void imapc_connection_starttls(struct imapc_connection *conn) { + struct imapc_command *cmd; + if (conn->client->set.ssl_mode == IMAPC_CLIENT_SSL_MODE_STARTTLS && conn->ssl_iostream == NULL) { if ((conn->capabilities & IMAPC_CAPABILITY_STARTTLS) == 0) { @@ -718,8 +724,9 @@ static void imapc_connection_starttls(struct imapc_connection *conn) imapc_connection_disconnect(conn); return; } - imapc_connection_cmd(conn, FALSE, "STARTTLS", - imapc_connection_starttls_cb, conn); + cmd = imapc_connection_cmd(conn, imapc_connection_starttls_cb, + conn); + imapc_command_send(cmd, "STARTTLS"); return; } imapc_connection_authenticate(conn); @@ -746,6 +753,7 @@ static int imapc_connection_input_banner(struct imapc_connection *conn) { const struct imap_arg *imap_args; const char *key, *value; + struct imapc_command *cmd; int ret; if ((ret = imapc_connection_read_line(conn, &imap_args)) <= 0) @@ -758,8 +766,9 @@ static int imapc_connection_input_banner(struct imapc_connection *conn) if (conn->capabilities == 0) { /* capabilities weren't sent in the banner. ask for them. */ - imapc_connection_cmd(conn, FALSE, "CAPABILITY", - imapc_connection_capability_cb, conn); + cmd = imapc_connection_cmd(conn, imapc_connection_capability_cb, + conn); + imapc_command_send(cmd, "CAPABILITY"); } else { imapc_connection_starttls(conn); } @@ -864,6 +873,15 @@ static int imapc_connection_input_plus(struct imapc_connection *conn) return 1; } +static void +imapc_command_reply_free(struct imapc_command *cmd, + const struct imapc_command_reply *reply) +{ + if (cmd->callback != NULL) + cmd->callback(reply, cmd->context); + imapc_command_free(cmd); +} + static int imapc_connection_input_tagged(struct imapc_connection *conn) { struct imapc_command *const *cmds, *cmd = NULL; @@ -951,9 +969,7 @@ static int imapc_connection_input_tagged(struct imapc_connection *conn) } imapc_connection_input_reset(conn); - if (cmd->callback != NULL) - cmd->callback(&reply, cmd->context); - imapc_command_free(cmd); + imapc_command_reply_free(cmd, &reply); return 1; } @@ -1165,12 +1181,13 @@ imapc_reidle_callback(const struct imapc_command_reply *reply ATTR_UNUSED, static void imapc_connection_reset_idle(struct imapc_connection *conn) { + struct imapc_command *cmd; + if (!conn->idling) - imapc_connection_cmd(conn, FALSE, "NOOP", NULL, NULL); - else { - imapc_connection_cmd(conn, FALSE, "NOOP", - imapc_reidle_callback, conn); - } + cmd = imapc_connection_cmd(conn, NULL, NULL); + else + cmd = imapc_connection_cmd(conn, imapc_reidle_callback, conn); + imapc_command_send(cmd, "NOOP"); } static void imapc_connection_connect_next_ip(struct imapc_connection *conn) @@ -1407,6 +1424,7 @@ static int imapc_command_try_send_stream(struct imapc_connection *conn, static void imapc_command_send_more(struct imapc_connection *conn, struct imapc_command *cmd) { + struct imapc_command_reply reply; const unsigned char *p, *data; unsigned int seek_pos, start_pos, end_pos, size; int ret; @@ -1414,6 +1432,15 @@ static void imapc_command_send_more(struct imapc_connection *conn, i_assert(!cmd->wait_for_literal); i_assert(cmd->send_pos < cmd->data->used); + if (cmd->box != NULL && !imapc_client_mailbox_is_connected(cmd->box)) { + /* shouldn't normally happen */ + memset(&reply, 0, sizeof(reply)); + reply.text_without_resp = reply.text_full = "Mailbox not open"; + reply.state = IMAPC_COMMAND_STATE_BAD; + imapc_command_reply_free(cmd, &reply); + return; + } + timeout_reset(conn->to_output); if ((ret = imapc_command_try_send_stream(conn, cmd)) == 0) return; @@ -1475,9 +1502,10 @@ static void imapc_connection_send_idle_done(struct imapc_connection *conn) } } -static void imapc_command_send(struct imapc_connection *conn, - struct imapc_command *cmd) +static void imapc_connection_cmd_send(struct imapc_command *cmd) { + struct imapc_connection *conn = cmd->conn; + imapc_connection_send_idle_done(conn); switch (conn->state) { case IMAPC_CONNECTION_STATE_AUTHENTICATING: @@ -1530,51 +1558,47 @@ static int imapc_connection_output(struct imapc_connection *conn) return ret; } -static struct imapc_command * -imapc_connection_cmd_build(const char *cmdline, - imapc_command_callback_t *callback, void *context) +struct imapc_command * +imapc_connection_cmd(struct imapc_connection *conn, + imapc_command_callback_t *callback, void *context) { struct imapc_command *cmd; - unsigned int len = strlen(cmdline); cmd = imapc_command_begin(callback, context); - cmd->data = str_new(cmd->pool, 6 + len + 2); - str_printfa(cmd->data, "%u %s\r\n", cmd->tag, cmdline); + cmd->conn = conn; return cmd; } -void imapc_connection_cmd(struct imapc_connection *conn, bool mailboxcmd, - const char *cmdline, - imapc_command_callback_t *callback, void *context) +void imapc_command_set_mailbox(struct imapc_command *cmd, + struct imapc_client_mailbox *box) { - struct imapc_command *cmd; + cmd->box = box; + box->pending_box_command_count++; +} + +void imapc_command_send(struct imapc_command *cmd, const char *cmd_str) +{ + unsigned int len = strlen(cmd_str); - cmd = imapc_connection_cmd_build(cmdline, callback, context); - cmd->mailboxcmd = mailboxcmd; - imapc_command_send(conn, cmd); + cmd->data = str_new(cmd->pool, 6 + len + 2); + str_printfa(cmd->data, "%u %s\r\n", cmd->tag, cmd_str); + imapc_connection_cmd_send(cmd); } -void imapc_connection_cmdf(struct imapc_connection *conn, bool mailboxcmd, - imapc_command_callback_t *callback, void *context, - const char *cmd_fmt, ...) +void imapc_command_sendf(struct imapc_command *cmd, const char *cmd_fmt, ...) { va_list args; va_start(args, cmd_fmt); - imapc_connection_cmdvf(conn, mailboxcmd, callback, context, - cmd_fmt, args); + imapc_command_sendvf(cmd, cmd_fmt, args); va_end(args); } -void imapc_connection_cmdvf(struct imapc_connection *conn, bool mailboxcmd, - imapc_command_callback_t *callback, void *context, - const char *cmd_fmt, va_list args) +void imapc_command_sendvf(struct imapc_command *cmd, + const char *cmd_fmt, va_list args) { - struct imapc_command *cmd; unsigned int i; - cmd = imapc_command_begin(callback, context); - cmd->mailboxcmd = mailboxcmd; cmd->data = str_new(cmd->pool, 128); str_printfa(cmd->data, "%u ", cmd->tag); @@ -1615,7 +1639,7 @@ void imapc_connection_cmdvf(struct imapc_connection *conn, bool mailboxcmd, if (!need_literal(arg)) imap_dquote_append(cmd->data, arg); - else if ((conn->capabilities & + else if ((cmd->conn->capabilities & IMAPC_CAPABILITY_LITERALPLUS) != 0) { str_printfa(cmd->data, "{%"PRIuSIZE_T"+}\r\n%s", strlen(arg), arg); @@ -1637,7 +1661,7 @@ void imapc_connection_cmdvf(struct imapc_connection *conn, bool mailboxcmd, } str_append(cmd->data, "\r\n"); - imapc_command_send(conn, cmd); + imapc_connection_cmd_send(cmd); } enum imapc_connection_state @@ -1657,6 +1681,7 @@ void imapc_connection_select(struct imapc_client_mailbox *box, imapc_command_callback_t *callback, void *context) { struct imapc_connection *conn = box->conn; + struct imapc_command *cmd; i_assert(conn->selecting_box == NULL); @@ -1671,8 +1696,8 @@ void imapc_connection_select(struct imapc_client_mailbox *box, conn->selected_box = box; } - imapc_connection_cmdf(conn, FALSE, callback, context, - examine ? "EXAMINE %s" : "SELECT %s", name); + cmd = imapc_connection_cmd(conn, callback, context); + imapc_command_sendf(cmd, examine ? "EXAMINE %s" : "SELECT %s", name); } void imapc_connection_unselect(struct imapc_client_mailbox *box) @@ -1692,7 +1717,7 @@ void imapc_connection_unselect(struct imapc_client_mailbox *box) imapc_connection_send_idle_done(conn); array_foreach(&conn->cmd_wait_list, cmdp) { - if ((*cmdp)->callback != NULL && (*cmdp)->mailboxcmd) { + if ((*cmdp)->callback != NULL && (*cmdp)->box != NULL) { (*cmdp)->callback(&reply, (*cmdp)->context); (*cmdp)->callback = NULL; } @@ -1700,7 +1725,7 @@ void imapc_connection_unselect(struct imapc_client_mailbox *box) for (i = 0; i < array_count(&conn->cmd_send_queue); ) { cmdp = array_idx(&conn->cmd_send_queue, i); cmd = *cmdp; - if (!cmd->mailboxcmd) + if (cmd->box == NULL) i++; else { array_delete(&conn->cmd_send_queue, i, 1); @@ -1750,8 +1775,7 @@ void imapc_connection_idle(struct imapc_connection *conn) (conn->capabilities & IMAPC_CAPABILITY_IDLE) == 0) return; - cmd = imapc_connection_cmd_build("IDLE", imapc_connection_idle_callback, - conn); + cmd = imapc_connection_cmd(conn, imapc_connection_idle_callback, conn); cmd->idle = TRUE; - imapc_command_send(conn, cmd); + imapc_command_send(cmd, "IDLE"); } diff --git a/src/lib-imap-client/imapc-connection.h b/src/lib-imap-client/imapc-connection.h index 7dcb7f1db3..3f550e9771 100644 --- a/src/lib-imap-client/imapc-connection.h +++ b/src/lib-imap-client/imapc-connection.h @@ -28,16 +28,10 @@ void imapc_connection_disconnect(struct imapc_connection *conn); void imapc_connection_ioloop_changed(struct imapc_connection *conn); void imapc_connection_input_pending(struct imapc_connection *conn); -void imapc_connection_cmd(struct imapc_connection *conn, bool mailboxcmd, - const char *cmdline, - imapc_command_callback_t *callback, void *context); -void imapc_connection_cmdf(struct imapc_connection *conn, bool mailboxcmd, - imapc_command_callback_t *callback, void *context, - const char *cmd_fmt, ...) ATTR_FORMAT(5, 6); -void imapc_connection_cmdvf(struct imapc_connection *conn, bool mailboxcmd, - imapc_command_callback_t *callback, void *context, - const char *cmd_fmt, va_list args) - ATTR_FORMAT(5, 0); +struct imapc_command * +imapc_connection_cmd(struct imapc_connection *conn, + imapc_command_callback_t *callback, void *context); + void imapc_connection_select(struct imapc_client_mailbox *box, const char *name, bool examine, imapc_command_callback_t *callback, void *context); diff --git a/src/lib-storage/index/imapc/imapc-list.c b/src/lib-storage/index/imapc/imapc-list.c index aa49ae5b70..9854d9f10c 100644 --- a/src/lib-storage/index/imapc/imapc-list.c +++ b/src/lib-storage/index/imapc/imapc-list.c @@ -278,8 +278,18 @@ imapc_list_join_refpattern(struct mailbox_list *list ATTR_UNUSED, return t_strconcat(ref, pattern, NULL); } +static struct imapc_command * +imapc_list_simple_context_init(struct imapc_simple_context *ctx, + struct imapc_mailbox_list *list) +{ + imapc_simple_context_init(ctx, list->storage); + return imapc_client_cmd(list->storage->client, + imapc_list_simple_callback, ctx); +} + static int imapc_list_refresh(struct imapc_mailbox_list *list) { + struct imapc_command *cmd; struct imapc_simple_context ctx; i_assert(list->sep != '\0'); @@ -287,9 +297,8 @@ static int imapc_list_refresh(struct imapc_mailbox_list *list) if (list->refreshed_mailboxes) return 0; - imapc_simple_context_init(&ctx, list->storage); - imapc_client_cmdf(list->storage->client, - imapc_list_simple_callback, &ctx, "LIST \"\" *"); + cmd = imapc_list_simple_context_init(&ctx, list); + imapc_command_send(cmd, "LIST \"\" *"); mailbox_tree_deinit(&list->mailboxes); list->mailboxes = mailbox_tree_init(list->sep); @@ -434,6 +443,7 @@ imapc_list_subscriptions_refresh(struct mailbox_list *_src_list, struct imapc_mailbox_list *src_list = (struct imapc_mailbox_list *)_src_list; struct imapc_simple_context ctx; + struct imapc_command *cmd; char sep; i_assert(src_list->tmp_subscriptions == NULL); @@ -452,10 +462,8 @@ imapc_list_subscriptions_refresh(struct mailbox_list *_src_list, src_list->tmp_subscriptions = mailbox_tree_init(src_list->sep); - imapc_simple_context_init(&ctx, src_list->storage); - imapc_client_cmdf(src_list->storage->client, - imapc_list_simple_callback, &ctx, - "LSUB \"\" *"); + cmd = imapc_list_simple_context_init(&ctx, src_list); + imapc_command_send(cmd, "LSUB \"\" *"); imapc_simple_run(&ctx); /* replace subscriptions tree in destination */ @@ -474,12 +482,11 @@ static int imapc_list_set_subscribed(struct mailbox_list *_list, const char *name, bool set) { struct imapc_mailbox_list *list = (struct imapc_mailbox_list *)_list; + struct imapc_command *cmd; struct imapc_simple_context ctx; - imapc_simple_context_init(&ctx, list->storage); - imapc_client_cmdf(list->storage->client, - imapc_list_simple_callback, &ctx, - set ? "SUBSCRIBE %s" : "UNSUBSCRIBE %s", name); + cmd = imapc_list_simple_context_init(&ctx, list); + imapc_command_sendf(cmd, set ? "SUBSCRIBE %s" : "UNSUBSCRIBE %s", name); imapc_simple_run(&ctx); return ctx.ret; } @@ -498,11 +505,11 @@ static int imapc_list_delete_mailbox(struct mailbox_list *_list, const char *name) { struct imapc_mailbox_list *list = (struct imapc_mailbox_list *)_list; + struct imapc_command *cmd; struct imapc_simple_context ctx; - imapc_simple_context_init(&ctx, list->storage); - imapc_client_cmdf(list->storage->client, - imapc_list_simple_callback, &ctx, "DELETE %s", name); + cmd = imapc_list_simple_context_init(&ctx, list); + imapc_command_sendf(cmd, "DELETE %s", name); imapc_simple_run(&ctx); return ctx.ret; } @@ -535,6 +542,7 @@ imapc_list_rename_mailbox(struct mailbox_list *oldlist, const char *oldname, { struct imapc_mailbox_list *list = (struct imapc_mailbox_list *)oldlist; struct mailbox_list *fs_list = imapc_list_get_fs(list); + struct imapc_command *cmd; struct imapc_simple_context ctx; if (!rename_children) { @@ -549,10 +557,8 @@ imapc_list_rename_mailbox(struct mailbox_list *oldlist, const char *oldname, return -1; } - imapc_simple_context_init(&ctx, list->storage); - imapc_client_cmdf(list->storage->client, - imapc_list_simple_callback, &ctx, - "RENAME %s %s", oldname, newname); + cmd = imapc_list_simple_context_init(&ctx, list); + imapc_command_sendf(cmd, "RENAME %s %s", oldname, newname); imapc_simple_run(&ctx); if (ctx.ret == 0 && fs_list != NULL && oldlist == newlist) { oldname = imapc_list_get_fs_name(list, oldname); @@ -568,6 +574,7 @@ int imapc_list_get_mailbox_flags(struct mailbox_list *_list, const char *name, enum mailbox_info_flags *flags_r) { struct imapc_mailbox_list *list = (struct imapc_mailbox_list *)_list; + struct imapc_command *cmd; struct imapc_simple_context sctx; struct mailbox_node *node; const char *vname; @@ -580,9 +587,8 @@ int imapc_list_get_mailbox_flags(struct mailbox_list *_list, const char *name, node->flags |= MAILBOX_NONEXISTENT; /* refresh the mailbox flags */ - imapc_simple_context_init(&sctx, list->storage); - imapc_client_cmdf(list->storage->client, imapc_simple_callback, - &sctx, "LIST \"\" %s", name); + cmd = imapc_list_simple_context_init(&sctx, list); + imapc_command_sendf(cmd, "LIST \"\" %s", name); imapc_simple_run(&sctx); if (sctx.ret < 0) return -1; diff --git a/src/lib-storage/index/imapc/imapc-mail-fetch.c b/src/lib-storage/index/imapc/imapc-mail-fetch.c index a8ffea859b..acb374c532 100644 --- a/src/lib-storage/index/imapc/imapc-mail-fetch.c +++ b/src/lib-storage/index/imapc/imapc-mail-fetch.c @@ -56,6 +56,7 @@ imapc_mail_send_fetch(struct mail *_mail, enum mail_fetch_field fields) { struct imapc_mail *mail = (struct imapc_mail *)_mail; struct imapc_mailbox *mbox = (struct imapc_mailbox *)_mail->box; + struct imapc_command *cmd; struct mail_index_view *view; string_t *str; uint32_t seq; @@ -106,9 +107,9 @@ imapc_mail_send_fetch(struct mail *_mail, enum mail_fetch_field fields) if (mail->fetch_count++ == 0) array_append(&mbox->fetch_mails, &mail, 1); - imapc_client_mailbox_cmd(mbox->client_box, - imapc_mail_prefetch_callback, - mail, str_c(str)); + cmd = imapc_client_mailbox_cmd(mbox->client_box, + imapc_mail_prefetch_callback, mail); + imapc_command_send(cmd, str_c(str)); mail->imail.data.prefetch_sent = TRUE; return 0; } diff --git a/src/lib-storage/index/imapc/imapc-mail.c b/src/lib-storage/index/imapc/imapc-mail.c index 5feff137ba..c974ca1269 100644 --- a/src/lib-storage/index/imapc/imapc-mail.c +++ b/src/lib-storage/index/imapc/imapc-mail.c @@ -30,6 +30,7 @@ static bool imapc_mail_is_expunged(struct mail *_mail) { struct imapc_mailbox *mbox = (struct imapc_mailbox *)_mail->box; struct imapc_msgmap *msgmap; + struct imapc_command *cmd; struct imapc_simple_context sctx; uint32_t lseq, rseq; @@ -47,8 +48,9 @@ static bool imapc_mail_is_expunged(struct mail *_mail) /* we may be running against a server that hasn't bothered sending us an EXPUNGE. see if NOOP sends it. */ imapc_simple_context_init(&sctx, mbox->storage); - imapc_client_mailbox_cmd(mbox->client_box, - imapc_simple_callback, &sctx, "NOOP"); + cmd = imapc_client_mailbox_cmd(mbox->client_box, + imapc_simple_callback, &sctx); + imapc_command_send(cmd, "NOOP"); imapc_simple_run(&sctx); return !imapc_msgmap_uid_to_rseq(msgmap, _mail->uid, &rseq); diff --git a/src/lib-storage/index/imapc/imapc-save.c b/src/lib-storage/index/imapc/imapc-save.c index 8f34ff36cb..3933f47e32 100644 --- a/src/lib-storage/index/imapc/imapc-save.c +++ b/src/lib-storage/index/imapc/imapc-save.c @@ -200,6 +200,7 @@ imapc_append_keywords(string_t *str, struct mail_keywords *kw) static int imapc_save_append(struct imapc_save_context *ctx) { struct mail_save_context *_ctx = &ctx->ctx; + struct imapc_command *cmd; struct imapc_save_cmd_context sctx; struct istream *input; const char *flags = "", *internaldate = ""; @@ -222,9 +223,10 @@ static int imapc_save_append(struct imapc_save_context *ctx) input = i_stream_create_fd(ctx->fd, IO_BLOCK_SIZE, FALSE); sctx.ctx = ctx; sctx.ret = -2; - imapc_client_cmdf(ctx->mbox->storage->client, - imapc_save_callback, &sctx, "APPEND %s%1s%1s %p", - ctx->mbox->box.name, flags, internaldate, input); + cmd = imapc_client_cmd(ctx->mbox->storage->client, + imapc_save_callback, &sctx); + imapc_command_sendf(cmd, "APPEND %s%1s%1s %p", + ctx->mbox->box.name, flags, internaldate, input); i_stream_unref(&input); while (sctx.ret == -2) imapc_storage_run(ctx->mbox->storage); @@ -373,6 +375,7 @@ int imapc_copy(struct mail_save_context *_ctx, struct mail *mail) struct imapc_save_context *ctx = (struct imapc_save_context *)_ctx; struct mailbox_transaction_context *_t = _ctx->transaction; struct imapc_mailbox *src_mbox = (struct imapc_mailbox *)mail->box; + struct imapc_command *cmd; struct imapc_save_cmd_context sctx; i_assert((_t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0); @@ -381,10 +384,10 @@ int imapc_copy(struct mail_save_context *_ctx, struct mail *mail) /* same server, we can use COPY for the mail */ sctx.ret = -2; sctx.ctx = ctx; - imapc_client_mailbox_cmdf(src_mbox->client_box, - imapc_copy_callback, &sctx, - "UID COPY %u %s", - mail->uid, _t->box->name); + cmd = imapc_client_mailbox_cmd(src_mbox->client_box, + imapc_copy_callback, &sctx); + imapc_command_sendf(cmd, "UID COPY %u %s", + mail->uid, _t->box->name); while (sctx.ret == -2) imapc_storage_run(src_mbox->storage); ctx->finished = TRUE; diff --git a/src/lib-storage/index/imapc/imapc-storage.c b/src/lib-storage/index/imapc/imapc-storage.c index 54b807f593..f0ef3222d3 100644 --- a/src/lib-storage/index/imapc/imapc-storage.c +++ b/src/lib-storage/index/imapc/imapc-storage.c @@ -209,11 +209,12 @@ static int imapc_storage_get_hierarchy_sep(struct imapc_storage *storage, const char **error_r) { + struct imapc_command *cmd; struct imapc_simple_context sctx; imapc_simple_context_init(&sctx, storage); - imapc_client_cmdf(storage->client, imapc_simple_callback, &sctx, - "LIST \"\" \"\""); + cmd = imapc_client_cmd(storage->client, imapc_simple_callback, &sctx); + imapc_command_send(cmd, "LIST \"\" \"\""); imapc_simple_run(&sctx); if (sctx.ret < 0) { @@ -474,6 +475,7 @@ imapc_mailbox_create(struct mailbox *box, bool directory) { struct imapc_mailbox *mbox = (struct imapc_mailbox *)box; + struct imapc_command *cmd; struct imapc_simple_context sctx; const char *name = box->name; @@ -482,8 +484,9 @@ imapc_mailbox_create(struct mailbox *box, mailbox_list_get_hierarchy_sep(box->list)); } imapc_simple_context_init(&sctx, mbox->storage); - imapc_client_cmdf(mbox->storage->client, imapc_simple_callback, &sctx, - "CREATE %s", name); + cmd = imapc_client_cmd(mbox->storage->client, + imapc_simple_callback, &sctx); + imapc_command_sendf(cmd, "CREATE %s", name); imapc_simple_run(&sctx); return sctx.ret; } @@ -551,6 +554,7 @@ static int imapc_mailbox_get_status(struct mailbox *box, struct mailbox_status *status_r) { struct imapc_mailbox *mbox = (struct imapc_mailbox *)box; + struct imapc_command *cmd; struct imapc_simple_context sctx; string_t *str; @@ -593,8 +597,9 @@ static int imapc_mailbox_get_status(struct mailbox *box, imapc_simple_context_init(&sctx, mbox->storage); mbox->storage->cur_status_box = mbox; mbox->storage->cur_status = status_r; - imapc_client_cmdf(mbox->storage->client, imapc_simple_callback, &sctx, - "STATUS %s (%1s)", box->name, str_c(str)+1); + cmd = imapc_client_cmd(mbox->storage->client, + imapc_simple_callback, &sctx); + imapc_command_sendf(cmd, "STATUS %s (%1s)", box->name, str_c(str)+1); imapc_simple_run(&sctx); mbox->storage->cur_status_box = NULL; mbox->storage->cur_status = NULL; @@ -617,8 +622,11 @@ static int imapc_mailbox_get_metadata(struct mailbox *box, static void imapc_idle_timeout(struct imapc_mailbox *mbox) { - imapc_client_mailbox_cmd(mbox->client_box, - imapc_noop_callback, mbox->storage, "NOOP"); + struct imapc_command *cmd; + + cmd = imapc_client_mailbox_cmd(mbox->client_box, + imapc_noop_callback, mbox->storage); + imapc_command_send(cmd, "NOOP"); } static void imapc_idle_noop_callback(const struct imapc_command_reply *reply, @@ -634,6 +642,7 @@ static void imapc_idle_noop_callback(const struct imapc_command_reply *reply, static void imapc_notify_changes(struct mailbox *box) { struct imapc_mailbox *mbox = (struct imapc_mailbox *)box; + struct imapc_command *cmd; enum imapc_capability capa; if (box->notify_min_interval == 0) { @@ -648,9 +657,9 @@ static void imapc_notify_changes(struct mailbox *box) don't notice changes immediately, we'll force them to check here by sending a NOOP. this helps with clients that break IDLE when clicking "get mail". */ - imapc_client_mailbox_cmd(mbox->client_box, - imapc_idle_noop_callback, mbox, - "NOOP"); + cmd = imapc_client_mailbox_cmd(mbox->client_box, + imapc_idle_noop_callback, mbox); + imapc_command_send(cmd, "NOOP"); } else { /* remote server doesn't support IDLE. check for changes with NOOP every once in a while. */ diff --git a/src/lib-storage/index/imapc/imapc-sync.c b/src/lib-storage/index/imapc/imapc-sync.c index 3885bbc412..9a3bd2d9a4 100644 --- a/src/lib-storage/index/imapc/imapc-sync.c +++ b/src/lib-storage/index/imapc/imapc-sync.c @@ -36,11 +36,14 @@ static void imapc_sync_callback(const struct imapc_command_reply *reply, imapc_client_stop(ctx->mbox->storage->client); } -static void imapc_sync_cmd(struct imapc_sync_context *ctx, const char *cmd) +static void imapc_sync_cmd(struct imapc_sync_context *ctx, const char *cmd_str) { + struct imapc_command *cmd; + ctx->sync_command_count++; - imapc_client_mailbox_cmd(ctx->mbox->client_box, - imapc_sync_callback, ctx, cmd); + cmd = imapc_client_mailbox_cmd(ctx->mbox->client_box, + imapc_sync_callback, ctx); + imapc_command_send(cmd, cmd_str); } static void @@ -387,6 +390,7 @@ struct mailbox_sync_context * imapc_mailbox_sync_init(struct mailbox *box, enum mailbox_sync_flags flags) { struct imapc_mailbox *mbox = (struct imapc_mailbox *)box; + struct imapc_command *cmd; enum imapc_capability capabilities; bool changes; int ret = 0; @@ -400,9 +404,10 @@ imapc_mailbox_sync_init(struct mailbox *box, enum mailbox_sync_flags flags) if ((capabilities & IMAPC_CAPABILITY_IDLE) == 0) { /* IDLE not supported. do NOOP to get latest changes before starting sync. */ - imapc_client_mailbox_cmd(mbox->client_box, - imapc_noop_stop_callback, - mbox->storage, "NOOP"); + cmd = imapc_client_mailbox_cmd(mbox->client_box, + imapc_noop_stop_callback, + mbox->storage); + imapc_command_send(cmd, "NOOP"); imapc_storage_run(mbox->storage); } -- 2.47.3