Mercurial > dovecot > core-2.2
changeset 12590:9e471f267fb4
imapc: Code cleanups and fixes.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 21 Jan 2011 17:39:24 +0200 |
parents | 2fd54529e7d6 |
children | 868f2de3898b |
files | src/lib-storage/index/imapc/Makefile.am src/lib-storage/index/imapc/imapc-client.h src/lib-storage/index/imapc/imapc-connection.c src/lib-storage/index/imapc/imapc-list.c src/lib-storage/index/imapc/imapc-list.h src/lib-storage/index/imapc/imapc-mailbox.c src/lib-storage/index/imapc/imapc-storage.c src/lib-storage/index/imapc/imapc-storage.h |
diffstat | 8 files changed, 346 insertions(+), 188 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/index/imapc/Makefile.am Fri Jan 21 01:05:00 2011 +0200 +++ b/src/lib-storage/index/imapc/Makefile.am Fri Jan 21 17:39:24 2011 +0200 @@ -14,6 +14,7 @@ imapc-connection.c \ imapc-list.c \ imapc-mail.c \ + imapc-mailbox.c \ imapc-save.c \ imapc-search.c \ imapc-seqmap.c \
--- a/src/lib-storage/index/imapc/imapc-client.h Fri Jan 21 01:05:00 2011 +0200 +++ b/src/lib-storage/index/imapc/imapc-client.h Fri Jan 21 17:39:24 2011 +0200 @@ -34,10 +34,14 @@ 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 { @@ -49,8 +53,10 @@ /* 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. */
--- a/src/lib-storage/index/imapc/imapc-connection.c Fri Jan 21 01:05:00 2011 +0200 +++ b/src/lib-storage/index/imapc/imapc-connection.c Fri Jan 21 17:39:24 2011 +0200 @@ -126,7 +126,8 @@ 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); @@ -241,17 +242,8 @@ 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; @@ -268,10 +260,36 @@ 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 *text, *p; + 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; if (args->type != IMAP_ARG_ATOM) return 0; @@ -285,17 +303,10 @@ } return 0; } - p = strchr(text, ']'); - if (p == NULL) { - imapc_connection_input_error(conn, "Missing ']' in resp-text"); + if (imapc_connection_handle_resp_text(conn, text, key_r, value_r) < 0) return -1; - } - if (p[1] == '\0' || p[1] != ' ' || p[2] == '\0') { - imapc_connection_input_error(conn, "Missing text in resp-text"); - 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) @@ -346,7 +357,7 @@ 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"); @@ -363,7 +374,7 @@ if (reply->state != IMAPC_COMMAND_STATE_OK) { imapc_connection_input_error(conn, "Authentication failed: %s", - reply->text); + reply->text_full); return; } @@ -406,13 +417,14 @@ { 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); @@ -482,8 +494,9 @@ 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; } @@ -535,10 +548,10 @@ 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) @@ -554,19 +567,20 @@ 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); + if (imapc_connection_handle_resp_text(conn, reply.text_full, + &reply.resp_text_key, + &reply.resp_text_value) < 0) 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) - 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
--- a/src/lib-storage/index/imapc/imapc-list.c Fri Jan 21 01:05:00 2011 +0200 +++ b/src/lib-storage/index/imapc/imapc-list.c Fri Jan 21 17:39:24 2011 +0200 @@ -77,9 +77,11 @@ 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') { @@ -99,9 +101,11 @@ (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') { @@ -115,6 +119,14 @@ 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) { @@ -279,10 +291,13 @@ } 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
--- a/src/lib-storage/index/imapc/imapc-list.h Fri Jan 21 01:05:00 2011 +0200 +++ b/src/lib-storage/index/imapc/imapc-list.h Fri Jan 21 17:39:24 2011 +0200 @@ -19,9 +19,6 @@ 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 Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-storage/index/imapc/imapc-mailbox.c Fri Jan 21 17:39:24 2011 +0200 @@ -0,0 +1,176 @@ +/* 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); +}
--- a/src/lib-storage/index/imapc/imapc-storage.c Fri Jan 21 01:05:00 2011 +0200 +++ b/src/lib-storage/index/imapc/imapc-storage.c Fri Jan 21 17:39:24 2011 +0200 @@ -2,20 +2,14 @@ #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 { @@ -92,15 +86,13 @@ 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); } } @@ -116,7 +108,7 @@ 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); @@ -133,133 +125,37 @@ 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); + } } } @@ -283,11 +179,14 @@ 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; } @@ -298,6 +197,17 @@ 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) @@ -331,6 +241,10 @@ 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; } @@ -349,7 +263,7 @@ } 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) @@ -404,8 +318,8 @@ 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, @@ -443,7 +357,7 @@ } 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);
--- a/src/lib-storage/index/imapc/imapc-storage.h Fri Jan 21 01:05:00 2011 +0200 +++ b/src/lib-storage/index/imapc/imapc-storage.h Fri Jan 21 17:39:24 2011 +0200 @@ -6,12 +6,32 @@ #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 { @@ -24,6 +44,9 @@ 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; }; @@ -59,4 +82,16 @@ 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