imapc-connection.c \
imapc-list.c \
imapc-mail.c \
+ imapc-mailbox.c \
imapc-save.c \
imapc-search.c \
imapc-seqmap.c \
struct imapc_command_reply {
enum imapc_command_state state;
- /* "RESP TEXT" when the reply contains [RESP TEXT], otherwise NULL */
- const char *resp_text;
+ /* "[RESP TEXT]" produces key=RESP, value=TEXT.
+ "[RESP]" produces key=RESP, value=NULL
+ otherwise both are NULL */
+ const char *resp_text_key, *resp_text_value;
/* The full tagged reply, including [RESP TEXT]. */
- const char *text;
+ const char *text_full;
+ /* Tagged reply text without [RESP TEXT] */
+ const char *text_without_resp;
};
struct imapc_untagged_reply {
/* the rest of the reply can be read from these args. */
const struct imap_arg *args;
- /* "RESP TEXT" when the reply is "* OK [RESP TEXT]", otherwise NULL */
- const char *resp_text;
+ /* "* OK [RESP TEXT]" produces key=RESP, value=TEXT.
+ "* OK [RESP]" produces key=RESP, value=NULL
+ otherwise both are NULL */
+ const char *resp_text_key, *resp_text_value;
/* If this reply occurred while a mailbox was selected, this contains
the mailbox's untagged_context. */
memset(&reply, 0, sizeof(reply));
reply.state = IMAPC_COMMAND_STATE_DISCONNECTED;
- reply.text = "Disconnected from server";
+ reply.text_without_resp = reply.text_full =
+ "Disconnected from server";
while (array_count(&conn->cmd_wait_list) > 0) {
cmdp = array_idx(&conn->cmd_wait_list, 0);
static int
imapc_connection_handle_resp_text_code(struct imapc_connection *conn,
- const char *text)
+ const char *key, const char *value)
{
- const char *key, *value;
-
- value = strchr(text, ' ');
- if (value != NULL)
- key = t_strdup_until(text, value++);
- else {
- key = text;
- value = "";
- }
if (strcasecmp(key, "CAPABILITY") == 0) {
if (imapc_connection_parse_capability(conn, value) < 0)
return -1;
static int
imapc_connection_handle_resp_text(struct imapc_connection *conn,
- const struct imap_arg *args,
- const char **text_r)
+ const char *text,
+ const char **key_r, const char **value_r)
+{
+ const char *p, *value;
+
+ i_assert(text[0] == '[');
+
+ p = strchr(text, ']');
+ if (p == NULL) {
+ imapc_connection_input_error(conn, "Missing ']' in resp-text");
+ return -1;
+ }
+ text = t_strdup_until(text + 1, p);
+ value = strchr(text, ' ');
+ if (value != NULL) {
+ *key_r = t_strdup_until(text, value);
+ *value_r = value + 1;
+ } else {
+ *key_r = text;
+ *value_r = NULL;
+ }
+ return 0;
+}
+
+static int
+imapc_connection_handle_imap_resp_text(struct imapc_connection *conn,
+ const struct imap_arg *args,
+ const char **key_r, const char **value_r)
{
- const char *text, *p;
+ const char *text;
if (args->type != IMAP_ARG_ATOM)
return 0;
}
return 0;
}
- p = strchr(text, ']');
- if (p == NULL) {
- imapc_connection_input_error(conn, "Missing ']' in resp-text");
- return -1;
- }
- if (p[1] == '\0' || p[1] != ' ' || p[2] == '\0') {
- imapc_connection_input_error(conn, "Missing text in resp-text");
+ if (imapc_connection_handle_resp_text(conn, text, key_r, value_r) < 0)
return -1;
- }
- *text_r = text = t_strdup_until(text + 1, p);
- return imapc_connection_handle_resp_text_code(conn, text);
+
+ return imapc_connection_handle_resp_text_code(conn, *key_r, *value_r);
}
static bool need_literal(const char *str)
if (reply->state != IMAPC_COMMAND_STATE_OK) {
imapc_connection_input_error(conn,
- "Failed to get capabilities: %s", reply->text);
+ "Failed to get capabilities: %s", reply->text_full);
} else if (conn->capabilities == 0) {
imapc_connection_input_error(conn,
"Capabilities not returned by server");
if (reply->state != IMAPC_COMMAND_STATE_OK) {
imapc_connection_input_error(conn, "Authentication failed: %s",
- reply->text);
+ reply->text_full);
return;
}
{
const struct imapc_client_settings *set = &conn->client->set;
const struct imap_arg *imap_args;
- const char *cmd, *text;
+ const char *cmd, *key, *value;
int ret;
if ((ret = imapc_connection_read_line(conn, &imap_args)) <= 0)
return ret;
- if (imapc_connection_handle_resp_text(conn, imap_args, &text) < 0)
+ if (imapc_connection_handle_imap_resp_text(conn, imap_args,
+ &key, &value) < 0)
return -1;
imapc_connection_set_state(conn, IMAPC_CONNECTION_STATE_AUTHENTICATING);
memset(&reply, 0, sizeof(reply));
if (strcasecmp(name, "OK") == 0) {
- if (imapc_connection_handle_resp_text(conn, imap_args,
- &reply.resp_text) < 0)
+ if (imapc_connection_handle_imap_resp_text(conn, imap_args,
+ &reply.resp_text_key,
+ &reply.resp_text_value) < 0)
return -1;
}
linep = strchr(line, ' ');
if (linep == NULL)
- reply.text = "";
+ reply.text_full = "";
else {
*linep = '\0';
- reply.text = linep + 1;
+ reply.text_full = linep + 1;
}
if (strcasecmp(line, "ok") == 0)
return -1;
}
- if (reply.text[0] == '[') {
+ if (reply.text_full[0] == '[') {
/* get resp-text */
- p = strchr(reply.text, ']');
- if (p == NULL) {
- imapc_connection_input_error(conn,
- "Missing ']' from resp-text: %u %s",
- conn->cur_tag, line);
- return -1;
- }
- reply.resp_text = t_strndup(reply.text + 1, p - reply.text - 1);
- if (imapc_connection_handle_resp_text_code(conn,
- reply.resp_text) < 0)
+ if (imapc_connection_handle_resp_text(conn, reply.text_full,
+ &reply.resp_text_key,
+ &reply.resp_text_value) < 0)
return -1;
+
+ p = strchr(reply.text_full, ']');
+ i_assert(p != NULL);
+ reply.text_without_resp = p + 1;
+ if (reply.text_without_resp[0] == ' ')
+ reply.text_without_resp++;
+ } else {
+ reply.text_without_resp = reply.text_full;
}
/* find the command. it's either the first command in send queue
return node;
}
-void imapc_list_update_mailbox(struct imapc_mailbox_list *list,
- const struct imap_arg *args)
+static void imapc_untagged_list(const struct imapc_untagged_reply *reply,
+ struct imapc_storage *storage)
{
+ struct imapc_mailbox_list *list = storage->list;
+ const struct imap_arg *args = reply->args;
const char *sep, *name;
if (list->sep == '\0') {
(void)imapc_list_update_tree(list->mailboxes, args);
}
-void imapc_list_update_subscription(struct imapc_mailbox_list *list,
- const struct imap_arg *args)
+static void imapc_untagged_lsub(const struct imapc_untagged_reply *reply,
+ struct imapc_storage *storage)
{
+ struct imapc_mailbox_list *list = storage->list;
+ const struct imap_arg *args = reply->args;
struct mailbox_node *node;
if (list->sep == '\0') {
node->flags |= MAILBOX_SUBSCRIBED;
}
+void imapc_list_register_callbacks(struct imapc_mailbox_list *list)
+{
+ imapc_storage_register_untagged(list->storage, "LIST",
+ imapc_untagged_list);
+ imapc_storage_register_untagged(list->storage, "LSUB",
+ imapc_untagged_lsub);
+}
+
static int imapc_list_refresh(struct imapc_mailbox_list *list,
enum mailbox_list_iter_flags flags)
{
}
static int
-imapc_list_create_mailbox_dir(struct mailbox_list *list, const char *name,
- enum mailbox_dir_create_type type)
+imapc_list_create_mailbox_dir(struct mailbox_list *list ATTR_UNUSED,
+ const char *name ATTR_UNUSED,
+ enum mailbox_dir_create_type type ATTR_UNUSED)
{
- return -1;
+ /* this gets called just before mailbox.create().
+ we don't need to do anything. */
+ return 0;
}
static int
unsigned int broken:1;
};
-void imapc_list_update_mailbox(struct imapc_mailbox_list *list,
- const struct imap_arg *args);
-void imapc_list_update_subscription(struct imapc_mailbox_list *list,
- const struct imap_arg *args);
+void imapc_list_register_callbacks(struct imapc_mailbox_list *list);
#endif
--- /dev/null
+/* Copyright (c) 2011 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "imap-arg.h"
+#include "imap-util.h"
+#include "imapc-client.h"
+#include "imapc-seqmap.h"
+#include "imapc-storage.h"
+
+static void imapc_untagged_exists(const struct imapc_untagged_reply *reply,
+ struct imapc_mailbox *mbox)
+{
+ uint32_t rcount = reply->num;
+ const struct mail_index_header *hdr;
+ struct imapc_seqmap *seqmap;
+ uint32_t next_lseq, next_rseq;
+
+ if (mbox == NULL)
+ return;
+
+ seqmap = imapc_client_mailbox_get_seqmap(mbox->client_box);
+ next_lseq = mail_index_view_get_messages_count(mbox->box.view) + 1;
+ next_rseq = imapc_seqmap_lseq_to_rseq(seqmap, next_lseq);
+ if (next_rseq > rcount)
+ return;
+
+ hdr = mail_index_get_header(mbox->box.view);
+
+ mbox->new_msgs = TRUE;
+ imapc_client_mailbox_cmdf(mbox->client_box, imapc_async_stop_callback,
+ mbox->storage, "UID FETCH %u:* FLAGS",
+ hdr->next_uid);
+}
+
+
+static void imapc_untagged_fetch(const struct imapc_untagged_reply *reply,
+ struct imapc_mailbox *mbox)
+{
+ uint32_t seq = reply->num;
+ struct imapc_seqmap *seqmap;
+ const struct imap_arg *list, *flags_list;
+ const char *atom;
+ const struct mail_index_record *rec;
+ enum mail_flags flags;
+ uint32_t uid, old_count;
+ unsigned int i, j;
+ bool seen_flags = FALSE;
+
+ if (mbox == NULL || seq == 0 || !imap_arg_get_list(reply->args, &list))
+ return;
+
+ uid = 0; flags = 0;
+ for (i = 0; list[i].type != IMAP_ARG_EOL; i += 2) {
+ if (!imap_arg_get_atom(&list[i], &atom))
+ return;
+
+ if (strcasecmp(atom, "UID") == 0) {
+ if (!imap_arg_get_atom(&list[i+1], &atom) ||
+ str_to_uint32(atom, &uid) < 0)
+ return;
+ } else if (strcasecmp(atom, "FLAGS") == 0) {
+ if (!imap_arg_get_list(&list[i+1], &flags_list))
+ return;
+
+ seen_flags = TRUE;
+ for (j = 0; flags_list[j].type != IMAP_ARG_EOL; j++) {
+ if (!imap_arg_get_atom(&flags_list[j], &atom))
+ return;
+ if (atom[0] == '\\')
+ flags |= imap_parse_system_flag(atom);
+ }
+ }
+ }
+
+ seqmap = imapc_client_mailbox_get_seqmap(mbox->client_box);
+ seq = imapc_seqmap_rseq_to_lseq(seqmap, seq);
+
+ if (mbox->cur_fetch_mail != NULL && mbox->cur_fetch_mail->seq == seq) {
+ i_assert(uid == 0 || mbox->cur_fetch_mail->uid == uid);
+ imapc_fetch_mail_update(mbox->cur_fetch_mail, list);
+ }
+
+ old_count = mail_index_view_get_messages_count(mbox->delayed_sync_view);
+ if (seq > old_count) {
+ if (uid == 0)
+ return;
+ i_assert(seq == old_count + 1);
+ mail_index_append(mbox->delayed_sync_trans, uid, &seq);
+ }
+ rec = mail_index_lookup(mbox->delayed_sync_view, seq);
+ if (seen_flags && rec->flags != flags) {
+ mail_index_update_flags(mbox->delayed_sync_trans, seq,
+ MODIFY_REPLACE, flags);
+ }
+}
+
+static void imapc_untagged_expunge(const struct imapc_untagged_reply *reply,
+ struct imapc_mailbox *mbox)
+{
+ struct imapc_seqmap *seqmap;
+ uint32_t lseq, rseq = reply->num;
+
+ if (mbox == NULL || rseq == 0)
+ return;
+
+ seqmap = imapc_client_mailbox_get_seqmap(mbox->client_box);
+ lseq = imapc_seqmap_rseq_to_lseq(seqmap, rseq);
+ mail_index_expunge(mbox->delayed_sync_trans, lseq);
+}
+
+static void
+imapc_resp_text_uidvalidity(const struct imapc_untagged_reply *reply,
+ struct imapc_mailbox *mbox)
+{
+ uint32_t uid_validity;
+
+ if (mbox == NULL || reply->resp_text_value == NULL ||
+ str_to_uint32(reply->resp_text_value, &uid_validity) < 0)
+ return;
+
+ mail_index_update_header(mbox->delayed_sync_trans,
+ offsetof(struct mail_index_header, uid_validity),
+ &uid_validity, sizeof(uid_validity), TRUE);
+}
+
+static void
+imapc_resp_text_uidnext(const struct imapc_untagged_reply *reply,
+ struct imapc_mailbox *mbox)
+{
+ uint32_t uid_next;
+
+ if (mbox == NULL || reply->resp_text_value == NULL ||
+ str_to_uint32(reply->resp_text_value, &uid_next) < 0)
+ return;
+
+ mail_index_update_header(mbox->delayed_sync_trans,
+ offsetof(struct mail_index_header, next_uid),
+ &uid_next, sizeof(uid_next), FALSE);
+}
+
+
+void imapc_mailbox_register_untagged(struct imapc_mailbox *mbox,
+ const char *key,
+ imapc_mailbox_callback_t *callback)
+{
+ struct imapc_mailbox_event_callback *cb;
+
+ cb = array_append_space(&mbox->untagged_callbacks);
+ cb->name = p_strdup(mbox->box.pool, key);
+ cb->callback = callback;
+}
+
+void imapc_mailbox_register_resp_text(struct imapc_mailbox *mbox,
+ const char *key,
+ imapc_mailbox_callback_t *callback)
+{
+ struct imapc_mailbox_event_callback *cb;
+
+ cb = array_append_space(&mbox->resp_text_callbacks);
+ cb->name = p_strdup(mbox->box.pool, key);
+ cb->callback = callback;
+}
+
+void imapc_mailbox_register_callbacks(struct imapc_mailbox *mbox)
+{
+ imapc_mailbox_register_untagged(mbox, "EXISTS",
+ imapc_untagged_exists);
+ imapc_mailbox_register_untagged(mbox, "FETCH",
+ imapc_untagged_fetch);
+ imapc_mailbox_register_untagged(mbox, "EXPUNGE",
+ imapc_untagged_expunge);
+ imapc_mailbox_register_resp_text(mbox, "UIDVALIDITY",
+ imapc_resp_text_uidvalidity);
+ imapc_mailbox_register_resp_text(mbox, "UIDNEXT",
+ imapc_resp_text_uidnext);
+}
#include "lib.h"
#include "str.h"
-#include "imap-util.h"
-#include "imap-arg.h"
#include "imap-resp-code.h"
#include "mail-copy.h"
#include "index-mail.h"
-#include "mailbox-list-private.h"
#include "imapc-client.h"
#include "imapc-list.h"
-#include "imapc-seqmap.h"
#include "imapc-sync.h"
#include "imapc-storage.h"
-#include <sys/stat.h>
-
#define DNS_CLIENT_SOCKET_NAME "dns-client"
struct imapc_open_context {
const struct imapc_command_reply *reply)
{
enum mail_error error;
- const char *p;
- if (imap_resp_text_code_parse(reply->resp_text, &error)) {
- p = strchr(reply->text, ']');
- i_assert(p != NULL);
- mail_storage_set_error(&storage->storage, error, p + 1);
+ if (imap_resp_text_code_parse(reply->resp_text_key, &error)) {
+ mail_storage_set_error(&storage->storage, error,
+ reply->text_without_resp);
} else {
mail_storage_set_error(&storage->storage, default_error,
- reply->text);
+ reply->text_without_resp);
}
}
ctx->ret = -1;
} else {
mail_storage_set_critical(&ctx->storage->storage,
- "imapc: Command failed: %s", reply->text);
+ "imapc: Command failed: %s", reply->text_full);
ctx->ret = -1;
}
imapc_client_stop(ctx->storage->client);
imapc_copy_error_from_reply(storage, MAIL_ERROR_PARAMS, reply);
} else {
mail_storage_set_critical(&storage->storage,
- "imapc: Command failed: %s", reply->text);
+ "imapc: Command failed: %s", reply->text_full);
}
imapc_client_stop(storage->client);
}
-static void
-imapc_mailbox_map_new_msgs(struct imapc_mailbox *mbox,
- struct imapc_seqmap *seqmap, uint32_t rcount)
-{
- const struct mail_index_header *hdr;
- uint32_t next_lseq, next_rseq;
-
- next_lseq = mail_index_view_get_messages_count(mbox->box.view) + 1;
- next_rseq = imapc_seqmap_lseq_to_rseq(seqmap, next_lseq);
- if (next_rseq > rcount)
- return;
-
- hdr = mail_index_get_header(mbox->box.view);
-
- mbox->new_msgs = TRUE;
- imapc_client_mailbox_cmdf(mbox->client_box, imapc_async_stop_callback,
- mbox->storage, "UID FETCH %u:* FLAGS",
- hdr->next_uid);
-}
-
-static void
-imapc_mailbox_map_fetch_reply(struct imapc_mailbox *mbox,
- const struct imap_arg *args, uint32_t seq)
-{
- struct imapc_seqmap *seqmap;
- const struct imap_arg *list, *flags_list;
- const char *atom;
- const struct mail_index_record *rec;
- enum mail_flags flags;
- uint32_t uid, old_count;
- unsigned int i, j;
- bool seen_flags = FALSE;
-
- if (seq == 0 || !imap_arg_get_list(args, &list))
- return;
-
- uid = 0; flags = 0;
- for (i = 0; list[i].type != IMAP_ARG_EOL; i += 2) {
- if (!imap_arg_get_atom(&list[i], &atom))
- return;
-
- if (strcasecmp(atom, "UID") == 0) {
- if (!imap_arg_get_atom(&list[i+1], &atom) ||
- str_to_uint32(atom, &uid) < 0)
- return;
- } else if (strcasecmp(atom, "FLAGS") == 0) {
- if (!imap_arg_get_list(&list[i+1], &flags_list))
- return;
-
- seen_flags = TRUE;
- for (j = 0; flags_list[j].type != IMAP_ARG_EOL; j++) {
- if (!imap_arg_get_atom(&flags_list[j], &atom))
- return;
- if (atom[0] == '\\')
- flags |= imap_parse_system_flag(atom);
- }
- }
- }
-
- seqmap = imapc_client_mailbox_get_seqmap(mbox->client_box);
- seq = imapc_seqmap_rseq_to_lseq(seqmap, seq);
-
- if (mbox->cur_fetch_mail != NULL && mbox->cur_fetch_mail->seq == seq) {
- i_assert(uid == 0 || mbox->cur_fetch_mail->uid == uid);
- imapc_fetch_mail_update(mbox->cur_fetch_mail, list);
- }
-
- old_count = mail_index_view_get_messages_count(mbox->delayed_sync_view);
- if (seq > old_count) {
- if (uid == 0)
- return;
- i_assert(seq == old_count + 1);
- mail_index_append(mbox->delayed_sync_trans, uid, &seq);
- }
- rec = mail_index_lookup(mbox->delayed_sync_view, seq);
- if (seen_flags && rec->flags != flags) {
- mail_index_update_flags(mbox->delayed_sync_trans, seq,
- MODIFY_REPLACE, flags);
- }
-}
-
static void imapc_storage_untagged_cb(const struct imapc_untagged_reply *reply,
void *context)
{
struct imapc_storage *storage = context;
struct imapc_mailbox *mbox = reply->untagged_box_context;
- struct imapc_seqmap *seqmap;
- uint32_t lseq;
+ const struct imapc_storage_event_callback *cb;
+ const struct imapc_mailbox_event_callback *mcb;
- if (strcasecmp(reply->name, "LIST") == 0)
- imapc_list_update_mailbox(storage->list, reply->args);
- else if (strcasecmp(reply->name, "LSUB") == 0)
- imapc_list_update_subscription(storage->list, reply->args);
+ array_foreach(&storage->untagged_callbacks, cb) {
+ if (strcasecmp(reply->name, cb->name) == 0)
+ cb->callback(reply, storage);
+ }
if (mbox == NULL)
return;
- if (reply->resp_text != NULL) {
- uint32_t uid_validity, uid_next;
-
- if (strncasecmp(reply->resp_text, "UIDVALIDITY ", 12) == 0 &&
- str_to_uint32(reply->resp_text + 12, &uid_validity) == 0) {
- mail_index_update_header(mbox->delayed_sync_trans,
- offsetof(struct mail_index_header, uid_validity),
- &uid_validity, sizeof(uid_validity), TRUE);
- }
- if (strncasecmp(reply->resp_text, "UIDNEXT ", 8) == 0 &&
- str_to_uint32(reply->resp_text + 8, &uid_next) == 0) {
- mail_index_update_header(mbox->delayed_sync_trans,
- offsetof(struct mail_index_header, next_uid),
- &uid_next, sizeof(uid_next), FALSE);
- }
+ array_foreach(&mbox->untagged_callbacks, mcb) {
+ if (strcasecmp(reply->name, mcb->name) == 0)
+ mcb->callback(reply, mbox);
}
- seqmap = imapc_client_mailbox_get_seqmap(mbox->client_box);
- if (strcasecmp(reply->name, "EXISTS") == 0) {
- imapc_mailbox_map_new_msgs(mbox, seqmap, reply->num);
- } else if (strcasecmp(reply->name, "FETCH") == 0) {
- imapc_mailbox_map_fetch_reply(mbox, reply->args, reply->num);
- } else if (strcasecmp(reply->name, "EXPUNGE") == 0) {
- lseq = imapc_seqmap_rseq_to_lseq(seqmap, reply->num);
- mail_index_expunge(mbox->delayed_sync_trans, lseq);
+ if (reply->resp_text_key != NULL) {
+ array_foreach(&mbox->resp_text_callbacks, mcb) {
+ if (strcasecmp(reply->resp_text_key, mcb->name) == 0)
+ mcb->callback(reply, mbox);
+ }
}
}
set.dns_client_socket_path =
t_strconcat(_storage->user->set->base_dir, "/",
DNS_CLIENT_SOCKET_NAME, NULL);
- storage->list = (struct imapc_list *)ns->list;
+ storage->list = (struct imapc_mailbox_list *)ns->list;
storage->list->storage = storage;
storage->client = imapc_client_init(&set);
+
+ p_array_init(&storage->untagged_callbacks, _storage->pool, 16);
imapc_client_register_untagged(storage->client,
imapc_storage_untagged_cb, storage);
+ imapc_list_register_callbacks(storage->list);
return 0;
}
imapc_client_deinit(&storage->client);
}
+void imapc_storage_register_untagged(struct imapc_storage *storage,
+ const char *name,
+ imapc_storage_callback_t *callback)
+{
+ struct imapc_storage_event_callback *cb;
+
+ cb = array_append_space(&storage->untagged_callbacks);
+ cb->name = p_strdup(storage->storage.pool, name);
+ cb->callback = callback;
+}
+
static void
imapc_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
struct mailbox_list_settings *set)
ibox->save_rollback = imapc_transaction_save_rollback;
mbox->storage = (struct imapc_storage *)storage;
+
+ p_array_init(&mbox->untagged_callbacks, pool, 16);
+ p_array_init(&mbox->resp_text_callbacks, pool, 16);
+ imapc_mailbox_register_callbacks(mbox);
return &mbox->box;
}
} else {
mail_storage_set_critical(ctx->mbox->box.storage,
"imapc: Opening mailbox '%s' failed: %s",
- ctx->mbox->box.name, reply->text);
+ ctx->mbox->box.name, reply->text_full);
ctx->ret = -1;
}
if (!ctx->mbox->new_msgs)
const char *name = box->name;
if (directory) {
- /* FIXME: hardcoded separator.. */
- name = t_strconcat(name, "/", NULL);
+ name = t_strdup_printf("%s%c", name,
+ mailbox_list_get_hierarchy_sep(box->list));
}
ctx.storage = mbox->storage;
imapc_client_cmdf(mbox->storage->client, imapc_simple_callback, &ctx,
} else {
mail_storage_set_critical(ctx->mbox->box.storage,
"imapc: STATUS for mailbox '%s' failed: %s",
- ctx->mbox->box.name, reply->text);
+ ctx->mbox->box.name, reply->text_full);
ctx->ret = -1;
}
imapc_client_stop(ctx->mbox->storage->client);
#define IMAPC_STORAGE_NAME "imapc"
struct imap_arg;
+struct imapc_untagged_reply;
struct imapc_command_reply;
+struct imapc_mailbox;
+struct imapc_storage;
+
+typedef void imapc_storage_callback_t(const struct imapc_untagged_reply *reply,
+ struct imapc_storage *storage);
+typedef void imapc_mailbox_callback_t(const struct imapc_untagged_reply *reply,
+ struct imapc_mailbox *mbox);
+
+struct imapc_storage_event_callback {
+ const char *name;
+ imapc_storage_callback_t *callback;
+};
+
+struct imapc_mailbox_event_callback {
+ const char *name;
+ imapc_mailbox_callback_t *callback;
+};
struct imapc_storage {
struct mail_storage storage;
struct imapc_mailbox_list *list;
struct imapc_client *client;
+
+ ARRAY_DEFINE(untagged_callbacks, struct imapc_storage_event_callback);
};
struct imapc_mailbox {
struct mail *cur_fetch_mail;
+ ARRAY_DEFINE(untagged_callbacks, struct imapc_mailbox_event_callback);
+ ARRAY_DEFINE(resp_text_callbacks, struct imapc_mailbox_event_callback);
+
unsigned int new_msgs:1;
};
void imapc_async_stop_callback(const struct imapc_command_reply *reply,
void *context);
+void imapc_storage_register_untagged(struct imapc_storage *storage,
+ const char *name,
+ imapc_storage_callback_t *callback);
+void imapc_mailbox_register_untagged(struct imapc_mailbox *mbox,
+ const char *name,
+ imapc_mailbox_callback_t *callback);
+void imapc_mailbox_register_resp_text(struct imapc_mailbox *mbox,
+ const char *key,
+ imapc_mailbox_callback_t *callback);
+
+void imapc_mailbox_register_callbacks(struct imapc_mailbox *mbox);
+
#endif