From: Timo Sirainen Date: Sun, 27 Jul 2003 05:37:58 +0000 (+0300) Subject: Namespace configuration. X-Git-Tag: 1.1.alpha1~4450 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a698e9a8fe3a250c1e3a719413543ffae622c4f5;p=thirdparty%2Fdovecot%2Fcore.git Namespace configuration. --HG-- branch : HEAD --- diff --git a/configure.in b/configure.in index 031acd019d..861423aa18 100644 --- a/configure.in +++ b/configure.in @@ -1051,7 +1051,7 @@ dnl ** dnl ** capabilities dnl ** -capability="IMAP4rev1 SORT THREAD=REFERENCES MULTIAPPEND UNSELECT LITERAL+ IDLE CHILDREN LISTEXT LIST-SUBSCRIBED" +capability="IMAP4rev1 SORT THREAD=REFERENCES MULTIAPPEND UNSELECT LITERAL+ IDLE CHILDREN LISTEXT LIST-SUBSCRIBED NAMESPACE" AC_DEFINE_UNQUOTED(CAPABILITY_STRING, "$capability", IMAP capabilities) CFLAGS="$CFLAGS $EXTRA_CFLAGS" diff --git a/src/master/mail-process.c b/src/master/mail-process.c index a57f207e23..faf42b0465 100644 --- a/src/master/mail-process.c +++ b/src/master/mail-process.c @@ -103,13 +103,41 @@ static const char *expand_mail_env(const char *env, const char *user, return str_c(str); } +static void env_put_namespace(struct namespace_settings *ns, + const char *user, const char *home) +{ + const char *location; + unsigned int i; + + for (i = 1; ns != NULL; i++, ns = ns->next) { + t_push(); + + location = expand_mail_env(ns->location, user, home); + env_put(t_strdup_printf("NAMESPACE_%u=%s", i, location)); + + if (ns->separator != NULL) { + env_put(t_strdup_printf("NAMESPACE_%u_SEP=%s", + i, ns->separator)); + } + if (ns->type != NULL) { + env_put(t_strdup_printf("NAMESPACE_%u_TYPE=%s", + i, ns->type)); + } + if (ns->prefix != NULL) { + env_put(t_strdup_printf("NAMESPACE_%u_PREFIX=%s", + i, ns->prefix)); + } + t_pop(); + } +} + int create_mail_process(struct login_group *group, int socket, struct ip_addr *ip, struct auth_master_reply *reply, const char *data) { static const char *argv[] = { NULL, NULL, NULL }; struct settings *set = group->set; - const char *addr, *mail, *chroot_dir, *home_dir, *full_home_dir; + const char *addr, *mail, *user, *chroot_dir, *home_dir, *full_home_dir; char title[1024]; pid_t pid; int i, err, ret; @@ -237,11 +265,12 @@ int create_mail_process(struct login_group *group, int socket, auth process, but don't trust that too much either. Some auth mechanism might allow leaving extra data there. */ mail = data + reply->mail_idx; - if (*mail == '\0' && set->default_mail_env != NULL) { - mail = expand_mail_env(set->default_mail_env, - data + reply->virtual_user_idx, - home_dir); - } + user = data + reply->virtual_user_idx; + if (*mail == '\0' && set->default_mail_env != NULL) + mail = expand_mail_env(set->default_mail_env, user, home_dir); + + if (set->server->namespaces != NULL) + env_put_namespace(set->server->namespaces, user, home_dir); env_put(t_strconcat("MAIL=", mail, NULL)); env_put(t_strconcat("USER=", data + reply->virtual_user_idx, NULL)); diff --git a/src/master/master-settings.c b/src/master/master-settings.c index 59f634dfed..827e58b53a 100644 --- a/src/master/master-settings.c +++ b/src/master/master-settings.c @@ -15,7 +15,8 @@ enum settings_type { SETTINGS_TYPE_ROOT, SETTINGS_TYPE_SERVER, - SETTINGS_TYPE_AUTH + SETTINGS_TYPE_AUTH, + SETTINGS_TYPE_NAMESPACE }; struct settings_parse_ctx { @@ -24,6 +25,7 @@ struct settings_parse_ctx { struct server_settings *root, *server; struct auth_settings *auth; + struct namespace_settings *namespace; int level; }; @@ -130,6 +132,19 @@ static struct setting_def auth_setting_defs[] = { { 0, NULL, 0 } }; +#undef DEF +#define DEF(type, name) \ + { type, #name, offsetof(struct namespace_settings, name) } + +static struct setting_def namespace_setting_defs[] = { + DEF(SET_STR, type), + DEF(SET_STR, separator), + DEF(SET_STR, prefix), + DEF(SET_STR, location), + + { 0, NULL, 0 } +}; + struct settings default_settings = { MEMBER(server) NULL, MEMBER(protocol) 0, @@ -287,6 +302,27 @@ static int auth_settings_verify(struct auth_settings *auth) return TRUE; } +static int namespace_settings_verify(struct namespace_settings *ns) +{ + const char *name; + + name = ns->prefix != NULL ? ns->prefix : ""; + if (ns->location == NULL) { + i_error("Namespace '%s': Missing location", name); + return FALSE; + } + + if (ns->separator != NULL && + ns->separator[0] != '\0' && ns->separator[1] != '\0') { + i_error("Namespace '%s': " + "Hierarchy separator must be only one character long", + name); + return FALSE; + } + + return TRUE; +} + static const char *get_directory(const char *path) { char *str, *p; @@ -508,6 +544,38 @@ parse_new_auth(struct server_settings *server, const char *name, return auth_settings_new(server, name); } +static struct namespace_settings * +namespace_settings_new(struct server_settings *server, const char *type) +{ + struct namespace_settings *ns, **ns_p; + + ns = p_new(settings_pool, struct namespace_settings, 1); + + ns->parent = server; + ns->type = str_lcase(p_strdup(settings_pool, type)); + + ns_p = &server->namespaces; + while (*ns_p != NULL) + ns_p = &(*ns_p)->next; + *ns_p = ns; + + return ns; +} + +static struct namespace_settings * +parse_new_namespace(struct server_settings *server, const char *name, + const char **errormsg) +{ + if (strcasecmp(name, "private") != 0 && + strcasecmp(name, "shared") != 0 && + strcasecmp(name, "public") != 0) { + *errormsg = "Unknown namespace type"; + return NULL; + } + + return namespace_settings_new(server, name); +} + static const char *parse_setting(const char *key, const char *value, void *context) { @@ -566,7 +634,11 @@ static const char *parse_setting(const char *key, const char *value, return error; case SETTINGS_TYPE_AUTH: return parse_setting_from_defs(settings_pool, auth_setting_defs, - ctx->auth, key + 5, value); + ctx->auth, key, value); + case SETTINGS_TYPE_NAMESPACE: + return parse_setting_from_defs(settings_pool, + namespace_setting_defs, + ctx->namespace, key, value); } i_unreached(); @@ -587,10 +659,12 @@ create_new_server(const char *name, *server->imap = *imap_defaults; *server->pop3 = *pop3_defaults; + server->imap->server = server; server->imap->protocol = MAIL_PROTOCOL_IMAP; server->imap->login_executable = PKG_LIBEXECDIR"/imap-login"; server->imap->mail_executable = PKG_LIBEXECDIR"/imap"; + server->pop3->server = server; server->pop3->protocol = MAIL_PROTOCOL_POP3; server->pop3->login_executable = PKG_LIBEXECDIR"/pop3-login"; server->pop3->mail_executable = PKG_LIBEXECDIR"/pop3"; @@ -614,6 +688,7 @@ static int parse_section(const char *type, const char *name, void *context, ctx->parent_type = SETTINGS_TYPE_ROOT; ctx->server = ctx->root; ctx->auth = NULL; + ctx->namespace = NULL; } return TRUE; } @@ -669,6 +744,19 @@ static int parse_section(const char *type, const char *name, void *context, return ctx->auth != NULL; } + if (strcmp(type, "namespace") == 0) { + if (ctx->type != SETTINGS_TYPE_ROOT && + ctx->type != SETTINGS_TYPE_SERVER) { + *errormsg = "Namespace section not allowed here"; + return FALSE; + } + + ctx->type = SETTINGS_TYPE_NAMESPACE; + ctx->namespace = parse_new_namespace(ctx->server, name, + errormsg); + return ctx->namespace != NULL; + } + *errormsg = "Unknown section type"; return FALSE; } @@ -678,6 +766,7 @@ int master_settings_read(const char *path) struct settings_parse_ctx ctx; struct server_settings *server, *prev; struct auth_settings *auth; + struct namespace_settings *ns; pool_t temp; memset(&ctx, 0, sizeof(ctx)); @@ -732,6 +821,11 @@ int master_settings_read(const char *path) if (!auth_settings_verify(auth)) return FALSE; } + ns = server->namespaces; + for (; ns != NULL; ns = ns->next) { + if (!namespace_settings_verify(ns)) + return FALSE; + } prev = server; } } diff --git a/src/master/master-settings.h b/src/master/master-settings.h index 64eb416470..cb4c150aec 100644 --- a/src/master/master-settings.h +++ b/src/master/master-settings.h @@ -15,6 +15,7 @@ struct server_settings { struct settings *imap; struct settings *pop3; struct auth_settings *auths; + struct namespace_settings *namespaces; }; struct settings { @@ -118,6 +119,16 @@ struct auth_settings { unsigned int process_size; }; +struct namespace_settings { + struct server_settings *parent; + struct namespace_settings *next; + + const char *type; + const char *separator; + const char *prefix; + const char *location; +}; + extern struct server_settings *settings_root; int master_settings_read(const char *path);