Mercurial > dovecot > original-hg > dovecot-1.2
changeset 1654:31c4bb26a1e9 HEAD
Getting ready for namespaces. LIST is still broken with them.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 27 Jul 2003 07:48:32 +0300 |
parents | 949ecc6c272b |
children | 26e150912cc6 |
files | src/imap/Makefile.am src/imap/client.c src/imap/client.h src/imap/cmd-append.c src/imap/cmd-close.c src/imap/cmd-copy.c src/imap/cmd-create.c src/imap/cmd-delete.c src/imap/cmd-expunge.c src/imap/cmd-fetch.c src/imap/cmd-idle.c src/imap/cmd-list.c src/imap/cmd-namespace.c src/imap/cmd-rename.c src/imap/cmd-search.c src/imap/cmd-select.c src/imap/cmd-sort.c src/imap/cmd-status.c src/imap/cmd-store.c src/imap/cmd-subscribe.c src/imap/cmd-thread.c src/imap/cmd-unselect.c src/imap/commands-util.c src/imap/commands-util.h src/imap/commands.c src/imap/commands.h src/imap/main.c src/imap/namespace.c src/imap/namespace.h |
diffstat | 29 files changed, 422 insertions(+), 121 deletions(-) [+] |
line wrap: on
line diff
--- a/src/imap/Makefile.am Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/Makefile.am Sun Jul 27 07:48:32 2003 +0300 @@ -43,6 +43,7 @@ cmd-login.c \ cmd-logout.c \ cmd-lsub.c \ + cmd-namespace.c \ cmd-noop.c \ cmd-rename.c \ cmd-search.c \ @@ -69,6 +70,7 @@ imap-thread.c \ mail-storage-callbacks.c \ main.c \ + namespace.c \ rawlog.c @@ -82,4 +84,5 @@ imap-search.h \ imap-sort.h \ imap-thread.h \ + namespace.h \ rawlog.h
--- a/src/imap/client.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/client.c Sun Jul 27 07:48:32 2003 +0300 @@ -6,6 +6,7 @@ #include "istream.h" #include "ostream.h" #include "commands.h" +#include "namespace.h" #include <stdlib.h> @@ -40,7 +41,7 @@ "Disconnected for inactivity while waiting for command data."); } -struct client *client_create(int hin, int hout, struct mail_storage *storage) +struct client *client_create(int hin, int hout, struct namespace *namespaces) { struct client *client; @@ -65,8 +66,14 @@ client->mailbox_flags.pool = pool_alloconly_create("mailbox_custom_flags", 512); - client->storage = storage; - storage->set_callbacks(storage, &mail_storage_callbacks, client); + client->namespaces = namespaces; + + while (namespaces != NULL) { + namespaces->storage->set_callbacks(namespaces->storage, + &mail_storage_callbacks, + client); + namespaces = namespaces->next; + } i_assert(my_client == NULL); my_client = client; @@ -82,7 +89,7 @@ if (client->mailbox != NULL) client->mailbox->close(client->mailbox); - mail_storage_destroy(client->storage); + namespace_deinit(client->namespaces); imap_parser_destroy(client->parser); io_remove(client->io);
--- a/src/imap/client.h Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/client.h Sun Jul 27 07:48:32 2003 +0300 @@ -21,7 +21,7 @@ struct istream *input; struct ostream *output; - struct mail_storage *storage; + struct namespace *namespaces; struct mailbox *mailbox; struct mailbox_custom_flags mailbox_flags; unsigned int select_counter; /* increased when mailbox is changed */ @@ -46,7 +46,7 @@ /* Create new client with specified input/output handles. socket specifies if the handle is a socket. */ -struct client *client_create(int hin, int hout, struct mail_storage *storage); +struct client *client_create(int hin, int hout, struct namespace *namespaces); void client_destroy(struct client *client); /* Disconnect client connection */
--- a/src/imap/cmd-append.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/cmd-append.c Sun Jul 27 07:48:32 2003 +0300 @@ -45,6 +45,7 @@ int cmd_append(struct client *client) { + struct mail_storage *storage; struct mailbox *box; struct mailbox_status status; struct mail_save_context *ctx; @@ -66,16 +67,19 @@ if (!client_verify_mailbox_name(client, mailbox, TRUE, FALSE)) return TRUE; - box = client->storage->open_mailbox(client->storage, - mailbox, mailbox_open_flags | - MAILBOX_OPEN_FAST); + storage = client_find_storage(client, mailbox); + if (storage == NULL) + return TRUE; + + box = storage->open_mailbox(storage, mailbox, + mailbox_open_flags | MAILBOX_OPEN_FAST); if (box == NULL) { - client_send_storage_error(client); + client_send_storage_error(client, storage); return TRUE; } if (!box->get_status(box, STATUS_CUSTOM_FLAGS, &status)) { - client_send_storage_error(client); + client_send_storage_error(client, storage); box->close(box); return TRUE; } @@ -86,7 +90,7 @@ ctx = box->save_init(box, TRUE); if (ctx == NULL) { - client_send_storage_error(client); + client_send_storage_error(client, storage); return TRUE; } @@ -188,7 +192,7 @@ client->input->v_offset + msg_size); if (!box->save_next(ctx, &flags, internal_date, timezone_offset, client->input)) { - client_send_storage_error(client); + client_send_storage_error(client, storage); break; } i_stream_set_read_limit(client->input, 0); @@ -202,7 +206,7 @@ if (!box->save_deinit(ctx, failed)) { failed = TRUE; - client_send_storage_error(client); + client_send_storage_error(client, storage); } box->close(box);
--- a/src/imap/cmd-close.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/cmd-close.c Sun Jul 27 07:48:32 2003 +0300 @@ -14,12 +14,14 @@ client->mailbox = NULL; if (!mailbox->is_readonly(mailbox)) { - if (!imap_expunge(mailbox, FALSE)) - client_send_untagged_storage_error(client); + if (!imap_expunge(mailbox, FALSE)) { + client_send_untagged_storage_error(client, + mailbox->storage); + } } if (!mailbox->close(mailbox)) - client_send_untagged_storage_error(client); + client_send_untagged_storage_error(client, mailbox->storage); client_send_tagline(client, "OK Close completed."); return TRUE;
--- a/src/imap/cmd-copy.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/cmd-copy.c Sun Jul 27 07:48:32 2003 +0300 @@ -31,6 +31,7 @@ int cmd_copy(struct client *client) { + struct mail_storage *storage; struct mailbox *destbox; struct mail_copy_context *copy_ctx; const char *messageset, *mailbox; @@ -47,11 +48,14 @@ if (!client_verify_mailbox_name(client, mailbox, TRUE, FALSE)) return TRUE; - destbox = client->storage->open_mailbox(client->storage, - mailbox, mailbox_open_flags | - MAILBOX_OPEN_FAST); + storage = client_find_storage(client, mailbox); + if (storage == NULL) + return TRUE; + + destbox = storage->open_mailbox(storage, mailbox, + mailbox_open_flags | MAILBOX_OPEN_FAST); if (destbox == NULL) { - client_send_storage_error(client); + client_send_storage_error(client, storage); return TRUE; } @@ -78,7 +82,7 @@ (void)destbox->lock(destbox, MAILBOX_LOCK_UNLOCK); if (failed) - client_send_storage_error(client); + client_send_storage_error(client, storage); else if (!all_found) { /* some messages were expunged, sync them */ client_sync_full(client);
--- a/src/imap/cmd-create.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/cmd-create.c Sun Jul 27 07:48:32 2003 +0300 @@ -5,6 +5,7 @@ int cmd_create(struct client *client) { + struct mail_storage *storage; const char *mailbox; int only_hiearchy; size_t len; @@ -13,8 +14,12 @@ if (!client_read_string_args(client, 1, &mailbox)) return FALSE; + storage = client_find_storage(client, mailbox); + if (storage == NULL) + return TRUE; + len = strlen(mailbox); - if (mailbox[len-1] != client->storage->hierarchy_sep) + if (mailbox[len-1] != storage->hierarchy_sep) only_hiearchy = FALSE; else { /* name ends with hierarchy separator - client is just @@ -27,9 +32,8 @@ if (!client_verify_mailbox_name(client, mailbox, FALSE, TRUE)) return TRUE; - if (!client->storage->create_mailbox(client->storage, mailbox, - only_hiearchy)) { - client_send_storage_error(client); + if (!storage->create_mailbox(storage, mailbox, only_hiearchy)) { + client_send_storage_error(client, storage); return TRUE; }
--- a/src/imap/cmd-delete.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/cmd-delete.c Sun Jul 27 07:48:32 2003 +0300 @@ -5,6 +5,7 @@ int cmd_delete(struct client *client) { + struct mail_storage *storage; struct mailbox *mailbox; const char *name; @@ -21,15 +22,20 @@ mailbox = client->mailbox; if (mailbox != NULL && strcmp(mailbox->name, name) == 0) { /* deleting selected mailbox. close it first */ + storage = mailbox->storage; client->mailbox = NULL; if (!mailbox->close(mailbox)) - client_send_untagged_storage_error(client); + client_send_untagged_storage_error(client, storage); + } else { + storage = client_find_storage(client, name); + if (storage == NULL) + return TRUE; } - if (client->storage->delete_mailbox(client->storage, name)) + if (storage->delete_mailbox(storage, name)) client_send_tagline(client, "OK Delete completed."); else - client_send_storage_error(client); + client_send_storage_error(client, storage); return TRUE; }
--- a/src/imap/cmd-expunge.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/cmd-expunge.c Sun Jul 27 07:48:32 2003 +0300 @@ -12,7 +12,7 @@ if (imap_expunge(client->mailbox, TRUE)) client_send_tagline(client, "OK Expunge completed."); else - client_send_storage_error(client); + client_send_storage_error(client, client->mailbox->storage); return TRUE; }
--- a/src/imap/cmd-fetch.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/cmd-fetch.c Sun Jul 27 07:48:32 2003 +0300 @@ -362,7 +362,7 @@ client_send_tagline(client, ret > 0 ? "OK Fetch completed." : "NO Some of the requested messages no longer exist."); } else { - client_send_storage_error(client); + client_send_storage_error(client, client->mailbox->storage); } return TRUE;
--- a/src/imap/cmd-idle.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/cmd-idle.c Sun Jul 27 07:48:32 2003 +0300 @@ -86,7 +86,8 @@ if (!client->mailbox->get_status(client->mailbox, STATUS_MESSAGES, &status)) { - client_send_untagged_storage_error(client); + client_send_untagged_storage_error(client, + client->mailbox->storage); idle_finish(client, TRUE); } else { client->idle_expunge = status.messages+1;
--- a/src/imap/cmd-list.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/cmd-list.c Sun Jul 27 07:48:32 2003 +0300 @@ -34,21 +34,20 @@ return *str == '\0' ? "" : str+1; } -static int mailbox_list(struct client *client, const char *mask, - const char *sep, const char *reply, +static int mailbox_list(struct client *client, struct mail_storage *storage, + const char *mask, const char *sep, const char *reply, enum mailbox_list_flags list_flags, int listext) { struct mailbox_list_context *ctx; struct mailbox_list *list; string_t *str; - ctx = client->storage->list_mailbox_init(client->storage, mask, - list_flags); + ctx = storage->list_mailbox_init(storage, mask, list_flags); if (ctx == NULL) return FALSE; str = t_str_new(256); - while ((list = client->storage->list_mailbox_next(ctx)) != NULL) { + while ((list = storage->list_mailbox_next(ctx)) != NULL) { str_truncate(str, 0); str_printfa(str, "* %s (%s) \"%s\" ", reply, mailbox_flags2str(list->flags, listext), @@ -60,7 +59,7 @@ client_send_line(client, str_c(str)); } - return client->storage->list_mailbox_deinit(ctx); + return storage->list_mailbox_deinit(ctx); } static int parse_list_flags(struct client *client, struct imap_arg *args, @@ -93,14 +92,19 @@ int _cmd_list_full(struct client *client, int lsub) { + struct mail_storage *storage; struct imap_arg *args; enum mailbox_list_flags list_flags; const char *ref, *mask; char sep_chr, sep[3]; int failed, listext; - sep_chr = client->storage->hierarchy_sep; - if (IS_ESCAPED_CHAR(sep_chr)) { + storage = client_find_storage(client, ""); + if (storage == NULL) + return TRUE; + + sep_chr = storage->hierarchy_sep; + if (sep_chr == '"' || sep_chr == '\\') { sep[0] = '\\'; sep[1] = sep_chr; sep[2] = '\0'; @@ -158,13 +162,13 @@ } } - failed = !mailbox_list(client, mask, sep, + failed = !mailbox_list(client, storage, mask, sep, lsub ? "LSUB" : "LIST", list_flags, listext); } if (failed) - client_send_storage_error(client); + client_send_storage_error(client, storage); else { client_send_tagline(client, lsub ? "OK Lsub completed." :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/imap/cmd-namespace.c Sun Jul 27 07:48:32 2003 +0300 @@ -0,0 +1,55 @@ +/* Copyright (C) 2003 Timo Sirainen */ + +#include "common.h" +#include "str.h" +#include "imap-quote.h" +#include "commands.h" +#include "namespace.h" + +static void list_namespaces(struct namespace *ns, enum namespace_type type, + string_t *str) +{ + int found = FALSE; + + while (ns != NULL) { + if (ns->type == type) { + if (!found) { + str_append_c(str, '('); + found = TRUE; + } + str_append_c(str, '('); + imap_quote_append_string(str, ns->prefix, FALSE); + str_append(str, " \""); + if (ns->hierarchy_sep == '"' || + ns->hierarchy_sep == '\\') + str_append_c(str, '\\'); + str_append_c(str, ns->hierarchy_sep); + str_append(str, "\")"); + } + + ns = ns->next; + } + + if (found) + str_append_c(str, ')'); + else + str_append(str, "NIL"); +} + +int cmd_namespace(struct client *client) +{ + string_t *str; + + str = t_str_new(256); + str_append(str, "* NAMESPACE "); + + list_namespaces(client->namespaces, NAMESPACE_PRIVATE, str); + str_append_c(str, ' '); + list_namespaces(client->namespaces, NAMESPACE_SHARED, str); + str_append_c(str, ' '); + list_namespaces(client->namespaces, NAMESPACE_PUBLIC, str); + + client_send_line(client, str_c(str)); + client_send_tagline(client, "OK Namespace completed."); + return TRUE; +}
--- a/src/imap/cmd-rename.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/cmd-rename.c Sun Jul 27 07:48:32 2003 +0300 @@ -5,6 +5,7 @@ int cmd_rename(struct client *client) { + struct mail_storage *old_storage, *new_storage; const char *oldname, *newname; /* <old name> <new name> */ @@ -14,11 +15,24 @@ if (!client_verify_mailbox_name(client, newname, FALSE, TRUE)) return TRUE; - if (client->storage->rename_mailbox(client->storage, - oldname, newname)) + old_storage = client_find_storage(client, oldname); + if (old_storage == NULL) + return TRUE; + + new_storage = client_find_storage(client, newname); + if (new_storage == NULL) + return TRUE; + + if (old_storage != new_storage) { + client_send_tagline(client, + "NO Can't rename mailbox to another namespace."); + return TRUE; + } + + if (old_storage->rename_mailbox(old_storage, oldname, newname)) client_send_tagline(client, "OK Rename completed."); else - client_send_storage_error(client); + client_send_storage_error(client, old_storage); return TRUE; }
--- a/src/imap/cmd-search.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/cmd-search.c Sun Jul 27 07:48:32 2003 +0300 @@ -97,7 +97,7 @@ client_sync_without_expunges(client); client_send_tagline(client, "OK Search completed."); } else { - client_send_storage_error(client); + client_send_storage_error(client, client->mailbox->storage); } pool_unref(pool);
--- a/src/imap/cmd-select.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/cmd-select.c Sun Jul 27 07:48:32 2003 +0300 @@ -5,6 +5,7 @@ int _cmd_select_full(struct client *client, int readonly) { + struct mail_storage *storage; struct mailbox *box; struct mailbox_status status; enum mailbox_open_flags flags; @@ -17,23 +18,29 @@ if (client->mailbox != NULL) { box = client->mailbox; client->mailbox = NULL; - if (!box->close(box)) - client_send_untagged_storage_error(client); + if (!box->close(box)) { + client_send_untagged_storage_error(client, + box->storage); + } } + storage = client_find_storage(client, mailbox); + if (storage == NULL) + return TRUE; + flags = mailbox_open_flags; if (readonly) flags |= MAILBOX_OPEN_READONLY; - box = client->storage->open_mailbox(client->storage, mailbox, flags); + box = storage->open_mailbox(storage, mailbox, flags); if (box == NULL) { - client_send_storage_error(client); + client_send_storage_error(client, storage); return TRUE; } if (!box->get_status(box, STATUS_MESSAGES | STATUS_RECENT | STATUS_FIRST_UNSEEN_SEQ | STATUS_UIDVALIDITY | STATUS_UIDNEXT | STATUS_CUSTOM_FLAGS, &status)) { - client_send_storage_error(client); + client_send_storage_error(client, storage); box->close(box); return TRUE; }
--- a/src/imap/cmd-sort.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/cmd-sort.c Sun Jul 27 07:48:32 2003 +0300 @@ -128,7 +128,7 @@ client_sync_without_expunges(client); client_send_tagline(client, "OK Sort completed."); } else { - client_send_storage_error(client); + client_send_storage_error(client, client->mailbox->storage); } pool_unref(pool);
--- a/src/imap/cmd-status.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/cmd-status.c Sun Jul 27 07:48:32 2003 +0300 @@ -51,7 +51,8 @@ return strcasecmp(box1, "INBOX") == 0 && strcasecmp(box2, "INBOX") == 0; } -static int get_mailbox_status(struct client *client, const char *mailbox, +static int get_mailbox_status(struct client *client, + struct mail_storage *storage, const char *mailbox, enum mailbox_status_items items, struct mailbox_status *status) { @@ -64,11 +65,10 @@ box = client->mailbox; } else { /* open the mailbox */ - box = client->storage->open_mailbox(client->storage, - mailbox, - mailbox_open_flags | - MAILBOX_OPEN_FAST | - MAILBOX_OPEN_READONLY); + box = storage->open_mailbox(storage, mailbox, + mailbox_open_flags | + MAILBOX_OPEN_FAST | + MAILBOX_OPEN_READONLY); if (box == NULL) return FALSE; } @@ -86,6 +86,7 @@ struct imap_arg *args; struct mailbox_status status; enum mailbox_status_items items; + struct mail_storage *storage; const char *mailbox; string_t *str; @@ -106,9 +107,13 @@ return TRUE; } + storage = client_find_storage(client, mailbox); + if (storage == NULL) + return FALSE; + /* get status */ - if (!get_mailbox_status(client, mailbox, items, &status)) { - client_send_storage_error(client); + if (!get_mailbox_status(client, storage, mailbox, items, &status)) { + client_send_storage_error(client, storage); return TRUE; }
--- a/src/imap/cmd-store.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/cmd-store.c Sun Jul 27 07:48:32 2003 +0300 @@ -132,7 +132,7 @@ client_send_tagline(client, all_found ? "OK Store completed." : "NO Some of the messages no longer exist."); } else { - client_send_storage_error(client); + client_send_storage_error(client, client->mailbox->storage); } return TRUE;
--- a/src/imap/cmd-subscribe.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/cmd-subscribe.c Sun Jul 27 07:48:32 2003 +0300 @@ -5,6 +5,7 @@ int _cmd_subscribe_full(struct client *client, int subscribe) { + struct mail_storage *storage; const char *mailbox; /* <mailbox> */ @@ -14,13 +15,16 @@ if (!client_verify_mailbox_name(client, mailbox, subscribe, FALSE)) return TRUE; - if (client->storage->set_subscribed(client->storage, - mailbox, subscribe)) { + storage = client_find_storage(client, mailbox); + if (storage == NULL) + return FALSE; + + if (storage->set_subscribed(storage, mailbox, subscribe)) { client_send_tagline(client, subscribe ? "OK Subscribe completed." : "OK Unsubscribe completed."); } else { - client_send_storage_error(client); + client_send_storage_error(client, storage); } return TRUE;
--- a/src/imap/cmd-thread.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/cmd-thread.c Sun Jul 27 07:48:32 2003 +0300 @@ -70,7 +70,7 @@ client_sync_without_expunges(client); client_send_tagline(client, "OK Search completed."); } else { - client_send_storage_error(client); + client_send_storage_error(client, client->mailbox->storage); } pool_unref(pool);
--- a/src/imap/cmd-unselect.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/cmd-unselect.c Sun Jul 27 07:48:32 2003 +0300 @@ -13,7 +13,7 @@ client->mailbox = NULL; if (!mailbox->close(mailbox)) - client_send_untagged_storage_error(client); + client_send_untagged_storage_error(client, mailbox->storage); client_send_tagline(client, "OK Unselect completed."); return TRUE;
--- a/src/imap/commands-util.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/commands-util.c Sun Jul 27 07:48:32 2003 +0300 @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Timo Sirainen */ +/* Copyright (C) 2002-2003 Timo Sirainen */ #include "common.h" #include "str.h" @@ -6,6 +6,7 @@ #include "imap-util.h" #include "mail-storage.h" #include "imap-parser.h" +#include "namespace.h" /* Maximum length for mailbox name, including it's path. This isn't fully exact since the user can create folder hierarchy with small names, then @@ -13,15 +14,33 @@ to them, mbox/maildir currently allow paths only up to PATH_MAX. */ #define MAILBOX_MAX_NAME_LEN 512 +struct mail_storage * +client_find_storage(struct client *client, const char *mailbox) +{ + struct namespace *ns; + + ns = namespace_find(client->namespaces, mailbox); + if (ns != NULL) + return ns->storage; + + client_send_tagline(client, "NO Unknown namespace."); + return NULL; +} + int client_verify_mailbox_name(struct client *client, const char *mailbox, int should_exist, int should_not_exist) { + struct mail_storage *storage; enum mailbox_name_status mailbox_status; const char *p; char sep; + storage = client_find_storage(client, mailbox); + if (storage == NULL) + return FALSE; + /* make sure it even looks valid */ - sep = client->storage->hierarchy_sep; + sep = storage->hierarchy_sep; if (*mailbox == '\0' || strspn(mailbox, "\r\n*%?") != 0) { client_send_tagline(client, "NO Invalid mailbox name."); return FALSE; @@ -41,9 +60,9 @@ } /* check what our storage thinks of it */ - if (!client->storage->get_mailbox_name_status(client->storage, mailbox, - &mailbox_status)) { - client_send_storage_error(client); + if (!storage->get_mailbox_name_status(storage, mailbox, + &mailbox_status)) { + client_send_storage_error(client, storage); return FALSE; } @@ -93,32 +112,40 @@ void client_sync_full(struct client *client) { - if (client->mailbox != NULL) { - if (!client->mailbox->sync(client->mailbox, 0)) - client_send_untagged_storage_error(client); + if (client->mailbox == NULL) + return; + + if (!client->mailbox->sync(client->mailbox, 0)) { + client_send_untagged_storage_error(client, + client->mailbox->storage); } } void client_sync_full_fast(struct client *client) { - if (client->mailbox != NULL) { - if (!client->mailbox->sync(client->mailbox, - MAIL_SYNC_FLAG_FAST)) - client_send_untagged_storage_error(client); + if (client->mailbox == NULL) + return; + + if (!client->mailbox->sync(client->mailbox, MAIL_SYNC_FLAG_FAST)) { + client_send_untagged_storage_error(client, + client->mailbox->storage); } } void client_sync_without_expunges(struct client *client) { - if (client->mailbox != NULL) { - if (!client->mailbox->sync(client->mailbox, - MAIL_SYNC_FLAG_NO_EXPUNGES | - MAIL_SYNC_FLAG_FAST)) - client_send_untagged_storage_error(client); + if (client->mailbox == NULL) + return; + + if (!client->mailbox->sync(client->mailbox, MAIL_SYNC_FLAG_NO_EXPUNGES | + MAIL_SYNC_FLAG_FAST)) { + client_send_untagged_storage_error(client, + client->mailbox->storage); } } -void client_send_storage_error(struct client *client) +void client_send_storage_error(struct client *client, + struct mail_storage *storage) { const char *error; int syntax; @@ -131,12 +158,13 @@ return; } - error = client->storage->get_last_error(client->storage, &syntax); + error = storage->get_last_error(storage, &syntax); client_send_tagline(client, t_strconcat(syntax ? "BAD " : "NO ", error, NULL)); } -void client_send_untagged_storage_error(struct client *client) +void client_send_untagged_storage_error(struct client *client, + struct mail_storage *storage) { const char *error; int syntax; @@ -149,7 +177,7 @@ return; } - error = client->storage->get_last_error(client->storage, &syntax); + error = storage->get_last_error(storage, &syntax); client_send_line(client, t_strconcat(syntax ? "* BAD " : "* NO ", error, NULL)); }
--- a/src/imap/commands-util.h Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/commands-util.h Sun Jul 27 07:48:32 2003 +0300 @@ -3,6 +3,11 @@ struct mail_full_flags; +/* Finds mail storage for given mailbox from namespaces. If not found, + sends "Unknown namespace" error message to client. */ +struct mail_storage * +client_find_storage(struct client *client, const char *mailbox); + /* If should_exist is TRUE, this function returns TRUE if the mailbox exists. If it doesn't exist but would be a valid mailbox name, the error message is prefixed with [TRYCREATE]. @@ -27,10 +32,12 @@ void client_sync_without_expunges(struct client *client); /* Send last mail storage error message to client. */ -void client_send_storage_error(struct client *client); +void client_send_storage_error(struct client *client, + struct mail_storage *storage); /* Send untagged error message to client. */ -void client_send_untagged_storage_error(struct client *client); +void client_send_untagged_storage_error(struct client *client, + struct mail_storage *storage); /* Parse flags. Returns TRUE if successful, if not sends an error message to client. */
--- a/src/imap/commands.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/commands.c Sun Jul 27 07:48:32 2003 +0300 @@ -43,6 +43,7 @@ const struct command imap_ext_commands[] = { { "IDLE", cmd_idle }, + { "NAMESPACE", cmd_namespace }, { "SORT", cmd_sort }, { "THREAD", cmd_thread }, { "UID SORT", cmd_sort },
--- a/src/imap/commands.h Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/commands.h Sun Jul 27 07:48:32 2003 +0300 @@ -62,10 +62,11 @@ int cmd_uid(struct client *client); /* IMAP extensions: */ +int cmd_idle(struct client *client); +int cmd_namespace(struct client *client); int cmd_sort(struct client *client); int cmd_thread(struct client *client); int cmd_unselect(struct client *client); -int cmd_idle(struct client *client); /* private: */ int _cmd_list_full(struct client *client, int lsub);
--- a/src/imap/main.c Sun Jul 27 07:35:44 2003 +0300 +++ b/src/imap/main.c Sun Jul 27 07:48:32 2003 +0300 @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Timo Sirainen */ +/* Copyright (C) 2002-2003 Timo Sirainen */ #include "common.h" #include "ioloop.h" @@ -13,6 +13,7 @@ #include "module-dir.h" #include "mail-storage.h" #include "commands.h" +#include "namespace.h" #include <stdlib.h> #include <unistd.h> @@ -28,6 +29,7 @@ static struct module *modules; static char log_prefix[128]; /* syslog() needs this to be permanent */ +static pool_t namespace_pool; void (*hook_mail_storage_created)(struct mail_storage **storage) = NULL; void (*hook_client_created)(struct client **client) = NULL; @@ -85,8 +87,7 @@ static void main_init(void) { struct client *client; - struct mail_storage *storage; - const char *user, *mail, *str; + const char *user, *str; int hin, hout; lib_init_signals(sig_quit); @@ -113,33 +114,6 @@ modules = getenv("MODULE_DIR") == NULL ? NULL : module_dir_load(getenv("MODULE_DIR")); - mail = getenv("MAIL"); - if (mail == NULL) { - /* support also maildir-specific environment */ - mail = getenv("MAILDIR"); - if (mail != NULL) - mail = t_strconcat("maildir:", mail, NULL); - } - - storage = mail_storage_create_with_data(mail, user, NULL, '\0'); - if (storage == NULL) { - /* failed */ - if (mail != NULL && *mail != '\0') - i_fatal("Failed to create storage with data: %s", mail); - else { - const char *home; - - home = getenv("HOME"); - if (home == NULL) home = "not set"; - - i_fatal("MAIL environment missing and " - "autodetection failed (home %s)", home); - } - } - - if (hook_mail_storage_created != NULL) - hook_mail_storage_created(&storage); - str = getenv("IMAP_MAX_LINE_LENGTH"); imap_max_line_length = str != NULL ? (unsigned int)strtoul(str, NULL, 10) : @@ -157,7 +131,8 @@ mailbox_open_flags = getenv("MMAP_INVALIDATE") != NULL ? MAILBOX_OPEN_MMAP_INVALIDATE : 0; - client = client_create(hin, hout, storage); + namespace_pool = pool_alloconly_create("namespaces", 1024); + client = client_create(hin, hout, namespace_init(namespace_pool, user)); o_stream_cork(client->output); if (IS_STANDALONE()) { @@ -185,6 +160,7 @@ clients_deinit(); mail_storage_deinit(); random_deinit(); + pool_unref(namespace_pool); closelog(); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/imap/namespace.c Sun Jul 27 07:48:32 2003 +0300 @@ -0,0 +1,143 @@ +/* Copyright (C) 2003 Timo Sirainen */ + +#include "common.h" +#include "commands.h" +#include "namespace.h" + +#include <stdlib.h> + +static struct namespace * +namespace_add_env(pool_t pool, const char *data, unsigned int num, + const char *user) +{ + struct namespace *ns; + const char *sep, *type, *prefix; + + ns = p_new(pool, struct namespace, 1); + + sep = getenv(t_strdup_printf("NAMESPACE_%u_SEP", num)); + type = getenv(t_strdup_printf("NAMESPACE_%u_TYPE", num)); + prefix = getenv(t_strdup_printf("NAMESPACE_%u_PREFIX", num)); + + if (type == NULL || *type == '\0' || strncmp(type, "private", 7) == 0) + ns->type = NAMESPACE_PRIVATE; + else if (strncmp(type, "shared", 6) == 0) + ns->type = NAMESPACE_SHARED; + else if (strncmp(type, "public", 6) == 0) + ns->type = NAMESPACE_PUBLIC; + else + i_fatal("Unknown namespace type: %s", type); + + if (prefix == NULL) + prefix = ""; + + ns->prefix = p_strdup(pool, prefix); + ns->storage = mail_storage_create_with_data(data, user, ns->prefix, + sep != NULL ? *sep : '\0'); + if (ns->storage == NULL) { + i_fatal("Failed to create storage for '%s' with data: %s", + ns->prefix, data); + } + + if (hook_mail_storage_created != NULL) + hook_mail_storage_created(&ns->storage); + + ns->hierarchy_sep = ns->storage->hierarchy_sep; + return ns; +} + +struct namespace *namespace_init(pool_t pool, const char *user) +{ + struct namespace *namespaces, *ns, **ns_p; + const char *mail, *data; + unsigned int i; + + namespaces = NULL; ns_p = &namespaces; + + /* first try NAMESPACE_* environments */ + for (i = 1; ; i++) { + t_push(); + data = getenv(t_strdup_printf("NAMESPACE_%u", i)); + t_pop(); + + if (data == NULL) + break; + + t_push(); + *ns_p = namespace_add_env(pool, data, i, user); + t_pop(); + + ns_p = &(*ns_p)->next; + } + + if (namespaces != NULL) + return namespaces; + + /* fallback to MAIL */ + mail = getenv("MAIL"); + if (mail == NULL) { + /* support also maildir-specific environment */ + mail = getenv("MAILDIR"); + if (mail != NULL) + mail = t_strconcat("maildir:", mail, NULL); + } + + ns = p_new(pool, struct namespace, 1); + ns->storage = mail_storage_create_with_data(mail, user, NULL, '\0'); + if (ns->storage == NULL) { + if (mail != NULL && *mail != '\0') + i_fatal("Failed to create storage with data: %s", mail); + else { + const char *home; + + home = getenv("HOME"); + if (home == NULL) home = "not set"; + + i_fatal("MAIL environment missing and " + "autodetection failed (home %s)", home); + } + } + + ns->type = NAMESPACE_PRIVATE; + ns->prefix = p_strdup(pool, ""); + ns->hierarchy_sep = ns->storage->hierarchy_sep; + if (hook_mail_storage_created != NULL) + hook_mail_storage_created(&ns->storage); + + return ns; +} + +void namespace_deinit(struct namespace *namespaces) +{ + while (namespaces != NULL) { + mail_storage_destroy(namespaces->storage); + namespaces = namespaces->next; + } +} + +struct namespace * +namespace_find(struct namespace *namespaces, const char *mailbox) +{ + struct namespace *best = NULL; + size_t len, best_len = 0; + int inbox; + + inbox = strncasecmp(mailbox, "INBOX", 5) == 0; + + while (namespaces != NULL) { + len = namespaces->prefix == NULL ? 0 : + strlen(namespaces->prefix); + if (len >= best_len && + (strncmp(namespaces->prefix, mailbox, len) == 0 || + (inbox && strncmp(namespaces->prefix, "INBOX", 5) == 0 && + mailbox[5] == namespaces->hierarchy_sep && + namespaces->prefix[5] == namespaces->hierarchy_sep && + strncmp(namespaces->prefix+6, mailbox+6, len-6) == 0))) { + best = namespaces; + best_len = len; + } + namespaces = namespaces->next; + } + + return best; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/imap/namespace.h Sun Jul 27 07:48:32 2003 +0300 @@ -0,0 +1,25 @@ +#ifndef __NAMESPACE_H +#define __NAMESPACE_H + +enum namespace_type { + NAMESPACE_PRIVATE, + NAMESPACE_SHARED, + NAMESPACE_PUBLIC +}; + +struct namespace { + struct namespace *next; + + enum namespace_type type; + char hierarchy_sep; + char *prefix; + struct mail_storage *storage; +}; + +struct namespace *namespace_init(pool_t pool, const char *user); +void namespace_deinit(struct namespace *namespaces); + +struct namespace * +namespace_find(struct namespace *namespaces, const char *mailbox); + +#endif