Mercurial > dovecot > original-hg > dovecot-1.2
view src/lib-storage/index/shared/shared-list.c @ 8938:3cc00d9d1c12 HEAD
Memory leak fixes.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 11 Apr 2009 21:59:26 -0400 |
parents | b6abc84440df |
children | 6a4cccf11702 |
line wrap: on
line source
/* Copyright (c) 2008-2009 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "imap-match.h" #include "mailbox-list-private.h" #include "index-storage.h" #include "shared-storage.h" struct shared_mailbox_list_iterate_context { struct mailbox_list_iterate_context ctx; struct mail_namespace *cur_ns; struct imap_match_glob *glob; struct mailbox_info info; }; extern struct mailbox_list shared_mailbox_list; static struct mailbox_list *shared_list_alloc(void) { struct mailbox_list *list; pool_t pool; pool = pool_alloconly_create("shared list", 1024); list = p_new(pool, struct mailbox_list, 1); *list = shared_mailbox_list; list->pool = pool; return list; } static void shared_list_deinit(struct mailbox_list *list) { pool_unref(&list->pool); } static void shared_list_copy_error(struct mailbox_list *shared_list, struct mail_namespace *backend_ns) { const char *str; enum mail_error error; str = mailbox_list_get_last_error(backend_ns->list, &error); mailbox_list_set_error(shared_list, error, str); } static int shared_get_storage(struct mailbox_list *list, const char **name, struct mail_storage **storage_r) { struct mail_namespace *ns; if (shared_storage_get_namespace(list->ns->storage, name, &ns) < 0) return -1; *storage_r = ns->storage; return 0; } static bool shared_is_valid_pattern(struct mailbox_list *list, const char *pattern) { struct mail_namespace *ns; if (shared_storage_get_namespace(list->ns->storage, &pattern, &ns) < 0) return FALSE; return mailbox_list_is_valid_pattern(ns->list, pattern); } static bool shared_is_valid_existing_name(struct mailbox_list *list, const char *name) { struct mail_namespace *ns; if (shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0) return FALSE; return mailbox_list_is_valid_existing_name(ns->list, name); } static bool shared_is_valid_create_name(struct mailbox_list *list, const char *name) { struct mail_namespace *ns; if (shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0) return FALSE; return mailbox_list_is_valid_create_name(ns->list, name); } static const char * shared_list_get_path(struct mailbox_list *list, const char *name, enum mailbox_list_path_type type) { struct mail_namespace *ns; if (list->ns->storage == NULL || name == NULL || shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0) { switch (type) { case MAILBOX_LIST_PATH_TYPE_DIR: case MAILBOX_LIST_PATH_TYPE_MAILBOX: case MAILBOX_LIST_PATH_TYPE_CONTROL: break; case MAILBOX_LIST_PATH_TYPE_INDEX: /* we can safely say we don't use indexes */ return ""; } /* we don't have a directory we can use. */ return NULL; } return mailbox_list_get_path(ns->list, name, type); } static int shared_list_get_mailbox_name_status(struct mailbox_list *list, const char *name, enum mailbox_name_status *status_r) { struct mail_namespace *ns; int ret; if (shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0) return -1; ret = mailbox_list_get_mailbox_name_status(ns->list, name, status_r); if (ret < 0) shared_list_copy_error(list, ns); return ret; } static const char * shared_list_get_temp_prefix(struct mailbox_list *list, bool global ATTR_UNUSED) { i_panic("shared mailbox list: Can't return a temp prefix for '%s'", list->ns->prefix); return NULL; } static const char * shared_list_join_refpattern(struct mailbox_list *list, const char *ref, const char *pattern) { struct mail_namespace *ns; const char *ns_ref, *prefix = list->ns->prefix; unsigned int prefix_len = strlen(prefix); if (*ref != '\0' && strncmp(ref, prefix, prefix_len) == 0) ns_ref = ref + prefix_len; else if (*ref == '\0' && strncmp(pattern, prefix, prefix_len) == 0) ns_ref = pattern + prefix_len; else ns_ref = NULL; if (ns_ref != NULL && shared_storage_get_namespace(list->ns->storage, &ns_ref, &ns) == 0) return mailbox_list_join_refpattern(ns->list, ref, pattern); /* fallback to default behavior */ if (*ref != '\0') pattern = t_strconcat(ref, pattern, NULL); return pattern; } static struct mailbox_list_iterate_context * shared_list_iter_init(struct mailbox_list *list, const char *const *patterns, enum mailbox_list_iter_flags flags) { struct shared_mailbox_list_iterate_context *ctx; ctx = i_new(struct shared_mailbox_list_iterate_context, 1); ctx->ctx.list = list; ctx->ctx.flags = flags; ctx->cur_ns = list->ns->user->namespaces; ctx->info.ns = list->ns; ctx->info.flags = MAILBOX_NONEXISTENT; ctx->glob = imap_match_init_multiple(default_pool, patterns, FALSE, list->ns->sep); return &ctx->ctx; } static const struct mailbox_info * shared_list_iter_next(struct mailbox_list_iterate_context *_ctx) { struct shared_mailbox_list_iterate_context *ctx = (struct shared_mailbox_list_iterate_context *)_ctx; struct mail_namespace *ns = ctx->cur_ns; for (; ns != NULL; ns = ns->next) { if (ns->type != NAMESPACE_SHARED || (ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0) continue; if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_LIST_CHILDREN)) == 0) continue; if (ns->prefix_len < ctx->info.ns->prefix_len || strncmp(ns->prefix, ctx->info.ns->prefix, ctx->info.ns->prefix_len) != 0) continue; /* visible and listable namespace under ourself, see if the prefix matches without the trailing separator */ i_assert(ns->prefix_len > 0); ctx->info.name = t_strndup(ns->prefix, ns->prefix_len - 1); if ((_ctx->flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) == 0) ctx->info.name += ctx->info.ns->prefix_len; if (imap_match(ctx->glob, ctx->info.name) == IMAP_MATCH_YES) { ctx->cur_ns = ns->next; return &ctx->info; } } ctx->cur_ns = NULL; return NULL; } static int shared_list_iter_deinit(struct mailbox_list_iterate_context *_ctx) { struct shared_mailbox_list_iterate_context *ctx = (struct shared_mailbox_list_iterate_context *)_ctx; imap_match_deinit(&ctx->glob); i_free(ctx); return 0; } static int shared_list_set_subscribed(struct mailbox_list *list, const char *name, bool set) { struct mail_namespace *ns; int ret; if (shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0) return -1; ret = mailbox_list_set_subscribed(ns->list, name, set); if (ret < 0) shared_list_copy_error(list, ns); return ret; } static int shared_list_delete_mailbox(struct mailbox_list *list, const char *name) { struct mail_namespace *ns; int ret; if (shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0) return -1; ret = mailbox_list_delete_mailbox(ns->list, name); if (ret < 0) shared_list_copy_error(list, ns); return ret; } static int shared_list_rename_get_ns(struct mailbox_list *list, const char **oldname, const char **newname, struct mail_namespace **ns_r) { struct mail_namespace *old_ns, *new_ns; if (shared_storage_get_namespace(list->ns->storage, oldname, &old_ns) < 0 || shared_storage_get_namespace(list->ns->storage, newname, &new_ns) < 0) return -1; if (old_ns != new_ns) { mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE, "Can't rename mailboxes across storages"); return -1; } *ns_r = old_ns; return 0; } static int shared_list_rename_mailbox(struct mailbox_list *list, const char *oldname, const char *newname) { struct mail_namespace *ns; int ret; if (shared_list_rename_get_ns(list, &oldname, &newname, &ns) < 0) return -1; ret = mailbox_list_rename_mailbox(ns->list, oldname, newname); if (ret < 0) shared_list_copy_error(list, ns); return ret; } static int shared_list_rename_mailbox_pre(struct mailbox_list *list, const char *oldname, const char *newname) { struct mail_namespace *ns; int ret; if (shared_list_rename_get_ns(list, &oldname, &newname, &ns) < 0) return -1; ret = ns->list->v.rename_mailbox_pre(ns->list, oldname, newname); if (ret < 0) shared_list_copy_error(list, ns); return ret; } struct mailbox_list shared_mailbox_list = { MEMBER(name) "shared", MEMBER(hierarchy_sep) '/', MEMBER(props) 0, MEMBER(mailbox_name_max_length) PATH_MAX, { shared_list_alloc, shared_list_deinit, shared_get_storage, shared_is_valid_pattern, shared_is_valid_existing_name, shared_is_valid_create_name, shared_list_get_path, shared_list_get_mailbox_name_status, shared_list_get_temp_prefix, shared_list_join_refpattern, shared_list_iter_init, shared_list_iter_next, shared_list_iter_deinit, NULL, shared_list_set_subscribed, shared_list_delete_mailbox, shared_list_rename_mailbox, shared_list_rename_mailbox_pre } };