extern struct mailbox_list imapc_mailbox_list;
+static void imapc_list_send_hierarcy_sep_lookup(struct imapc_mailbox_list *list);
+static void imapc_untagged_list(const struct imapc_untagged_reply *reply,
+ struct imapc_storage_client *client);
+static void imapc_untagged_lsub(const struct imapc_untagged_reply *reply,
+ struct imapc_storage_client *client);
+
static struct mailbox_list *imapc_list_alloc(void)
{
struct imapc_mailbox_list *list;
list = p_new(pool, struct imapc_mailbox_list, 1);
list->list = imapc_mailbox_list;
list->list.pool = pool;
- /* separator is set when storage is created */
+ /* separator is set lazily */
list->mailboxes = mailbox_tree_init('\0');
mailbox_tree_set_parents_nonexistent(list->mailboxes);
return &list->list;
}
-static int
-imapc_list_init(struct mailbox_list *_list, const char **error_r ATTR_UNUSED)
+static int imapc_list_init(struct mailbox_list *_list, const char **error_r)
{
struct imapc_mailbox_list *list = (struct imapc_mailbox_list *)_list;
+ char sep;
list->set = mail_user_set_get_driver_settings(_list->ns->user->set_info,
_list->ns->user->set,
IMAPC_STORAGE_NAME);
+ if (imapc_storage_client_create(_list->ns, list->set, _list->mail_set,
+ &list->client, error_r) < 0)
+ return -1;
+ list->client->_list = list;
+
+ imapc_storage_client_register_untagged(list->client, "LIST",
+ imapc_untagged_list);
+ imapc_storage_client_register_untagged(list->client, "LSUB",
+ imapc_untagged_lsub);
+ imapc_list_send_hierarcy_sep_lookup(list);
+ if ((_list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) {
+ /* we're using imapc for the INBOX namespace. wait and make
+ sure we can successfully access the IMAP server (so if the
+ username is invalid we don't just keep failing every
+ command). */
+ if (imapc_list_try_get_root_sep(list, &sep) < 0) {
+ imapc_storage_client_unref(&list->client);
+ *error_r = "Failed to access imapc backend";
+ return -1;
+ }
+ }
return 0;
}
mailbox_tree_deinit(&list->mailboxes);
if (list->tmp_subscriptions != NULL)
mailbox_tree_deinit(&list->tmp_subscriptions);
+ imapc_storage_client_unref(&list->client);
pool_unref(&list->list.pool);
}
+static void
+imapc_list_copy_error_from_reply(struct imapc_mailbox_list *list,
+ enum mail_error default_error,
+ const struct imapc_command_reply *reply)
+{
+ enum mail_error error;
+
+ if (imap_resp_text_code_parse(reply->resp_text_key, &error)) {
+ mailbox_list_set_error(&list->list, error,
+ reply->text_without_resp);
+ } else {
+ mailbox_list_set_error(&list->list, default_error,
+ reply->text_without_resp);
+ }
+}
+
static void imapc_list_simple_callback(const struct imapc_command_reply *reply,
void *context)
{
struct imapc_simple_context *ctx = context;
- const char *str;
- enum mail_error error;
- imapc_simple_callback(reply, context);
- if (ctx->ret < 0) {
- str = mail_storage_get_last_error(&ctx->storage->storage, &error);
- mailbox_list_set_error(&ctx->storage->list->list, error, str);
+ if (reply->state == IMAPC_COMMAND_STATE_OK)
+ ctx->ret = 0;
+ else if (reply->state == IMAPC_COMMAND_STATE_NO) {
+ imapc_list_copy_error_from_reply(ctx->client->_list,
+ MAIL_ERROR_PARAMS, reply);
+ ctx->ret = -1;
+ } else {
+ mailbox_list_set_critical(&ctx->client->_list->list,
+ "imapc: Command failed: %s", reply->text_full);
+ ctx->ret = -1;
}
+ imapc_client_stop(ctx->client->client);
}
static bool
}
static void imapc_untagged_list(const struct imapc_untagged_reply *reply,
- struct imapc_storage *storage)
+ struct imapc_storage_client *client)
{
- struct imapc_mailbox_list *list = storage->list;
+ struct imapc_mailbox_list *list = client->_list;
const struct imap_arg *args = reply->args;
const char *sep, *name;
- if (storage->root_sep == '\0') {
+ if (list->root_sep == '\0') {
/* we haven't asked for the separator yet.
lets see if this is the reply for its request. */
if (args[0].type == IMAP_ARG_EOL ||
return;
/* we can't handle NIL separator yet */
- storage->root_sep = sep == NULL ? '/' : sep[0];
- mailbox_tree_set_separator(list->mailboxes, storage->root_sep);
+ list->root_sep = sep == NULL ? '/' : sep[0];
+ mailbox_tree_set_separator(list->mailboxes, list->root_sep);
} else {
(void)imapc_list_update_tree(list, list->mailboxes, args);
}
}
static void imapc_untagged_lsub(const struct imapc_untagged_reply *reply,
- struct imapc_storage *storage)
+ struct imapc_storage_client *client)
{
- struct imapc_mailbox_list *list = storage->list;
+ struct imapc_mailbox_list *list = client->_list;
const struct imap_arg *args = reply->args;
struct mailbox_node *node;
- if (storage->root_sep == '\0') {
+ if (list->root_sep == '\0') {
/* we haven't asked for the separator yet */
return;
}
}
}
-void imapc_list_register_callbacks(struct imapc_mailbox_list *list)
+static void imapc_list_sep_verify(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);
+ const char *imapc_list_prefix = list->set->imapc_list_prefix;
+
+ if (list->root_sep == '\0') {
+ mailbox_list_set_critical(&list->list,
+ "imapc: LIST didn't return hierarchy separator");
+ } else if (imapc_list_prefix[0] != '\0' &&
+ imapc_list_prefix[strlen(imapc_list_prefix)-1] == list->root_sep) {
+ mailbox_list_set_critical(&list->list,
+ "imapc_list_prefix must not end with hierarchy separator");
+ }
+}
+
+static void imapc_storage_sep_callback(const struct imapc_command_reply *reply,
+ void *context)
+{
+ struct imapc_mailbox_list *list = context;
+
+ list->root_sep_pending = FALSE;
+ if (reply->state == IMAPC_COMMAND_STATE_OK)
+ imapc_list_sep_verify(list);
+ else if (reply->state == IMAPC_COMMAND_STATE_NO)
+ imapc_list_copy_error_from_reply(list, MAIL_ERROR_PARAMS, reply);
+ else {
+ mailbox_list_set_critical(&list->list,
+ "imapc: Command failed: %s", reply->text_full);
+ }
+ imapc_client_stop(list->client->client);
+}
+
+static void imapc_list_send_hierarcy_sep_lookup(struct imapc_mailbox_list *list)
+{
+ struct imapc_command *cmd;
+
+ if (list->root_sep_pending)
+ return;
+ list->root_sep_pending = TRUE;
+
+ cmd = imapc_client_cmd(list->client->client,
+ imapc_storage_sep_callback, list);
+ imapc_command_send(cmd, "LIST \"\" \"\"");
+}
+
+int imapc_list_try_get_root_sep(struct imapc_mailbox_list *list, char *sep_r)
+{
+ if (list->root_sep == '\0') {
+ imapc_list_send_hierarcy_sep_lookup(list);
+ while (list->root_sep_pending)
+ imapc_client_run(list->client->client);
+ if (list->root_sep == '\0')
+ return -1;
+ }
+ *sep_r = list->root_sep;
+ return 0;
}
static char imapc_list_get_hierarchy_sep(struct mailbox_list *_list)
struct imapc_mailbox_list *list = (struct imapc_mailbox_list *)_list;
char sep;
- if (imapc_storage_try_get_root_sep(list->storage, &sep) < 0) {
+ if (imapc_list_try_get_root_sep(list, &sep) < 0) {
/* we can't really fail here. just return a common separator
and keep failing all list commands until it succeeds. */
return '/';
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_simple_context_init(ctx, list->client);
+ return imapc_client_cmd(list->client->client,
imapc_list_simple_callback, ctx);
}
struct imapc_command *cmd;
struct imapc_simple_context ctx;
- capa = imapc_client_get_capabilities(list->storage->client);
+ capa = imapc_client_get_capabilities(list->client->client);
cmd = imapc_list_simple_context_init(&ctx, list);
imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_SELECT);
struct imapc_mailbox_list {
struct mailbox_list list;
const struct imapc_settings *set;
- struct imapc_storage *storage;
+ struct imapc_storage_client *client;
struct mailbox_list *index_list;
struct mailbox_tree_context *mailboxes, *tmp_subscriptions;
+ char root_sep;
unsigned int iter_count;
unsigned int refreshed_subscriptions:1;
unsigned int refreshed_mailboxes:1;
unsigned int index_list_failed:1;
+ unsigned int root_sep_pending:1;
};
int imapc_list_get_mailbox_flags(struct mailbox_list *list, const char *name,
enum mailbox_info_flags *flags_r);
-
-void imapc_list_register_callbacks(struct imapc_mailbox_list *list);
+int imapc_list_try_get_root_sep(struct imapc_mailbox_list *list, char *sep_r);
#endif
"imapc: Mail prefetch failed: %s", reply->text_full);
}
pool_unref(&mail->imail.mail.pool);
- imapc_client_stop(mbox->storage->client);
+ imapc_client_stop(mbox->storage->client->client);
}
static int
if (!match) {
/* this is only a FETCH FLAGS update for the wanted mail */
} else {
- imapc_client_stop(mbox->storage->client);
+ imapc_client_stop(mbox->storage->client->client);
}
}
i_assert(ctx->fd == -1);
- ctx->fd = imapc_client_create_temp_fd(ctx->mbox->storage->client, &path);
+ ctx->fd = imapc_client_create_temp_fd(ctx->mbox->storage->client->client,
+ &path);
if (ctx->fd == -1) {
mail_storage_set_critical(storage,
"Couldn't create temp file %s", path);
"imapc: COPY failed: %s", reply->text_full);
ctx->ret = -1;
}
- imapc_client_stop(ctx->ctx->mbox->storage->client);
+ imapc_client_stop(ctx->ctx->mbox->storage->client->client);
}
static void
/* we don't really care about the reply */
ctx->ret = 0;
- imapc_client_stop(ctx->ctx->mbox->storage->client);
+ imapc_client_stop(ctx->ctx->mbox->storage->client->client);
}
static void
input = i_stream_create_fd(ctx->fd, IO_BLOCK_SIZE, FALSE);
sctx.ctx = ctx;
sctx.ret = -2;
- cmd = imapc_client_cmd(ctx->mbox->storage->client,
+ cmd = imapc_client_cmd(ctx->mbox->storage->client->client,
imapc_save_callback, &sctx);
imapc_command_sendf(cmd, "APPEND %s%1s%1s %p",
ctx->mbox->box.name, flags, internaldate, input);
but it makes the behavior better. See if NOOP finds
the mail. */
sctx.ret = -2;
- cmd = imapc_client_cmd(ctx->mbox->storage->client,
+ cmd = imapc_client_cmd(ctx->mbox->storage->client->client,
imapc_save_noop_callback, &sctx);
imapc_command_send(cmd, "NOOP");
while (sctx.ret == -2)
"imapc: COPY failed: %s", reply->text_full);
ctx->ret = -1;
}
- imapc_client_stop(ctx->ctx->mbox->storage->client);
+ imapc_client_stop(ctx->ctx->mbox->storage->client->client);
}
int imapc_copy(struct mail_save_context *_ctx, struct mail *mail)
};
static void imapc_untagged_status(const struct imapc_untagged_reply *reply,
- struct imapc_storage *storage);
+ struct imapc_storage_client *client);
static void imapc_untagged_namespace(const struct imapc_untagged_reply *reply,
- struct imapc_storage *storage);
+ struct imapc_storage_client *client);
-static bool
-imap_resp_text_code_parse(const char *str, enum mail_error *error_r)
+bool imap_resp_text_code_parse(const char *str, enum mail_error *error_r)
{
unsigned int i;
}
void imapc_simple_context_init(struct imapc_simple_context *sctx,
- struct imapc_storage *storage)
+ struct imapc_storage_client *client)
{
memset(sctx, 0, sizeof(*sctx));
- sctx->storage = storage;
+ sctx->client = client;
sctx->ret = -2;
}
void imapc_simple_run(struct imapc_simple_context *sctx)
{
while (sctx->ret == -2)
- imapc_storage_run(sctx->storage);
+ imapc_client_run(sctx->client->client);
}
void imapc_storage_run(struct imapc_storage *storage)
{
do {
- imapc_client_run(storage->client);
+ imapc_client_run(storage->client->client);
} while (storage->reopen_count > 0);
}
if (reply->state == IMAPC_COMMAND_STATE_OK)
ctx->ret = 0;
else if (reply->state == IMAPC_COMMAND_STATE_NO) {
- imapc_copy_error_from_reply(ctx->storage, MAIL_ERROR_PARAMS, reply);
+ imapc_copy_error_from_reply(ctx->client->_storage,
+ MAIL_ERROR_PARAMS, reply);
ctx->ret = -1;
} else {
- mail_storage_set_critical(&ctx->storage->storage,
+ mail_storage_set_critical(&ctx->client->_storage->storage,
"imapc: Command failed: %s", reply->text_full);
ctx->ret = -1;
}
- imapc_client_stop(ctx->storage->client);
+ imapc_client_stop(ctx->client->client);
}
void imapc_mailbox_noop(struct imapc_mailbox *mbox)
struct imapc_command *cmd;
struct imapc_simple_context sctx;
- imapc_simple_context_init(&sctx, mbox->storage);
+ imapc_simple_context_init(&sctx, mbox->storage->client);
cmd = imapc_client_mailbox_cmd(mbox->client_box,
imapc_simple_callback, &sctx);
imapc_command_send(cmd, "NOOP");
imapc_simple_run(&sctx);
}
-static void imapc_storage_untagged_cb(const struct imapc_untagged_reply *reply,
- void *context)
+static void
+imapc_storage_client_untagged_cb(const struct imapc_untagged_reply *reply,
+ void *context)
{
- struct imapc_storage *storage = context;
+ struct imapc_storage_client *client = context;
struct imapc_mailbox *mbox = reply->untagged_box_context;
const struct imapc_storage_event_callback *cb;
const struct imapc_mailbox_event_callback *mcb;
- array_foreach(&storage->untagged_callbacks, cb) {
+ array_foreach(&client->untagged_callbacks, cb) {
if (strcasecmp(reply->name, cb->name) == 0)
- cb->callback(reply, storage);
+ cb->callback(reply, client);
}
if (mbox == NULL)
}
}
-static void imapc_storage_sep_verify(struct imapc_storage *storage)
-{
- const char *imapc_list_prefix = storage->set->imapc_list_prefix;
-
- if (storage->root_sep == '\0') {
- mail_storage_set_critical(&storage->storage,
- "imapc: LIST didn't return hierarchy separator");
- } else if (imapc_list_prefix[0] != '\0' &&
- imapc_list_prefix[strlen(imapc_list_prefix)-1] == storage->root_sep) {
- mail_storage_set_critical(&storage->storage,
- "imapc_list_prefix must not end with hierarchy separator");
- }
-}
-
-static void imapc_storage_sep_callback(const struct imapc_command_reply *reply,
- void *context)
-{
- struct imapc_storage *storage = context;
-
- storage->root_sep_pending = FALSE;
- if (reply->state == IMAPC_COMMAND_STATE_OK)
- imapc_storage_sep_verify(storage);
- else if (reply->state == IMAPC_COMMAND_STATE_NO)
- imapc_copy_error_from_reply(storage, MAIL_ERROR_PARAMS, reply);
- else {
- mail_storage_set_critical(&storage->storage,
- "imapc: Command failed: %s", reply->text_full);
- }
- imapc_client_stop(storage->client);
-}
-
-static void imapc_storage_send_hierarcy_sep_lookup(struct imapc_storage *storage)
-{
- struct imapc_command *cmd;
-
- if (storage->root_sep_pending)
- return;
- storage->root_sep_pending = TRUE;
-
- cmd = imapc_client_cmd(storage->client,
- imapc_storage_sep_callback, storage);
- imapc_command_send(cmd, "LIST \"\" \"\"");
-}
-
-int imapc_storage_try_get_root_sep(struct imapc_storage *storage, char *sep_r)
-{
- i_assert(storage->list != NULL);
-
- if (storage->root_sep == '\0') {
- imapc_storage_send_hierarcy_sep_lookup(storage);
- while (storage->root_sep_pending)
- imapc_client_run(storage->client);
- if (storage->root_sep == '\0')
- return -1;
- }
- *sep_r = storage->root_sep;
- return 0;
-}
-
-static int
-imapc_client_create(struct mail_namespace *ns,
- const struct imapc_settings *imapc_set,
- const struct mail_storage_settings *mail_set,
- struct imapc_client **client_r, const char **error_r)
+int imapc_storage_client_create(struct mail_namespace *ns,
+ const struct imapc_settings *imapc_set,
+ const struct mail_storage_settings *mail_set,
+ struct imapc_storage_client **client_r,
+ const char **error_r)
{
+ struct imapc_storage_client *client;
struct imapc_client_settings set;
string_t *str;
set.ssl_mode = IMAPC_CLIENT_SSL_MODE_NONE;
set.ssl_crypto_device = mail_set->ssl_crypto_device;
- *client_r = imapc_client_init(&set);
+ client = i_new(struct imapc_storage_client, 1);
+ client->refcount = 1;
+ i_array_init(&client->untagged_callbacks, 16);
+ client->client = imapc_client_init(&set);
+ imapc_client_register_untagged(client->client,
+ imapc_storage_client_untagged_cb, client);
+ /* start logging in immediately */
+ imapc_client_login(client->client, NULL, NULL);
+
+ *client_r = client;
return 0;
}
+void imapc_storage_client_unref(struct imapc_storage_client **_client)
+{
+ struct imapc_storage_client *client = *_client;
+ struct imapc_storage_event_callback *cb;
+
+ *_client = NULL;
+
+ i_assert(client->refcount > 0);
+ if (--client->refcount > 0)
+ return;
+ imapc_client_deinit(&client->client);
+ array_foreach_modifiable(&client->untagged_callbacks, cb)
+ i_free(cb->name);
+ array_free(&client->untagged_callbacks);
+ i_free(client);
+}
+
static int
imapc_storage_create(struct mail_storage *_storage,
struct mail_namespace *ns,
const char **error_r)
{
struct imapc_storage *storage = (struct imapc_storage *)_storage;
- char sep;
+ struct imapc_mailbox_list *imapc_list = NULL;
storage->set = mail_storage_get_driver_settings(_storage);
- if (imapc_client_create(ns, storage->set, _storage->set,
- &storage->client, error_r) < 0)
- return -1;
-
- p_array_init(&storage->remote_namespaces, _storage->pool, 4);
- p_array_init(&storage->untagged_callbacks, _storage->pool, 16);
if (strcmp(ns->list->name, MAILBOX_LIST_NAME_IMAPC) == 0) {
- storage->list = (struct imapc_mailbox_list *)ns->list;
- storage->list->storage = storage;
- imapc_list_register_callbacks(storage->list);
- }
-
- imapc_client_register_untagged(storage->client,
- imapc_storage_untagged_cb, storage);
- imapc_storage_register_untagged(storage, "STATUS",
- imapc_untagged_status);
- imapc_storage_register_untagged(storage, "NAMESPACE",
- imapc_untagged_namespace);
- /* start connecting to imap server and get the hierarchy separator. */
- imapc_client_login(storage->client, NULL, NULL);
- if (storage->list != NULL)
- imapc_storage_send_hierarcy_sep_lookup(storage);
- if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 &&
- storage->list != NULL) {
- /* we're using imapc for the INBOX namespace. wait and make
- sure we can successfully access the IMAP server (so if the
- username is invalid we don't just keep failing every
- command). */
- if (imapc_storage_try_get_root_sep(storage, &sep) < 0) {
- imapc_client_deinit(&storage->client);
- *error_r = "Failed to access imapc backend";
+ imapc_list = (struct imapc_mailbox_list *)ns->list;
+ storage->client = imapc_list->client;
+ storage->client->refcount++;
+ } else {
+ if (imapc_storage_client_create(ns, storage->set, _storage->set,
+ &storage->client, error_r) < 0)
return -1;
- }
}
+ storage->client->_storage = storage;
+ p_array_init(&storage->remote_namespaces, _storage->pool, 4);
+
+ imapc_storage_client_register_untagged(storage->client, "STATUS",
+ imapc_untagged_status);
+ imapc_storage_client_register_untagged(storage->client, "NAMESPACE",
+ imapc_untagged_namespace);
return 0;
}
{
struct imapc_storage *storage = (struct imapc_storage *)_storage;
- imapc_client_deinit(&storage->client);
+ imapc_storage_client_unref(&storage->client);
index_storage_destroy(_storage);
}
-static void imapc_storage_add_list(struct mail_storage *_storage,
- struct mailbox_list *_list)
-{
- struct imapc_storage *storage = (struct imapc_storage *)_storage;
- struct imapc_mailbox_list *list = (struct imapc_mailbox_list *)_list;
-
- if (strcmp(_list->name, MAILBOX_LIST_NAME_IMAPC) == 0) {
- i_assert(storage->list != NULL);
- list->storage = storage;
- }
-}
-
-void imapc_storage_register_untagged(struct imapc_storage *storage,
- const char *name,
- imapc_storage_callback_t *callback)
+void imapc_storage_client_register_untagged(struct imapc_storage_client *client,
+ 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 = array_append_space(&client->untagged_callbacks);
+ cb->name = i_strdup(name);
cb->callback = callback;
}
mbox->box.name, reply->text_full);
imapc_client_mailbox_reconnect(mbox->client_box);
}
- imapc_client_stop(mbox->storage->client);
+ imapc_client_stop(mbox->storage->client->client);
}
static void imapc_mailbox_reopen(void *context)
ctx->mbox->box.name, reply->text_full);
ctx->ret = -1;
}
- imapc_client_stop(ctx->mbox->storage->client);
+ imapc_client_stop(ctx->mbox->storage->client->client);
}
static void imapc_mailbox_get_extensions(struct imapc_mailbox *mbox)
{
enum imapc_capability capa =
- imapc_client_get_capabilities(mbox->storage->client);
+ imapc_client_get_capabilities(mbox->storage->client->client);
if (mbox->guid_fetch_field_name == NULL) {
/* see if we can get message GUIDs somehow */
i_assert(mbox->client_box == NULL);
mbox->client_box =
- imapc_client_mailbox_open(mbox->storage->client, mbox);
+ imapc_client_mailbox_open(mbox->storage->client->client, mbox);
imapc_client_mailbox_set_reopen_cb(mbox->client_box,
imapc_mailbox_reopen, mbox);
name = t_strdup_printf("%s%c", name,
mailbox_list_get_hierarchy_sep(box->list));
}
- imapc_simple_context_init(&sctx, mbox->storage);
- cmd = imapc_client_cmd(mbox->storage->client,
+ imapc_simple_context_init(&sctx, mbox->storage->client);
+ cmd = imapc_client_cmd(mbox->storage->client->client,
imapc_simple_callback, &sctx);
imapc_command_sendf(cmd, "CREATE %s", name);
imapc_simple_run(&sctx);
}
static void imapc_untagged_status(const struct imapc_untagged_reply *reply,
- struct imapc_storage *storage)
+ struct imapc_storage_client *client)
{
+ struct imapc_storage *storage = client->_storage;
struct mailbox_status *status;
const struct imap_arg *list;
const char *name, *key, *value;
}
static void imapc_untagged_namespace(const struct imapc_untagged_reply *reply,
- struct imapc_storage *storage)
+ struct imapc_storage_client *client)
{
+ struct imapc_storage *storage = client->_storage;
static enum mail_namespace_type ns_types[] = {
MAIL_NAMESPACE_TYPE_PRIVATE,
MAIL_NAMESPACE_TYPE_SHARED,
return 0;
}
- imapc_simple_context_init(&sctx, mbox->storage);
+ imapc_simple_context_init(&sctx, mbox->storage->client);
mbox->storage->cur_status_box = mbox;
mbox->storage->cur_status = status_r;
- cmd = imapc_client_cmd(mbox->storage->client,
+ cmd = imapc_client_cmd(mbox->storage->client->client,
imapc_simple_callback, &sctx);
imapc_command_sendf(cmd, "STATUS %s (%1s)", box->name, str_c(str)+1);
imapc_simple_run(&sctx);
if (storage->namespaces_requested)
return 0;
- capa = imapc_client_get_capabilities(storage->client);
+ capa = imapc_client_get_capabilities(storage->client->client);
if ((capa & IMAPC_CAPABILITY_NAMESPACE) == 0) {
/* NAMESPACE capability not supported */
return 0;
}
- imapc_simple_context_init(&sctx, storage);
- cmd = imapc_client_cmd(storage->client,
+ imapc_simple_context_init(&sctx, storage->client);
+ cmd = imapc_client_cmd(storage->client->client,
imapc_simple_callback, &sctx);
imapc_command_send(cmd, "NAMESPACE");
imapc_simple_run(&sctx);
return;
}
- capa = imapc_client_get_capabilities(mbox->storage->client);
+ capa = imapc_client_get_capabilities(mbox->storage->client->client);
if ((capa & IMAPC_CAPABILITY_IDLE) != 0) {
/* remote server is already in IDLE. but since some servers
don't notice changes immediately, we'll force them to check
} else {
/* remote server doesn't support IDLE.
check for changes with NOOP every once in a while. */
- i_assert(!imapc_client_is_running(mbox->storage->client));
+ i_assert(!imapc_client_is_running(mbox->storage->client->client));
mbox->to_idle_check =
timeout_add(set->mailbox_idle_check_interval * 1000,
imapc_idle_timeout, mbox);
imapc_storage_alloc,
imapc_storage_create,
imapc_storage_destroy,
- imapc_storage_add_list,
+ NULL,
imapc_storage_get_list_settings,
NULL,
imapc_mailbox_alloc,
struct imapc_untagged_reply;
struct imapc_command_reply;
struct imapc_mailbox;
-struct imapc_storage;
+struct imapc_storage_client;
typedef void imapc_storage_callback_t(const struct imapc_untagged_reply *reply,
- struct imapc_storage *storage);
+ struct imapc_storage_client *client);
typedef void imapc_mailbox_callback_t(const struct imapc_untagged_reply *reply,
struct imapc_mailbox *mbox);
struct imapc_storage_event_callback {
- const char *name;
+ char *name;
imapc_storage_callback_t *callback;
};
enum mail_namespace_type type;
};
+struct imapc_storage_client {
+ int refcount;
+
+ /* either one of these may not be available: */
+ struct imapc_storage *_storage;
+ struct imapc_mailbox_list *_list;
+
+ struct imapc_client *client;
+
+ ARRAY(struct imapc_storage_event_callback) untagged_callbacks;
+};
+
struct imapc_storage {
struct mail_storage storage;
const struct imapc_settings *set;
struct ioloop *root_ioloop;
- struct imapc_mailbox_list *list;
- struct imapc_client *client;
- char root_sep;
+ struct imapc_storage_client *client;
struct imapc_mailbox *cur_status_box;
struct mailbox_status *cur_status;
unsigned int reopen_count;
ARRAY(struct imapc_namespace) remote_namespaces;
- ARRAY(struct imapc_storage_event_callback) untagged_callbacks;
unsigned int namespaces_requested:1;
- unsigned int root_sep_pending:1;
};
struct imapc_mail_cache {
};
struct imapc_simple_context {
- struct imapc_storage *storage;
+ struct imapc_storage_client *client;
int ret;
};
+int imapc_storage_client_create(struct mail_namespace *ns,
+ const struct imapc_settings *imapc_set,
+ const struct mail_storage_settings *mail_set,
+ struct imapc_storage_client **client_r,
+ const char **error_r);
+void imapc_storage_client_unref(struct imapc_storage_client **client);
+
struct mail_save_context *
imapc_save_alloc(struct mailbox_transaction_context *_t);
int imapc_save_begin(struct mail_save_context *ctx, struct istream *input);
void imapc_storage_run(struct imapc_storage *storage);
void imapc_mail_cache_free(struct imapc_mail_cache *cache);
int imapc_mailbox_select(struct imapc_mailbox *mbox);
-int imapc_storage_try_get_root_sep(struct imapc_storage *storage, char *sep_r);
+bool imap_resp_text_code_parse(const char *str, enum mail_error *error_r);
void imapc_copy_error_from_reply(struct imapc_storage *storage,
enum mail_error default_error,
const struct imapc_command_reply *reply);
void imapc_simple_context_init(struct imapc_simple_context *sctx,
- struct imapc_storage *storage);
+ struct imapc_storage_client *client);
void imapc_simple_run(struct imapc_simple_context *sctx);
void imapc_simple_callback(const struct imapc_command_reply *reply,
void *context);
void imapc_mailbox_set_corrupted(struct imapc_mailbox *mbox,
const char *reason, ...) ATTR_FORMAT(2, 3);
-void imapc_storage_register_untagged(struct imapc_storage *storage,
- const char *name,
- imapc_storage_callback_t *callback);
+void imapc_storage_client_register_untagged(struct imapc_storage_client *client,
+ 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);
}
if (--ctx->sync_command_count == 0)
- imapc_client_stop(ctx->mbox->storage->client);
+ imapc_client_stop(ctx->mbox->storage->client->client);
}
static void imapc_sync_cmd(struct imapc_sync_context *ctx, const char *cmd_str)
if (array_count(&ctx->expunged_uids) == 0)
return;
- caps = imapc_client_get_capabilities(ctx->mbox->storage->client);
+ caps = imapc_client_get_capabilities(ctx->mbox->storage->client->client);
if ((caps & IMAPC_CAPABILITY_UIDPLUS) == 0) {
/* just expunge everything */
imapc_sync_cmd(ctx, "EXPUNGE");
ret = -1;
}
- capabilities = imapc_client_get_capabilities(mbox->storage->client);
+ capabilities = imapc_client_get_capabilities(mbox->storage->client->client);
if ((capabilities & IMAPC_CAPABILITY_IDLE) == 0) {
/* IDLE not supported. do NOOP to get latest changes
before starting sync. */