bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2011-2018 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"
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 },
2898ad0028a9b0c30df96dd6b68930fd4dc57527Timo Sirainen { IMAP_RESP_CODE_LIMIT, MAIL_ERROR_LIMIT },
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);
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainenstatic int imapc_mailbox_run_status(struct mailbox *box,
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen enum mailbox_status_items items,
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen struct mailbox_status *status_r);
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
6e40a39f6886edbba5ad498391c299983f8f94e9Timo Sirainenbool imapc_mailbox_has_modseqs(struct imapc_mailbox *mbox)
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen{
150542702397445873dca327c82c5c7f09322437Timo Sirainen return (mbox->capabilities & (IMAPC_CAPABILITY_CONDSTORE |
150542702397445873dca327c82c5c7f09322437Timo Sirainen IMAPC_CAPABILITY_QRESYNC)) != 0 &&
6e40a39f6886edbba5ad498391c299983f8f94e9Timo Sirainen IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_MODSEQ);
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen}
90355e35d1139e446a99733986a9181bd7f05dd4Timo 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{
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(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{
be21b9e65a37c29995899f7923f6d7e5771dc3adTimo Sirainen if (imapc_storage_client_handle_auth_failure(sctx->client)) {
d35da39e688b94bb7e9adc6c865a45004c64a506Timo Sirainen imapc_client_logout(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);
f8f30bd27e41e1041a8de0b97f35d7d75e0a412eTimo Sirainen } while (mbox->storage->reopen_count > 0 ||
f8f30bd27e41e1041a8de0b97f35d7d75e0a412eTimo Sirainen mbox->state_fetching_uid1);
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;
be21b9e65a37c29995899f7923f6d7e5771dc3adTimo Sirainen } else if (imapc_storage_client_handle_auth_failure(ctx->client)) {
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen ctx->ret = -1;
b80e0097ab96ca62d1b9ddf4b2d7b7c77c745307Timo Sirainen } else if (reply->state == IMAPC_COMMAND_STATE_DISCONNECTED) {
b80e0097ab96ca62d1b9ddf4b2d7b7c77c745307Timo Sirainen mail_storage_set_internal_error(&ctx->client->_storage->storage);
b80e0097ab96ca62d1b9ddf4b2d7b7c77c745307Timo 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
92cd929df2ebf3291886a11542b2815a426e906dTimo Sirainenimapc_storage_client_login_callback(const struct imapc_command_reply *reply,
92cd929df2ebf3291886a11542b2815a426e906dTimo Sirainen void *context)
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen{
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen struct imapc_storage_client *client = context;
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen
92cd929df2ebf3291886a11542b2815a426e906dTimo Sirainen client->auth_returned = TRUE;
92cd929df2ebf3291886a11542b2815a426e906dTimo Sirainen imapc_client_stop(client->client);
92cd929df2ebf3291886a11542b2815a426e906dTimo Sirainen
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen if (reply->state == IMAPC_COMMAND_STATE_OK)
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen return;
9a717bf84366bdd2ee25f95c49ffc911999dbd1fTimo Sirainen if (client->destroying &&
9a717bf84366bdd2ee25f95c49ffc911999dbd1fTimo Sirainen reply->state == IMAPC_COMMAND_STATE_DISCONNECTED) {
9a717bf84366bdd2ee25f95c49ffc911999dbd1fTimo Sirainen /* user's work was finished before imapc login finished -
9a717bf84366bdd2ee25f95c49ffc911999dbd1fTimo Sirainen it's not an error */
9a717bf84366bdd2ee25f95c49ffc911999dbd1fTimo Sirainen return;
9a717bf84366bdd2ee25f95c49ffc911999dbd1fTimo Sirainen }
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen
be21b9e65a37c29995899f7923f6d7e5771dc3adTimo Sirainen client->auth_failed_state = reply->state;
28576b6283287ef3ca6ae0d818ebd4ce6c879107Timo Sirainen client->auth_failed_reason = i_strdup(reply->text_full);
ab838f1555795d5766bdaef795a14c98a5437c9eTimo Sirainen if (!imapc_storage_client_handle_auth_failure(client))
ab838f1555795d5766bdaef795a14c98a5437c9eTimo Sirainen i_unreached();
ab838f1555795d5766bdaef795a14c98a5437c9eTimo Sirainen}
ab838f1555795d5766bdaef795a14c98a5437c9eTimo Sirainen
ab838f1555795d5766bdaef795a14c98a5437c9eTimo Sirainenbool imapc_storage_client_handle_auth_failure(struct imapc_storage_client *client)
ab838f1555795d5766bdaef795a14c98a5437c9eTimo Sirainen{
ab838f1555795d5766bdaef795a14c98a5437c9eTimo Sirainen if (client->auth_failed_state == IMAPC_COMMAND_STATE_OK)
ab838f1555795d5766bdaef795a14c98a5437c9eTimo Sirainen return FALSE;
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen
ab838f1555795d5766bdaef795a14c98a5437c9eTimo Sirainen /* We need to set the error to either storage or to list, depending on
ab838f1555795d5766bdaef795a14c98a5437c9eTimo Sirainen whether the caller is from mail-storage.h API or mailbox-list.h API.
ab838f1555795d5766bdaef795a14c98a5437c9eTimo Sirainen We don't know here what the caller is though, so just set the error
ab838f1555795d5766bdaef795a14c98a5437c9eTimo Sirainen to both of them. */
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen if (client->_storage != NULL) {
ab838f1555795d5766bdaef795a14c98a5437c9eTimo Sirainen if (client->auth_failed_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,
ab838f1555795d5766bdaef795a14c98a5437c9eTimo Sirainen MAIL_ERROR_PERM, client->auth_failed_reason);
014cfdf92b145bc7ff4d1393ca24dfef5c109b0fTimo Sirainen }
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen }
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen if (client->_list != NULL) {
ab838f1555795d5766bdaef795a14c98a5437c9eTimo Sirainen if (client->auth_failed_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,
ab838f1555795d5766bdaef795a14c98a5437c9eTimo Sirainen MAIL_ERROR_PERM, client->auth_failed_reason);
014cfdf92b145bc7ff4d1393ca24dfef5c109b0fTimo Sirainen }
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen }
ab838f1555795d5766bdaef795a14c98a5437c9eTimo Sirainen return TRUE;
be21b9e65a37c29995899f7923f6d7e5771dc3adTimo Sirainen}
be21b9e65a37c29995899f7923f6d7e5771dc3adTimo Sirainen
92cd929df2ebf3291886a11542b2815a426e906dTimo Sirainenstatic void imapc_storage_client_login(struct imapc_storage_client *client,
92cd929df2ebf3291886a11542b2815a426e906dTimo Sirainen struct mail_user *user, const char *host)
92cd929df2ebf3291886a11542b2815a426e906dTimo Sirainen{
276c62e4538faf5bf3ae127a7b7c246c5d37add2Aki Tuomi imapc_client_login(client->client);
92cd929df2ebf3291886a11542b2815a426e906dTimo Sirainen if (!user->namespaces_created) {
92cd929df2ebf3291886a11542b2815a426e906dTimo Sirainen /* we're still initializing the user. wait for the
92cd929df2ebf3291886a11542b2815a426e906dTimo Sirainen login to finish, so we can fail the user creation
92cd929df2ebf3291886a11542b2815a426e906dTimo Sirainen if it fails. */
92cd929df2ebf3291886a11542b2815a426e906dTimo Sirainen while (!client->auth_returned)
92cd929df2ebf3291886a11542b2815a426e906dTimo Sirainen imapc_client_run(client->client);
be21b9e65a37c29995899f7923f6d7e5771dc3adTimo Sirainen if (imapc_storage_client_handle_auth_failure(client)) {
92cd929df2ebf3291886a11542b2815a426e906dTimo Sirainen user->error = p_strdup_printf(user->pool,
92cd929df2ebf3291886a11542b2815a426e906dTimo Sirainen "imapc: Login to %s failed: %s",
28576b6283287ef3ca6ae0d818ebd4ce6c879107Timo Sirainen host, client->auth_failed_reason);
92cd929df2ebf3291886a11542b2815a426e906dTimo Sirainen }
92cd929df2ebf3291886a11542b2815a426e906dTimo Sirainen }
92cd929df2ebf3291886a11542b2815a426e906dTimo Sirainen}
92cd929df2ebf3291886a11542b2815a426e906dTimo 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
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&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;
bd06c77a12bb02871b25dceb749fa955f4a272ffTimo Sirainen set.use_proxyauth = (imapc_set->parsed_features & IMAPC_FEATURE_PROXYAUTH) != 0;
cff23ec51177f11902c99b727268eb05ea7c97c7Timo Sirainen set.cmd_timeout_msecs = imapc_set->imapc_cmd_timeout * 1000;
c515f5c969f7a3a5b525ab15bde2f116cbe932deAki Tuomi set.connect_retry_count = imapc_set->imapc_connection_retry_count;
efd4de737ee4febffced006511f357959234a6caTimo Sirainen set.connect_retry_interval_msecs = imapc_set->imapc_connection_retry_interval;
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen set.max_idle_time = imapc_set->imapc_max_idle_time;
c23ebb9b0e0b760ca8da16fde34ff33f5ece5e07Timo Sirainen set.max_line_length = imapc_set->imapc_max_line_length;
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);
3c8055b25beef96e7be25895bac34f3eda7ceca1Timo Sirainen if ((imapc_set->parsed_features & IMAPC_FEATURE_SEND_ID) != 0)
3c8055b25beef96e7be25895bac34f3eda7ceca1Timo Sirainen set.session_id_prefix = ns->user->session_id;
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);
276c62e4538faf5bf3ae127a7b7c246c5d37add2Aki Tuomi
276c62e4538faf5bf3ae127a7b7c246c5d37add2Aki Tuomi imapc_client_set_login_callback(client->client, imapc_storage_client_login_callback, client);
276c62e4538faf5bf3ae127a7b7c246c5d37add2Aki Tuomi
30871b77e627d3d6b244305fbea7aeee578f2927Timo Sirainen if ((ns->flags & NAMESPACE_FLAG_LIST_PREFIX) != 0 &&
30871b77e627d3d6b244305fbea7aeee578f2927Timo Sirainen (imapc_set->parsed_features & IMAPC_FEATURE_DELAY_LOGIN) == 0) {
c1a2ab40974dc48ca68b9fc58799b01bbcb9520bTimo Sirainen /* start logging in immediately */
92cd929df2ebf3291886a11542b2815a426e906dTimo Sirainen imapc_storage_client_login(client, ns->user, set.host);
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);
28576b6283287ef3ca6ae0d818ebd4ce6c879107Timo Sirainen i_free(client->auth_failed_reason);
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{
7b0a52bf38f8a7ab0c262acf4c761d6a0f22a07cJosef 'Jeff' Sipek struct imapc_storage *storage = IMAPC_STORAGE(_storage);
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen struct imapc_mailbox_list *imapc_list = NULL;
4ee385fb4e4b007d3fa907b7616988006a21e85fTimo Sirainen
46e917c9fa05cbe7bddf805d3a9838b61e3960e1Timo Sirainen storage->set = mail_namespace_get_driver_settings(ns, _storage);
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek /* serialize all the settings */
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek _storage->unique_root_dir = p_strdup_printf(_storage->pool,
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek "%s%s://(%s|%s):%s@%s:%u/%s mechs:%s features:%s "
2f26f75219804e775c44f6b45a201a941d5590c3Timo Sirainen "rawlog:%s cmd_timeout:%u maxidle:%u maxline:%"PRIuSIZE_T"u "
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek "pop3delflg:%s root_dir:%s",
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek storage->set->imapc_ssl,
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek storage->set->imapc_ssl_verify ? "(verify)" : "",
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek storage->set->imapc_user,
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek storage->set->imapc_master_user,
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek storage->set->imapc_password,
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek storage->set->imapc_host,
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek storage->set->imapc_port,
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek storage->set->imapc_list_prefix,
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek storage->set->imapc_sasl_mechanisms,
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek storage->set->imapc_features,
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek storage->set->imapc_rawlog_dir,
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek storage->set->imapc_cmd_timeout,
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek storage->set->imapc_max_idle_time,
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek (size_t) storage->set->imapc_max_line_length,
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek storage->set->pop3_deleted_flag,
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek ns->list->set.root_dir);
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek
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);
e1005f8bf9190e1778010032dbd20c64acb53610Timo Sirainen if (IMAPC_HAS_FEATURE(storage, IMAPC_FEATURE_FETCH_BODYSTRUCTURE)) {
e1005f8bf9190e1778010032dbd20c64acb53610Timo Sirainen _storage->nonbody_access_fields |=
e1005f8bf9190e1778010032dbd20c64acb53610Timo Sirainen MAIL_FETCH_IMAP_BODY | MAIL_FETCH_IMAP_BODYSTRUCTURE;
e1005f8bf9190e1778010032dbd20c64acb53610Timo Sirainen }
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);
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen return 0;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstatic void imapc_storage_destroy(struct mail_storage *_storage)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
7b0a52bf38f8a7ab0c262acf4c761d6a0f22a07cJosef 'Jeff' Sipek struct imapc_storage *storage = IMAPC_STORAGE(_storage);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
9a717bf84366bdd2ee25f95c49ffc911999dbd1fTimo Sirainen storage->client->destroying = TRUE;
9a717bf84366bdd2ee25f95c49ffc911999dbd1fTimo Sirainen
9a7f22e2c14b507e6044e5534df978a0c3b638d0Timo Sirainen /* make sure all pending commands are aborted before anything is
9a7f22e2c14b507e6044e5534df978a0c3b638d0Timo Sirainen deinitialized */
d35da39e688b94bb7e9adc6c865a45004c64a506Timo Sirainen imapc_client_logout(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{
64a36868b6e11c91da3d051d581e1a52c6da2f43Timo Sirainen if (set->layout == NULL)
64a36868b6e11c91da3d051d581e1a52c6da2f43Timo 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
7b0a52bf38f8a7ab0c262acf4c761d6a0f22a07cJosef 'Jeff' Sipek mbox->storage = 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
f97b503210435b74de3b26cba07315cbc9ea1dfcTimo Sirainenconst char *imapc_mailbox_get_remote_name(struct imapc_mailbox *mbox)
f97b503210435b74de3b26cba07315cbc9ea1dfcTimo Sirainen{
f97b503210435b74de3b26cba07315cbc9ea1dfcTimo Sirainen if (strcmp(mbox->box.list->name, MAILBOX_LIST_NAME_IMAPC) != 0)
f97b503210435b74de3b26cba07315cbc9ea1dfcTimo Sirainen return mbox->box.name;
f97b503210435b74de3b26cba07315cbc9ea1dfcTimo Sirainen return imapc_list_to_remote((struct imapc_mailbox_list *)mbox->box.list,
f97b503210435b74de3b26cba07315cbc9ea1dfcTimo Sirainen mbox->box.name);
f97b503210435b74de3b26cba07315cbc9ea1dfcTimo Sirainen}
f97b503210435b74de3b26cba07315cbc9ea1dfcTimo 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{
378653a02a5a673e995f47e48a3371804171f964Timo Sirainen if (strcmp(box->list->name, MAILBOX_LIST_NAME_IMAPC) != 0) {
378653a02a5a673e995f47e48a3371804171f964Timo Sirainen if (box->inbox_any)
378653a02a5a673e995f47e48a3371804171f964Timo Sirainen *existence_r = MAILBOX_EXISTENCE_SELECT;
378653a02a5a673e995f47e48a3371804171f964Timo Sirainen else
378653a02a5a673e995f47e48a3371804171f964Timo Sirainen *existence_r = MAILBOX_EXISTENCE_NONE;
378653a02a5a673e995f47e48a3371804171f964Timo Sirainen return 0;
378653a02a5a673e995f47e48a3371804171f964Timo Sirainen }
378653a02a5a673e995f47e48a3371804171f964Timo Sirainen
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainen enum mailbox_info_flags flags;
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainen
1f31b38b6668439f0ee135c150dd2a71c2fa54c9Aki Tuomi struct imapc_mailbox_list *list = (struct imapc_mailbox_list *)box->list;
1f31b38b6668439f0ee135c150dd2a71c2fa54c9Aki Tuomi
be21b9e65a37c29995899f7923f6d7e5771dc3adTimo Sirainen if (imapc_storage_client_handle_auth_failure(list->client)) {
1f31b38b6668439f0ee135c150dd2a71c2fa54c9Aki Tuomi mail_storage_copy_list_error(box->storage, box->list);
1f31b38b6668439f0ee135c150dd2a71c2fa54c9Aki Tuomi return -1;
1f31b38b6668439f0ee135c150dd2a71c2fa54c9Aki Tuomi }
e74f4afdd0cdeeb9a5cebd7973dfc9adbe6cb426Timo Sirainen if (imapc_list_get_mailbox_flags(box->list, box->name, &flags) < 0) {
e74f4afdd0cdeeb9a5cebd7973dfc9adbe6cb426Timo Sirainen mail_storage_copy_list_error(box->storage, box->list);
1228c0604b8e21e170bba3e2060331599a378110Timo Sirainen return -1;
e74f4afdd0cdeeb9a5cebd7973dfc9adbe6cb426Timo Sirainen }
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{
df596e34b604e6ac873de9ca92fb5df2a5fed45fTimo Sirainen if (IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_NO_EXAMINE)) {
df596e34b604e6ac873de9ca92fb5df2a5fed45fTimo Sirainen /* mainly a Courier-workaround: With POP3-only Maildir that
df596e34b604e6ac873de9ca92fb5df2a5fed45fTimo Sirainen doesn't have UIDVALIDITY set, EXAMINE won't generate a
df596e34b604e6ac873de9ca92fb5df2a5fed45fTimo Sirainen permanent UIDVALIDITY while SELECT will. */
df596e34b604e6ac873de9ca92fb5df2a5fed45fTimo Sirainen return FALSE;
df596e34b604e6ac873de9ca92fb5df2a5fed45fTimo 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
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainenstatic bool
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainenimapc_mailbox_verify_select(struct imapc_mailbox *mbox, const char **error_r)
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen{
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen if (!mbox->exists_received)
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen *error_r = "EXISTS not received";
7efe57b10e55b29d3e618fa8194c01a9093f0d07Timo Sirainen else if (mbox->sync_uid_validity == 0)
7efe57b10e55b29d3e618fa8194c01a9093f0d07Timo Sirainen *error_r = "UIDVALIDITY not received";
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen else
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen return TRUE;
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen return FALSE;
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen}
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo 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;
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen const char *errmsg;
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen i_assert(mbox->storage->reopen_count > 0);
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen mbox->storage->reopen_count--;
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen mbox->selecting = FALSE;
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen if (reply->state != IMAPC_COMMAND_STATE_OK)
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen errmsg = reply->text_full;
2352ce293bab6bb5371805d8c58a09f15a11e0c9Timo Sirainen else if (imapc_mailbox_verify_select(mbox, &errmsg)) {
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen errmsg = NULL;
2352ce293bab6bb5371805d8c58a09f15a11e0c9Timo Sirainen mbox->selected = TRUE;
2352ce293bab6bb5371805d8c58a09f15a11e0c9Timo Sirainen }
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen if (errmsg != NULL) {
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen imapc_client_mailbox_reconnect(mbox->client_box,
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen t_strdup_printf("Reopening mailbox '%s' failed: %s",
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen mbox->box.name, errmsg));
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen }
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo 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 */
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
bc3309d262b7e38e20446d302caea9a05888f6c1Timo Sirainen if (mbox->selecting) {
bc3309d262b7e38e20446d302caea9a05888f6c1Timo Sirainen /* We reconnected during the initial SELECT/EXAMINE. It'll be
bc3309d262b7e38e20446d302caea9a05888f6c1Timo Sirainen automatically resent by lib-imap-client, so we don't need to
bc3309d262b7e38e20446d302caea9a05888f6c1Timo Sirainen send it again here. */
bc3309d262b7e38e20446d302caea9a05888f6c1Timo Sirainen i_assert(!mbox->initial_sync_done);
bc3309d262b7e38e20446d302caea9a05888f6c1Timo Sirainen return;
bc3309d262b7e38e20446d302caea9a05888f6c1Timo Sirainen }
bc3309d262b7e38e20446d302caea9a05888f6c1Timo Sirainen
bc3309d262b7e38e20446d302caea9a05888f6c1Timo Sirainen mbox->initial_sync_done = FALSE;
bc3309d262b7e38e20446d302caea9a05888f6c1Timo Sirainen mbox->selecting = TRUE;
2352ce293bab6bb5371805d8c58a09f15a11e0c9Timo Sirainen mbox->selected = FALSE;
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen mbox->exists_received = FALSE;
bc3309d262b7e38e20446d302caea9a05888f6c1Timo 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);
ae9b70a446dccba3160fb0df332f84ef98825604Timo Sirainen if (imapc_mailbox_want_examine(mbox)) {
ae9b70a446dccba3160fb0df332f84ef98825604Timo Sirainen imapc_command_sendf(cmd, "EXAMINE %s",
f97b503210435b74de3b26cba07315cbc9ea1dfcTimo Sirainen imapc_mailbox_get_remote_name(mbox));
ae9b70a446dccba3160fb0df332f84ef98825604Timo Sirainen } else {
ae9b70a446dccba3160fb0df332f84ef98825604Timo Sirainen imapc_command_sendf(cmd, "SELECT %s",
f97b503210435b74de3b26cba07315cbc9ea1dfcTimo Sirainen imapc_mailbox_get_remote_name(mbox));
ae9b70a446dccba3160fb0df332f84ef98825604Timo Sirainen }
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen mbox->storage->reopen_count++;
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;
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen const char *error;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
edcd6f7223568e080d5a6767c5038e3bc891e963Timo Sirainen ctx->mbox->selecting = FALSE;
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen if (reply->state == IMAPC_COMMAND_STATE_OK) {
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen if (!imapc_mailbox_verify_select(ctx->mbox, &error)) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(&ctx->mbox->box,
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi "imapc: Opening mailbox failed: %s", error);
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen ctx->ret = -1;
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen } else {
2352ce293bab6bb5371805d8c58a09f15a11e0c9Timo Sirainen ctx->mbox->selected = TRUE;
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen ctx->ret = 0;
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen }
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo 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;
be21b9e65a37c29995899f7923f6d7e5771dc3adTimo Sirainen } else if (imapc_storage_client_handle_auth_failure(ctx->mbox->storage->client)) {
ce7c2091ca9f19a13c835d1d522832a73f7cfaa0Timo Sirainen ctx->ret = -1;
b80e0097ab96ca62d1b9ddf4b2d7b7c77c745307Timo Sirainen } else if (reply->state == IMAPC_COMMAND_STATE_DISCONNECTED) {
b80e0097ab96ca62d1b9ddf4b2d7b7c77c745307Timo Sirainen ctx->ret = -1;
b80e0097ab96ca62d1b9ddf4b2d7b7c77c745307Timo Sirainen mail_storage_set_internal_error(ctx->mbox->box.storage);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen } else {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(&ctx->mbox->box,
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi "imapc: Opening mailbox failed: %s", reply->text_full);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen ctx->ret = -1;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen }
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_client_stop(ctx->mbox->storage->client->client);
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen}
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
e00612b245b41cc47a5c6214794c415aaa8c91b7Timo Sirainenstatic int imapc_mailbox_get_capabilities(struct imapc_mailbox *mbox)
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen{
f94abb02d228a078defac6d457f15cb6d8f82ddaTimo Sirainen /* If authentication failed, don't check again. */
f94abb02d228a078defac6d457f15cb6d8f82ddaTimo Sirainen if (imapc_storage_client_handle_auth_failure(mbox->storage->client))
f94abb02d228a078defac6d457f15cb6d8f82ddaTimo Sirainen return -1;
f94abb02d228a078defac6d457f15cb6d8f82ddaTimo Sirainen
e00612b245b41cc47a5c6214794c415aaa8c91b7Timo Sirainen return imapc_client_get_capabilities(mbox->storage->client->client,
e00612b245b41cc47a5c6214794c415aaa8c91b7Timo Sirainen &mbox->capabilities);
e00612b245b41cc47a5c6214794c415aaa8c91b7Timo Sirainen
150542702397445873dca327c82c5c7f09322437Timo Sirainen}
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen
150542702397445873dca327c82c5c7f09322437Timo Sirainenstatic void imapc_mailbox_get_extensions(struct imapc_mailbox *mbox)
150542702397445873dca327c82c5c7f09322437Timo Sirainen{
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen if (mbox->guid_fetch_field_name == NULL) {
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen /* see if we can get message GUIDs somehow */
150542702397445873dca327c82c5c7f09322437Timo Sirainen if ((mbox->capabilities & 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
e00612b245b41cc47a5c6214794c415aaa8c91b7Timo Sirainen if (imapc_mailbox_get_capabilities(mbox) < 0)
e00612b245b41cc47a5c6214794c415aaa8c91b7Timo Sirainen return -1;
a7348c7fdc2c65d6452f740ccdfa29e66916e5d7Timo Sirainen
6e40a39f6886edbba5ad498391c299983f8f94e9Timo Sirainen if (imapc_mailbox_has_modseqs(mbox)) {
fc452ed724837734a04214bc8f9f112c603b28f7Timo Sirainen if (!array_is_created(&mbox->rseq_modseqs))
fc452ed724837734a04214bc8f9f112c603b28f7Timo Sirainen i_array_init(&mbox->rseq_modseqs, 32);
fc452ed724837734a04214bc8f9f112c603b28f7Timo Sirainen else
fc452ed724837734a04214bc8f9f112c603b28f7Timo Sirainen array_clear(&mbox->rseq_modseqs);
fc452ed724837734a04214bc8f9f112c603b28f7Timo Sirainen }
fc452ed724837734a04214bc8f9f112c603b28f7Timo 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;
6e853fdf3a5670a2eb2d57b059afcee7fb6cbd47Timo Sirainen mbox->exists_received = FALSE;
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);
e82efb347c91c199218e41065c2acb3464247b1aTimo Sirainen imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_SELECT |
e82efb347c91c199218e41065c2acb3464247b1aTimo Sirainen IMAPC_COMMAND_FLAG_RETRIABLE);
ae9b70a446dccba3160fb0df332f84ef98825604Timo Sirainen if (imapc_mailbox_want_examine(mbox)) {
ae9b70a446dccba3160fb0df332f84ef98825604Timo Sirainen imapc_command_sendf(cmd, "EXAMINE %s",
f97b503210435b74de3b26cba07315cbc9ea1dfcTimo Sirainen imapc_mailbox_get_remote_name(mbox));
ae9b70a446dccba3160fb0df332f84ef98825604Timo Sirainen } else {
ae9b70a446dccba3160fb0df332f84ef98825604Timo Sirainen imapc_command_sendf(cmd, "SELECT %s",
f97b503210435b74de3b26cba07315cbc9ea1dfcTimo Sirainen imapc_mailbox_get_remote_name(mbox));
ae9b70a446dccba3160fb0df332f84ef98825604Timo Sirainen }
fb37a9b7bb71807a394e3ecdb74511f32a79c39bTimo Sirainen
f8f30bd27e41e1041a8de0b97f35d7d75e0a412eTimo Sirainen while (ctx.ret == -2 || mbox->state_fetching_uid1)
1a878b9d2a823abc6b1c8b1631e50a15d534665fTimo Sirainen imapc_mailbox_run(mbox);
f8f30bd27e41e1041a8de0b97f35d7d75e0a412eTimo Sirainen if (!mbox->state_fetched_success)
f8f30bd27e41e1041a8de0b97f35d7d75e0a412eTimo Sirainen ctx.ret = -1;
afb49e8adab954708e3f192386a3c7faa07e5ae5Timo Sirainen return ctx.ret;
afb49e8adab954708e3f192386a3c7faa07e5ae5Timo Sirainen}
afb49e8adab954708e3f192386a3c7faa07e5ae5Timo Sirainen
afb49e8adab954708e3f192386a3c7faa07e5ae5Timo Sirainenstatic int imapc_mailbox_open(struct mailbox *box)
afb49e8adab954708e3f192386a3c7faa07e5ae5Timo Sirainen{
7b0a52bf38f8a7ab0c262acf4c761d6a0f22a07cJosef 'Jeff' Sipek struct imapc_mailbox *mbox = 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{
a943ed0f901e312445fd393249b91932797bba79Josef 'Jeff' Sipek i_close_fd(&cache->fd);
6307d76096764e66bddc63d4a3e5a1aa19cc528fJosef 'Jeff' Sipek buffer_free(&cache->buf);
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen cache->uid = 0;
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen}
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainenstatic void imapc_mailbox_close(struct mailbox *box)
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen{
7b0a52bf38f8a7ab0c262acf4c761d6a0f22a07cJosef 'Jeff' Sipek struct imapc_mailbox *mbox = IMAPC_MAILBOX(box);
e709efb3dc325b2badbefdf140c940281d415d14Timo Sirainen bool changes;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
e709efb3dc325b2badbefdf140c940281d415d14Timo Sirainen (void)imapc_mailbox_commit_delayed_trans(mbox, &changes);
1a878b9d2a823abc6b1c8b1631e50a15d534665fTimo Sirainen imapc_mail_fetch_flush(mbox);
51130f00bbd1e119ec042d63c148a78ac06ab85eTimo Sirainen if (mbox->client_box != NULL)
51130f00bbd1e119ec042d63c148a78ac06ab85eTimo Sirainen imapc_client_mailbox_close(&mbox->client_box);
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen if (array_is_created(&mbox->rseq_modseqs))
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen array_free(&mbox->rseq_modseqs);
df48643c3c240ad5b8a3e2e2132c46f7dc541b5eTimo Sirainen if (mbox->sync_view != NULL)
df48643c3c240ad5b8a3e2e2132c46f7dc541b5eTimo Sirainen mail_index_view_close(&mbox->sync_view);
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&mbox->to_idle_delay);
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek 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{
7b0a52bf38f8a7ab0c262acf4c761d6a0f22a07cJosef 'Jeff' Sipek struct imapc_mailbox *mbox = IMAPC_MAILBOX(box);
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen struct imapc_command *cmd;
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen struct imapc_simple_context sctx;
6e2bb07ff164bbac054cc53a4b4ca0d8aee909d1Timo Sirainen const char *name = imapc_mailbox_get_remote_name(mbox);
6e2bb07ff164bbac054cc53a4b4ca0d8aee909d1Timo Sirainen
6e2bb07ff164bbac054cc53a4b4ca0d8aee909d1Timo Sirainen if (!directory)
6e2bb07ff164bbac054cc53a4b4ca0d8aee909d1Timo Sirainen ;
6e2bb07ff164bbac054cc53a4b4ca0d8aee909d1Timo Sirainen else if (strcmp(box->list->name, MAILBOX_LIST_NAME_IMAPC) == 0) {
6e2bb07ff164bbac054cc53a4b4ca0d8aee909d1Timo Sirainen struct imapc_mailbox_list *imapc_list =
6e2bb07ff164bbac054cc53a4b4ca0d8aee909d1Timo Sirainen (struct imapc_mailbox_list *)box->list;
6e2bb07ff164bbac054cc53a4b4ca0d8aee909d1Timo Sirainen name = t_strdup_printf("%s%c", name, imapc_list->root_sep);
6e2bb07ff164bbac054cc53a4b4ca0d8aee909d1Timo Sirainen } else {
c5c71245fec4331d6598376f0ff2f3b9d4372cc8Timo Sirainen name = t_strdup_printf("%s%c", name,
6e2bb07ff164bbac054cc53a4b4ca0d8aee909d1Timo 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
d78eb0a68297f3588a9ffe5a78e496ad500fb1e0Timo Sirainen if (storage->cur_status_box == NULL)
719bda7961b0ceced935b56a4f4494f2f6191b15Timo Sirainen return;
d78eb0a68297f3588a9ffe5a78e496ad500fb1e0Timo Sirainen if (strcmp(storage->cur_status_box->box.name, name) == 0) {
d78eb0a68297f3588a9ffe5a78e496ad500fb1e0Timo Sirainen /* match */
d78eb0a68297f3588a9ffe5a78e496ad500fb1e0Timo Sirainen } else if (strcasecmp(storage->cur_status_box->box.name, "INBOX") == 0 &&
d78eb0a68297f3588a9ffe5a78e496ad500fb1e0Timo Sirainen strcasecmp(name, "INBOX") == 0) {
d78eb0a68297f3588a9ffe5a78e496ad500fb1e0Timo Sirainen /* case-insensitive INBOX */
d78eb0a68297f3588a9ffe5a78e496ad500fb1e0Timo Sirainen } else {
d78eb0a68297f3588a9ffe5a78e496ad500fb1e0Timo Sirainen return;
d78eb0a68297f3588a9ffe5a78e496ad500fb1e0Timo Sirainen }
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;
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen else if (strcasecmp(key, "HIGHESTMODSEQ") == 0 &&
6e40a39f6886edbba5ad498391c299983f8f94e9Timo Sirainen imapc_mailbox_has_modseqs(storage->cur_status_box))
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen status->highest_modseq = 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
67445e2ac5a75d361d3c68eedcb9e1a3655440b8Timo Sirainenstatic void imapc_mailbox_get_selected_status(struct imapc_mailbox *mbox,
67445e2ac5a75d361d3c68eedcb9e1a3655440b8Timo Sirainen enum mailbox_status_items items,
67445e2ac5a75d361d3c68eedcb9e1a3655440b8Timo 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;
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen if ((items & STATUS_HIGHESTMODSEQ) != 0) {
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen /* FIXME: this doesn't work perfectly. we're now just returning
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen the HIGHESTMODSEQ from the current index, which may or may
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen not be correct. with QRESYNC enabled we could be returning
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen sync_highestmodseq, but that would require implementing
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen VANISHED replies. and without QRESYNC we'd have to issue
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen STATUS (HIGHESTMODSEQ), which isn't efficient since we get
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen here constantly (after every IMAP command). */
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen }
6e40a39f6886edbba5ad498391c299983f8f94e9Timo Sirainen if (imapc_mailbox_has_modseqs(mbox)) {
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen /* even if local indexes are only in memory, we still
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen have modseqs on the IMAP server itself. */
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen status_r->nonpermanent_modseqs = FALSE;
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen }
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{
7b0a52bf38f8a7ab0c262acf4c761d6a0f22a07cJosef 'Jeff' Sipek struct imapc_mailbox *mbox = IMAPC_MAILBOX(box);
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen struct imapc_command *cmd;
29371e68adc180501454783b44ec8e43b4e6ddc1Timo Sirainen struct imapc_simple_context sctx;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen string_t *str;
9fb018dea4e2073639249ea8a14ae27cab2c0aacTimo Sirainen
e00612b245b41cc47a5c6214794c415aaa8c91b7Timo Sirainen if (imapc_mailbox_get_capabilities(mbox) < 0)
e00612b245b41cc47a5c6214794c415aaa8c91b7Timo Sirainen return -1;
150542702397445873dca327c82c5c7f09322437Timo 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");
90355e35d1139e446a99733986a9181bd7f05dd4Timo Sirainen if ((items & STATUS_HIGHESTMODSEQ) != 0 &&
6e40a39f6886edbba5ad498391c299983f8f94e9Timo Sirainen imapc_mailbox_has_modseqs(mbox))
90355e35d1139e446a99733986a9181bd7f05dd4Timo 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
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);
06116e6a19bc4916ddf349108e59e38eda83d533Timo Sirainen imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_RETRIABLE);
e21baa33b4f1e7ad095566341515e65f51acadf6Timo Sirainen imapc_command_sendf(cmd, "STATUS %s (%1s)",
e21baa33b4f1e7ad095566341515e65f51acadf6Timo Sirainen imapc_mailbox_get_remote_name(mbox), 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{
7b0a52bf38f8a7ab0c262acf4c761d6a0f22a07cJosef 'Jeff' Sipek struct imapc_mailbox *mbox = 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) {
67445e2ac5a75d361d3c68eedcb9e1a3655440b8Timo 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;
67445e2ac5a75d361d3c68eedcb9e1a3655440b8Timo 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
08b9350b17bb0abd822dd1f11452df1476077747Timo Sirainen if (box->opened && !box->deleting && (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
150542702397445873dca327c82c5c7f09322437Timo Sirainenstatic int imapc_mailbox_get_namespaces(struct imapc_mailbox *mbox)
d6c06730a0a1ba6ac784d95eadc42c8c9a62661cTimo Sirainen{
150542702397445873dca327c82c5c7f09322437Timo Sirainen struct imapc_storage *storage = mbox->storage;
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
e00612b245b41cc47a5c6214794c415aaa8c91b7Timo Sirainen if (imapc_mailbox_get_capabilities(mbox) < 0)
e00612b245b41cc47a5c6214794c415aaa8c91b7Timo Sirainen return -1;
150542702397445873dca327c82c5c7f09322437Timo Sirainen if ((mbox->capabilities & 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);
06116e6a19bc4916ddf349108e59e38eda83d533Timo Sirainen imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_RETRIABLE);
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;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t 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{
7b0a52bf38f8a7ab0c262acf4c761d6a0f22a07cJosef 'Jeff' Sipek struct imapc_mailbox *mbox = 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) {
150542702397445873dca327c82c5c7f09322437Timo Sirainen if (imapc_mailbox_get_namespaces(mbox) < 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{
7b0a52bf38f8a7ab0c262acf4c761d6a0f22a07cJosef 'Jeff' Sipek struct imapc_mailbox *mbox = IMAPC_MAILBOX(box);
9438ecaf1caee1bb33c8d7f638742875ac42c4e5Timo Sirainen const struct mail_storage_settings *set = box->storage->set;
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen struct imapc_command *cmd;
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen
9438ecaf1caee1bb33c8d7f638742875ac42c4e5Timo Sirainen if (box->notify_callback == NULL) {
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&mbox->to_idle_check);
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen return;
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen }
8c98b8adba0e70743d5d8c35ae922038881b1f47Timo Sirainen
150542702397445873dca327c82c5c7f09322437Timo Sirainen if ((mbox->capabilities & 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{
7b0a52bf38f8a7ab0c262acf4c761d6a0f22a07cJosef 'Jeff' Sipek struct imapc_mailbox *mbox = 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,
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek .class_flags = MAIL_STORAGE_CLASS_FLAG_NO_ROOT |
1f4d459111419a47021e677839439f2e2ca78ad5Josef 'Jeff' Sipek MAIL_STORAGE_CLASS_FLAG_UNIQUE_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,
857c471c13ca215f4be9dd4b336b742b8d434e31Timo Sirainen NULL,
857c471c13ca215f4be9dd4b336b742b8d434e31Timo 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};