imapc-storage.c revision 94a77d6e5d7600859e4c5e4a7ea19dc3e91998b9
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zeleny/* Copyright (c) 2011 Dovecot authors, see the included COPYING file */
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zeleny const char *code;
cf1a8af5556b1d8eab68802918c881ae1a0b89ebPavel Březinastatic struct imapc_resp_code_map imapc_resp_code_map[] = {
cf1a8af5556b1d8eab68802918c881ae1a0b89ebPavel Březina { IMAP_RESP_CODE_UNAVAILABLE, MAIL_ERROR_TEMP },
cf1a8af5556b1d8eab68802918c881ae1a0b89ebPavel Březina { IMAP_RESP_CODE_AUTHFAILED, MAIL_ERROR_PERM },
cf1a8af5556b1d8eab68802918c881ae1a0b89ebPavel Březina { IMAP_RESP_CODE_AUTHZFAILED, MAIL_ERROR_PERM },
cf1a8af5556b1d8eab68802918c881ae1a0b89ebPavel Březina { IMAP_RESP_CODE_PRIVACYREQUIRED, MAIL_ERROR_PERM },
cf1a8af5556b1d8eab68802918c881ae1a0b89ebPavel Březina { IMAP_RESP_CODE_CONTACTADMIN, MAIL_ERROR_PERM },
cf1a8af5556b1d8eab68802918c881ae1a0b89ebPavel Březina { IMAP_RESP_CODE_EXPUNGEISSUED, MAIL_ERROR_EXPUNGED },
cf1a8af5556b1d8eab68802918c881ae1a0b89ebPavel Březina { IMAP_RESP_CODE_CORRUPTION, MAIL_ERROR_TEMP },
cf1a8af5556b1d8eab68802918c881ae1a0b89ebPavel Březina { IMAP_RESP_CODE_SERVERBUG, MAIL_ERROR_TEMP },
cf1a8af5556b1d8eab68802918c881ae1a0b89ebPavel Březina /* { IMAP_RESP_CODE_CLIENTBUG, 0 }, */
0232747f04b650796db56fd7b487aee8a96fab03Simo Sorce { IMAP_RESP_CODE_CANNOT, MAIL_ERROR_NOTPOSSIBLE },
0232747f04b650796db56fd7b487aee8a96fab03Simo Sorce { IMAP_RESP_CODE_LIMIT, MAIL_ERROR_NOTPOSSIBLE },
0232747f04b650796db56fd7b487aee8a96fab03Simo Sorce { IMAP_RESP_CODE_OVERQUOTA, MAIL_ERROR_NOSPACE },
0232747f04b650796db56fd7b487aee8a96fab03Simo Sorce { IMAP_RESP_CODE_ALREADYEXISTS, MAIL_ERROR_EXISTS },
0232747f04b650796db56fd7b487aee8a96fab03Simo Sorce { IMAP_RESP_CODE_NONEXISTENT, MAIL_ERROR_NOTFOUND }
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorcestatic void imapc_untagged_status(const struct imapc_untagged_reply *reply,
07b92f78d1751d8a2a538a440e1fdb24c59021e0Pavel Březinaimap_resp_text_code_parse(const char *str, enum mail_error *error_r)
1f800ebb0f190854b8296146174f3d696a426333Simo Sorce unsigned int i;
1f800ebb0f190854b8296146174f3d696a426333Simo Sorce for (i = 0; i < N_ELEMENTS(imapc_resp_code_map); i++) {
0232747f04b650796db56fd7b487aee8a96fab03Simo Sorce if (strcmp(imapc_resp_code_map[i].code, str) == 0) {
33c865412732554ef255e93c4e7a58b0bce963c6Jakub Hrozekstatic struct mail_storage *imapc_storage_alloc(void)
33c865412732554ef255e93c4e7a58b0bce963c6Jakub Hrozek pool = pool_alloconly_create("imapc storage", 512+256);
33c865412732554ef255e93c4e7a58b0bce963c6Jakub Hrozek storage = p_new(pool, struct imapc_storage, 1);
33c865412732554ef255e93c4e7a58b0bce963c6Jakub Hrozekvoid imapc_copy_error_from_reply(struct imapc_storage *storage,
33c865412732554ef255e93c4e7a58b0bce963c6Jakub Hrozek if (imap_resp_text_code_parse(reply->resp_text_key, &error)) {
33c865412732554ef255e93c4e7a58b0bce963c6Jakub Hrozek mail_storage_set_error(&storage->storage, error,
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce mail_storage_set_error(&storage->storage, default_error,
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorcevoid imapc_simple_callback(const struct imapc_command_reply *reply,
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce else if (reply->state == IMAPC_COMMAND_STATE_NO) {
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce imapc_copy_error_from_reply(ctx->storage, MAIL_ERROR_PARAMS, reply);
bba1a5fd62cffcae076d1351df5a83fbc4a6ec17Simo Sorce mail_storage_set_critical(&ctx->storage->storage,
e1f68731525116ce686ffcdc07ad3a14e4fb1cd7Pavel Březinavoid imapc_async_stop_callback(const struct imapc_command_reply *reply,
e1f68731525116ce686ffcdc07ad3a14e4fb1cd7Pavel Březina else if (reply->state == IMAPC_COMMAND_STATE_NO) {
e1f68731525116ce686ffcdc07ad3a14e4fb1cd7Pavel Březina imapc_copy_error_from_reply(storage, MAIL_ERROR_PARAMS, reply);
e1f68731525116ce686ffcdc07ad3a14e4fb1cd7Pavel Březina "imapc: Command failed: %s", reply->text_full);
e1f68731525116ce686ffcdc07ad3a14e4fb1cd7Pavel Březinastatic void imapc_storage_untagged_cb(const struct imapc_untagged_reply *reply,
e1f68731525116ce686ffcdc07ad3a14e4fb1cd7Pavel Březina struct imapc_mailbox *mbox = reply->untagged_box_context;
e1f68731525116ce686ffcdc07ad3a14e4fb1cd7Pavel Březina const struct imapc_storage_event_callback *cb;
e1f68731525116ce686ffcdc07ad3a14e4fb1cd7Pavel Březina const struct imapc_mailbox_event_callback *mcb;
e1f68731525116ce686ffcdc07ad3a14e4fb1cd7Pavel Březina array_foreach(&storage->untagged_callbacks, cb) {
0b81cc5d41ec6a1c58e610f402fd93a1fbda4affPavel Březina array_foreach(&mbox->untagged_callbacks, mcb) {
0b81cc5d41ec6a1c58e610f402fd93a1fbda4affPavel Březina array_foreach(&mbox->resp_text_callbacks, mcb) {
0b81cc5d41ec6a1c58e610f402fd93a1fbda4affPavel Březina if (strcasecmp(reply->resp_text_key, mcb->name) == 0)
0b81cc5d41ec6a1c58e610f402fd93a1fbda4affPavel Březinaimapc_storage_create(struct mail_storage *_storage,
0b81cc5d41ec6a1c58e610f402fd93a1fbda4affPavel Březina const char **error_r)
0b81cc5d41ec6a1c58e610f402fd93a1fbda4affPavel Březina struct imapc_storage *storage = (struct imapc_storage *)_storage;
0b81cc5d41ec6a1c58e610f402fd93a1fbda4affPavel Březina port = mail_user_plugin_getenv(_storage->user, "imapc_port");
0b81cc5d41ec6a1c58e610f402fd93a1fbda4affPavel Březina *error_r = t_strdup_printf("Invalid port: %s", port);
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zeleny set.username = mail_user_plugin_getenv(_storage->user, "imapc_user");
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zeleny set.password = mail_user_plugin_getenv(_storage->user, "pass");
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zeleny storage->list = (struct imapc_mailbox_list *)ns->list;
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zeleny p_array_init(&storage->untagged_callbacks, _storage->pool, 16);
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zeleny imapc_storage_register_untagged(storage, "STATUS",
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zelenystatic void imapc_storage_destroy(struct mail_storage *_storage)
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zeleny struct imapc_storage *storage = (struct imapc_storage *)_storage;
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zelenyvoid imapc_storage_register_untagged(struct imapc_storage *storage,
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zeleny const char *name,
b8dcd1216e5ea7065213c750a92dabfe01fa3b70Simo Sorce cb = array_append_space(&storage->untagged_callbacks);
b8dcd1216e5ea7065213c750a92dabfe01fa3b70Simo Sorce cb->name = p_strdup(storage->storage.pool, name);
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zelenyimapc_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zelenystatic struct mailbox *
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zelenyimapc_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
58fd3aa25c5292bc67432647ab7e5059439fcc6dSimo Sorce pool = pool_alloconly_create("imapc mailbox", 1024*3);
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zeleny index_storage_mailbox_alloc(&mbox->box, vname, flags, NULL);
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zeleny ibox->save_commit_pre = imapc_transaction_save_commit_pre;
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zeleny ibox->save_commit_post = imapc_transaction_save_commit_post;
3c60433641ce2e86b9b04778c8f8652ef0d097e4Stef Walter ibox->save_rollback = imapc_transaction_save_rollback;
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zeleny p_array_init(&mbox->untagged_callbacks, pool, 16);
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zeleny p_array_init(&mbox->resp_text_callbacks, pool, 16);
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zelenyimapc_mailbox_open_callback(const struct imapc_command_reply *reply,
234958be042980242fff6da936af674da877c5efSimo Sorce else if (reply->state == IMAPC_COMMAND_STATE_NO) {
234958be042980242fff6da936af674da877c5efSimo Sorce mail_storage_set_critical(ctx->mbox->box.storage,
234958be042980242fff6da936af674da877c5efSimo Sorce "imapc: Opening mailbox '%s' failed: %s",
234958be042980242fff6da936af674da877c5efSimo Sorcestatic int imapc_mailbox_open(struct mailbox *box)
234958be042980242fff6da936af674da877c5efSimo Sorce struct imapc_mailbox *mbox = (struct imapc_mailbox *)box;
234958be042980242fff6da936af674da877c5efSimo Sorce if (box->deleting || (box->flags & MAILBOX_FLAG_SAVEONLY) != 0) {
234958be042980242fff6da936af674da877c5efSimo Sorce /* We don't actually want to SELECT the mailbox. */
234958be042980242fff6da936af674da877c5efSimo Sorce imapc_client_mailbox_open(mbox->storage->client, box->name,
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozekstatic void imapc_mailbox_close(struct mailbox *box)
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek struct imapc_mailbox *mbox = (struct imapc_mailbox *)box;
144e7bad57748aaab395b9fb8ad136cdad864a00Lukas Slebodnik imapc_client_mailbox_close(&mbox->client_box);
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek mail_index_view_close(&mbox->delayed_sync_view);
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek if (mail_index_transaction_commit(&mbox->delayed_sync_trans) < 0)
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek const struct mailbox_update *update ATTR_UNUSED,
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek struct imapc_mailbox *mbox = (struct imapc_mailbox *)box;
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek imapc_client_cmdf(mbox->storage->client, imapc_simple_callback, &ctx,
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozekstatic int imapc_mailbox_update(struct mailbox *box,
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek const struct mailbox_update *update ATTR_UNUSED)
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek "Not supported");
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozekstatic void imapc_untagged_status(const struct imapc_untagged_reply *reply,
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek unsigned int i;
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek if (!imap_arg_get_astring(&reply->args[0], &name) ||
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek strcmp(storage->cur_status_box->box.name, name) != 0)
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek for (i = 0; list[i].type != IMAP_ARG_EOL; i += 2) {
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek else if (strcasecmp(key, "HIGHESTMODSEQ") == 0)
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozekstatic void imapc_mailbox_get_selected_status(struct imapc_mailbox *mbox,
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek index_storage_get_status(&mbox->box, items, status_r);
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozekstatic int imapc_mailbox_get_status(struct mailbox *box,
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek struct imapc_mailbox *mbox = (struct imapc_mailbox *)box;
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek imapc_mailbox_get_selected_status(mbox, items, status_r);
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek /* mailbox isn't opened yet */
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek if ((items & (STATUS_FIRST_UNSEEN_SEQ | STATUS_KEYWORDS)) != 0) {
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek /* getting these requires opening the mailbox */
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek imapc_mailbox_get_selected_status(mbox, items, status_r);
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek /* nothing requested */
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozekstatic int imapc_mailbox_get_metadata(struct mailbox *box,
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek /* a bit ugly way to do this, but better than nothing for now.
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek FIXME: if indexes are enabled, keep this there. */
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek mail_generate_guid_128_hash(box->name, metadata_r->guid);
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek return index_mailbox_get_metadata(box, items, metadata_r);
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozekstatic void imapc_notify_changes(struct mailbox *box ATTR_UNUSED)
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozek /* we're doing IDLE all the time anyway - nothing to do here */
58dd26b1c5b60ee992dd5d1214bb168aebb42d54Jakub Hrozekint imapc_create_temp_fd(struct mail_user *user, const char **path_r)
return fd;
.class_flags = 0,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,