imapc-storage.c revision a2d397c3a8024156eb3b4b53c37d07d60588f1e4
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen/* Copyright (c) 2011 Dovecot authors, see the included COPYING file */
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen#include "lib.h"
6f9a5ecb55d8c024a0953647b77711b5622e9bbbTimo Sirainen#include "ioloop.h"
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen#include "str.h"
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen#include "imap-arg.h"
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen#include "imap-resp-code.h"
94a77d6e5d7600859e4c5e4a7ea19dc3e91998b9Timo Sirainen#include "imapc-mail.h"
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen#include "imapc-client.h"
90de49eb151c2be7655ce6aef5aa3b58295d5c84Timo Sirainen#include "imapc-list.h"
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen#include "imapc-sync.h"
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen#include "imapc-settings.h"
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen#include "imapc-storage.h"
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen#define DNS_CLIENT_SOCKET_NAME "dns-client"
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstruct imapc_open_context {
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct imapc_mailbox *mbox;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen int ret;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen};
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstruct imapc_resp_code_map {
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen const char *code;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen enum mail_error error;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen};
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenextern struct mail_storage imapc_storage;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenextern struct mailbox imapc_mailbox;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstatic struct imapc_resp_code_map imapc_resp_code_map[] = {
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen { IMAP_RESP_CODE_UNAVAILABLE, MAIL_ERROR_TEMP },
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen { IMAP_RESP_CODE_AUTHFAILED, MAIL_ERROR_PERM },
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen { IMAP_RESP_CODE_AUTHZFAILED, MAIL_ERROR_PERM },
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen { IMAP_RESP_CODE_EXPIRED, MAIL_ERROR_PERM },
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen { IMAP_RESP_CODE_PRIVACYREQUIRED, MAIL_ERROR_PERM },
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen { IMAP_RESP_CODE_CONTACTADMIN, MAIL_ERROR_PERM },
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen { IMAP_RESP_CODE_NOPERM, MAIL_ERROR_PERM },
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen { IMAP_RESP_CODE_INUSE, MAIL_ERROR_INUSE },
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen { IMAP_RESP_CODE_EXPUNGEISSUED, MAIL_ERROR_EXPUNGED },
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen { IMAP_RESP_CODE_CORRUPTION, MAIL_ERROR_TEMP },
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen { IMAP_RESP_CODE_SERVERBUG, MAIL_ERROR_TEMP },
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen /* { IMAP_RESP_CODE_CLIENTBUG, 0 }, */
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen { IMAP_RESP_CODE_CANNOT, MAIL_ERROR_NOTPOSSIBLE },
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen { IMAP_RESP_CODE_LIMIT, MAIL_ERROR_NOTPOSSIBLE },
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen { IMAP_RESP_CODE_OVERQUOTA, MAIL_ERROR_NOSPACE },
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen { IMAP_RESP_CODE_ALREADYEXISTS, MAIL_ERROR_EXISTS },
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen { IMAP_RESP_CODE_NONEXISTENT, MAIL_ERROR_NOTFOUND }
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen};
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainenstatic void imapc_untagged_status(const struct imapc_untagged_reply *reply,
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen struct imapc_storage *storage);
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstatic bool
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenimap_resp_text_code_parse(const char *str, enum mail_error *error_r)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen unsigned int i;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen if (str == NULL)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return FALSE;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen for (i = 0; i < N_ELEMENTS(imapc_resp_code_map); i++) {
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen if (strcmp(imapc_resp_code_map[i].code, str) == 0) {
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen *error_r = imapc_resp_code_map[i].error;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return TRUE;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen }
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen }
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return FALSE;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstatic struct mail_storage *imapc_storage_alloc(void)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct imapc_storage *storage;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen pool_t pool;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
df48643c3c240ad5b8a3e2e2132c46f7dc541b5eTimo Sirainen pool = pool_alloconly_create("imapc storage", 2048);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen storage = p_new(pool, struct imapc_storage, 1);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen storage->storage = imapc_storage;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen storage->storage.pool = pool;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return &storage->storage;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
689b06e33729491b593fe34ad3267d65b79be149Timo Sirainenvoid imapc_copy_error_from_reply(struct imapc_storage *storage,
689b06e33729491b593fe34ad3267d65b79be149Timo Sirainen enum mail_error default_error,
689b06e33729491b593fe34ad3267d65b79be149Timo Sirainen const struct imapc_command_reply *reply)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen enum mail_error error;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen if (imap_resp_text_code_parse(reply->resp_text_key, &error)) {
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen mail_storage_set_error(&storage->storage, error,
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen reply->text_without_resp);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen } else {
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen mail_storage_set_error(&storage->storage, default_error,
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen reply->text_without_resp);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen }
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainenvoid imapc_simple_context_init(struct imapc_simple_context *sctx,
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen struct imapc_storage *storage)
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen{
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen memset(sctx, 0, sizeof(*sctx));
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen sctx->storage = storage;
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen sctx->ret = -2;
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen}
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainenvoid imapc_simple_run(struct imapc_simple_context *sctx)
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen{
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen while (sctx->ret == -2)
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen imapc_client_run(sctx->storage->client);
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen}
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen
90de49eb151c2be7655ce6aef5aa3b58295d5c84Timo Sirainenvoid imapc_simple_callback(const struct imapc_command_reply *reply,
90de49eb151c2be7655ce6aef5aa3b58295d5c84Timo Sirainen void *context)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct imapc_simple_context *ctx = context;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen if (reply->state == IMAPC_COMMAND_STATE_OK)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen ctx->ret = 0;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen else if (reply->state == IMAPC_COMMAND_STATE_NO) {
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_copy_error_from_reply(ctx->storage, MAIL_ERROR_PARAMS, reply);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen ctx->ret = -1;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen } else {
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen mail_storage_set_critical(&ctx->storage->storage,
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen "imapc: Command failed: %s", reply->text_full);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen ctx->ret = -1;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen }
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_client_stop(ctx->storage->client);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainenstatic void imapc_async_callback(const struct imapc_command_reply *reply,
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen void *context)
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct imapc_storage *storage = context;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen if (reply->state == IMAPC_COMMAND_STATE_OK)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen ;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen else if (reply->state == IMAPC_COMMAND_STATE_NO) {
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_copy_error_from_reply(storage, MAIL_ERROR_PARAMS, reply);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen } else {
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen mail_storage_set_critical(&storage->storage,
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen "imapc: Command failed: %s", reply->text_full);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen }
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen}
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainenvoid imapc_async_stop_callback(const struct imapc_command_reply *reply,
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen void *context)
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen{
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen struct imapc_storage *storage = context;
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen imapc_async_callback(reply, context);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_client_stop(storage->client);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstatic void imapc_storage_untagged_cb(const struct imapc_untagged_reply *reply,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen void *context)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct imapc_storage *storage = context;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct imapc_mailbox *mbox = reply->untagged_box_context;
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen const struct imapc_storage_event_callback *cb;
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen const struct imapc_mailbox_event_callback *mcb;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen array_foreach(&storage->untagged_callbacks, cb) {
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen if (strcasecmp(reply->name, cb->name) == 0)
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen cb->callback(reply, storage);
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen }
90de49eb151c2be7655ce6aef5aa3b58295d5c84Timo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen if (mbox == NULL)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen array_foreach(&mbox->untagged_callbacks, mcb) {
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen if (strcasecmp(reply->name, mcb->name) == 0)
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen mcb->callback(reply, mbox);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen }
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen if (reply->resp_text_key != NULL) {
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen array_foreach(&mbox->resp_text_callbacks, mcb) {
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen if (strcasecmp(reply->resp_text_key, mcb->name) == 0)
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen mcb->callback(reply, mbox);
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen }
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen }
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstatic int
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenimapc_storage_create(struct mail_storage *_storage,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct mail_namespace *ns,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen const char **error_r)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct imapc_storage *storage = (struct imapc_storage *)_storage;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct imapc_client_settings set;
8a26102b8b1e08a774398980a8f92ae8f8575da8Timo Sirainen string_t *str;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen storage->set = mail_storage_get_driver_settings(_storage);
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen memset(&set, 0, sizeof(set));
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen set.host = storage->set->imapc_host;
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen if (*set.host == '\0') {
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen *error_r = "missing imapc_host";
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen return -1;
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen }
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen set.port = storage->set->imapc_port;
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen set.username = storage->set->imapc_user;
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen set.password = storage->set->imapc_password;
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen if (*set.password == '\0') {
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen *error_r = "missing imapc_password";
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return -1;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen }
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen set.dns_client_socket_path =
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen t_strconcat(_storage->user->set->base_dir, "/",
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen DNS_CLIENT_SOCKET_NAME, NULL);
97dc3902e9bcf2e17b9c249999bffba908231b62Timo Sirainen set.debug = _storage->set->mail_debug;
97dc3902e9bcf2e17b9c249999bffba908231b62Timo Sirainen
8a26102b8b1e08a774398980a8f92ae8f8575da8Timo Sirainen str = t_str_new(128);
8a26102b8b1e08a774398980a8f92ae8f8575da8Timo Sirainen mail_user_set_get_temp_prefix(str, _storage->user->set);
8a26102b8b1e08a774398980a8f92ae8f8575da8Timo Sirainen set.temp_path_prefix = str_c(str);
8a26102b8b1e08a774398980a8f92ae8f8575da8Timo Sirainen
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen set.ssl_ca_dir = storage->set->imapc_ssl_ca_dir;
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen if (strcmp(storage->set->imapc_ssl, "imaps") == 0)
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen set.ssl_mode = IMAPC_CLIENT_SSL_MODE_IMMEDIATE;
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen else if (strcmp(storage->set->imapc_ssl, "starttls") == 0)
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen set.ssl_mode = IMAPC_CLIENT_SSL_MODE_STARTTLS;
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen else
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen set.ssl_mode = IMAPC_CLIENT_SSL_MODE_NONE;
bfc7fcde95de729c7e5f18cca7566a3cf754c0ceTimo Sirainen
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen storage->list = (struct imapc_mailbox_list *)ns->list;
90de49eb151c2be7655ce6aef5aa3b58295d5c84Timo Sirainen storage->list->storage = storage;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen storage->client = imapc_client_init(&set);
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen p_array_init(&storage->untagged_callbacks, _storage->pool, 16);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_client_register_untagged(storage->client,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_storage_untagged_cb, storage);
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen imapc_list_register_callbacks(storage->list);
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen imapc_storage_register_untagged(storage, "STATUS",
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen imapc_untagged_status);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return 0;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstatic void imapc_storage_destroy(struct mail_storage *_storage)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct imapc_storage *storage = (struct imapc_storage *)_storage;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_client_deinit(&storage->client);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainenvoid imapc_storage_register_untagged(struct imapc_storage *storage,
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen const char *name,
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen imapc_storage_callback_t *callback)
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen{
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen struct imapc_storage_event_callback *cb;
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen cb = array_append_space(&storage->untagged_callbacks);
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen cb->name = p_strdup(storage->storage.pool, name);
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen cb->callback = callback;
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen}
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstatic void
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenimapc_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct mailbox_list_settings *set)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
90de49eb151c2be7655ce6aef5aa3b58295d5c84Timo Sirainen set->layout = MAILBOX_LIST_NAME_IMAPC;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstatic struct mailbox *
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenimapc_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen const char *vname, enum mailbox_flags flags)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct imapc_mailbox *mbox;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen pool_t pool;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen pool = pool_alloconly_create("imapc mailbox", 1024*3);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen mbox = p_new(pool, struct imapc_mailbox, 1);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen mbox->box = imapc_mailbox;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen mbox->box.pool = pool;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen mbox->box.storage = storage;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen mbox->box.list = list;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen mbox->box.mail_vfuncs = &imapc_mail_vfuncs;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
d83e46e7cd1ffd76210823dadcac549124c96d4eTimo Sirainen index_storage_mailbox_alloc(&mbox->box, vname, flags,
d83e46e7cd1ffd76210823dadcac549124c96d4eTimo Sirainen IMAPC_INDEX_PREFIX);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen mbox->storage = (struct imapc_storage *)storage;
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen p_array_init(&mbox->untagged_callbacks, pool, 16);
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen p_array_init(&mbox->resp_text_callbacks, pool, 16);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen p_array_init(&mbox->fetch_mails, pool, 16);
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen imapc_mailbox_register_callbacks(mbox);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return &mbox->box;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstatic void
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenimapc_mailbox_open_callback(const struct imapc_command_reply *reply,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen void *context)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct imapc_open_context *ctx = context;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen if (reply->state == IMAPC_COMMAND_STATE_OK)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen ctx->ret = 0;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen else if (reply->state == IMAPC_COMMAND_STATE_NO) {
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_copy_error_from_reply(ctx->mbox->storage,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen MAIL_ERROR_NOTFOUND, reply);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen ctx->ret = -1;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen } else {
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen mail_storage_set_critical(ctx->mbox->box.storage,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen "imapc: Opening mailbox '%s' failed: %s",
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen ctx->mbox->box.name, reply->text_full);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen ctx->ret = -1;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen }
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen if (!ctx->mbox->new_msgs)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_client_stop(ctx->mbox->storage->client);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstatic int imapc_mailbox_open(struct mailbox *box)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct imapc_mailbox *mbox = (struct imapc_mailbox *)box;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct imapc_open_context ctx;
0d5b4840dbb0abe79e1bddc77608c89fd0419e53Timo Sirainen bool examine;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen if (index_storage_mailbox_open(box, FALSE) < 0)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return -1;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
689b06e33729491b593fe34ad3267d65b79be149Timo Sirainen if (box->deleting || (box->flags & MAILBOX_FLAG_SAVEONLY) != 0) {
51130f00bbd1e119ec042d63c148a78ac06ab85eTimo Sirainen /* We don't actually want to SELECT the mailbox. */
51130f00bbd1e119ec042d63c148a78ac06ab85eTimo Sirainen return 0;
51130f00bbd1e119ec042d63c148a78ac06ab85eTimo Sirainen }
0d5b4840dbb0abe79e1bddc77608c89fd0419e53Timo Sirainen examine = (box->flags & MAILBOX_FLAG_READONLY) != 0 &&
0d5b4840dbb0abe79e1bddc77608c89fd0419e53Timo Sirainen (box->flags & MAILBOX_FLAG_DROP_RECENT) == 0;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
689b06e33729491b593fe34ad3267d65b79be149Timo Sirainen mbox->opening = TRUE;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen ctx.mbox = mbox;
0102d0a013e82fc352779f60e3d7bb49dee44bf0Timo Sirainen ctx.ret = -2;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen mbox->client_box =
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen imapc_client_mailbox_open(mbox->storage->client,
0d5b4840dbb0abe79e1bddc77608c89fd0419e53Timo Sirainen box->name, examine,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_mailbox_open_callback,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen &ctx, mbox);
0102d0a013e82fc352779f60e3d7bb49dee44bf0Timo Sirainen while (ctx.ret == -2)
0102d0a013e82fc352779f60e3d7bb49dee44bf0Timo Sirainen imapc_client_run(mbox->storage->client);
689b06e33729491b593fe34ad3267d65b79be149Timo Sirainen mbox->opening = FALSE;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen if (ctx.ret < 0) {
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen mailbox_close(box);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return -1;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen }
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return 0;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstatic void imapc_mailbox_close(struct mailbox *box)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct imapc_mailbox *mbox = (struct imapc_mailbox *)box;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
51130f00bbd1e119ec042d63c148a78ac06ab85eTimo Sirainen if (mbox->client_box != NULL)
51130f00bbd1e119ec042d63c148a78ac06ab85eTimo Sirainen imapc_client_mailbox_close(&mbox->client_box);
51130f00bbd1e119ec042d63c148a78ac06ab85eTimo Sirainen if (mbox->delayed_sync_view != NULL)
51130f00bbd1e119ec042d63c148a78ac06ab85eTimo Sirainen mail_index_view_close(&mbox->delayed_sync_view);
51130f00bbd1e119ec042d63c148a78ac06ab85eTimo Sirainen if (mbox->delayed_sync_trans != NULL) {
51130f00bbd1e119ec042d63c148a78ac06ab85eTimo Sirainen if (mail_index_transaction_commit(&mbox->delayed_sync_trans) < 0)
51130f00bbd1e119ec042d63c148a78ac06ab85eTimo Sirainen mail_storage_set_index_error(&mbox->box);
51130f00bbd1e119ec042d63c148a78ac06ab85eTimo Sirainen }
df48643c3c240ad5b8a3e2e2132c46f7dc541b5eTimo Sirainen if (mbox->sync_view != NULL)
df48643c3c240ad5b8a3e2e2132c46f7dc541b5eTimo Sirainen mail_index_view_close(&mbox->sync_view);
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen if (mbox->to_idle_delay != NULL)
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen timeout_remove(&mbox->to_idle_delay);
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen if (mbox->to_idle_check != NULL)
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen timeout_remove(&mbox->to_idle_check);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return index_storage_mailbox_close(box);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstatic int
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenimapc_mailbox_create(struct mailbox *box,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen const struct mailbox_update *update ATTR_UNUSED,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen bool directory)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct imapc_mailbox *mbox = (struct imapc_mailbox *)box;
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen struct imapc_simple_context sctx;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen const char *name = box->name;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen if (directory) {
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen name = t_strdup_printf("%s%c", name,
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen mailbox_list_get_hierarchy_sep(box->list));
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen }
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen imapc_simple_context_init(&sctx, mbox->storage);
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen imapc_client_cmdf(mbox->storage->client, imapc_simple_callback, &sctx,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen "CREATE %s", name);
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen imapc_simple_run(&sctx);
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen return sctx.ret;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstatic int imapc_mailbox_update(struct mailbox *box,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen const struct mailbox_update *update ATTR_UNUSED)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen "Not supported");
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return -1;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainenstatic void imapc_untagged_status(const struct imapc_untagged_reply *reply,
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen struct imapc_storage *storage)
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen{
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen struct mailbox_status *status;
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen const struct imap_arg *list;
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen const char *name, *key, *value;
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen uint32_t num;
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen unsigned int i;
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen if (!imap_arg_get_astring(&reply->args[0], &name) ||
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen !imap_arg_get_list(&reply->args[1], &list))
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen return;
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen if (storage->cur_status_box == NULL ||
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen strcmp(storage->cur_status_box->box.name, name) != 0)
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen return;
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen status = storage->cur_status;
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen for (i = 0; list[i].type != IMAP_ARG_EOL; i += 2) {
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen if (!imap_arg_get_atom(&list[i], &key) ||
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen !imap_arg_get_atom(&list[i+1], &value) ||
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen str_to_uint32(value, &num) < 0)
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen return;
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen if (strcasecmp(key, "MESSAGES") == 0)
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen status->messages = num;
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen else if (strcasecmp(key, "RECENT") == 0)
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen status->recent = num;
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen else if (strcasecmp(key, "UIDNEXT") == 0)
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen status->uidnext = num;
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen else if (strcasecmp(key, "UIDVALIDITY") == 0)
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen status->uidvalidity = num;
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen else if (strcasecmp(key, "UNSEEN") == 0)
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen status->unseen = num;
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen else if (strcasecmp(key, "HIGHESTMODSEQ") == 0)
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen status->highest_modseq = num;
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen }
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen}
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstatic void imapc_mailbox_get_selected_status(struct imapc_mailbox *mbox,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen enum mailbox_status_items items,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct mailbox_status *status_r)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen index_storage_get_status(&mbox->box, items, status_r);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstatic int imapc_mailbox_get_status(struct mailbox *box,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen enum mailbox_status_items items,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct mailbox_status *status_r)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct imapc_mailbox *mbox = (struct imapc_mailbox *)box;
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen struct imapc_simple_context sctx;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen string_t *str;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen memset(status_r, 0, sizeof(*status_r));
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen if (box->opened) {
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_mailbox_get_selected_status(mbox, items, status_r);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return 0;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen }
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen /* mailbox isn't opened yet */
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen if ((items & (STATUS_FIRST_UNSEEN_SEQ | STATUS_KEYWORDS)) != 0) {
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen /* getting these requires opening the mailbox */
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen if (mailbox_open(box) < 0)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return -1;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_mailbox_get_selected_status(mbox, items, status_r);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return 0;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen }
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen str = t_str_new(256);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen if ((items & STATUS_MESSAGES) != 0)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen str_append(str, " MESSAGES");
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen if ((items & STATUS_RECENT) != 0)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen str_append(str, " RECENT");
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen if ((items & STATUS_UIDNEXT) != 0)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen str_append(str, " UIDNEXT");
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen if ((items & STATUS_UIDVALIDITY) != 0)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen str_append(str, " UIDVALIDITY");
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen if ((items & STATUS_UNSEEN) != 0)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen str_append(str, " UNSEEN");
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen if ((items & STATUS_HIGHESTMODSEQ) != 0)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen str_append(str, " HIGHESTMODSEQ");
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen if (str_len(str) == 0) {
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen /* nothing requested */
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return 0;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen }
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen imapc_simple_context_init(&sctx, mbox->storage);
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen mbox->storage->cur_status_box = mbox;
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen mbox->storage->cur_status = status_r;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_client_cmdf(mbox->storage->client,
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen imapc_simple_callback, &sctx,
5235a79ca4ea7a9bc7e64bd17ed1617357a25034Timo Sirainen "STATUS %s (%1s)", box->name, str_c(str)+1);
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen imapc_simple_run(&sctx);
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen mbox->storage->cur_status_box = NULL;
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen mbox->storage->cur_status = NULL;
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen return sctx.ret;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstatic int imapc_mailbox_get_metadata(struct mailbox *box,
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen enum mailbox_metadata_items items,
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen struct mailbox_metadata *metadata_r)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen if ((items & MAILBOX_METADATA_GUID) != 0) {
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen /* a bit ugly way to do this, but better than nothing for now.
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen FIXME: if indexes are enabled, keep this there. */
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen mail_generate_guid_128_hash(box->name, metadata_r->guid);
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen }
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen return index_mailbox_get_metadata(box, items, metadata_r);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainenstatic void imapc_idle_timeout(struct imapc_mailbox *mbox)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen imapc_client_mailbox_cmd(mbox->client_box, "NOOP",
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen imapc_async_callback, mbox->storage);
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen}
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen
6021cfec086e455d5bf5db35522953e13a97bb61Timo Sirainenstatic void imapc_idle_noop_callback(const struct imapc_command_reply *reply,
6021cfec086e455d5bf5db35522953e13a97bb61Timo Sirainen void *context)
6021cfec086e455d5bf5db35522953e13a97bb61Timo Sirainen
6021cfec086e455d5bf5db35522953e13a97bb61Timo Sirainen{
6021cfec086e455d5bf5db35522953e13a97bb61Timo Sirainen struct imapc_mailbox *mbox = context;
6021cfec086e455d5bf5db35522953e13a97bb61Timo Sirainen
6021cfec086e455d5bf5db35522953e13a97bb61Timo Sirainen imapc_async_callback(reply, mbox->box.storage);
6021cfec086e455d5bf5db35522953e13a97bb61Timo Sirainen imapc_client_mailbox_idle(mbox->client_box);
6021cfec086e455d5bf5db35522953e13a97bb61Timo Sirainen}
6021cfec086e455d5bf5db35522953e13a97bb61Timo Sirainen
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainenstatic void imapc_notify_changes(struct mailbox *box)
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen{
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen struct imapc_mailbox *mbox = (struct imapc_mailbox *)box;
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen enum imapc_capability capa;
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen if (box->notify_min_interval == 0) {
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen if (mbox->to_idle_check != NULL)
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen timeout_remove(&mbox->to_idle_check);
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen return;
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen }
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen capa = imapc_client_get_capabilities(mbox->storage->client);
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen if ((capa & IMAPC_CAPABILITY_IDLE) != 0) {
847112173a65f36251cf39a7fd7d86eba6739953Timo Sirainen /* remote server is already in IDLE. but since some servers
847112173a65f36251cf39a7fd7d86eba6739953Timo Sirainen don't notice changes immediately, we'll force them to check
847112173a65f36251cf39a7fd7d86eba6739953Timo Sirainen here by sending a NOOP. this helps with clients that break
847112173a65f36251cf39a7fd7d86eba6739953Timo Sirainen IDLE when clicking "get mail". */
847112173a65f36251cf39a7fd7d86eba6739953Timo Sirainen imapc_client_mailbox_cmd(mbox->client_box, "NOOP",
6021cfec086e455d5bf5db35522953e13a97bb61Timo Sirainen imapc_idle_noop_callback, mbox);
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen } else {
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen /* remote server doesn't support IDLE.
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen check for changes with NOOP every once in a while. */
a2d397c3a8024156eb3b4b53c37d07d60588f1e4Timo Sirainen i_assert(!imapc_client_is_running(mbox->storage->client));
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen mbox->to_idle_check =
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen timeout_add(box->notify_min_interval * 1000,
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen imapc_idle_timeout, mbox);
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen }
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
df48643c3c240ad5b8a3e2e2132c46f7dc541b5eTimo Sirainenstatic bool imapc_is_inconsistent(struct mailbox *box)
df48643c3c240ad5b8a3e2e2132c46f7dc541b5eTimo Sirainen{
df48643c3c240ad5b8a3e2e2132c46f7dc541b5eTimo Sirainen struct imapc_mailbox *mbox = (struct imapc_mailbox *)box;
df48643c3c240ad5b8a3e2e2132c46f7dc541b5eTimo Sirainen
df48643c3c240ad5b8a3e2e2132c46f7dc541b5eTimo Sirainen if (mail_index_view_is_inconsistent(box->view))
df48643c3c240ad5b8a3e2e2132c46f7dc541b5eTimo Sirainen return TRUE;
df48643c3c240ad5b8a3e2e2132c46f7dc541b5eTimo Sirainen
df48643c3c240ad5b8a3e2e2132c46f7dc541b5eTimo Sirainen return !imapc_client_mailbox_is_connected(mbox->client_box);
df48643c3c240ad5b8a3e2e2132c46f7dc541b5eTimo Sirainen}
df48643c3c240ad5b8a3e2e2132c46f7dc541b5eTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstruct mail_storage imapc_storage = {
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen .name = IMAPC_STORAGE_NAME,
dfaefeabae939803ceb8c503101e86b5496541d1Timo Sirainen .class_flags = MAIL_STORAGE_CLASS_FLAG_NO_ROOT,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen .v = {
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen imapc_get_setting_parser_info,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_storage_alloc,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_storage_create,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_storage_destroy,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen NULL,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_storage_get_list_settings,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen NULL,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_mailbox_alloc,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen NULL
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen }
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen};
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstruct mailbox imapc_mailbox = {
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen .v = {
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen index_storage_is_readonly,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen index_storage_mailbox_enable,
306cfd77100131c08b243de10f6d40500f4c27c6Timo Sirainen index_storage_mailbox_exists,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_mailbox_open,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_mailbox_close,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen index_storage_mailbox_free,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_mailbox_create,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_mailbox_update,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen index_storage_mailbox_delete,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen index_storage_mailbox_rename,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_mailbox_get_status,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_mailbox_get_metadata,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen NULL,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen NULL,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_mailbox_sync_init,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen index_mailbox_sync_next,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_mailbox_sync_deinit,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen NULL,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_notify_changes,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen index_transaction_begin,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen index_transaction_commit,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen index_transaction_rollback,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen NULL,
94a77d6e5d7600859e4c5e4a7ea19dc3e91998b9Timo Sirainen imapc_mail_alloc,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen index_storage_search_init,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen index_storage_search_deinit,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen index_storage_search_next_nonblock,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen index_storage_search_next_update_seq,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_save_alloc,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_save_begin,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_save_continue,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_save_finish,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_save_cancel,
689b06e33729491b593fe34ad3267d65b79be149Timo Sirainen imapc_copy,
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen imapc_transaction_save_commit_pre,
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen imapc_transaction_save_commit_post,
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen imapc_transaction_save_rollback,
df48643c3c240ad5b8a3e2e2132c46f7dc541b5eTimo Sirainen imapc_is_inconsistent
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen }
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen};