1
/* Copyright (c) 2008-2009 Dovecot authors, see the included COPYING file */
4
#include "imap-match.h"
5
#include "mailbox-list-private.h"
6
#include "index-storage.h"
7
#include "shared-storage.h"
9
struct shared_mailbox_list_iterate_context {
10
struct mailbox_list_iterate_context ctx;
11
struct mail_namespace *cur_ns;
12
struct imap_match_glob *glob;
13
struct mailbox_info info;
16
extern struct mailbox_list shared_mailbox_list;
18
static struct mailbox_list *shared_list_alloc(void)
20
struct mailbox_list *list;
23
pool = pool_alloconly_create("shared list", 1024);
24
list = p_new(pool, struct mailbox_list, 1);
25
*list = shared_mailbox_list;
30
static void shared_list_deinit(struct mailbox_list *list)
32
pool_unref(&list->pool);
35
static void shared_list_copy_error(struct mailbox_list *shared_list,
36
struct mail_namespace *backend_ns)
39
enum mail_error error;
41
str = mailbox_list_get_last_error(backend_ns->list, &error);
42
mailbox_list_set_error(shared_list, error, str);
46
shared_get_storage(struct mailbox_list *list, const char **name,
47
struct mail_storage **storage_r)
49
struct mail_namespace *ns;
51
if (shared_storage_get_namespace(list->ns->storage, name, &ns) < 0)
53
*storage_r = ns->storage;
58
shared_is_valid_pattern(struct mailbox_list *list, const char *pattern)
60
struct mail_namespace *ns;
62
if (shared_storage_get_namespace(list->ns->storage, &pattern, &ns) < 0)
64
return mailbox_list_is_valid_pattern(ns->list, pattern);
68
shared_is_valid_existing_name(struct mailbox_list *list, const char *name)
70
struct mail_namespace *ns;
72
if (shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0)
74
return mailbox_list_is_valid_existing_name(ns->list, name);
78
shared_is_valid_create_name(struct mailbox_list *list, const char *name)
80
struct mail_namespace *ns;
82
if (shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0)
84
return mailbox_list_is_valid_create_name(ns->list, name);
88
shared_list_get_path(struct mailbox_list *list, const char *name,
89
enum mailbox_list_path_type type)
91
struct mail_namespace *ns;
93
if (list->ns->storage == NULL || name == NULL ||
94
shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0) {
96
case MAILBOX_LIST_PATH_TYPE_DIR:
97
case MAILBOX_LIST_PATH_TYPE_MAILBOX:
98
case MAILBOX_LIST_PATH_TYPE_CONTROL:
100
case MAILBOX_LIST_PATH_TYPE_INDEX:
101
/* we can safely say we don't use indexes */
104
/* we don't have a directory we can use. */
107
return mailbox_list_get_path(ns->list, name, type);
111
shared_list_get_mailbox_name_status(struct mailbox_list *list, const char *name,
112
enum mailbox_name_status *status_r)
114
struct mail_namespace *ns;
117
if (shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0)
119
ret = mailbox_list_get_mailbox_name_status(ns->list, name, status_r);
121
shared_list_copy_error(list, ns);
126
shared_list_get_temp_prefix(struct mailbox_list *list, bool global ATTR_UNUSED)
128
i_panic("shared mailbox list: Can't return a temp prefix for '%s'",
134
shared_list_join_refpattern(struct mailbox_list *list,
135
const char *ref, const char *pattern)
137
struct mail_namespace *ns;
138
const char *ns_ref, *prefix = list->ns->prefix;
139
unsigned int prefix_len = strlen(prefix);
141
if (*ref != '\0' && strncmp(ref, prefix, prefix_len) == 0)
142
ns_ref = ref + prefix_len;
146
if (ns_ref != NULL &&
147
shared_storage_get_namespace(list->ns->storage,
149
return mailbox_list_join_refpattern(ns->list, ns_ref, pattern);
151
/* fallback to default behavior */
153
pattern = t_strconcat(ref, pattern, NULL);
157
static struct mailbox_list_iterate_context *
158
shared_list_iter_init(struct mailbox_list *list, const char *const *patterns,
159
enum mailbox_list_iter_flags flags)
161
struct shared_mailbox_list_iterate_context *ctx;
163
ctx = i_new(struct shared_mailbox_list_iterate_context, 1);
164
ctx->ctx.list = list;
165
ctx->ctx.flags = flags;
166
ctx->cur_ns = list->ns->user->namespaces;
167
ctx->info.ns = list->ns;
168
ctx->info.flags = MAILBOX_NONEXISTENT;
169
ctx->glob = imap_match_init_multiple(default_pool, patterns,
170
FALSE, list->ns->sep);
174
static const struct mailbox_info *
175
shared_list_iter_next(struct mailbox_list_iterate_context *_ctx)
177
struct shared_mailbox_list_iterate_context *ctx =
178
(struct shared_mailbox_list_iterate_context *)_ctx;
179
struct mail_namespace *ns = ctx->cur_ns;
181
for (; ns != NULL; ns = ns->next) {
182
if (ns->type != NAMESPACE_SHARED ||
183
(ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0)
185
if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
186
NAMESPACE_FLAG_LIST_CHILDREN)) == 0)
189
if (ns->prefix_len < ctx->info.ns->prefix_len ||
190
strncmp(ns->prefix, ctx->info.ns->prefix,
191
ctx->info.ns->prefix_len) != 0)
194
/* visible and listable namespace under ourself, see if the
195
prefix matches without the trailing separator */
196
i_assert(ns->prefix_len > 0);
197
ctx->info.name = t_strndup(ns->prefix, ns->prefix_len - 1);
198
if ((_ctx->flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) == 0)
199
ctx->info.name += ctx->info.ns->prefix_len;
200
if (imap_match(ctx->glob, ctx->info.name) == IMAP_MATCH_YES) {
201
ctx->cur_ns = ns->next;
210
static int shared_list_iter_deinit(struct mailbox_list_iterate_context *_ctx)
212
struct shared_mailbox_list_iterate_context *ctx =
213
(struct shared_mailbox_list_iterate_context *)_ctx;
215
imap_match_deinit(&ctx->glob);
220
static int shared_list_set_subscribed(struct mailbox_list *list,
221
const char *name, bool set)
223
struct mail_namespace *ns;
226
if (shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0)
228
ret = mailbox_list_set_subscribed(ns->list, name, set);
230
shared_list_copy_error(list, ns);
235
shared_list_delete_mailbox(struct mailbox_list *list, const char *name)
237
struct mail_namespace *ns;
240
if (shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0)
242
ret = mailbox_list_delete_mailbox(ns->list, name);
244
shared_list_copy_error(list, ns);
248
static int shared_list_rename_get_ns(struct mailbox_list *list,
249
const char **oldname, const char **newname,
250
struct mail_namespace **ns_r)
252
struct mail_namespace *old_ns, *new_ns;
254
if (shared_storage_get_namespace(list->ns->storage,
255
oldname, &old_ns) < 0 ||
256
shared_storage_get_namespace(list->ns->storage,
257
newname, &new_ns) < 0)
259
if (old_ns != new_ns) {
260
mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
261
"Can't rename mailboxes across storages");
268
static int shared_list_rename_mailbox(struct mailbox_list *list,
269
const char *oldname, const char *newname)
271
struct mail_namespace *ns;
274
if (shared_list_rename_get_ns(list, &oldname, &newname, &ns) < 0)
276
ret = mailbox_list_rename_mailbox(ns->list, oldname, newname);
278
shared_list_copy_error(list, ns);
283
shared_list_rename_mailbox_pre(struct mailbox_list *list,
284
const char *oldname, const char *newname)
286
struct mail_namespace *ns;
289
if (shared_list_rename_get_ns(list, &oldname, &newname, &ns) < 0)
291
ret = ns->list->v.rename_mailbox_pre(ns->list, oldname, newname);
293
shared_list_copy_error(list, ns);
297
struct mailbox_list shared_mailbox_list = {
298
MEMBER(name) "shared",
299
MEMBER(hierarchy_sep) '/',
301
MEMBER(mailbox_name_max_length) PATH_MAX,
307
shared_is_valid_pattern,
308
shared_is_valid_existing_name,
309
shared_is_valid_create_name,
310
shared_list_get_path,
311
shared_list_get_mailbox_name_status,
312
shared_list_get_temp_prefix,
313
shared_list_join_refpattern,
314
shared_list_iter_init,
315
shared_list_iter_next,
316
shared_list_iter_deinit,
318
shared_list_set_subscribed,
319
shared_list_delete_mailbox,
320
shared_list_rename_mailbox,
321
shared_list_rename_mailbox_pre