Mercurial > dovecot > original-hg > dovecot-1.2
changeset 1218:a70ebd3a59e2 HEAD
Removed list-sort workarounds. It's pretty much needed for maildir listing.
Also added some more complexity and kludging to make everything work
correctly.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 20 Feb 2003 18:41:16 +0200 |
parents | 15c1353d74d9 |
children | e4210f1ea3f1 |
files | dovecot-example.conf src/imap/cmd-list.c src/lib-imap/imap-match.c src/lib-storage/index/maildir/maildir-list.c src/lib-storage/index/mbox/mbox-list.c src/lib-storage/mail-storage.c src/lib-storage/mail-storage.h |
diffstat | 7 files changed, 91 insertions(+), 55 deletions(-) [+] |
line wrap: on
line diff
--- a/dovecot-example.conf Thu Feb 20 18:40:16 2003 +0200 +++ b/dovecot-example.conf Thu Feb 20 18:41:16 2003 +0200 @@ -215,11 +215,6 @@ # seems to think they are FETCH replies and gives user "Message no longer # in server" error. Note that OE6 still breaks even with this workaround # if synchronization is set to "Headers Only". -# list-sort: -# When replying to LIST and LSUB requests, make sure that the parent -# mailboxes are sent before any of their children. This is mostly -# maildir-specific, mbox list replies are always sorted. MacOS X's Mail.app -# at least wants this. # outlook-idle: # Outlook and Outlook Express never abort IDLE command, so if no mail # arrives in half a hour, Dovecot closes the connection. This is still
--- a/src/imap/cmd-list.c Thu Feb 20 18:40:16 2003 +0200 +++ b/src/imap/cmd-list.c Thu Feb 20 18:41:16 2003 +0200 @@ -2,6 +2,7 @@ #include "common.h" #include "strescape.h" +#include "imap-match.h" #include "commands.h" struct list_node { @@ -22,6 +23,9 @@ { const char *str; + if (flags == MAILBOX_PLACEHOLDER) + flags = MAILBOX_NOSELECT; + str = t_strconcat((flags & MAILBOX_NOSELECT) ? " \\Noselect" : "", (flags & MAILBOX_NOINFERIORS) ? " \\NoInferiors" : "", (flags & MAILBOX_MARKED) ? " \\Marked" : "", @@ -60,7 +64,7 @@ /* not found, create it */ *node = p_new(pool, struct list_node, 1); (*node)->name = p_strdup(pool, name); - (*node)->flags = MAILBOX_NOSELECT; + (*node)->flags = MAILBOX_PLACEHOLDER; } t_pop(); @@ -77,9 +81,11 @@ } static void list_send(struct client *client, struct list_node *node, - const char *cmd, const char *path, const char *sep) + const char *cmd, const char *path, const char *sep, + struct imap_match_glob *glob) { - const char *name, *str; + const char *name, *send_name, *str; + enum imap_match_result match; for (; node != NULL; node = node->next) { t_push(); @@ -91,20 +97,63 @@ name = "INBOX"; else name = node->name; + send_name = name; - /* node->name should already be escaped */ - str = t_strdup_printf("* %s (%s) \"%s\" \"%s\"", cmd, - mailbox_flags2str(node->flags), - sep, name); - client_send_line(client, str); + if (node->flags != MAILBOX_PLACEHOLDER) + match = IMAP_MATCH_YES; + else { + /* make sure the placeholder matches. */ + const char *buf; + + buf = str_unescape(t_strdup_noconst(name)); + match = imap_match(glob, buf); + if (match == IMAP_MATCH_CHILDREN) { + send_name = t_strconcat(name, sep, NULL); + buf = str_unescape(t_strdup_noconst(send_name)); + match = imap_match(glob, buf); + } + } + + if (match == IMAP_MATCH_YES) { + /* node->name should already be escaped */ + str = t_strdup_printf("* %s (%s) \"%s\" \"%s\"", cmd, + mailbox_flags2str(node->flags), + sep, send_name); + client_send_line(client, str); + } if (node->children != NULL) - list_send(client, node->children, cmd, name, sep); + list_send(client, node->children, cmd, name, sep, glob); t_pop(); } } +static void list_and_sort(struct client *client, + struct mailbox_list_context *ctx, + const char *cmd, const char *sep, const char *mask) +{ + struct mailbox_list *list; + struct list_node *nodes, *node; + struct imap_match_glob *glob; + pool_t pool; + + pool = pool_alloconly_create("list_mailboxes", 10240); + nodes = NULL; + + while ((list = client->storage->list_mailbox_next(ctx)) != NULL) { + node = list_node_get(pool, &nodes, list->name, + client->storage->hierarchy_sep); + node->flags |= list->flags; + } + + glob = imap_match_init(data_stack_pool, mask, TRUE, + client->storage->hierarchy_sep); + list_send(client, nodes, cmd, NULL, sep, glob); + imap_match_deinit(glob); + pool_unref(pool); +} + static void list_unsorted(struct client *client, struct mailbox_list_context *ctx, const char *cmd, const char *sep) @@ -126,30 +175,6 @@ } } -static void list_and_sort(struct client *client, - struct mailbox_list_context *ctx, - const char *cmd, const char *sep) -{ - struct mailbox_list *list; - struct list_node *nodes, *node; - pool_t pool; - - pool = pool_alloconly_create("list_mailboxes", 10240); - nodes = NULL; - - while ((list = client->storage->list_mailbox_next(ctx)) != NULL) { - node = list_node_get(pool, &nodes, list->name, - client->storage->hierarchy_sep); - - /* set the flags, this also overrides the - NOSELECT flag set by list_node_get() */ - node->flags = list->flags; - } - - list_send(client, nodes, cmd, NULL, sep); - pool_unref(pool); -} - static int list_mailboxes(struct client *client, const char *mask, int subscribed, const char *sep) { @@ -165,10 +190,10 @@ return FALSE; cmd = subscribed ? "LSUB" : "LIST"; - if (sorted || (client_workarounds & WORKAROUND_LIST_SORT) == 0) + if (sorted) list_unsorted(client, ctx, cmd, sep); else - list_and_sort(client, ctx, cmd, sep); + list_and_sort(client, ctx, cmd, sep, mask); return client->storage->list_mailbox_deinit(ctx); }
--- a/src/lib-imap/imap-match.c Thu Feb 20 18:40:16 2003 +0200 +++ b/src/lib-imap/imap-match.c Thu Feb 20 18:41:16 2003 +0200 @@ -135,8 +135,10 @@ if (ret > 0) break; - if (ret == IMAP_MATCH_CHILDREN) - best_ret = IMAP_MATCH_CHILDREN; + if (ret == IMAP_MATCH_CHILDREN || + (ret == IMAP_MATCH_PARENT && + best_ret == IMAP_MATCH_NO)) + best_ret = ret; } if (*data == glob->sep_char)
--- a/src/lib-storage/index/maildir/maildir-list.c Thu Feb 20 18:40:16 2003 +0200 +++ b/src/lib-storage/index/maildir/maildir-list.c Thu Feb 20 18:41:16 2003 +0200 @@ -152,7 +152,7 @@ if (match == IMAP_MATCH_PARENT) { /* placeholder */ - ctx->list.flags = MAILBOX_NOSELECT; + ctx->list.flags = MAILBOX_PLACEHOLDER; while ((p = strrchr(name, '.')) != NULL) { name = t_strdup_until(name, p); if (imap_match(ctx->glob, name) > 0) { @@ -181,14 +181,15 @@ { struct dirent *d; struct stat st; + const char *fname, *p; char path[PATH_MAX]; - int ret; + enum imap_match_result match; if (ctx->dirp == NULL) return NULL; while ((d = readdir(ctx->dirp)) != NULL) { - const char *fname = d->d_name; + fname = d->d_name; if (fname[0] != '.') continue; @@ -200,10 +201,11 @@ /* make sure the mask matches - dirs beginning with ".." should be deleted and we always want to check those. */ t_push(); - ret = imap_match(ctx->glob, - t_strconcat(ctx->prefix, fname+1, NULL)); + match = imap_match(ctx->glob, + t_strconcat(ctx->prefix, fname+1, NULL)); t_pop(); - if (fname[1] == '.' || ret <= 0) + if (fname[1] != '.' && match != IMAP_MATCH_YES && + match != IMAP_MATCH_PARENT) continue; if (str_path(path, sizeof(path), ctx->dir, fname) < 0) @@ -223,7 +225,8 @@ if (!S_ISDIR(st.st_mode)) continue; - if (fname[1] == '.') { + fname++; + if (*fname == '.') { /* this mailbox is in the middle of being deleted, or the process trying to delete it had died. @@ -234,14 +237,26 @@ continue; } - if (strcasecmp(fname+1, "INBOX") == 0) + if (strcasecmp(fname, "INBOX") == 0) continue; /* ignore inboxes */ + if (match == IMAP_MATCH_PARENT) { + ctx->list.flags = MAILBOX_PLACEHOLDER; + while ((p = strrchr(fname, '.')) != NULL) { + fname = t_strdup_until(fname, p); + if (imap_match(ctx->glob, fname) > 0) { + ctx->list.name = fname; + return &ctx->list; + } + } + i_unreached(); + } + p_clear(ctx->list_pool); if ((ctx->flags & MAILBOX_LIST_NO_FLAGS) == 0) ctx->list.flags = maildir_get_marked_flags(path); ctx->list.name = p_strconcat(ctx->list_pool, - ctx->prefix, fname+1, NULL); + ctx->prefix, fname, NULL); return &ctx->list; }
--- a/src/lib-storage/index/mbox/mbox-list.c Thu Feb 20 18:40:16 2003 +0200 +++ b/src/lib-storage/index/mbox/mbox-list.c Thu Feb 20 18:41:16 2003 +0200 @@ -291,7 +291,7 @@ if (match == IMAP_MATCH_PARENT) { /* placeholder */ - ctx->list.flags = MAILBOX_NOSELECT; + ctx->list.flags = MAILBOX_PLACEHOLDER; while ((p = strrchr(name, '/')) != NULL) { name = t_strdup_until(name, p); if (imap_match(ctx->glob, name) > 0) {
--- a/src/lib-storage/mail-storage.c Thu Feb 20 18:40:16 2003 +0200 +++ b/src/lib-storage/mail-storage.c Thu Feb 20 18:41:16 2003 +0200 @@ -23,7 +23,6 @@ struct client_workaround_list client_workaround_list[] = { { "oe6-fetch-no-newmail", WORKAROUND_OE6_FETCH_NO_NEWMAIL }, - { "list-sort", WORKAROUND_LIST_SORT }, { "outlook-idle", WORKAROUND_OUTLOOK_IDLE }, { NULL, 0 } };
--- a/src/lib-storage/mail-storage.h Thu Feb 20 18:40:16 2003 +0200 +++ b/src/lib-storage/mail-storage.h Thu Feb 20 18:41:16 2003 +0200 @@ -17,6 +17,7 @@ MAILBOX_NOINFERIORS = 0x08, MAILBOX_MARKED = 0x10, MAILBOX_UNMARKED = 0x20, + MAILBOX_PLACEHOLDER = 0x40, MAILBOX_READONLY = 0x40 }; @@ -92,8 +93,7 @@ enum client_workarounds { WORKAROUND_OE6_FETCH_NO_NEWMAIL = 0x01, - WORKAROUND_LIST_SORT = 0x02, - WORKAROUND_OUTLOOK_IDLE = 0x04 + WORKAROUND_OUTLOOK_IDLE = 0x02 }; struct mail_full_flags {