mail-storage.c revision 6acaa359928215b48e97373fb96a3dc326bbd65b
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "lib.h"
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen#include "ioloop.h"
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen#include "array.h"
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen#include "llist.h"
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "mkdir-parents.h"
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen#include "var-expand.h"
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen#include "mail-index-private.h"
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen#include "mailbox-list-private.h"
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen#include "mail-storage-private.h"
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen#include "mail-storage-settings.h"
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen#include "mail-namespace.h"
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen#include "mail-search.h"
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen#include "mailbox-search-result-private.h"
25d624dd86700c82cd28427f3d3bebe7c8f7f459Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen#include <stdlib.h>
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen#include <ctype.h>
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenstruct mail_storage_module_register mail_storage_module_register = { 0 };
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenstruct mail_module_register mail_module_register = { 0 };
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenstruct mail_storage_mail_index_module mail_storage_mail_index_module =
714e2da5096fb52b8845d3c79f9bb26225a606c9Timo Sirainen MODULE_CONTEXT_INIT(&mail_index_module_register);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenvoid (*hook_mail_storage_created)(struct mail_storage *storage);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenvoid (*hook_mailbox_allocated)(struct mailbox *box) = NULL;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenvoid (*hook_mailbox_index_opened)(struct mailbox *box) = NULL;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo SirainenARRAY_TYPE(mail_storage) mail_storage_classes;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenvoid mail_storage_init(void)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen mailbox_lists_init();
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen i_array_init(&mail_storage_classes, 8);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
04870054863757edf048c81dcce3c5e7dec453cdTimo Sirainenvoid mail_storage_deinit(void)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (array_is_created(&mail_storage_classes))
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen array_free(&mail_storage_classes);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen mailbox_lists_deinit();
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenvoid mail_storage_class_register(struct mail_storage *storage_class)
bd63b5b860658b01b1f46f26d406e1e4a9dc019aTimo Sirainen{
15a07b47846c47a81d69a14d649564e222d6f742Timo Sirainen i_assert(mail_storage_find_class(storage_class->name) == NULL);
cd2cd224d3216a243d55c71c298a5b7684de0ac4Timo Sirainen
c1faff067b29fb48426cb84260adba563e93189aTimo Sirainen if (storage_class->v.class_init != NULL)
6882df5fbca4a09cdaa95f54d70bb31b5920528cTimo Sirainen storage_class->v.class_init();
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* append it after the list, so the autodetection order is correct */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen array_append(&mail_storage_classes, &storage_class, 1);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
eacce2276278ce6a8176a9a100807dba50bbfb36Timo Sirainenvoid mail_storage_class_unregister(struct mail_storage *storage_class)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen struct mail_storage *const *classes;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen unsigned int i, count;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen classes = array_get(&mail_storage_classes, &count);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen for (i = 0; i < count; i++) {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (classes[i] == storage_class) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen array_delete(&mail_storage_classes, i, 1);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen break;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen }
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen }
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (storage_class->v.class_deinit != NULL)
4145cbac82bfc0c8bfeceeca0ef841700117930cTimo Sirainen storage_class->v.class_deinit();
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen}
eacce2276278ce6a8176a9a100807dba50bbfb36Timo Sirainen
eacce2276278ce6a8176a9a100807dba50bbfb36Timo Sirainenstruct mail_storage *mail_storage_find_class(const char *name)
eacce2276278ce6a8176a9a100807dba50bbfb36Timo Sirainen{
eacce2276278ce6a8176a9a100807dba50bbfb36Timo Sirainen struct mail_storage *const *classes;
eacce2276278ce6a8176a9a100807dba50bbfb36Timo Sirainen unsigned int i, count;
eacce2276278ce6a8176a9a100807dba50bbfb36Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen i_assert(name != NULL);
eacce2276278ce6a8176a9a100807dba50bbfb36Timo Sirainen
eacce2276278ce6a8176a9a100807dba50bbfb36Timo Sirainen classes = array_get(&mail_storage_classes, &count);
eacce2276278ce6a8176a9a100807dba50bbfb36Timo Sirainen for (i = 0; i < count; i++) {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (strcasecmp(classes[i]->name, name) == 0)
e1203014de25c8c3d3975a9f4b4a04616df4bba2Timo Sirainen return classes[i];
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen }
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return NULL;
e1203014de25c8c3d3975a9f4b4a04616df4bba2Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
e10d8b1291090c26b9ef499637e6e632485ca5beTimo Sirainenstatic struct mail_storage *
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenmail_storage_autodetect(const struct mail_namespace *ns,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen struct mailbox_list_settings *set)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen struct mail_storage *const *classes;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen unsigned int i, count;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen classes = array_get(&mail_storage_classes, &count);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen for (i = 0; i < count; i++) {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (classes[i]->v.autodetect != NULL) {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (classes[i]->v.autodetect(ns, set))
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return classes[i];
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen }
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen }
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return NULL;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenstatic void
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenmail_storage_set_autodetection(const char **data, const char **driver)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen const char *p;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* check if data is in driver:data format (eg. mbox:~/mail) */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen p = *data;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen while (i_isalnum(*p)) p++;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (*p == ':' && p != *data) {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* no autodetection if the storage driver is given. */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen *driver = t_strdup_until(*data, p);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen *data = p + 1;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen }
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenstatic struct mail_storage *
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenmail_storage_get_class(struct mail_namespace *ns, const char *driver,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen struct mailbox_list_settings *list_set,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen const char **error_r)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen struct mail_storage *storage_class;
411f318ed3a25fa66c1b932e10df43841e2725c9Timo Sirainen const char *home;
411f318ed3a25fa66c1b932e10df43841e2725c9Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (driver != NULL) {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen storage_class = mail_storage_find_class(driver);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (storage_class == NULL) {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen *error_r = t_strdup_printf(
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen "Unknown mail storage driver %s", driver);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen }
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen i_assert(list_set->root_dir != NULL);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen storage_class->v.get_list_settings(ns, list_set);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return storage_class;
3a9eb305fd4aad5502cb7e64625874385ab5bc19Timo Sirainen }
714e2da5096fb52b8845d3c79f9bb26225a606c9Timo Sirainen
714e2da5096fb52b8845d3c79f9bb26225a606c9Timo Sirainen storage_class = mail_storage_autodetect(ns, list_set);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (storage_class != NULL)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return storage_class;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (ns->set->location == NULL || *ns->set->location == '\0') {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen (void)mail_user_get_home(ns->user, &home);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (home == NULL || *home == '\0') home = "(not set)";
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen *error_r = t_strdup_printf(
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen "Mail storage autodetection failed with home=%s", home);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen } else {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen *error_r = t_strdup_printf(
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen "Ambiguous mail location setting, "
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen "don't know what to do with it: %s "
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen "(try prefixing it with mbox: or maildir:)",
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen ns->set->location);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen }
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return NULL;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenstatic int
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenmail_storage_create_root(struct mailbox_list *list,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen enum mail_storage_flags flags, const char **error_r)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen const char *root_dir, *origin;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen struct stat st;
44f93baa7b8dca7d00bf187cd3db1c15eed384d2Timo Sirainen mode_t mode;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen gid_t gid;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen root_dir = mailbox_list_get_path(list, NULL,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen if (root_dir == NULL) {
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen /* storage doesn't use directories (e.g. shared root) */
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen return 0;
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen }
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen if (stat(root_dir, &st) == 0) {
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen /* ok */
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen return 0;
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen } else if (errno == EACCES) {
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen *error_r = mail_error_eacces_msg("stat", root_dir);
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen return -1;
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen } else if (errno != ENOENT && errno != ENOTDIR) {
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen *error_r = t_strdup_printf("stat(%s) failed: %m", root_dir);
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen return -1;
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen } else if (list->ns->type == NAMESPACE_SHARED) {
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen /* can't create a new user, but we don't want to fail
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen the storage creation. */
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen } else if ((flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) {
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen *error_r = t_strdup_printf(
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen "Root mail directory doesn't exist: %s", root_dir);
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen return -1;
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen }
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen /* we need to create the root directory. */
c7f6992db44e9cd33b3b0d754833a1503ee9a53fAki Tuomi mailbox_list_get_dir_permissions(list, NULL, &mode, &gid, &origin);
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen if (mkdir_parents_chgrp(root_dir, mode, gid, origin) < 0 &&
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen errno != EEXIST) {
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen *error_r = mail_error_create_eacces_msg("mkdir", root_dir);
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen return -1;
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen } else {
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen /* created */
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen return 0;
c7f6992db44e9cd33b3b0d754833a1503ee9a53fAki Tuomi }
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen}
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainenstatic struct mail_storage *
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainenmail_storage_find(struct mail_user *user,
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen const struct mail_storage *storage_class,
45c872f65e4f327ef166c6e2b71bb43e188ac562Timo Sirainen const struct mailbox_list_settings *set)
45c872f65e4f327ef166c6e2b71bb43e188ac562Timo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen struct mail_storage *storage = user->storages;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen for (; storage != NULL; storage = storage->next) {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (strcmp(storage->name, storage_class->name) == 0 &&
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen ((storage->class_flags &
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) == 0 ||
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen strcmp(storage->unique_root_dir, set->root_dir) == 0))
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return storage;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen }
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen return NULL;
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen}
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainenint mail_storage_create(struct mail_namespace *ns, const char *driver,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen enum mail_storage_flags flags, const char **error_r)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
c7f6992db44e9cd33b3b0d754833a1503ee9a53fAki Tuomi struct mail_storage *storage_class, *storage = NULL;
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen struct mailbox_list_settings list_set;
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen enum mailbox_list_flags list_flags = 0;
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen const char *data = ns->set->location;
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen const char *p;
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen if ((flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) == 0 &&
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen ns->mail_set->pop3_uidl_format != NULL) {
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen /* if pop3_uidl_format contains %m, we want to keep the
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen header MD5 sums stored even if we're not running POP3
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen right now. */
45c872f65e4f327ef166c6e2b71bb43e188ac562Timo Sirainen p = ns->mail_set->pop3_uidl_format;
45c872f65e4f327ef166c6e2b71bb43e188ac562Timo Sirainen while ((p = strchr(p, '%')) != NULL) {
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen if (p[1] == '%')
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen p += 2;
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen else if (var_get_key(++p) == 'm') {
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen flags |= MAIL_STORAGE_FLAG_KEEP_HEADER_MD5;
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen break;
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen }
34015eb0b74735f2fac07c12697bde20a94735e6Timo Sirainen }
34015eb0b74735f2fac07c12697bde20a94735e6Timo Sirainen }
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
34015eb0b74735f2fac07c12697bde20a94735e6Timo Sirainen memset(&list_set, 0, sizeof(list_set));
34015eb0b74735f2fac07c12697bde20a94735e6Timo Sirainen if (data == NULL) {
34015eb0b74735f2fac07c12697bde20a94735e6Timo Sirainen /* autodetect */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen } else if (driver != NULL && strcmp(driver, "shared") == 0) {
34015eb0b74735f2fac07c12697bde20a94735e6Timo Sirainen /* internal shared namespace */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen list_set.root_dir = ns->user->set->base_dir;
c7f6992db44e9cd33b3b0d754833a1503ee9a53fAki Tuomi } else {
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen if (driver == NULL)
45c872f65e4f327ef166c6e2b71bb43e188ac562Timo Sirainen mail_storage_set_autodetection(&data, &driver);
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen if (mailbox_list_settings_parse(data, &list_set, ns,
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch error_r) < 0)
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen return -1;
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen }
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen if ((flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) != 0 &&
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen list_set.root_dir == NULL) {
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen *error_r = "Root mail directory not given";
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen return -1;
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen }
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen storage_class = mail_storage_get_class(ns, driver, &list_set, error_r);
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen if (storage_class == NULL)
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen return -1;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen i_assert(list_set.layout != NULL);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (ns->list == NULL) {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* first storage for namespace */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (mail_storage_is_mailbox_file(storage_class))
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen list_flags |= MAILBOX_LIST_FLAG_MAILBOX_FILES;
45c872f65e4f327ef166c6e2b71bb43e188ac562Timo Sirainen if (mailbox_list_create(list_set.layout, ns, &list_set,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen list_flags, error_r) < 0)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return -1;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (mail_storage_create_root(ns->list, flags, error_r) < 0)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return -1;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen }
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainen
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainen storage = mail_storage_find(ns->user, storage_class, &list_set);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (storage != NULL) {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* using an existing storage */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen storage->refcount++;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen mail_namespace_add_storage(ns, storage);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return 0;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen }
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
44f93baa7b8dca7d00bf187cd3db1c15eed384d2Timo Sirainen storage = storage_class->v.alloc();
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen storage->refcount = 1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen storage->storage_class = storage_class;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen storage->user = ns->user;
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen storage->set = ns->mail_set;
45c872f65e4f327ef166c6e2b71bb43e188ac562Timo Sirainen storage->flags = flags;
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen p_array_init(&storage->module_contexts, storage->pool, 5);
75771bd32a86b7360d28f1254ffba99f63d763d9Aki Tuomi
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (storage->v.create != NULL &&
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen storage->v.create(storage, ns, error_r) < 0) {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen *error_r = t_strdup_printf("%s: %s", storage->name, *error_r);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen pool_unref(&storage->pool);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return -1;
e10d8b1291090c26b9ef499637e6e632485ca5beTimo Sirainen }
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (hook_mail_storage_created != NULL) T_BEGIN {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen hook_mail_storage_created(storage);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen } T_END;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen DLLIST_PREPEND(&ns->user->storages, storage);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen mail_namespace_add_storage(ns, storage);
ec5fec7eab19e134a2607b7e224b3e14a1771ee0Timo Sirainen return 0;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenvoid mail_storage_ref(struct mail_storage *storage)
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainen{
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainen storage->refcount++;
ec5fec7eab19e134a2607b7e224b3e14a1771ee0Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenvoid mail_storage_unref(struct mail_storage **_storage)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen{
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen struct mail_storage *storage = *_storage;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen i_assert(storage->refcount > 0);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *_storage = NULL;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (--storage->refcount > 0)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return;
4145cbac82bfc0c8bfeceeca0ef841700117930cTimo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen DLLIST_REMOVE(&storage->user->storages, storage);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (storage->v.destroy != NULL)
e10d8b1291090c26b9ef499637e6e632485ca5beTimo Sirainen storage->v.destroy(storage);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen i_free(storage->error_string);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen pool_unref(&storage->pool);
04870054863757edf048c81dcce3c5e7dec453cdTimo Sirainen}
04870054863757edf048c81dcce3c5e7dec453cdTimo Sirainen
04870054863757edf048c81dcce3c5e7dec453cdTimo Sirainenvoid mail_storage_clear_error(struct mail_storage *storage)
04870054863757edf048c81dcce3c5e7dec453cdTimo Sirainen{
e1203014de25c8c3d3975a9f4b4a04616df4bba2Timo Sirainen i_free_and_null(storage->error_string);
e1203014de25c8c3d3975a9f4b4a04616df4bba2Timo Sirainen
e593e507ee5ea3869271a631874c5c4b5c7a294dTimo Sirainen storage->error = MAIL_ERROR_NONE;
e10d8b1291090c26b9ef499637e6e632485ca5beTimo Sirainen}
e1203014de25c8c3d3975a9f4b4a04616df4bba2Timo Sirainen
e1203014de25c8c3d3975a9f4b4a04616df4bba2Timo Sirainenvoid mail_storage_set_error(struct mail_storage *storage,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen enum mail_error error, const char *string)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen i_free(storage->error_string);
44f93baa7b8dca7d00bf187cd3db1c15eed384d2Timo Sirainen storage->error_string = i_strdup(string);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen storage->error = error;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenvoid mail_storage_set_internal_error(struct mail_storage *storage)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
e10d8b1291090c26b9ef499637e6e632485ca5beTimo Sirainen struct tm *tm;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen char str[256];
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen tm = localtime(&ioloop_time);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen i_free(storage->error_string);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen storage->error_string =
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen strftime(str, sizeof(str),
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen MAIL_ERRSTR_CRITICAL_MSG_STAMP, tm) > 0 ?
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen i_strdup(str) : i_strdup(MAIL_ERRSTR_CRITICAL_MSG);
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainen storage->error = MAIL_ERROR_TEMP;
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenvoid mail_storage_set_critical(struct mail_storage *storage,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen const char *fmt, ...)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen va_list va;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen mail_storage_clear_error(storage);
44f93baa7b8dca7d00bf187cd3db1c15eed384d2Timo Sirainen if (fmt != NULL) {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen va_start(va, fmt);
44f93baa7b8dca7d00bf187cd3db1c15eed384d2Timo Sirainen i_error("%s", t_strdup_vprintf(fmt, va));
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen va_end(va);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* critical errors may contain sensitive data, so let user
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen see only "Internal error" with a timestamp to make it
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen easier to look from log files the actual error message. */
e10d8b1291090c26b9ef499637e6e632485ca5beTimo Sirainen mail_storage_set_internal_error(storage);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen }
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenconst struct mail_storage_settings *
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenmail_storage_get_settings(struct mail_storage *storage)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return storage->set;
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen}
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainenvoid mail_storage_set_callbacks(struct mail_storage *storage,
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen struct mail_storage_callbacks *callbacks,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen void *context)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen storage->callbacks = *callbacks;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen storage->callback_context = context;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenint mail_storage_purge(struct mail_storage *storage)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen mail_storage_clear_error(storage);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return storage->v.purge == NULL ? 0 :
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen storage->v.purge(storage);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen}
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainenconst char *mail_storage_get_last_error(struct mail_storage *storage,
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen enum mail_error *error_r)
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen{
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen /* We get here only in error situations, so we have to return some
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen error. If storage->error is NONE, it means we forgot to set it at
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen some point.. */
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen if (storage->error == MAIL_ERROR_NONE) {
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen if (error_r != NULL)
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen *error_r = MAIL_ERROR_TEMP;
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen return storage->error_string != NULL ? storage->error_string :
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen "BUG: Unknown internal error";
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen }
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen if (storage->error_string == NULL) {
e5b723864630e40c9028808ef417dd3d6fbf495bTimo Sirainen /* This shouldn't happen.. */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen storage->error_string =
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen i_strdup_printf("BUG: Unknown 0x%x error",
31a574fda352ef4f71dbff9c30e15e4744e132c0Timo Sirainen storage->error);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen }
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (error_r != NULL)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen *error_r = storage->error;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen return storage->error_string;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen}
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenbool mail_storage_is_mailbox_file(struct mail_storage *storage)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen{
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen return (storage->class_flags &
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen MAIL_STORAGE_CLASS_FLAG_MAILBOX_IS_FILE) != 0;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenbool mail_storage_set_error_from_errno(struct mail_storage *storage)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen{
6882df5fbca4a09cdaa95f54d70bb31b5920528cTimo Sirainen const char *error_string;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen enum mail_error error;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (!mail_error_from_errno(&error, &error_string))
714e2da5096fb52b8845d3c79f9bb26225a606c9Timo Sirainen return FALSE;
714e2da5096fb52b8845d3c79f9bb26225a606c9Timo Sirainen if (storage->set->mail_debug && error != MAIL_ERROR_NOTFOUND) {
714e2da5096fb52b8845d3c79f9bb26225a606c9Timo Sirainen /* debugging is enabled - admin may be debugging a
714e2da5096fb52b8845d3c79f9bb26225a606c9Timo Sirainen (permission) problem, so return FALSE to get the caller to
714e2da5096fb52b8845d3c79f9bb26225a606c9Timo Sirainen log the full error message. */
714e2da5096fb52b8845d3c79f9bb26225a606c9Timo Sirainen return FALSE;
714e2da5096fb52b8845d3c79f9bb26225a606c9Timo Sirainen }
6882df5fbca4a09cdaa95f54d70bb31b5920528cTimo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen mail_storage_set_error(storage, error, error_string);
6882df5fbca4a09cdaa95f54d70bb31b5920528cTimo Sirainen return TRUE;
6882df5fbca4a09cdaa95f54d70bb31b5920528cTimo Sirainen}
6882df5fbca4a09cdaa95f54d70bb31b5920528cTimo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenstruct mailbox *mailbox_alloc(struct mailbox_list *list, const char *name,
6882df5fbca4a09cdaa95f54d70bb31b5920528cTimo Sirainen struct istream *input,
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen enum mailbox_flags flags)
6882df5fbca4a09cdaa95f54d70bb31b5920528cTimo Sirainen{
6882df5fbca4a09cdaa95f54d70bb31b5920528cTimo Sirainen struct mailbox_list *new_list = list;
6882df5fbca4a09cdaa95f54d70bb31b5920528cTimo Sirainen struct mail_storage *storage;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen struct mailbox *box;
6882df5fbca4a09cdaa95f54d70bb31b5920528cTimo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (mailbox_list_get_storage(&new_list, &name, &storage) < 0) {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen /* just use the first storage. FIXME: does this break? */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen storage = list->ns->storage;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen }
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen T_BEGIN {
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen box = storage->v.mailbox_alloc(storage, new_list,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen name, input, flags);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (hook_mailbox_allocated != NULL)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen hook_mailbox_allocated(box);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen } T_END;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return box;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenint mailbox_open(struct mailbox *box)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen int ret;
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen mail_storage_clear_error(box->storage);
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen if (!mailbox_list_is_valid_existing_name(box->list, box->name)) {
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen "Invalid mailbox name");
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen return -1;
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen }
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen T_BEGIN {
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen ret = box->v.open(box);
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen } T_END;
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen if (ret < 0)
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen return -1;
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen box->list->ns->flags |= NAMESPACE_FLAG_USABLE;
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen return 0;
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen}
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainenint mailbox_enable(struct mailbox *box, enum mailbox_feature features)
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen{
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen return box->v.enable(box, features);
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen}
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainenenum mailbox_feature mailbox_get_enabled_features(struct mailbox *box)
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen{
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen return box->enabled_features;
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen}
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainenvoid mailbox_close(struct mailbox **_box)
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen{
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen struct mailbox *box = *_box;
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen if (box->transaction_count != 0) {
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen i_panic("Trying to close mailbox %s with open transactions",
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen box->name);
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen }
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen *_box = NULL;
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen box->v.close(box);
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen}
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainenint mailbox_create(struct mailbox *box, const struct mailbox_update *update,
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen bool directory)
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen{
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen mail_storage_clear_error(box->storage);
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen
31a574fda352ef4f71dbff9c30e15e4744e132c0Timo Sirainen if (!mailbox_list_is_valid_create_name(box->list, box->name)) {
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen "Invalid mailbox name");
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen return -1;
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainen }
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainen
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainen return box->v.create(box, update, directory);
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainen}
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainen
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainenint mailbox_update(struct mailbox *box, const struct mailbox_update *update)
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainen{
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainen mail_storage_clear_error(box->storage);
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainen
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainen return box->v.update(box, update);
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainen}
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainen
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainenstruct mail_storage *mailbox_get_storage(const struct mailbox *box)
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi{
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi return box->storage;
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainen}
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainen
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainenstruct mail_namespace *
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainenmailbox_get_namespace(const struct mailbox *box)
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainen{
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainen return box->list->ns;
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenconst struct mail_storage_settings *mailbox_get_settings(struct mailbox *box)
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return box->storage->set;
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen}
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenconst char *mailbox_get_name(const struct mailbox *box)
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return box->name;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainenconst char *mailbox_get_vname(const struct mailbox *box)
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainen{
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainen return box->vname;
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenbool mailbox_is_readonly(struct mailbox *box)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return box->v.is_readonly(box);
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenbool mailbox_allow_new_keywords(struct mailbox *box)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return box->v.allow_new_keywords(box);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenbool mailbox_backends_equal(const struct mailbox *box1,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen const struct mailbox *box2)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen struct mail_namespace *ns1 = box1->list->ns, *ns2 = box2->list->ns;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (strcmp(box1->name, box2->name) != 0)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return FALSE;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen while (ns1->alias_for != NULL)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen ns1 = ns1->alias_for;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen while (ns2->alias_for != NULL)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen ns2 = ns2->alias_for;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return ns1 == ns2;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen}
c3d40f3092af25cad9e807a85eaad4d92aab107bTimo Sirainen
c3d40f3092af25cad9e807a85eaad4d92aab107bTimo Sirainenvoid mailbox_get_status(struct mailbox *box,
c3d40f3092af25cad9e807a85eaad4d92aab107bTimo Sirainen enum mailbox_status_items items,
c3d40f3092af25cad9e807a85eaad4d92aab107bTimo Sirainen struct mailbox_status *status_r)
c3d40f3092af25cad9e807a85eaad4d92aab107bTimo Sirainen{
c3d40f3092af25cad9e807a85eaad4d92aab107bTimo Sirainen box->v.get_status(box, items, status_r);
c3d40f3092af25cad9e807a85eaad4d92aab107bTimo Sirainen}
c3d40f3092af25cad9e807a85eaad4d92aab107bTimo Sirainen
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainenstruct mailbox_sync_context *
c3d40f3092af25cad9e807a85eaad4d92aab107bTimo Sirainenmailbox_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
c3d40f3092af25cad9e807a85eaad4d92aab107bTimo Sirainen{
c3d40f3092af25cad9e807a85eaad4d92aab107bTimo Sirainen if (box->transaction_count != 0) {
c3d40f3092af25cad9e807a85eaad4d92aab107bTimo Sirainen i_panic("Trying to sync mailbox %s with open transactions",
c3d40f3092af25cad9e807a85eaad4d92aab107bTimo Sirainen box->name);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return box->v.sync_init(box, flags);
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen}
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainenbool mailbox_sync_next(struct mailbox_sync_context *ctx,
e10d8b1291090c26b9ef499637e6e632485ca5beTimo Sirainen struct mailbox_sync_rec *sync_rec_r)
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen{
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen return ctx->box->v.sync_next(ctx, sync_rec_r);
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen}
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen
411f318ed3a25fa66c1b932e10df43841e2725c9Timo Sirainenint mailbox_sync_deinit(struct mailbox_sync_context **_ctx,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen enum mailbox_status_items status_items,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen struct mailbox_status *status_r)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen struct mailbox_sync_context *ctx = *_ctx;
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen *_ctx = NULL;
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen return ctx->box->v.sync_deinit(ctx, status_items, status_r);
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen}
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainenint mailbox_sync(struct mailbox *box, enum mailbox_sync_flags flags,
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen enum mailbox_status_items status_items,
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen struct mailbox_status *status_r)
bd4de9c8152e6ea032c1cb1df8b79635ff5ddf9eTimo Sirainen{
4530cfa7456c10cd03fe9120c75f8bcb2f623ba4Timo Sirainen struct mailbox_sync_context *ctx;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (array_count(&box->search_results) == 0) {
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainen /* we don't care about mailbox's current state, so we might
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainen as well fix inconsistency state */
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen flags |= MAILBOX_SYNC_FLAG_FIX_INCONSISTENT;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen }
e10d8b1291090c26b9ef499637e6e632485ca5beTimo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen ctx = mailbox_sync_init(box, flags);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return mailbox_sync_deinit(&ctx, status_items, status_r);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen#undef mailbox_notify_changes
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenvoid mailbox_notify_changes(struct mailbox *box, unsigned int min_interval,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen mailbox_notify_callback_t *callback, void *context)
714e2da5096fb52b8845d3c79f9bb26225a606c9Timo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen box->notify_min_interval = min_interval;
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainen box->notify_callback = callback;
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainen box->notify_context = context;
04a7b696e5255aa956277a0f7cabee736c69ec96Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen box->v.notify_changes(box);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenvoid mailbox_notify_changes_stop(struct mailbox *box)
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen mailbox_notify_changes(box, 0, NULL, NULL);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenint mailbox_keywords_create(struct mailbox *box, const char *const keywords[],
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen struct mail_keywords **keywords_r)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen const char *empty_keyword_list = NULL;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
6882df5fbca4a09cdaa95f54d70bb31b5920528cTimo Sirainen if (keywords == NULL)
714e2da5096fb52b8845d3c79f9bb26225a606c9Timo Sirainen keywords = &empty_keyword_list;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return box->v.keywords_create(box, keywords, keywords_r, FALSE);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenstruct mail_keywords *
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenmailbox_keywords_create_valid(struct mailbox *box,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen const char *const keywords[])
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainen const char *empty_keyword_list = NULL;
eb4d4f557fa75aa2a47639e9deb75a21f44eb42aTimo Sirainen struct mail_keywords *kw;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (keywords == NULL)
e10d8b1291090c26b9ef499637e6e632485ca5beTimo Sirainen keywords = &empty_keyword_list;
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen if (box->v.keywords_create(box, keywords, &kw, TRUE) < 0)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen i_unreached();
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return kw;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
2c719bcb92302f45df4badb71d1d97f57235d0ccTimo Sirainenstruct mail_keywords *
2c719bcb92302f45df4badb71d1d97f57235d0ccTimo Sirainenmailbox_keywords_create_from_indexes(struct mailbox *box,
2c719bcb92302f45df4badb71d1d97f57235d0ccTimo Sirainen const ARRAY_TYPE(keyword_indexes) *idx)
2c719bcb92302f45df4badb71d1d97f57235d0ccTimo Sirainen{
6882df5fbca4a09cdaa95f54d70bb31b5920528cTimo Sirainen return box->v.keywords_create_from_indexes(box, idx);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenvoid mailbox_keywords_ref(struct mailbox *box, struct mail_keywords *keywords)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
cd2cd224d3216a243d55c71c298a5b7684de0ac4Timo Sirainen box->v.keywords_ref(keywords);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenvoid mailbox_keywords_unref(struct mailbox *box,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen struct mail_keywords **_keywords)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen struct mail_keywords *keywords = *_keywords;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
cd2cd224d3216a243d55c71c298a5b7684de0ac4Timo Sirainen *_keywords = NULL;
ac0fed903142d28ae3a1d5d00d2097fdf161b138Timo Sirainen box->v.keywords_unref(keywords);
ac0fed903142d28ae3a1d5d00d2097fdf161b138Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenbool mailbox_keyword_is_valid(struct mailbox *box, const char *keyword,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen const char **error_r)
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen{
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen return box->v.keyword_is_valid(box, keyword, error_r);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen}
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainenvoid mailbox_get_seq_range(struct mailbox *box, uint32_t uid1, uint32_t uid2,
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen uint32_t *seq1_r, uint32_t *seq2_r)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen box->v.get_seq_range(box, uid1, uid2, seq1_r, seq2_r);
02a54da28f376dd66d7939d8546a196a0045b486Timo Sirainen}
23fdad6c7e2581921f511e24cd9371c9eaebcef9Timo Sirainen
23fdad6c7e2581921f511e24cd9371c9eaebcef9Timo Sirainenvoid mailbox_get_uid_range(struct mailbox *box,
8552b0cad8ffe9ccb8270577ba28b8010c89af11Timo Sirainen const ARRAY_TYPE(seq_range) *seqs,
ARRAY_TYPE(seq_range) *uids)
{
box->v.get_uid_range(box, seqs, uids);
}
bool mailbox_get_expunges(struct mailbox *box, uint64_t prev_modseq,
const ARRAY_TYPE(seq_range) *uids_filter,
ARRAY_TYPE(mailbox_expunge_rec) *expunges)
{
return box->v.get_expunges(box, prev_modseq,
uids_filter, expunges);
}
bool mailbox_get_virtual_uid(struct mailbox *box, const char *backend_mailbox,
uint32_t backend_uidvalidity,
uint32_t backend_uid, uint32_t *uid_r)
{
if (box->v.get_virtual_uid == NULL)
return FALSE;
return box->v.get_virtual_uid(box, backend_mailbox, backend_uidvalidity,
backend_uid, uid_r);
}
void mailbox_get_virtual_backend_boxes(struct mailbox *box,
ARRAY_TYPE(mailboxes) *mailboxes,
bool only_with_msgs)
{
if (box->v.get_virtual_backend_boxes == NULL)
array_append(mailboxes, &box, 1);
else
box->v.get_virtual_backend_boxes(box, mailboxes, only_with_msgs);
}
void mailbox_get_virtual_box_patterns(struct mailbox *box,
ARRAY_TYPE(mailbox_virtual_patterns) *includes,
ARRAY_TYPE(mailbox_virtual_patterns) *excludes)
{
if (box->v.get_virtual_box_patterns == NULL) {
struct mailbox_virtual_pattern pat;
memset(&pat, 0, sizeof(pat));
pat.ns = box->list->ns;
pat.pattern = box->name;
array_append(includes, &pat, 1);
} else {
box->v.get_virtual_box_patterns(box, includes, excludes);
}
}
struct mailbox_header_lookup_ctx *
mailbox_header_lookup_init(struct mailbox *box, const char *const headers[])
{
return box->v.header_lookup_init(box, headers);
}
void mailbox_header_lookup_ref(struct mailbox_header_lookup_ctx *ctx)
{
i_assert(ctx->refcount > 0);
ctx->refcount++;
}
void mailbox_header_lookup_unref(struct mailbox_header_lookup_ctx **_ctx)
{
struct mailbox_header_lookup_ctx *ctx = *_ctx;
*_ctx = NULL;
i_assert(ctx->refcount > 0);
if (--ctx->refcount > 0)
return;
ctx->box->v.header_lookup_deinit(ctx);
}
struct mail_search_context *
mailbox_search_init(struct mailbox_transaction_context *t,
struct mail_search_args *args,
const enum mail_sort_type *sort_program)
{
mail_search_args_ref(args);
if (!args->simplified)
mail_search_args_simplify(args);
return t->box->v.search_init(t, args, sort_program);
}
int mailbox_search_deinit(struct mail_search_context **_ctx)
{
struct mail_search_context *ctx = *_ctx;
struct mail_search_args *args = ctx->args;
int ret;
*_ctx = NULL;
mailbox_search_results_initial_done(ctx);
ret = ctx->transaction->box->v.search_deinit(ctx);
mail_search_args_unref(&args);
return ret;
}
int mailbox_search_next(struct mail_search_context *ctx, struct mail *mail)
{
bool tryagain;
int ret;
while ((ret = mailbox_search_next_nonblock(ctx, mail,
&tryagain)) == 0) {
if (!tryagain)
break;
}
return ret;
}
int mailbox_search_next_nonblock(struct mail_search_context *ctx,
struct mail *mail, bool *tryagain_r)
{
int ret;
ret = ctx->transaction->box->v.
search_next_nonblock(ctx, mail, tryagain_r);
if (ret > 0)
mailbox_search_results_add(ctx, mail->uid);
return ret;
}
bool mailbox_search_seen_lost_data(struct mail_search_context *ctx)
{
return ctx->seen_lost_data;
}
int mailbox_search_result_build(struct mailbox_transaction_context *t,
struct mail_search_args *args,
enum mailbox_search_result_flags flags,
struct mail_search_result **result_r)
{
struct mail_search_context *ctx;
struct mail *mail;
int ret;
ctx = mailbox_search_init(t, args, NULL);
*result_r = mailbox_search_result_save(ctx, flags);
mail = mail_alloc(t, 0, NULL);
while (mailbox_search_next(ctx, mail) > 0) ;
mail_free(&mail);
ret = mailbox_search_deinit(&ctx);
if (ret < 0)
mailbox_search_result_free(result_r);
return ret;
}
struct mailbox_transaction_context *
mailbox_transaction_begin(struct mailbox *box,
enum mailbox_transaction_flags flags)
{
struct mailbox_transaction_context *trans;
box->transaction_count++;
trans = box->v.transaction_begin(box, flags);
trans->flags = flags;
return trans;
}
int mailbox_transaction_commit(struct mailbox_transaction_context **t)
{
struct mail_transaction_commit_changes changes;
int ret;
/* Store changes temporarily so that plugins overriding
transaction_commit() can look at them. */
ret = mailbox_transaction_commit_get_changes(t, &changes);
pool_unref(&changes.pool);
return ret;
}
int mailbox_transaction_commit_get_changes(
struct mailbox_transaction_context **_t,
struct mail_transaction_commit_changes *changes_r)
{
struct mailbox_transaction_context *t = *_t;
t->box->transaction_count--;
*_t = NULL;
return t->box->v.transaction_commit(t, changes_r);
}
void mailbox_transaction_rollback(struct mailbox_transaction_context **_t)
{
struct mailbox_transaction_context *t = *_t;
t->box->transaction_count--;
*_t = NULL;
t->box->v.transaction_rollback(t);
}
unsigned int mailbox_transaction_get_count(const struct mailbox *box)
{
return box->transaction_count;
}
void mailbox_transaction_set_max_modseq(struct mailbox_transaction_context *t,
uint64_t max_modseq,
ARRAY_TYPE(seq_range) *seqs)
{
t->box->v.transaction_set_max_modseq(t, max_modseq, seqs);
}
struct mailbox *
mailbox_transaction_get_mailbox(const struct mailbox_transaction_context *t)
{
return t->box;
}
struct mail_save_context *
mailbox_save_alloc(struct mailbox_transaction_context *t)
{
struct mail_save_context *ctx;
ctx = t->box->v.save_alloc(t);
ctx->received_date = (time_t)-1;
ctx->save_date = (time_t)-1;
return ctx;
}
void mailbox_save_set_flags(struct mail_save_context *ctx,
enum mail_flags flags,
struct mail_keywords *keywords)
{
ctx->flags = flags;
ctx->keywords = keywords;
if (keywords != NULL)
mailbox_keywords_ref(ctx->transaction->box, keywords);
}
void mailbox_save_copy_flags(struct mail_save_context *ctx, struct mail *mail)
{
const char *const *keywords_list;
keywords_list = mail_get_keywords(mail);
ctx->keywords = str_array_length(keywords_list) == 0 ? NULL :
mailbox_keywords_create_valid(ctx->transaction->box,
keywords_list);
ctx->flags = mail_get_flags(mail);
}
void mailbox_save_set_received_date(struct mail_save_context *ctx,
time_t received_date, int timezone_offset)
{
ctx->received_date = received_date;
ctx->received_tz_offset = timezone_offset;
}
void mailbox_save_set_save_date(struct mail_save_context *ctx,
time_t save_date)
{
ctx->save_date = save_date;
}
void mailbox_save_set_from_envelope(struct mail_save_context *ctx,
const char *envelope)
{
i_free(ctx->from_envelope);
ctx->from_envelope = i_strdup(envelope);
}
void mailbox_save_set_uid(struct mail_save_context *ctx, uint32_t uid)
{
ctx->uid = uid;
}
void mailbox_save_set_guid(struct mail_save_context *ctx, const char *guid)
{
i_assert(guid == NULL || *guid != '\0');
i_free(ctx->guid);
ctx->guid = i_strdup(guid);
}
void mailbox_save_set_pop3_uidl(struct mail_save_context *ctx, const char *uidl)
{
i_free(ctx->pop3_uidl);
ctx->pop3_uidl = i_strdup(uidl);
}
void mailbox_save_set_dest_mail(struct mail_save_context *ctx,
struct mail *mail)
{
ctx->dest_mail = mail;
}
int mailbox_save_begin(struct mail_save_context **ctx, struct istream *input)
{
struct mailbox *box = (*ctx)->transaction->box;
int ret;
if (box->v.save_begin == NULL) {
mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
"Saving messages not supported");
ret = -1;
} else {
ret = box->v.save_begin(*ctx, input);
}
if (ret < 0) {
mailbox_save_cancel(ctx);
return -1;
}
return 0;
}
int mailbox_save_continue(struct mail_save_context *ctx)
{
return ctx->transaction->box->v.save_continue(ctx);
}
int mailbox_save_finish(struct mail_save_context **_ctx)
{
struct mail_save_context *ctx = *_ctx;
struct mailbox *box = ctx->transaction->box;
struct mail_keywords *keywords = ctx->keywords;
int ret;
*_ctx = NULL;
ret = box->v.save_finish(ctx);
if (keywords != NULL)
mailbox_keywords_unref(box, &keywords);
return ret;
}
void mailbox_save_cancel(struct mail_save_context **_ctx)
{
struct mail_save_context *ctx = *_ctx;
struct mailbox *box = ctx->transaction->box;
struct mail_keywords *keywords = ctx->keywords;
*_ctx = NULL;
ctx->transaction->box->v.save_cancel(ctx);
if (keywords != NULL)
mailbox_keywords_unref(box, &keywords);
}
int mailbox_copy(struct mail_save_context **_ctx, struct mail *mail)
{
struct mail_save_context *ctx = *_ctx;
struct mailbox *box = ctx->transaction->box;
struct mail_keywords *keywords = ctx->keywords;
int ret;
*_ctx = NULL;
ret = ctx->transaction->box->v.copy(ctx, mail);
if (keywords != NULL)
mailbox_keywords_unref(box, &keywords);
return ret;
}
bool mailbox_is_inconsistent(struct mailbox *box)
{
return box->mailbox_deleted || box->v.is_inconsistent(box);
}
void mailbox_set_deleted(struct mailbox *box)
{
mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
"Mailbox was deleted under us");
box->mailbox_deleted = TRUE;
}
bool mailbox_guid_is_empty(const uint8_t guid[MAILBOX_GUID_SIZE])
{
return mail_guid_128_is_empty(guid);
}