imapc-storage.c revision c1a2ab40974dc48ca68b9fc58799b01bbcb9520b
7cb128dc4cae2a03a742f63ba7afee23c78e3af0Phil Carmody/* Copyright (c) 2011-2015 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"
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainen#include "mailbox-tree.h"
f5be4f5b4a1bba7f3497f52d01e582b82af2b355Timo Sirainen#include "imapc-client.h"
951c92a29c36d22a60e56cae4b47d5d0fa5dd6b5Timo Sirainen#include "imapc-connection.h"
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen#include "imapc-msgmap.h"
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen#include "imapc-mail.h"
90de49eb151c2be7655ce6aef5aa3b58295d5c84Timo Sirainen#include "imapc-list.h"
6e1cac3defe84a222b804f3ef41ff558e1a86391Timo Sirainen#include "imapc-search.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
0db42260be85e797aa9909a29b20296996f52e75Timo Sirainenextern struct mail_storage imapc_storage;
0db42260be85e797aa9909a29b20296996f52e75Timo Sirainenextern struct mailbox imapc_mailbox;
0db42260be85e797aa9909a29b20296996f52e75Timo 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 },
2ed2459dbd183bb371da4a0aecb2d2b74ae7c815Timo Sirainen { IMAP_RESP_CODE_OVERQUOTA, MAIL_ERROR_NOQUOTA },
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,
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen struct imapc_storage_client *client);
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainenstatic void imapc_untagged_namespace(const struct imapc_untagged_reply *reply,
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen struct imapc_storage_client *client);
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainenbool imap_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;
f5be4f5b4a1bba7f3497f52d01e582b82af2b355Timo Sirainen storage->root_ioloop = current_ioloop;
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,
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen struct imapc_storage_client *client)
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen{
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen memset(sctx, 0, sizeof(*sctx));
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen sctx->client = client;
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen sctx->ret = -2;
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen}
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainenvoid imapc_simple_run(struct imapc_simple_context *sctx)
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen{
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen if (sctx->client->auth_failed) {
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen imapc_client_disconnect(sctx->client->client);
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen sctx->ret = -1;
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen }
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen while (sctx->ret == -2)
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_client_run(sctx->client->client);
951c92a29c36d22a60e56cae4b47d5d0fa5dd6b5Timo Sirainen}
951c92a29c36d22a60e56cae4b47d5d0fa5dd6b5Timo Sirainen
1a878b9d2a823abc6b1c8b1631e50a15d534665fTimo Sirainenvoid imapc_mailbox_run(struct imapc_mailbox *mbox)
951c92a29c36d22a60e56cae4b47d5d0fa5dd6b5Timo Sirainen{
1a878b9d2a823abc6b1c8b1631e50a15d534665fTimo Sirainen imapc_mail_fetch_flush(mbox);
fda7b3649d2ccdb4a95f5bf09eb8cf5435d57261Timo Sirainen imapc_mailbox_run_nofetch(mbox);
fda7b3649d2ccdb4a95f5bf09eb8cf5435d57261Timo Sirainen}
fda7b3649d2ccdb4a95f5bf09eb8cf5435d57261Timo Sirainen
fda7b3649d2ccdb4a95f5bf09eb8cf5435d57261Timo Sirainenvoid imapc_mailbox_run_nofetch(struct imapc_mailbox *mbox)
fda7b3649d2ccdb4a95f5bf09eb8cf5435d57261Timo Sirainen{
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen do {
1a878b9d2a823abc6b1c8b1631e50a15d534665fTimo Sirainen imapc_client_run(mbox->storage->client->client);
1a878b9d2a823abc6b1c8b1631e50a15d534665fTimo Sirainen } while (mbox->storage->reopen_count > 0);
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) {
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_copy_error_from_reply(ctx->client->_storage,
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen MAIL_ERROR_PARAMS, reply);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen ctx->ret = -1;
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen } else if (ctx->client->auth_failed) {
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen ctx->ret = -1;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen } else {
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen mail_storage_set_critical(&ctx->client->_storage->storage,
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen "imapc: Command failed: %s", reply->text_full);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen ctx->ret = -1;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen }
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_client_stop(ctx->client->client);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
b50e80d237435686c4ea525643f266731a600981Timo Sirainenvoid imapc_mailbox_noop(struct imapc_mailbox *mbox)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
b50e80d237435686c4ea525643f266731a600981Timo Sirainen struct imapc_command *cmd;
b50e80d237435686c4ea525643f266731a600981Timo Sirainen struct imapc_simple_context sctx;
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen
ad9403d54b5a0f312de6fa22abda6c120988d3deTimo Sirainen if (mbox->client_box == NULL) {
ad9403d54b5a0f312de6fa22abda6c120988d3deTimo Sirainen /* mailbox opening hasn't finished yet */
ad9403d54b5a0f312de6fa22abda6c120988d3deTimo Sirainen return;
ad9403d54b5a0f312de6fa22abda6c120988d3deTimo Sirainen }
ad9403d54b5a0f312de6fa22abda6c120988d3deTimo Sirainen
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_simple_context_init(&sctx, mbox->storage->client);
b50e80d237435686c4ea525643f266731a600981Timo Sirainen cmd = imapc_client_mailbox_cmd(mbox->client_box,
b50e80d237435686c4ea525643f266731a600981Timo Sirainen imapc_simple_callback, &sctx);
b50e80d237435686c4ea525643f266731a600981Timo Sirainen imapc_command_send(cmd, "NOOP");
b50e80d237435686c4ea525643f266731a600981Timo Sirainen imapc_simple_run(&sctx);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainenstatic void
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainenimapc_storage_client_untagged_cb(const struct imapc_untagged_reply *reply,
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen void *context)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen struct imapc_storage_client *client = 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
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen array_foreach(&client->untagged_callbacks, cb) {
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen if (strcasecmp(reply->name, cb->name) == 0)
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen cb->callback(reply, client);
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
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainenstatic void
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainenimapc_storage_client_login(const struct imapc_command_reply *reply,
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen void *context)
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen{
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen struct imapc_storage_client *client = context;
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen if (reply->state == IMAPC_COMMAND_STATE_OK)
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen return;
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen i_error("imapc: Authentication failed: %s", reply->text_full);
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen client->auth_failed = TRUE;
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen if (client->_storage != NULL) {
014cfdf92b145bc7ff4d1393ca24dfef5c109b0fTimo Sirainen if (reply->state == IMAPC_COMMAND_STATE_DISCONNECTED)
014cfdf92b145bc7ff4d1393ca24dfef5c109b0fTimo Sirainen mail_storage_set_internal_error(&client->_storage->storage);
014cfdf92b145bc7ff4d1393ca24dfef5c109b0fTimo Sirainen else {
014cfdf92b145bc7ff4d1393ca24dfef5c109b0fTimo Sirainen mail_storage_set_error(&client->_storage->storage,
014cfdf92b145bc7ff4d1393ca24dfef5c109b0fTimo Sirainen MAIL_ERROR_PERM, reply->text_full);
014cfdf92b145bc7ff4d1393ca24dfef5c109b0fTimo Sirainen }
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen }
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen if (client->_list != NULL) {
014cfdf92b145bc7ff4d1393ca24dfef5c109b0fTimo Sirainen if (reply->state == IMAPC_COMMAND_STATE_DISCONNECTED)
014cfdf92b145bc7ff4d1393ca24dfef5c109b0fTimo Sirainen mailbox_list_set_internal_error(&client->_list->list);
014cfdf92b145bc7ff4d1393ca24dfef5c109b0fTimo Sirainen else {
014cfdf92b145bc7ff4d1393ca24dfef5c109b0fTimo Sirainen mailbox_list_set_error(&client->_list->list,
014cfdf92b145bc7ff4d1393ca24dfef5c109b0fTimo Sirainen MAIL_ERROR_PERM, reply->text_full);
014cfdf92b145bc7ff4d1393ca24dfef5c109b0fTimo Sirainen }
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen }
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen}
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainenint imapc_storage_client_create(struct mail_namespace *ns,
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen const struct imapc_settings *imapc_set,
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen const struct mail_storage_settings *mail_set,
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen struct imapc_storage_client **client_r,
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen const char **error_r)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen struct imapc_storage_client *client;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct imapc_client_settings set;
8a26102b8b1e08a774398980a8f92ae8f8575da8Timo Sirainen string_t *str;
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen memset(&set, 0, sizeof(set));
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen set.host = imapc_set->imapc_host;
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen if (*set.host == '\0') {
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen *error_r = "missing imapc_host";
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen return -1;
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen }
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen set.port = imapc_set->imapc_port;
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen if (imapc_set->imapc_user[0] != '\0')
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen set.username = imapc_set->imapc_user;
0bf0c44fce1df29e60f4f5b312ebe862d44aa237Timo Sirainen else if (ns->owner != NULL)
0bf0c44fce1df29e60f4f5b312ebe862d44aa237Timo Sirainen set.username = ns->owner->username;
0bf0c44fce1df29e60f4f5b312ebe862d44aa237Timo Sirainen else
0bf0c44fce1df29e60f4f5b312ebe862d44aa237Timo Sirainen set.username = ns->user->username;
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen set.master_user = imapc_set->imapc_master_user;
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen set.password = imapc_set->imapc_password;
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen if (*set.password == '\0') {
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen *error_r = "missing imapc_password";
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return -1;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen }
c6033074ada5c7441ff7bb12c4b433cae737fea2Timo Sirainen set.sasl_mechanisms = imapc_set->imapc_sasl_mechanisms;
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen set.max_idle_time = imapc_set->imapc_max_idle_time;
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen set.dns_client_socket_path = *ns->user->set->base_dir == '\0' ? "" :
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen t_strconcat(ns->user->set->base_dir, "/",
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen DNS_CLIENT_SOCKET_NAME, NULL);
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen set.debug = mail_set->mail_debug;
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen set.rawlog_dir = mail_user_home_expand(ns->user,
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen imapc_set->imapc_rawlog_dir);
97dc3902e9bcf2e17b9c249999bffba908231b62Timo Sirainen
8a26102b8b1e08a774398980a8f92ae8f8575da8Timo Sirainen str = t_str_new(128);
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen mail_user_set_get_temp_prefix(str, ns->user->set);
8a26102b8b1e08a774398980a8f92ae8f8575da8Timo Sirainen set.temp_path_prefix = str_c(str);
8a26102b8b1e08a774398980a8f92ae8f8575da8Timo Sirainen
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen set.ssl_ca_dir = mail_set->ssl_client_ca_dir;
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen set.ssl_ca_file = mail_set->ssl_client_ca_file;
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen set.ssl_verify = imapc_set->imapc_ssl_verify;
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen if (strcmp(imapc_set->imapc_ssl, "imaps") == 0)
c5d6b453eccc0962eae967abc10e028a740e1256Timo Sirainen set.ssl_mode = IMAPC_CLIENT_SSL_MODE_IMMEDIATE;
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen else if (strcmp(imapc_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;
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen set.ssl_crypto_device = mail_set->ssl_crypto_device;
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen
de26c21cfadf24c1fa59f06414854d58b3d8baadTimo Sirainen set.throttle_set.init_msecs = imapc_set->throttle_init_msecs;
de26c21cfadf24c1fa59f06414854d58b3d8baadTimo Sirainen set.throttle_set.max_msecs = imapc_set->throttle_max_msecs;
de26c21cfadf24c1fa59f06414854d58b3d8baadTimo Sirainen set.throttle_set.shrink_min_msecs = imapc_set->throttle_shrink_min_msecs;
de26c21cfadf24c1fa59f06414854d58b3d8baadTimo Sirainen
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen client = i_new(struct imapc_storage_client, 1);
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen client->refcount = 1;
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen i_array_init(&client->untagged_callbacks, 16);
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen client->client = imapc_client_init(&set);
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_client_register_untagged(client->client,
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_storage_client_untagged_cb, client);
c1a2ab40974dc48ca68b9fc58799b01bbcb9520bTimo Sirainen if ((ns->flags & NAMESPACE_FLAG_LIST_PREFIX) != 0) {
c1a2ab40974dc48ca68b9fc58799b01bbcb9520bTimo Sirainen /* start logging in immediately */
c1a2ab40974dc48ca68b9fc58799b01bbcb9520bTimo Sirainen imapc_client_login(client->client, imapc_storage_client_login, client);
c1a2ab40974dc48ca68b9fc58799b01bbcb9520bTimo Sirainen }
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen *client_r = client;
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen return 0;
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen}
bfc7fcde95de729c7e5f18cca7566a3cf754c0ceTimo Sirainen
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainenvoid imapc_storage_client_unref(struct imapc_storage_client **_client)
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen{
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen struct imapc_storage_client *client = *_client;
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen struct imapc_storage_event_callback *cb;
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen *_client = NULL;
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen i_assert(client->refcount > 0);
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen if (--client->refcount > 0)
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen return;
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_client_deinit(&client->client);
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen array_foreach_modifiable(&client->untagged_callbacks, cb)
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen i_free(cb->name);
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen array_free(&client->untagged_callbacks);
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen i_free(client);
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen}
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainenstatic int
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainenimapc_storage_create(struct mail_storage *_storage,
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen struct mail_namespace *ns,
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen const char **error_r)
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen{
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen struct imapc_storage *storage = (struct imapc_storage *)_storage;
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen struct imapc_mailbox_list *imapc_list = NULL;
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen storage->set = mail_storage_get_driver_settings(_storage);
af466fd3ee9d17f2e7b264079d25306c5598b200Timo Sirainen if (strcmp(ns->list->name, MAILBOX_LIST_NAME_IMAPC) == 0) {
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_list = (struct imapc_mailbox_list *)ns->list;
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen storage->client = imapc_list->client;
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen storage->client->refcount++;
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen } else {
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen if (imapc_storage_client_create(ns, storage->set, _storage->set,
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen &storage->client, error_r) < 0)
3ec969c5cee55a7b08ab5c5bf7afae310176e2bdTimo Sirainen return -1;
b720f55c568cce0a1c8c2be74e588b66bb467e82Timo Sirainen }
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen storage->client->_storage = storage;
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen p_array_init(&storage->remote_namespaces, _storage->pool, 4);
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_storage_client_register_untagged(storage->client, "STATUS",
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_untagged_status);
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_storage_client_register_untagged(storage->client, "NAMESPACE",
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_untagged_namespace);
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
9a7f22e2c14b507e6044e5534df978a0c3b638d0Timo Sirainen /* make sure all pending commands are aborted before anything is
9a7f22e2c14b507e6044e5534df978a0c3b638d0Timo Sirainen deinitialized */
9a7f22e2c14b507e6044e5534df978a0c3b638d0Timo Sirainen imapc_client_disconnect(storage->client->client);
9a7f22e2c14b507e6044e5534df978a0c3b638d0Timo Sirainen
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_storage_client_unref(&storage->client);
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen index_storage_destroy(_storage);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainenvoid imapc_storage_client_register_untagged(struct imapc_storage_client *client,
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen const char *name,
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_storage_callback_t *callback)
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen{
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen struct imapc_storage_event_callback *cb;
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen cb = array_append_space(&client->untagged_callbacks);
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen cb->name = i_strdup(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;
7cf1c7dd3dfd989cba1ed32a8e17c1b031c4629bTimo Sirainen set->escape_char = IMAPC_LIST_ESCAPE_CHAR;
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
feccf3f8679807f25d105521d5f6ddce6df7cdceTimo Sirainen pool = pool_alloconly_create("imapc mailbox", 1024*4);
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
8c909e451d14075c05d90382cf8eebc4e354f569Timo Sirainen index_storage_mailbox_alloc(&mbox->box, vname, flags, MAIL_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);
1a878b9d2a823abc6b1c8b1631e50a15d534665fTimo Sirainen p_array_init(&mbox->fetch_requests, pool, 16);
d30c35e25ea6d935393e031509e6e22422b1e006Timo Sirainen p_array_init(&mbox->delayed_expunged_uids, pool, 16);
1a878b9d2a823abc6b1c8b1631e50a15d534665fTimo Sirainen mbox->pending_fetch_cmd = str_new(pool, 128);
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen mbox->prev_mail_cache.fd = -1;
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen imapc_mailbox_register_callbacks(mbox);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return &mbox->box;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainenstatic int
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainenimapc_mailbox_exists(struct mailbox *box, bool auto_boxes ATTR_UNUSED,
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainen enum mailbox_existence *existence_r)
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainen{
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainen enum mailbox_info_flags flags;
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainen
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainen if (imapc_list_get_mailbox_flags(box->list, box->name, &flags) < 0)
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainen return -1;
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainen if ((flags & MAILBOX_NONEXISTENT) != 0)
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainen *existence_r = MAILBOX_EXISTENCE_NONE;
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainen else if ((flags & MAILBOX_NOSELECT) != 0)
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainen *existence_r = MAILBOX_EXISTENCE_NOSELECT;
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainen else
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainen *existence_r = MAILBOX_EXISTENCE_SELECT;
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainen return 0;
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainen}
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainen
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainenstatic bool imapc_mailbox_want_examine(struct imapc_mailbox *mbox)
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen{
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen return (mbox->box.flags & MAILBOX_FLAG_DROP_RECENT) == 0 &&
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen ((mbox->box.flags & MAILBOX_FLAG_READONLY) != 0 ||
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen (mbox->box.flags & MAILBOX_FLAG_SAVEONLY) != 0);
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen}
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainenstatic void
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainenimapc_mailbox_reopen_callback(const struct imapc_command_reply *reply,
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen void *context)
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen{
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen struct imapc_mailbox *mbox = context;
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen i_assert(mbox->storage->reopen_count > 0);
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen mbox->storage->reopen_count--;
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen mbox->selecting = FALSE;
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen if (reply->state != IMAPC_COMMAND_STATE_OK) {
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen mail_storage_set_critical(mbox->box.storage,
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen "imapc: Reopening mailbox '%s' failed: %s",
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen mbox->box.name, reply->text_full);
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen imapc_client_mailbox_reconnect(mbox->client_box);
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen }
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_client_stop(mbox->storage->client->client);
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen}
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainenstatic void imapc_mailbox_reopen(void *context)
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen{
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen struct imapc_mailbox *mbox = context;
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen struct imapc_command *cmd;
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen /* we're reconnecting and need to reopen the mailbox */
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen mbox->initial_sync_done = FALSE;
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen mbox->selecting = TRUE;
b2048c45f6c6ace7d90a2c05f0f3fc6e03e30f38Timo Sirainen mbox->prev_skipped_rseq = 0;
b2048c45f6c6ace7d90a2c05f0f3fc6e03e30f38Timo Sirainen mbox->prev_skipped_uid = 0;
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen imapc_msgmap_reset(imapc_client_mailbox_get_msgmap(mbox->client_box));
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen cmd = imapc_client_mailbox_cmd(mbox->client_box,
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen imapc_mailbox_reopen_callback, mbox);
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_SELECT);
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen if (imapc_mailbox_want_examine(mbox))
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen imapc_command_sendf(cmd, "EXAMINE %s", mbox->box.name);
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen else
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen imapc_command_sendf(cmd, "SELECT %s", mbox->box.name);
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen mbox->storage->reopen_count++;
f87844c400cf9741abad57d9815121d0738a738fTimo Sirainen
f87844c400cf9741abad57d9815121d0738a738fTimo Sirainen if (mbox->syncing)
f87844c400cf9741abad57d9815121d0738a738fTimo Sirainen imapc_sync_mailbox_reopened(mbox);
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen}
edcd6f7223568e080d5a6767c5038e3bc891e963Timo 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
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen ctx->mbox->selecting = FALSE;
03f2a189a0985d87cfe443a1a5cc8ab6da052c30Timo Sirainen ctx->mbox->selected = TRUE;
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;
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen } else if (ctx->mbox->storage->client->auth_failed) {
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo 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 }
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_client_stop(ctx->mbox->storage->client->client);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainenstatic void imapc_mailbox_get_extensions(struct imapc_mailbox *mbox)
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen{
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen enum imapc_capability capa =
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_client_get_capabilities(mbox->storage->client->client);
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen if (mbox->guid_fetch_field_name == NULL) {
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen /* see if we can get message GUIDs somehow */
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen if ((capa & IMAPC_CAPABILITY_X_GM_EXT_1) != 0) {
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen /* GMail */
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen mbox->guid_fetch_field_name = "X-GM-MSGID";
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen }
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen }
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen}
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainenint imapc_mailbox_select(struct imapc_mailbox *mbox)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
fb37a9b7bb71807a394e3ecdb74511f32a79c39bTimo Sirainen struct imapc_command *cmd;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct imapc_open_context ctx;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
fb37a9b7bb71807a394e3ecdb74511f32a79c39bTimo Sirainen i_assert(mbox->client_box == NULL);
fb37a9b7bb71807a394e3ecdb74511f32a79c39bTimo Sirainen
a7348c7fdc2c65d6452f740ccdfa29e66916e5d7Timo Sirainen /* If authentication failed, don't check again. */
a7348c7fdc2c65d6452f740ccdfa29e66916e5d7Timo Sirainen if (mbox->storage->client->auth_failed) {
a7348c7fdc2c65d6452f740ccdfa29e66916e5d7Timo Sirainen mail_storage_set_internal_error(&mbox->storage->storage);
a7348c7fdc2c65d6452f740ccdfa29e66916e5d7Timo Sirainen return -1;
a7348c7fdc2c65d6452f740ccdfa29e66916e5d7Timo Sirainen }
a7348c7fdc2c65d6452f740ccdfa29e66916e5d7Timo Sirainen
fb37a9b7bb71807a394e3ecdb74511f32a79c39bTimo Sirainen mbox->client_box =
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_client_mailbox_open(mbox->storage->client->client, mbox);
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen imapc_client_mailbox_set_reopen_cb(mbox->client_box,
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen imapc_mailbox_reopen, mbox);
fb37a9b7bb71807a394e3ecdb74511f32a79c39bTimo Sirainen
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen imapc_mailbox_get_extensions(mbox);
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen
afb49e8adab954708e3f192386a3c7faa07e5ae5Timo Sirainen mbox->selecting = TRUE;
afb49e8adab954708e3f192386a3c7faa07e5ae5Timo Sirainen ctx.mbox = mbox;
afb49e8adab954708e3f192386a3c7faa07e5ae5Timo Sirainen ctx.ret = -2;
fb37a9b7bb71807a394e3ecdb74511f32a79c39bTimo Sirainen cmd = imapc_client_mailbox_cmd(mbox->client_box,
fb37a9b7bb71807a394e3ecdb74511f32a79c39bTimo Sirainen imapc_mailbox_open_callback, &ctx);
fb37a9b7bb71807a394e3ecdb74511f32a79c39bTimo Sirainen imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_SELECT);
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen if (imapc_mailbox_want_examine(mbox))
fb37a9b7bb71807a394e3ecdb74511f32a79c39bTimo Sirainen imapc_command_sendf(cmd, "EXAMINE %s", mbox->box.name);
fb37a9b7bb71807a394e3ecdb74511f32a79c39bTimo Sirainen else
fb37a9b7bb71807a394e3ecdb74511f32a79c39bTimo Sirainen imapc_command_sendf(cmd, "SELECT %s", mbox->box.name);
fb37a9b7bb71807a394e3ecdb74511f32a79c39bTimo Sirainen
afb49e8adab954708e3f192386a3c7faa07e5ae5Timo Sirainen while (ctx.ret == -2)
1a878b9d2a823abc6b1c8b1631e50a15d534665fTimo Sirainen imapc_mailbox_run(mbox);
afb49e8adab954708e3f192386a3c7faa07e5ae5Timo Sirainen return ctx.ret;
afb49e8adab954708e3f192386a3c7faa07e5ae5Timo Sirainen}
afb49e8adab954708e3f192386a3c7faa07e5ae5Timo Sirainen
afb49e8adab954708e3f192386a3c7faa07e5ae5Timo Sirainenstatic int imapc_mailbox_open(struct mailbox *box)
afb49e8adab954708e3f192386a3c7faa07e5ae5Timo Sirainen{
afb49e8adab954708e3f192386a3c7faa07e5ae5Timo Sirainen struct imapc_mailbox *mbox = (struct imapc_mailbox *)box;
afb49e8adab954708e3f192386a3c7faa07e5ae5Timo 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 }
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
2dc23f3416724163cc5d7162c577a8ed9f985fedTimo Sirainen if (*box->name == '\0' &&
2dc23f3416724163cc5d7162c577a8ed9f985fedTimo Sirainen (box->list->ns->flags & NAMESPACE_FLAG_INBOX_ANY) != 0) {
2dc23f3416724163cc5d7162c577a8ed9f985fedTimo Sirainen /* trying to open INBOX as the namespace prefix.
2dc23f3416724163cc5d7162c577a8ed9f985fedTimo Sirainen Don't allow this. */
2dc23f3416724163cc5d7162c577a8ed9f985fedTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
2dc23f3416724163cc5d7162c577a8ed9f985fedTimo Sirainen "Mailbox isn't selectable");
2dc23f3416724163cc5d7162c577a8ed9f985fedTimo Sirainen mailbox_close(box);
2dc23f3416724163cc5d7162c577a8ed9f985fedTimo Sirainen return -1;
2dc23f3416724163cc5d7162c577a8ed9f985fedTimo Sirainen }
2dc23f3416724163cc5d7162c577a8ed9f985fedTimo Sirainen
afb49e8adab954708e3f192386a3c7faa07e5ae5Timo Sirainen if (imapc_mailbox_select(mbox) < 0) {
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen mailbox_close(box);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return -1;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen }
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return 0;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainenvoid imapc_mail_cache_free(struct imapc_mail_cache *cache)
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen{
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen if (cache->fd != -1) {
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen if (close(cache->fd) < 0)
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen i_error("close(imapc cached mail) failed: %m");
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen cache->fd = -1;
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen }
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen if (cache->buf != NULL)
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen buffer_free(&cache->buf);
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen cache->uid = 0;
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen}
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstatic void imapc_mailbox_close(struct mailbox *box)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen struct imapc_mailbox *mbox = (struct imapc_mailbox *)box;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
1a878b9d2a823abc6b1c8b1631e50a15d534665fTimo Sirainen imapc_mail_fetch_flush(mbox);
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)
1f1ee8db68d9ae1604350801cd8dc33ebe29fe8aTimo Sirainen mailbox_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);
97ff916ad7977bb8147750b8cf40d0d25d0730f6Timo Sirainen imapc_mail_cache_free(&mbox->prev_mail_cache);
c5a7be1b6f1a957065951f24530741faa18c58a6Timo Sirainen 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;
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen struct imapc_command *cmd;
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen struct imapc_simple_context sctx;
4bb24a20bb017b6e3301d6a8e961a08aa71cf10fTimo 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 }
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_simple_context_init(&sctx, mbox->storage->client);
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen cmd = imapc_client_cmd(mbox->storage->client->client,
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen imapc_simple_callback, &sctx);
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen imapc_command_sendf(cmd, "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,
6bb12832eb490920803b5ad184b1759c63f455bfTimo Sirainen const struct mailbox_update *update)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
6bb12832eb490920803b5ad184b1759c63f455bfTimo Sirainen if (!guid_128_is_empty(update->mailbox_guid) ||
6bb12832eb490920803b5ad184b1759c63f455bfTimo Sirainen update->uid_validity != 0 || update->min_next_uid != 0 ||
6bb12832eb490920803b5ad184b1759c63f455bfTimo Sirainen update->min_first_recent_uid != 0) {
6bb12832eb490920803b5ad184b1759c63f455bfTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
6bb12832eb490920803b5ad184b1759c63f455bfTimo Sirainen "Not supported");
6bb12832eb490920803b5ad184b1759c63f455bfTimo Sirainen }
6bb12832eb490920803b5ad184b1759c63f455bfTimo Sirainen return index_storage_mailbox_update(box, update);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainenstatic void imapc_untagged_status(const struct imapc_untagged_reply *reply,
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen struct imapc_storage_client *client)
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen{
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen struct imapc_storage *storage = client->_storage;
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 }
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen}
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainenstatic void imapc_untagged_namespace(const struct imapc_untagged_reply *reply,
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen struct imapc_storage_client *client)
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen{
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen struct imapc_storage *storage = client->_storage;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen static enum mail_namespace_type ns_types[] = {
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen MAIL_NAMESPACE_TYPE_PRIVATE,
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen MAIL_NAMESPACE_TYPE_SHARED,
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen MAIL_NAMESPACE_TYPE_PUBLIC
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen };
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen struct imapc_namespace *ns;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen const struct imap_arg *list, *list2;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen const char *prefix, *sep;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen unsigned int i;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen array_clear(&storage->remote_namespaces);
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen for (i = 0; i < N_ELEMENTS(ns_types); i++) {
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen if (reply->args[i].type == IMAP_ARG_NIL)
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen continue;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen if (!imap_arg_get_list(&reply->args[i], &list))
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen break;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen for (; list->type != IMAP_ARG_EOL; list++) {
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen if (!imap_arg_get_list(list, &list2) ||
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen !imap_arg_get_astring(&list2[0], &prefix) ||
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen !imap_arg_get_nstring(&list2[1], &sep))
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen break;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen ns = array_append_space(&storage->remote_namespaces);
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen ns->prefix = p_strdup(storage->storage.pool, prefix);
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen ns->separator = sep == NULL ? '\0' : sep[0];
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen ns->type = ns_types[i];
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen }
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen }
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen}
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo 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{
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen index_storage_get_open_status(&mbox->box, items, status_r);
d1b3f17d857237ea9a27bb58785bd5c6f0d3a185Timo Sirainen if ((items & STATUS_PERMANENT_FLAGS) != 0)
d1b3f17d857237ea9a27bb58785bd5c6f0d3a185Timo Sirainen status_r->permanent_flags = mbox->permanent_flags;
acfdd1b1625fae310faee8e5e2480c4f224fb648Timo Sirainen if ((items & STATUS_FIRST_RECENT_UID) != 0)
acfdd1b1625fae310faee8e5e2480c4f224fb648Timo Sirainen status_r->first_recent_uid = mbox->highest_nonrecent_uid + 1;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
58ba0fe5a6904d3a65cfe268411f4cbb881234eeTimo Sirainenstatic int imapc_mailbox_delete(struct mailbox *box)
58ba0fe5a6904d3a65cfe268411f4cbb881234eeTimo Sirainen{
58ba0fe5a6904d3a65cfe268411f4cbb881234eeTimo Sirainen box->delete_skip_empty_check = TRUE;
58ba0fe5a6904d3a65cfe268411f4cbb881234eeTimo Sirainen return index_storage_mailbox_delete(box);
58ba0fe5a6904d3a65cfe268411f4cbb881234eeTimo Sirainen}
58ba0fe5a6904d3a65cfe268411f4cbb881234eeTimo Sirainen
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainenstatic int imapc_mailbox_run_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;
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen struct imapc_command *cmd;
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen struct imapc_simple_context sctx;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen string_t *str;
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
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen if (str_len(str) == 0) {
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen /* nothing requested */
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return 0;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen }
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_simple_context_init(&sctx, mbox->storage->client);
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen mbox->storage->cur_status_box = mbox;
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen mbox->storage->cur_status = status_r;
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen cmd = imapc_client_cmd(mbox->storage->client->client,
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen imapc_simple_callback, &sctx);
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen imapc_command_sendf(cmd, "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
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainenstatic int imapc_mailbox_get_status(struct mailbox *box,
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen enum mailbox_status_items items,
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen struct mailbox_status *status_r)
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen{
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen struct imapc_mailbox *mbox = (struct imapc_mailbox *)box;
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen if (mbox->guid_fetch_field_name != NULL ||
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_GUID_FORCED))
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen status_r->have_guids = TRUE;
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen if (box->opened) {
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen imapc_mailbox_get_selected_status(mbox, items, status_r);
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen } else if ((items & (STATUS_FIRST_UNSEEN_SEQ | STATUS_KEYWORDS |
acfdd1b1625fae310faee8e5e2480c4f224fb648Timo Sirainen STATUS_PERMANENT_FLAGS |
acfdd1b1625fae310faee8e5e2480c4f224fb648Timo Sirainen STATUS_FIRST_RECENT_UID)) != 0) {
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen /* getting these requires opening the mailbox */
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen if (mailbox_open(box) < 0)
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen return -1;
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen imapc_mailbox_get_selected_status(mbox, items, status_r);
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen } else {
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen if (imapc_mailbox_run_status(box, items, status_r) < 0)
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen return -1;
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen }
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen if (box->opened && (items & STATUS_UIDNEXT) != 0 &&
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen mbox->sync_uid_next == 0) {
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen /* Courier-workaround, it doesn't send UIDNEXT on SELECT */
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen if (imapc_mailbox_run_status(box, STATUS_UIDNEXT, status_r) < 0)
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen return -1;
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen }
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen return 0;
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen}
b5d2b15b763729a19a03b905d5ae341f759c7db2Timo Sirainen
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainenstatic int imapc_mailbox_get_namespaces(struct imapc_storage *storage)
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen{
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen enum imapc_capability capa;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen struct imapc_command *cmd;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen struct imapc_simple_context sctx;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen if (storage->namespaces_requested)
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen return 0;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen capa = imapc_client_get_capabilities(storage->client->client);
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen if ((capa & IMAPC_CAPABILITY_NAMESPACE) == 0) {
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen /* NAMESPACE capability not supported */
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen return 0;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen }
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_simple_context_init(&sctx, storage->client);
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen cmd = imapc_client_cmd(storage->client->client,
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen imapc_simple_callback, &sctx);
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen imapc_command_send(cmd, "NAMESPACE");
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen imapc_simple_run(&sctx);
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen if (sctx.ret < 0)
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen return -1;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen storage->namespaces_requested = TRUE;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen return 0;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen}
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainenstatic const struct imapc_namespace *
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainenimapc_namespace_find_mailbox(struct imapc_storage *storage, const char *name)
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen{
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen const struct imapc_namespace *ns, *best_ns = NULL;
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen unsigned int best_len = UINT_MAX, len;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen array_foreach(&storage->remote_namespaces, ns) {
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen len = strlen(ns->prefix);
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen if (strncmp(ns->prefix, name, len) == 0) {
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen if (best_len > len) {
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen best_ns = ns;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen best_len = len;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen }
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen }
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen }
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen return best_ns;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen}
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo 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{
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen struct imapc_mailbox *mbox = (struct imapc_mailbox *)box;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen const struct imapc_namespace *ns;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo 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);
40c0aad390ce459959f5e26bab8a2ea7818d1addTimo Sirainen items &= ~MAILBOX_METADATA_GUID;
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen }
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen if ((items & MAILBOX_METADATA_BACKEND_NAMESPACE) != 0) {
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen if (imapc_mailbox_get_namespaces(mbox->storage) < 0)
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen return -1;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen ns = imapc_namespace_find_mailbox(mbox->storage, box->name);
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen if (ns != NULL) {
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen metadata_r->backend_ns_prefix = ns->prefix;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen metadata_r->backend_ns_type = ns->type;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen }
40c0aad390ce459959f5e26bab8a2ea7818d1addTimo Sirainen items &= ~MAILBOX_METADATA_BACKEND_NAMESPACE;
40c0aad390ce459959f5e26bab8a2ea7818d1addTimo Sirainen }
40c0aad390ce459959f5e26bab8a2ea7818d1addTimo Sirainen if (items != 0) {
40c0aad390ce459959f5e26bab8a2ea7818d1addTimo Sirainen if (index_mailbox_get_metadata(box, items, metadata_r) < 0)
40c0aad390ce459959f5e26bab8a2ea7818d1addTimo Sirainen return -1;
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen }
206ed2f6fa3a6fb291498627b2da626581c07a18Timo Sirainen return 0;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
b50e80d237435686c4ea525643f266731a600981Timo Sirainenstatic void imapc_noop_callback(const struct imapc_command_reply *reply,
b50e80d237435686c4ea525643f266731a600981Timo Sirainen void *context)
b50e80d237435686c4ea525643f266731a600981Timo Sirainen
b50e80d237435686c4ea525643f266731a600981Timo Sirainen{
b50e80d237435686c4ea525643f266731a600981Timo Sirainen struct imapc_storage *storage = context;
b50e80d237435686c4ea525643f266731a600981Timo Sirainen
b50e80d237435686c4ea525643f266731a600981Timo Sirainen if (reply->state == IMAPC_COMMAND_STATE_OK)
b50e80d237435686c4ea525643f266731a600981Timo Sirainen ;
b50e80d237435686c4ea525643f266731a600981Timo Sirainen else if (reply->state == IMAPC_COMMAND_STATE_NO)
b50e80d237435686c4ea525643f266731a600981Timo Sirainen imapc_copy_error_from_reply(storage, MAIL_ERROR_PARAMS, reply);
b50e80d237435686c4ea525643f266731a600981Timo Sirainen else if (reply->state == IMAPC_COMMAND_STATE_DISCONNECTED)
b50e80d237435686c4ea525643f266731a600981Timo Sirainen mail_storage_set_internal_error(&storage->storage);
b50e80d237435686c4ea525643f266731a600981Timo Sirainen else {
b50e80d237435686c4ea525643f266731a600981Timo Sirainen mail_storage_set_critical(&storage->storage,
b50e80d237435686c4ea525643f266731a600981Timo Sirainen "imapc: NOOP failed: %s", reply->text_full);
b50e80d237435686c4ea525643f266731a600981Timo Sirainen }
b50e80d237435686c4ea525643f266731a600981Timo Sirainen}
b50e80d237435686c4ea525643f266731a600981Timo Sirainen
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainenstatic void imapc_idle_timeout(struct imapc_mailbox *mbox)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen struct imapc_command *cmd;
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen cmd = imapc_client_mailbox_cmd(mbox->client_box,
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen imapc_noop_callback, mbox->storage);
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen imapc_command_send(cmd, "NOOP");
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
e809db9220c804b16d4d74782433a1075da12274Timo Sirainen imapc_noop_callback(reply, mbox->box.storage);
14a717c9600c1e9e41ea2c4f7e52af613d874d7eTimo Sirainen if (mbox->client_box != NULL)
14a717c9600c1e9e41ea2c4f7e52af613d874d7eTimo 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;
9438ecaf1caee1bb33c8d7f638742875ac42c4e5Timo Sirainen const struct mail_storage_settings *set = box->storage->set;
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen struct imapc_command *cmd;
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen enum imapc_capability capa;
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen
9438ecaf1caee1bb33c8d7f638742875ac42c4e5Timo Sirainen if (box->notify_callback == NULL) {
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen if (mbox->to_idle_check != NULL)
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen timeout_remove(&mbox->to_idle_check);
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen return;
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen }
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen capa = imapc_client_get_capabilities(mbox->storage->client->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". */
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen cmd = imapc_client_mailbox_cmd(mbox->client_box,
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen imapc_idle_noop_callback, mbox);
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen imapc_command_send(cmd, "NOOP");
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen } else {
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen /* remote server doesn't support IDLE.
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen check for changes with NOOP every once in a while. */
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen i_assert(!imapc_client_is_running(mbox->storage->client->client));
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen mbox->to_idle_check =
9438ecaf1caee1bb33c8d7f638742875ac42c4e5Timo Sirainen timeout_add(set->mailbox_idle_check_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
4733d3729d64480179a30698bb3412d0a074b6ebTimo Sirainen if (box->view != NULL &&
4733d3729d64480179a30698bb3412d0a074b6ebTimo Sirainen mail_index_view_is_inconsistent(box->view))
df48643c3c240ad5b8a3e2e2132c46f7dc541b5eTimo Sirainen return TRUE;
df48643c3c240ad5b8a3e2e2132c46f7dc541b5eTimo Sirainen
4733d3729d64480179a30698bb3412d0a074b6ebTimo Sirainen return mbox->client_box == NULL ? FALSE :
4733d3729d64480179a30698bb3412d0a074b6ebTimo Sirainen !imapc_client_mailbox_is_opened(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,
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo 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,
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainen imapc_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,
58ba0fe5a6904d3a65cfe268411f4cbb881234eeTimo Sirainen imapc_mailbox_delete,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen index_storage_mailbox_rename,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_mailbox_get_status,
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen imapc_mailbox_get_metadata,
6469cf211a57433335641725dc236ebb2b9fdd3bTimo Sirainen index_storage_set_subscribed,
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen index_storage_attribute_set,
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen index_storage_attribute_get,
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen index_storage_attribute_iter_init,
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen index_storage_attribute_iter_next,
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen index_storage_attribute_iter_deinit,
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,
6e1cac3defe84a222b804f3ef41ff558e1a86391Timo Sirainen imapc_search_init,
6e1cac3defe84a222b804f3ef41ff558e1a86391Timo Sirainen imapc_search_deinit,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen index_storage_search_next_nonblock,
6e1cac3defe84a222b804f3ef41ff558e1a86391Timo Sirainen imapc_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};