[dovecot-cvs] dovecot/src/plugins/acl Makefile.am, 1.4, 1.5 acl-api-private.h, 1.5, 1.6 acl-api.c, 1.6, 1.7 acl-api.h, 1.4, 1.5 acl-backend-vfile-acllist.c, NONE, 1.1 acl-backend-vfile.c, 1.18, 1.19 acl-backend-vfile.h, NONE, 1.1 acl-backend.c, 1.6, 1.7 acl-cache.c, 1.7, 1.8 acl-cache.h, 1.3, 1.4 acl-mailbox-list.c, 1.5, 1.6 acl-plugin.c, 1.5, 1.6 acl-storage.c, 1.6, 1.7
tss at dovecot.org
tss at dovecot.org
Wed Apr 11 22:33:40 EEST 2007
Update of /var/lib/cvs/dovecot/src/plugins/acl
In directory talvi:/tmp/cvs-serv4498
Modified Files:
Makefile.am acl-api-private.h acl-api.c acl-api.h
acl-backend-vfile.c acl-backend.c acl-cache.c acl-cache.h
acl-mailbox-list.c acl-plugin.c acl-storage.c
Added Files:
acl-backend-vfile-acllist.c acl-backend-vfile.h
Log Message:
Create dovecot-acl-list file that lists all mailboxes where non-owner has
lookup right. Use the file when listing mailboxes in shared/public
namespace.
Index: Makefile.am
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/acl/Makefile.am,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- Makefile.am 29 Mar 2007 11:51:09 -0000 1.4
+++ Makefile.am 11 Apr 2007 19:33:37 -0000 1.5
@@ -1,6 +1,7 @@
AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/lib-mail \
+ -I$(top_srcdir)/src/lib-imap \
-I$(top_srcdir)/src/lib-index \
-I$(top_srcdir)/src/lib-storage
@@ -13,6 +14,7 @@
acl-api.c \
acl-backend.c \
acl-backend-vfile.c \
+ acl-backend-vfile-acllist.c \
acl-cache.c \
acl-mailbox.c \
acl-mailbox-list.c \
@@ -22,6 +24,7 @@
noinst_HEADERS = \
acl-api.h \
acl-api-private.h \
+ acl-backend-vfile.h \
acl-cache.h \
acl-plugin.h
Index: acl-api-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/acl/acl-api-private.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- acl-api-private.h 11 Apr 2007 11:02:31 -0000 1.5
+++ acl-api-private.h 11 Apr 2007 19:33:37 -0000 1.6
@@ -8,6 +8,13 @@
int (*init)(struct acl_backend *backend, const char *data);
void (*deinit)(struct acl_backend *backend);
+ struct acl_mailbox_list_context *
+ (*nonowner_lookups_iter_init)(struct acl_backend *backend);
+ int (*nonowner_lookups_iter_next)(struct acl_mailbox_list_context *ctx,
+ const char **name_r);
+ void (*nonowner_lookups_iter_deinit)
+ (struct acl_mailbox_list_context *ctx);
+
struct acl_object *(*object_init)(struct acl_backend *backend,
struct mail_storage *storage,
const char *name);
@@ -15,7 +22,7 @@
int (*object_refresh_cache)(struct acl_object *aclobj);
int (*object_update)(struct acl_object *aclobj,
- const struct acl_rights *rights);
+ const struct acl_rights_update *rights);
struct acl_object_list_iter *
(*object_list_init)(struct acl_object *aclobj);
@@ -26,7 +33,7 @@
struct acl_backend {
pool_t pool;
- const char *username, *owner_username;
+ const char *username;
const char **groups;
unsigned int group_count;
@@ -38,9 +45,14 @@
struct acl_backend_vfuncs v;
+ unsigned int owner:1;
unsigned int debug:1;
};
+struct acl_mailbox_list_context {
+ struct acl_backend *backend;
+};
+
struct acl_object {
struct acl_backend *backend;
char *name;
@@ -48,6 +60,12 @@
struct acl_object_list_iter {
struct acl_object *aclobj;
+
+ unsigned int idx;
+ unsigned int failed:1;
};
+int acl_backend_get_default_rights(struct acl_backend *backend,
+ const struct acl_mask **mask_r);
+
#endif
Index: acl-api.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/acl/acl-api.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- acl-api.c 11 Apr 2007 12:08:22 -0000 1.6
+++ acl-api.c 11 Apr 2007 19:33:37 -0000 1.7
@@ -20,23 +20,10 @@
aclobj->backend->v.object_deinit(aclobj);
}
-static int acl_backend_get_default_rights(struct acl_backend *backend,
- const struct acl_mask **mask_r)
-{
- if (backend->v.object_refresh_cache(backend->default_aclobj) < 0)
- return -1;
-
- *mask_r = acl_cache_get_my_rights(backend->cache, "");
- if (*mask_r == NULL)
- *mask_r = backend->default_aclmask;
- return 0;
-}
-
int acl_object_have_right(struct acl_object *aclobj, unsigned int right_idx)
{
struct acl_backend *backend = aclobj->backend;
const struct acl_mask *have_mask;
- unsigned int mask_idx;
if (*aclobj->name == '\0') {
/* we want to look up default rights */
@@ -55,10 +42,7 @@
}
}
- mask_idx = right_idx / CHAR_BIT;
- return mask_idx < have_mask->size &&
- (have_mask->mask[mask_idx] &
- (1 << (right_idx % CHAR_BIT))) != 0;
+ return acl_cache_mask_isset(have_mask, right_idx);
}
int acl_object_get_my_rights(struct acl_object *aclobj, pool_t pool,
@@ -118,7 +102,7 @@
}
int acl_object_update(struct acl_object *aclobj,
- const struct acl_rights *rights)
+ const struct acl_rights_update *rights)
{
return aclobj->backend->v.object_update(aclobj, rights);
}
@@ -131,7 +115,10 @@
int acl_object_list_next(struct acl_object_list_iter *iter,
struct acl_rights *rights_r)
{
- return iter->aclobj->backend->v.object_list_next(iter, rights_r);
+ if (iter->failed)
+ return -1;
+
+ return iter->aclobj->backend->v.object_list_next(iter, rights_r);
}
void acl_object_list_deinit(struct acl_object_list_iter **_iter)
@@ -141,3 +128,24 @@
*_iter = NULL;
iter->aclobj->backend->v.object_list_deinit(iter);
}
+
+struct acl_mailbox_list_context *
+acl_backend_nonowner_lookups_iter_init(struct acl_backend *backend)
+{
+ return backend->v.nonowner_lookups_iter_init(backend);
+}
+
+int acl_backend_nonowner_lookups_iter_next(struct acl_mailbox_list_context *ctx,
+ const char **name_r)
+{
+ return ctx->backend->v.nonowner_lookups_iter_next(ctx, name_r);
+}
+
+void
+acl_backend_nonowner_lookups_iter_deinit(struct acl_mailbox_list_context **_ctx)
+{
+ struct acl_mailbox_list_context *ctx = *_ctx;
+
+ *_ctx = NULL;
+ ctx->backend->v.nonowner_lookups_iter_deinit(ctx);
+}
Index: acl-api.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/acl/acl-api.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- acl-api.h 11 Apr 2007 12:08:50 -0000 1.4
+++ acl-api.h 11 Apr 2007 19:33:37 -0000 1.5
@@ -27,16 +27,19 @@
/* Allow changing ACL state in this mailbox */
#define MAIL_ACL_ADMIN "admin"
+/* ACL identifiers in override order */
enum acl_id_type {
/* Anyone's rights, including anonymous's.
identifier name is ignored. */
ACL_ID_ANYONE,
- /* Authenticate users' rights, overrides anyone's rights.
- identifier name is ignored. */
+ /* Authenticate users' rights. identifier name is ignored. */
ACL_ID_AUTHENTICATED,
- /* Group's rights, overrides authenticated users' rights */
+ /* Group's rights */
ACL_ID_GROUP,
- /* User's rights, overrides group's rights */
+ /* Owner's rights, used when user is the storage's owner.
+ identifier name is ignored. */
+ ACL_ID_OWNER,
+ /* User's rights */
ACL_ID_USER,
/* Same as group's rights, but also overrides user's rights */
ACL_ID_GROUP_OVERRIDE,
@@ -63,8 +66,11 @@
const char *const *rights;
/* Negative rights assigned */
const char *const *neg_rights;
+};
+
+struct acl_rights_update {
+ struct acl_rights rights;
- /* For set: */
enum acl_modify_mode modify_mode;
enum acl_modify_mode neg_modify_mode;
};
@@ -75,10 +81,12 @@
struct acl_backend *
acl_backend_init(const char *data, struct mailbox_list *list,
const char *acl_username, const char *const *groups,
- const char *owner_username);
+ bool owner);
void acl_backend_deinit(struct acl_backend **backend);
/* Returns TRUE if user isn't anonymous. */
bool acl_backend_user_is_authenticated(struct acl_backend *backend);
+/* Returns TRUE if user owns the storage. */
+bool acl_backend_user_is_owner(struct acl_backend *backend);
/* Returns TRUE if given name matches the ACL user name. */
bool acl_backend_user_name_equals(struct acl_backend *backend,
const char *username);
@@ -89,6 +97,14 @@
unsigned int acl_backend_lookup_right(struct acl_backend *backend,
const char *right);
+/* List mailboxes that have lookup right to some non-owners. */
+struct acl_mailbox_list_context *
+acl_backend_nonowner_lookups_iter_init(struct acl_backend *backend);
+int acl_backend_nonowner_lookups_iter_next(struct acl_mailbox_list_context *ctx,
+ const char **name_r);
+void
+acl_backend_nonowner_lookups_iter_deinit(struct acl_mailbox_list_context **ctx);
+
struct acl_object *acl_object_init_from_name(struct acl_backend *backend,
struct mail_storage *storage,
const char *name);
@@ -103,7 +119,7 @@
/* Update ACL of given object. */
int acl_object_update(struct acl_object *aclobj,
- const struct acl_rights *rights);
+ const struct acl_rights_update *rights);
/* List all identifiers. */
struct acl_object_list_iter *acl_object_list_init(struct acl_object *aclobj);
--- NEW FILE: acl-backend-vfile-acllist.c ---
/* Copyright (C) 2007 Timo Sirainen */
#include "lib.h"
#include "array.h"
#include "str.h"
#include "safe-mkstemp.h"
#include "istream.h"
#include "ostream.h"
#include "mail-namespace.h"
#include "mail-storage.h"
#include "acl-plugin.h"
#include "acl-cache.h"
#include "acl-backend-vfile.h"
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
struct acl_mailbox_list_context_vfile {
struct acl_mailbox_list_context ctx;
unsigned int acllist_change_counter;
unsigned int idx;
};
static void
acllist_clear(struct acl_backend_vfile *backend, uoff_t file_size)
{
backend->acllist_change_counter++;
if (backend->acllist_pool == NULL) {
backend->acllist_pool =
pool_alloconly_create("vfile acllist",
I_MAX(file_size / 2, 128));
i_array_init(&backend->acllist, I_MAX(16, file_size / 60));
} else {
p_clear(backend->acllist_pool);
array_clear(&backend->acllist);
}
}
static int acl_backend_vfile_acllist_read(struct acl_backend_vfile *backend)
{
struct acl_backend_vfile_acllist acllist;
struct istream *input;
struct stat st;
const char *rootdir, *path, *line, *p;
int fd, ret = 0;
backend->acllist_last_check = ioloop_time;
rootdir = mailbox_list_get_path(backend->backend.list, NULL,
MAILBOX_LIST_PATH_TYPE_DIR);
path = t_strdup_printf("%s/"ACLLIST_FILENAME, rootdir);
if (backend->acllist_mtime != 0) {
/* see if the file's mtime has changed */
if (stat(path, &st) < 0) {
if (errno == ENOENT)
backend->acllist_mtime = 0;
else
i_error("stat(%s) failed: %m", path);
return -1;
}
if (st.st_mtime == backend->acllist_mtime)
return 0;
}
fd = open(path, O_RDONLY);
if (fd == -1) {
if (errno == ENOENT) {
backend->acllist_mtime = 0;
return -1;
}
i_error("open(%s) failed: %m", path);
return -1;
}
if (fstat(fd, &st) < 0) {
i_error("fstat(%s) failed: %m", path);
(void)close(fd);
return -1;
}
backend->acllist_mtime = st.st_mtime;
acllist_clear(backend, st.st_size);
input = i_stream_create_file(fd, default_pool, (size_t)-1, FALSE);
while ((line = i_stream_read_next_line(input)) != NULL) {
acllist.mtime = 0;
for (p = line; *p >= '0' && *p <= '9'; p++)
acllist.mtime = acllist.mtime * 10 + (*p - '0');
if (p == line || *p != ' ' || p[1] == '\0') {
i_error("Broken acllist file: %s", path);
if (unlink(path) < 0 && errno != ENOENT)
i_error("unlink(%s) failed: %m", path);
return -1;
}
acllist.name = p_strdup(backend->acllist_pool, p + 1);
array_append(&backend->acllist, &acllist, 1);
}
if (input->stream_errno != 0)
ret = -1;
i_stream_destroy(&input);
if (close(fd) < 0)
i_error("close(%s) failed: %m", path);
return ret;
}
void acl_backend_vfile_acllist_refresh(struct acl_backend_vfile *backend)
{
if (backend->acllist_last_check + backend->cache_secs > ioloop_time)
return;
if (acl_backend_vfile_acllist_read(backend) < 0) {
acllist_clear(backend, 0);
if (!backend->rebuilding_acllist)
(void)acl_backend_vfile_acllist_rebuild(backend);
}
}
static bool rights_has_lookup_changes(const struct acl_rights *rights)
{
const char *const *p;
if (rights->id_type == ACL_ID_OWNER) {
/* ignore owner rights */
return FALSE;
}
if (rights->rights == NULL)
return FALSE;
for (p = rights->rights; *p != NULL; p++) {
if (strcmp(*p, MAIL_ACL_LOOKUP) == 0)
return TRUE;
}
return FALSE;
}
static int
acllist_append(struct acl_backend_vfile *backend, struct ostream *output,
struct mail_storage *storage, const char *name)
{
struct acl_object *aclobj;
struct acl_object_list_iter *iter;
struct acl_rights rights;
struct acl_backend_vfile_acllist acllist;
const char *line;
int ret;
acl_cache_flush(backend->backend.cache, name);
aclobj = acl_object_init_from_name(&backend->backend, storage, name);
iter = acl_object_list_init(aclobj);
while ((ret = acl_object_list_next(iter, &rights)) > 0) {
if (rights_has_lookup_changes(&rights))
break;
}
acl_object_list_deinit(&iter);
if (acl_backend_vfile_object_get_mtime(aclobj, &acllist.mtime) < 0)
ret = -1;
if (ret > 0) {
acllist.name = p_strdup(backend->acllist_pool, name);
array_append(&backend->acllist, &acllist, 1);
t_push();
line = t_strdup_printf("%s %s\n", dec2str(acllist.mtime), name);
o_stream_send_str(output, line);
t_pop();
}
acl_object_deinit(&aclobj);
return ret < 0 ? -1 : 0;
}
int acl_backend_vfile_acllist_rebuild(struct acl_backend_vfile *backend)
{
struct mailbox_list *list = backend->backend.list;
struct mail_namespace *ns;
struct mailbox_list_iterate_context *iter;
struct mailbox_info *info;
const char *rootdir, *acllist_path;
struct ostream *output;
struct stat st;
string_t *path;
mode_t mode;
uid_t uid;
gid_t gid;
int fd, ret;
ret = mailbox_list_get_permissions(list, NULL, &mode, &uid, &gid);
if (ret <= 0) {
/* Return success if the whole root directory was lost */
return ret;
}
path = t_str_new(256);
rootdir = mailbox_list_get_path(list, NULL,
MAILBOX_LIST_PATH_TYPE_DIR);
str_printfa(path, "%s/%s", rootdir, mailbox_list_get_temp_prefix(list));
/* Build it into a temporary file and rename() over. There's no need
to use locking, because even if multiple processes are rebuilding
the file at the same time the result should be the same. */
fd = safe_mkstemp(path, mode, uid, gid);
if (fd == -1)
return -1;
output = o_stream_create_file(fd, default_pool, 0, FALSE);
ret = 0;
acllist_clear(backend, 0);
ns = mailbox_list_get_namespace(list);
backend->rebuilding_acllist = TRUE;
iter = mailbox_list_iter_init(list, "*", MAILBOX_LIST_ITER_FAST_FLAGS |
MAILBOX_LIST_ITER_RAW_LIST);
while ((info = mailbox_list_iter_next(iter)) != NULL) {
if (acllist_append(backend, output, ns->storage,
info->name) < 0) {
ret = -1;
break;
}
}
if (mailbox_list_iter_deinit(&iter) < 0)
ret = -1;
o_stream_destroy(&output);
backend->rebuilding_acllist = FALSE;
if (ret == 0) {
if (fstat(fd, &st) < 0) {
i_error("fstat(%s) failed: %m", str_c(path));
ret = -1;
}
}
if (close(fd) < 0) {
i_error("close(%s) failed: %m", str_c(path));
ret = -1;
}
if (ret == 0) {
acllist_path = t_strdup_printf("%s/"ACLLIST_FILENAME, rootdir);
if (rename(str_c(path), acllist_path) < 0) {
i_error("rename(%s, %s) failed: %m",
str_c(path), acllist_path);
ret = -1;
}
}
if (ret == 0) {
backend->acllist_mtime = st.st_mtime;
backend->acllist_last_check = ioloop_time;
} else {
acllist_clear(backend, 0);
if (unlink(str_c(path)) < 0 && errno != ENOENT)
i_error("unlink(%s) failed: %m", str_c(path));
}
return ret;
}
static const struct acl_backend_vfile_acllist *
acl_backend_vfile_acllist_find(struct acl_backend_vfile *backend,
const char *name)
{
const struct acl_backend_vfile_acllist *acllist;
unsigned int i, count;
acllist = array_get(&backend->acllist, &count);
for (i = 0; i < count; i++) {
if (strcmp(acllist[i].name, name) == 0)
return &acllist[i];
}
return NULL;
}
void acl_backend_vfile_acllist_verify(struct acl_backend_vfile *backend,
const char *name, time_t mtime)
{
const struct acl_backend_vfile_acllist *acllist;
acl_backend_vfile_acllist_refresh(backend);
acllist = acl_backend_vfile_acllist_find(backend, name);
if (acllist != NULL && acllist->mtime != mtime &&
!backend->rebuilding_acllist)
(void)acl_backend_vfile_acllist_rebuild(backend);
}
struct acl_mailbox_list_context *
acl_backend_vfile_nonowner_iter_init(struct acl_backend *_backend)
{
struct acl_backend_vfile *backend =
(struct acl_backend_vfile *)_backend;
struct acl_mailbox_list_context_vfile *ctx;
acl_backend_vfile_acllist_refresh(backend);
ctx = i_new(struct acl_mailbox_list_context_vfile, 1);
ctx->ctx.backend = _backend;
ctx->acllist_change_counter = backend->acllist_change_counter;
return &ctx->ctx;
}
int acl_backend_vfile_nonowner_iter_next(struct acl_mailbox_list_context *_ctx,
const char **name_r)
{
struct acl_mailbox_list_context_vfile *ctx =
(struct acl_mailbox_list_context_vfile *)_ctx;
struct acl_backend_vfile *backend =
(struct acl_backend_vfile *)_ctx->backend;
const struct acl_backend_vfile_acllist *acllist;
unsigned int count;
if (ctx->acllist_change_counter != backend->acllist_change_counter)
return -1;
acllist = array_get(&backend->acllist, &count);
if (ctx->idx == count)
return 0;
*name_r = acllist[ctx->idx++].name;
return 1;
}
void
acl_backend_vfile_nonowner_iter_deinit(struct acl_mailbox_list_context *ctx)
{
i_free(ctx);
}
Index: acl-backend-vfile.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/acl/acl-backend-vfile.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- acl-backend-vfile.c 11 Apr 2007 19:31:29 -0000 1.18
+++ acl-backend-vfile.c 11 Apr 2007 19:33:37 -0000 1.19
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006 Timo Sirainen */
+/* Copyright (C) 2006-2007 Timo Sirainen */
#include "lib.h"
#include "ioloop.h"
@@ -7,15 +7,13 @@
#include "nfs-workarounds.h"
#include "mail-storage-private.h"
#include "acl-cache.h"
-#include "acl-api-private.h"
+#include "acl-backend-vfile.h"
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
-#define ACL_FILENAME "dovecot-acl"
-
#define ACL_ESTALE_RETRY_COUNT NFS_ESTALE_RETRY_COUNT
#define ACL_VFILE_DEFAULT_CACHE_SECS (60*5)
@@ -31,18 +29,6 @@
struct acl_vfile_validity global_validity, local_validity;
};
-struct acl_backend_vfile {
- struct acl_backend backend;
- const char *global_dir;
- unsigned int cache_secs;
-};
-
-struct acl_object_vfile {
- struct acl_object aclobj;
-
- char *global_path, *local_path;
-};
-
struct acl_letter_map {
char letter;
const char *name;
@@ -148,6 +134,11 @@
{
struct acl_object_vfile *aclobj = (struct acl_object_vfile *)_aclobj;
+ if (array_is_created(&aclobj->rights))
+ array_free(&aclobj->rights);
+ if (aclobj->rights_pool != NULL)
+ pool_unref(aclobj->rights_pool);
+
i_free(aclobj->local_path);
i_free(aclobj->global_path);
i_free(aclobj->aclobj.name);
@@ -155,11 +146,11 @@
}
static const char *const *
-acl_parse_rights(const char *acl, const char **error_r)
+acl_parse_rights(pool_t pool, const char *acl, const char **error_r)
{
ARRAY_DEFINE(rights, const char *);
- const char *const *names;
- unsigned int i;
+ const char *const *names, **ret_rights;
+ unsigned int i, count;
/* parse IMAP ACL list */
while (*acl == ' ' || *acl == '\t')
@@ -180,29 +171,32 @@
array_append(&rights, &acl_letter_map[i].name, 1);
}
- if (*acl == '\0') {
- (void)array_append_space(&rights);
- return array_idx(&rights, 0);
- }
+ if (*acl != '\0') {
+ /* parse our own extended ACLs */
+ i_assert(*acl == ':');
- /* parse our own extended ACLs */
- i_assert(*acl == ':');
+ names = t_strsplit_spaces(acl, ", ");
+ for (; *names != NULL; names++) {
+ const char *name = p_strdup(pool, *names);
+ array_append(&rights, &name, 1);
+ }
+ }
- names = t_strsplit_spaces(acl, ", ");
- if (array_count(&rights) == 0)
- return names;
-
- for (; *names != NULL; names++)
- array_append(&rights, names, 1);
- (void)array_append_space(&rights);
- return array_idx(&rights, 0);
+ /* @UNSAFE */
+ count = array_count(&rights);
+ ret_rights = p_new(pool, const char *, count + 1);
+ if (count > 0) {
+ memcpy(ret_rights, array_idx(&rights, 0),
+ sizeof(const char *) * count);
+ }
+ return ret_rights;
}
static int
-acl_object_vfile_parse_line(struct acl_object *aclobj, const char *path,
+acl_object_vfile_parse_line(struct acl_object_vfile *aclobj, const char *path,
const char *line, unsigned int linenum)
{
- struct acl_rights rights;
+ struct acl_rights_update rights;
const char *p, *const *right_names, *error = NULL;
if (*line == '\0' || *line == '#')
@@ -220,35 +214,50 @@
memset(&rights, 0, sizeof(rights));
- right_names = acl_parse_rights(p, &error);
+ right_names = acl_parse_rights(aclobj->rights_pool, p, &error);
if (*line != '-') {
rights.modify_mode = ACL_MODIFY_MODE_REPLACE;
- rights.rights = right_names;
+ rights.rights.rights = right_names;
} else {
line++;
rights.neg_modify_mode = ACL_MODIFY_MODE_REPLACE;
- rights.neg_rights = right_names;
+ rights.rights.neg_rights = right_names;
}
- if (strncmp(line, "user=", 5) == 0) {
- rights.id_type = ACL_ID_USER;
- rights.identifier = line + 5;
- } else if (strncmp(line, "group=", 6) == 0) {
- rights.id_type = ACL_ID_GROUP;
- rights.identifier = line + 6;
- } else if (strncmp(line, "group-override=", 15) == 0) {
- rights.id_type = ACL_ID_GROUP_OVERRIDE;
- rights.identifier = line + 15;
- } else if (strcmp(line, "owner") == 0) {
- rights.id_type = ACL_ID_USER;
- rights.identifier = aclobj->backend->owner_username;
- } else if (strcmp(line, "authenticated") == 0) {
- rights.id_type = ACL_ID_AUTHENTICATED;
- } else if (strcmp(line, "anyone") == 0 ||
- strcmp(line, "anonymous") == 0) {
- rights.id_type = ACL_ID_ANYONE;
- } else {
+ switch (*line) {
+ case 'u':
+ if (strncmp(line, "user=", 5) == 0) {
+ rights.rights.id_type = ACL_ID_USER;
+ rights.rights.identifier = line + 5;
+ break;
+ }
+ case 'o':
+ if (strcmp(line, "owner") == 0) {
+ rights.rights.id_type = ACL_ID_OWNER;
+ break;
+ }
+ case 'g':
+ if (strncmp(line, "group=", 6) == 0) {
+ rights.rights.id_type = ACL_ID_GROUP;
+ rights.rights.identifier = line + 6;
+ break;
+ } else if (strncmp(line, "group-override=", 15) == 0) {
+ rights.rights.id_type = ACL_ID_GROUP_OVERRIDE;
+ rights.rights.identifier = line + 15;
+ break;
+ }
+ case 'a':
+ if (strcmp(line, "authenticated") == 0) {
+ rights.rights.id_type = ACL_ID_AUTHENTICATED;
+ break;
+ } else if (strcmp(line, "anyone") == 0 ||
+ strcmp(line, "anonymous") == 0) {
+ rights.rights.id_type = ACL_ID_ANYONE;
+ break;
+ }
+ default:
error = t_strdup_printf("Unknown ID '%s'", line);
+ break;
}
if (error != NULL) {
@@ -257,14 +266,19 @@
return -1;
}
- acl_cache_update(aclobj->backend->cache, aclobj->name, &rights);
+ rights.rights.identifier =
+ p_strdup(aclobj->rights_pool, rights.rights.identifier);
+ array_append(&aclobj->rights, &rights.rights, 1);
+
+ acl_cache_update(aclobj->aclobj.backend->cache,
+ aclobj->aclobj.name, &rights);
t_pop();
return 0;
}
static int
-acl_backend_vfile_read(struct acl_object *aclobj, const char *path,
+acl_backend_vfile_read(struct acl_object_vfile *aclobj, const char *path,
struct acl_vfile_validity *validity, bool try_retry,
bool *is_dir_r)
{
@@ -279,7 +293,7 @@
fd = nfs_safe_open(path, O_RDONLY);
if (fd == -1) {
if (errno == ENOENT) {
- if (aclobj->backend->debug)
+ if (aclobj->aclobj.backend->debug)
i_info("acl vfile: file %s not found", path);
validity->last_size = 0;
@@ -308,11 +322,21 @@
return 0;
}
- if (aclobj->backend->debug)
+ if (aclobj->aclobj.backend->debug)
i_info("acl vfile: reading file %s", path);
input = i_stream_create_file(fd, default_pool, 4096, FALSE);
+ if (!array_is_created(&aclobj->rights)) {
+ aclobj->rights_pool =
+ pool_alloconly_create("acl rights",
+ I_MAX(256, st.st_size / 2));
+ i_array_init(&aclobj->rights, I_MAX(16, st.st_size / 40));
+ } else {
+ array_clear(&aclobj->rights);
+ p_clear(aclobj->rights_pool);
+ }
+
linenum = 1;
while ((line = i_stream_read_next_line(input)) != NULL) {
if (acl_object_vfile_parse_line(aclobj, path, line,
@@ -358,7 +382,8 @@
}
static int
-acl_backend_vfile_read_with_retry(struct acl_object *aclobj, const char *path,
+acl_backend_vfile_read_with_retry(struct acl_object_vfile *aclobj,
+ const char *path,
struct acl_vfile_validity *validity)
{
unsigned int i;
@@ -427,11 +452,32 @@
return 1;
}
+int acl_backend_vfile_object_get_mtime(struct acl_object *aclobj,
+ time_t *mtime_r)
+{
+ struct acl_backend_vfile_validity *validity;
+
+ validity = acl_cache_get_validity(aclobj->backend->cache, aclobj->name);
+ if (validity == NULL)
+ return -1;
+
+ if (validity->local_validity.last_mtime != 0)
+ *mtime_r = validity->local_validity.last_mtime;
+ else if (validity->global_validity.last_mtime != 0)
+ *mtime_r = validity->global_validity.last_mtime;
+ else
+ *mtime_r = 0;
+ return 0;
+}
+
static int acl_backend_vfile_object_refresh_cache(struct acl_object *_aclobj)
{
struct acl_object_vfile *aclobj = (struct acl_object_vfile *)_aclobj;
+ struct acl_backend_vfile *backend =
+ (struct acl_backend_vfile *)_aclobj->backend;
struct acl_backend_vfile_validity *old_validity;
struct acl_backend_vfile_validity validity;
+ time_t mtime;
int ret;
old_validity = acl_cache_get_validity(_aclobj->backend->cache,
@@ -451,21 +497,25 @@
acl_cache_flush(_aclobj->backend->cache, _aclobj->name);
memset(&validity, 0, sizeof(validity));
- if (acl_backend_vfile_read_with_retry(_aclobj, aclobj->global_path,
+ if (acl_backend_vfile_read_with_retry(aclobj, aclobj->global_path,
&validity.global_validity) < 0)
return -1;
- if (acl_backend_vfile_read_with_retry(_aclobj, aclobj->local_path,
+ if (acl_backend_vfile_read_with_retry(aclobj, aclobj->local_path,
&validity.local_validity) < 0)
return -1;
acl_cache_set_validity(_aclobj->backend->cache,
_aclobj->name, &validity);
+
+ if (acl_backend_vfile_object_get_mtime(_aclobj, &mtime) == 0)
+ acl_backend_vfile_acllist_verify(backend, _aclobj->name, mtime);
return 0;
}
static int
acl_backend_vfile_object_update(struct acl_object *aclobj __attr_unused__,
- const struct acl_rights *rights __attr_unused__)
+ const struct acl_rights_update *rights
+ __attr_unused__)
{
/* FIXME */
return -1;
@@ -478,15 +528,27 @@
iter = i_new(struct acl_object_list_iter, 1);
iter->aclobj = aclobj;
+
+ if (aclobj->backend->v.object_refresh_cache(aclobj) < 0)
+ iter->failed = TRUE;
return iter;
}
static int
-acl_backend_vfile_object_list_next(struct acl_object_list_iter *iter
- __attr_unused__,
- struct acl_rights *rights_r __attr_unused__)
+acl_backend_vfile_object_list_next(struct acl_object_list_iter *iter,
+ struct acl_rights *rights_r)
{
- return -1;
+ struct acl_object_vfile *aclobj =
+ (struct acl_object_vfile *)iter->aclobj;
+ const struct acl_rights *rights;
+
+ if (!array_is_created(&aclobj->rights) ||
+ iter->idx == array_count(&aclobj->rights))
+ return 0;
+
+ rights = array_idx(&aclobj->rights, iter->idx++);
+ *rights_r = *rights;
+ return 1;
}
static void
@@ -499,6 +561,9 @@
acl_backend_vfile_alloc,
acl_backend_vfile_init,
acl_backend_vfile_deinit,
+ acl_backend_vfile_nonowner_iter_init,
+ acl_backend_vfile_nonowner_iter_next,
+ acl_backend_vfile_nonowner_iter_deinit,
acl_backend_vfile_object_init,
acl_backend_vfile_object_deinit,
acl_backend_vfile_object_refresh_cache,
--- NEW FILE: acl-backend-vfile.h ---
#ifndef __ACL_BACKEND_VFILE_H
#define __ACL_BACKEND_VFILE_H
#include "acl-api-private.h"
#define ACL_FILENAME "dovecot-acl"
#define ACLLIST_FILENAME "dovecot-acl-list"
struct acl_object_vfile {
struct acl_object aclobj;
pool_t rights_pool;
ARRAY_DEFINE(rights, struct acl_rights);
char *global_path, *local_path;
};
struct acl_backend_vfile_acllist {
time_t mtime;
const char *name;
};
struct acl_backend_vfile {
struct acl_backend backend;
const char *global_dir;
pool_t acllist_pool;
ARRAY_DEFINE(acllist, struct acl_backend_vfile_acllist);
time_t acllist_last_check;
time_t acllist_mtime;
unsigned int acllist_change_counter;
unsigned int cache_secs;
unsigned int rebuilding_acllist:1;
};
void acl_backend_vfile_acllist_refresh(struct acl_backend_vfile *backend);
int acl_backend_vfile_acllist_rebuild(struct acl_backend_vfile *backend);
void acl_backend_vfile_acllist_verify(struct acl_backend_vfile *backend,
const char *name, time_t mtime);
struct acl_mailbox_list_context *
acl_backend_vfile_nonowner_iter_init(struct acl_backend *backend);
int acl_backend_vfile_nonowner_iter_next(struct acl_mailbox_list_context *ctx,
const char **name_r);
void
acl_backend_vfile_nonowner_iter_deinit(struct acl_mailbox_list_context *ctx);
int acl_backend_vfile_object_get_mtime(struct acl_object *aclobj,
time_t *mtime_r);
#endif
Index: acl-backend.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/acl/acl-backend.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- acl-backend.c 11 Apr 2007 11:02:31 -0000 1.6
+++ acl-backend.c 11 Apr 2007 19:33:37 -0000 1.7
@@ -28,18 +28,17 @@
struct acl_backend *
acl_backend_init(const char *data, struct mailbox_list *list,
const char *acl_username, const char *const *groups,
- const char *owner_username)
+ bool owner)
{
struct acl_backend *backend;
unsigned int i, group_count;
- bool storage_owner, debug;
+ bool debug;
debug = getenv("DEBUG") != NULL;
if (debug) {
i_info("acl: initializing backend with data: %s", data);
i_info("acl: acl username = %s", acl_username);
- i_info("acl: owner username = %s",
- owner_username != NULL ? owner_username : "");
+ i_info("acl: owner = %d", owner);
}
group_count = strarray_length(groups);
@@ -56,8 +55,7 @@
backend->v = acl_backend_vfile;
backend->list = list;
backend->username = p_strdup(backend->pool, acl_username);
- backend->owner_username = owner_username == NULL ? "" :
- p_strdup(backend->pool, owner_username);
+ backend->owner = owner;
if (group_count > 0) {
backend->group_count = group_count;
@@ -72,11 +70,9 @@
if (acl_backend_vfile.init(backend, data) < 0)
i_fatal("acl: backend vfile init failed with data: %s", data);
- storage_owner = owner_username != NULL &&
- strcmp(acl_username, owner_username) == 0;
backend->default_aclmask =
acl_cache_mask_init(backend->cache, backend->pool,
- storage_owner ? owner_mailbox_rights :
+ owner ? owner_mailbox_rights :
non_owner_mailbox_rights);
backend->default_aclobj = acl_object_init_from_name(backend, NULL, "");
@@ -99,6 +95,11 @@
return backend->username != NULL;
}
+bool acl_backend_user_is_owner(struct acl_backend *backend)
+{
+ return backend->owner;
+}
+
bool acl_backend_user_name_equals(struct acl_backend *backend,
const char *username)
{
@@ -122,3 +123,15 @@
{
return acl_cache_right_lookup(backend->cache, right);
}
+
+int acl_backend_get_default_rights(struct acl_backend *backend,
+ const struct acl_mask **mask_r)
+{
+ if (backend->v.object_refresh_cache(backend->default_aclobj) < 0)
+ return -1;
+
+ *mask_r = acl_cache_get_my_rights(backend->cache, "");
+ if (*mask_r == NULL)
+ *mask_r = backend->default_aclmask;
+ return 0;
+}
Index: acl-cache.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/acl/acl-cache.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- acl-cache.c 10 Sep 2006 12:48:33 -0000 1.7
+++ acl-cache.c 11 Apr 2007 19:33:37 -0000 1.8
@@ -251,15 +251,15 @@
static void
acl_cache_update_rights(struct acl_cache *cache,
struct acl_object_cache *obj_cache,
- const struct acl_rights *rights)
+ const struct acl_rights_update *rights)
{
- enum acl_id_type id_type = rights->id_type;
+ enum acl_id_type id_type = rights->rights.id_type;
acl_cache_update_rights_mask(cache, obj_cache, rights->modify_mode,
- rights->rights,
+ rights->rights.rights,
&obj_cache->my_rights[id_type]);
acl_cache_update_rights_mask(cache, obj_cache, rights->neg_modify_mode,
- rights->neg_rights,
+ rights->rights.neg_rights,
&obj_cache->my_neg_rights[id_type]);
}
@@ -283,7 +283,7 @@
}
void acl_cache_update(struct acl_cache *cache, const char *objname,
- const struct acl_rights *rights)
+ const struct acl_rights_update *rights)
{
struct acl_object_cache *obj_cache;
bool created;
@@ -291,7 +291,7 @@
obj_cache = acl_cache_object_get(cache, objname, &created);
i_assert(obj_cache->my_current_rights != &negative_cache_entry);
- switch (rights->id_type) {
+ switch (rights->rights.id_type) {
case ACL_ID_ANYONE:
acl_cache_update_rights(cache, obj_cache, rights);
break;
@@ -302,12 +302,16 @@
case ACL_ID_GROUP:
case ACL_ID_GROUP_OVERRIDE:
if (acl_backend_user_is_in_group(cache->backend,
- rights->identifier))
+ rights->rights.identifier))
acl_cache_update_rights(cache, obj_cache, rights);
break;
case ACL_ID_USER:
if (acl_backend_user_name_equals(cache->backend,
- rights->identifier))
+ rights->rights.identifier))
+ acl_cache_update_rights(cache, obj_cache, rights);
+ break;
+ case ACL_ID_OWNER:
+ if (acl_backend_user_is_owner(cache->backend))
acl_cache_update_rights(cache, obj_cache, rights);
break;
case ACL_ID_TYPE_COUNT:
@@ -402,3 +406,12 @@
acl_cache_my_current_rights_recalculate(obj_cache);
return obj_cache->my_current_rights;
}
+
+bool acl_cache_mask_isset(const struct acl_mask *mask, unsigned int right_idx)
+{
+ unsigned int mask_idx;
+
+ mask_idx = right_idx / CHAR_BIT;
+ return mask_idx < mask->size &&
+ (mask->mask[mask_idx] & (1 << (right_idx % CHAR_BIT))) != 0;
+}
Index: acl-cache.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/acl/acl-cache.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- acl-cache.h 30 May 2006 12:20:30 -0000 1.3
+++ acl-cache.h 11 Apr 2007 19:33:37 -0000 1.4
@@ -2,7 +2,7 @@
#define __ACL_CACHE_H
struct acl_backend;
-struct acl_rights;
+struct acl_rights_update;
struct acl_mask {
pool_t pool;
@@ -34,7 +34,7 @@
/* Update object ACLs. */
void acl_cache_update(struct acl_cache *cache, const char *objname,
- const struct acl_rights *rights);
+ const struct acl_rights_update *rights);
/* Return ACL object validity, or NULL if object doesn't exit. */
void *acl_cache_get_validity(struct acl_cache *cache, const char *objname);
/* Update ACL object validity, creating the object if needed. */
@@ -51,4 +51,7 @@
const struct acl_mask *
acl_cache_get_my_rights(struct acl_cache *cache, const char *objname);
+/* Returns TRUE if given right index is set in mask. */
+bool acl_cache_mask_isset(const struct acl_mask *mask, unsigned int right_idx);
+
#endif
Index: acl-mailbox-list.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/acl/acl-mailbox-list.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- acl-mailbox-list.c 11 Apr 2007 11:02:31 -0000 1.5
+++ acl-mailbox-list.c 11 Apr 2007 19:33:37 -0000 1.6
@@ -2,8 +2,11 @@
#include "lib.h"
#include "array.h"
+#include "imap-match.h"
+#include "mailbox-tree.h"
#include "mail-namespace.h"
#include "mailbox-list-private.h"
+#include "acl-cache.h"
#include "acl-api-private.h"
#include "acl-plugin.h"
@@ -12,12 +15,23 @@
#define ACL_LIST_CONTEXT(obj) \
MODULE_CONTEXT(obj, acl_mailbox_list_module)
+#define MAILBOX_FLAG_MATCHED 0x40000000
+
struct acl_mailbox_list {
union mailbox_list_module_context module_ctx;
struct acl_storage_rights_context rights;
};
+struct acl_mailbox_list_iterate_context {
+ struct mailbox_list_iterate_context ctx;
+ struct mailbox_list_iterate_context *super_ctx;
+
+ struct mailbox_tree_context *tree;
+ struct mailbox_tree_iterate_context *tree_iter;
+ struct mailbox_info info;
+};
+
static MODULE_CONTEXT_DEFINE_INIT(acl_mailbox_list_module,
&mailbox_list_module_register);
@@ -48,17 +62,127 @@
can_see_r);
}
+static bool
+acl_mailbox_try_list_fast(struct acl_mailbox_list_iterate_context *ctx,
+ const char *mask)
+{
+ struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(ctx->ctx.list);
+ struct acl_backend *backend = alist->rights.backend;
+ const unsigned int *idxp =
+ alist->rights.acl_storage_right_idx + ACL_STORAGE_RIGHT_LOOKUP;
+ const struct acl_mask *acl_mask;
+ struct acl_mailbox_list_context *nonowner_list_ctx;
+ struct imap_match_glob *glob;
+ struct mailbox_node *node;
+ const char *name;
+ char sep;
+ int try, ret;
+ bool created;
+
+ if ((ctx->ctx.flags & MAILBOX_LIST_ITER_RAW_LIST) != 0)
+ return FALSE;
+
+ if (acl_backend_get_default_rights(backend, &acl_mask) < 0 ||
+ acl_cache_mask_isset(acl_mask, *idxp))
+ return FALSE;
+
+ /* default is to not list mailboxes. we can optimize this. */
+ t_push();
+ sep = mailbox_list_get_hierarchy_sep(ctx->ctx.list);
+ glob = imap_match_init(pool_datastack_create(), mask, TRUE, sep);
+
+ for (try = 0; try < 2; try++) {
+ nonowner_list_ctx =
+ acl_backend_nonowner_lookups_iter_init(backend);
+ ctx->tree = mailbox_tree_init(sep);
+
+ while ((ret = acl_backend_nonowner_lookups_iter_next(
+ nonowner_list_ctx, &name)) > 0) {
+ switch (imap_match(glob, name)) {
+ case IMAP_MATCH_YES:
+ node = mailbox_tree_get(ctx->tree, name,
+ &created);
+ if (created)
+ node->flags |= MAILBOX_NOCHILDREN;
+ node->flags |= MAILBOX_FLAG_MATCHED;
+ node->flags &= ~MAILBOX_NONEXISTENT;
+ break;
+ case IMAP_MATCH_PARENT:
+ node = mailbox_tree_get(ctx->tree, name,
+ &created);
+ if (created)
+ node->flags |= MAILBOX_NONEXISTENT;
+ node->flags |= MAILBOX_FLAG_MATCHED |
+ MAILBOX_CHILDREN;
+ node->flags &= ~MAILBOX_NOCHILDREN;
+ break;
+ default:
+ break;
+ }
+ }
+ if (ret == 0)
+ break;
+
+ /* try again */
+ mailbox_tree_deinit(&ctx->tree);
+ acl_backend_nonowner_lookups_iter_deinit(&nonowner_list_ctx);
+ }
+ t_pop();
+ if (ret < 0)
+ return FALSE;
+
+ ctx->tree_iter = mailbox_tree_iterate_init(ctx->tree, NULL,
+ MAILBOX_FLAG_MATCHED);
+ return TRUE;
+}
+
+static struct mailbox_list_iterate_context *
+acl_mailbox_list_iter_init(struct mailbox_list *list, const char *mask,
+ enum mailbox_list_iter_flags flags)
+{
+ struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
+ struct acl_mailbox_list_iterate_context *ctx;
+
+ ctx = i_new(struct acl_mailbox_list_iterate_context, 1);
+ ctx->ctx.list = list;
+ ctx->ctx.flags = flags;
+
+ if (!acl_mailbox_try_list_fast(ctx, mask)) {
+ ctx->super_ctx =
+ alist->module_ctx.super.iter_init(list, mask, flags);
+ }
+ return &ctx->ctx;
+}
+
static struct mailbox_info *
-acl_mailbox_list_iter_next(struct mailbox_list_iterate_context *ctx)
+acl_mailbox_list_iter_next(struct mailbox_list_iterate_context *_ctx)
{
- struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(ctx->list);
+ struct acl_mailbox_list_iterate_context *ctx =
+ (struct acl_mailbox_list_iterate_context *)_ctx;
+ struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(_ctx->list);
struct mailbox_info *info;
+ struct mailbox_node *node;
int ret;
for (;;) {
- info = alist->module_ctx.super.iter_next(ctx);
- if (info == NULL)
- return NULL;
+ if (ctx->tree_iter != NULL) {
+ node = mailbox_tree_iterate_next(ctx->tree_iter,
+ &ctx->info.name);
+ if (node == NULL)
+ return NULL;
+ info = &ctx->info;
+ info->flags = node->flags;
+ } else {
+ info = alist->module_ctx.super.
+ iter_next(ctx->super_ctx);
+ if (info == NULL)
+ return NULL;
+ }
+
+ if ((ctx->ctx.flags & MAILBOX_LIST_ITER_RAW_LIST) != 0) {
+ /* skip ACL checks. */
+ return info;
+ }
ret = acl_mailbox_list_have_right(alist, info->name,
ACL_STORAGE_RIGHT_LOOKUP,
@@ -66,14 +190,15 @@
if (ret > 0)
return info;
if (ret < 0) {
- ctx->failed = TRUE;
+ ctx->ctx.failed = TRUE;
return NULL;
}
/* no permission to see this mailbox */
- if ((ctx->flags & MAILBOX_LIST_ITER_SUBSCRIBED) != 0) {
+ if ((ctx->ctx.flags & MAILBOX_LIST_ITER_SUBSCRIBED) != 0) {
/* it's subscribed, show it as non-existent */
- if ((ctx->flags & MAILBOX_LIST_ITER_FAST_FLAGS) == 0)
+ if ((ctx->ctx.flags &
+ MAILBOX_LIST_ITER_FAST_FLAGS) == 0)
info->flags = MAILBOX_NONEXISTENT;
return info;
}
@@ -82,6 +207,25 @@
}
}
+static int
+acl_mailbox_list_iter_deinit(struct mailbox_list_iterate_context *_ctx)
+{
+ struct acl_mailbox_list_iterate_context *ctx =
+ (struct acl_mailbox_list_iterate_context *)_ctx;
+ struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(_ctx->list);
+ int ret = ctx->ctx.failed ? -1 : 0;
+
+ if (ctx->super_ctx != NULL) {
+ if (alist->module_ctx.super.iter_deinit(ctx->super_ctx) < 0)
+ ret = -1;
+ }
+ if (ctx->tree_iter != NULL)
+ mailbox_tree_iterate_deinit(&ctx->tree_iter);
+
+ i_free(ctx);
+ return ret;
+}
+
static int acl_get_mailbox_name_status(struct mailbox_list *list,
const char *name,
enum mailbox_name_status *status)
@@ -243,7 +387,9 @@
alist = p_new(list->pool, struct acl_mailbox_list, 1);
alist->module_ctx.super = list->v;
+ list->v.iter_init = acl_mailbox_list_iter_init;
list->v.iter_next = acl_mailbox_list_iter_next;
+ list->v.iter_deinit = acl_mailbox_list_iter_deinit;
list->v.get_mailbox_name_status = acl_get_mailbox_name_status;
list->v.delete_mailbox = acl_mailbox_list_delete;
list->v.rename_mailbox = acl_mailbox_list_rename;
Index: acl-plugin.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/acl/acl-plugin.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- acl-plugin.c 15 Mar 2007 17:05:44 -0000 1.5
+++ acl-plugin.c 11 Apr 2007 19:33:37 -0000 1.6
@@ -1,7 +1,6 @@
/* Copyright (C) 2005 Timo Sirainen */
#include "lib.h"
-#include "mail-storage.h"
#include "mailbox-list-private.h"
#include "acl-api.h"
#include "acl-plugin.h"
Index: acl-storage.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/acl/acl-storage.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- acl-storage.c 11 Apr 2007 11:02:31 -0000 1.6
+++ acl-storage.c 11 Apr 2007 19:33:37 -0000 1.7
@@ -3,9 +3,9 @@
#include "lib.h"
#include "array.h"
#include "istream.h"
-#include "acl-api-private.h"
#include "mail-namespace.h"
#include "mailbox-list-private.h"
+#include "acl-api-private.h"
#include "acl-plugin.h"
struct acl_storage_module acl_storage_module =
More information about the dovecot-cvs
mailing list