Mercurial > dovecot > original-hg > dovecot-1.2
view src/imap/cmd-list.c @ 296:d66aa1f1fb2d HEAD
Added fast-flag for mailbox opening, which doesn't do any index compressing
or cache updating. This flag is set when mailbox is opened by APPEND, COPY
or STATUS (ie. not SELECT/EXAMINE).
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 23 Sep 2002 13:42:20 +0300 |
parents | 6f837354f2fe |
children | cc795d74d08f |
line wrap: on
line source
/* Copyright (C) 2002 Timo Sirainen */ #include "common.h" #include "commands.h" #include "imap-match.h" typedef struct _ListNode ListNode; struct _ListNode { ListNode *next; ListNode *children; char *name; /* escaped */ MailboxFlags flags; }; typedef struct { Pool pool; ListNode *nodes; MailStorage *storage; } ListContext; static const char *mailbox_flags2str(MailboxFlags flags) { const char *str; str = t_strconcat((flags & MAILBOX_NOSELECT) ? " \\Noselect" : "", (flags & MAILBOX_NOINFERIORS) ? " \\NoInferiors" : "", (flags & MAILBOX_MARKED) ? " \\Marked" : "", (flags & MAILBOX_UNMARKED) ? " \\UnMarked" : "", NULL); return *str == '\0' ? "" : str+1; } static ListNode *list_node_get(Pool pool, ListNode **node, const char *path, char separator) { const char *name, *parent; parent = NULL; t_push(); for (name = path;; path++) { if (*path != separator && *path != '\0') continue; /* escaping is done here to make sure we don't try to escape the separator char */ name = imap_escape(t_strdup_until(name, path)); /* find the node */ while (*node != NULL) { if (strcmp((*node)->name, name) == 0) break; node = &(*node)->next; } if (*node == NULL) { /* not found, create it */ *node = p_new(pool, ListNode, 1); (*node)->name = p_strdup(pool, name); (*node)->flags = MAILBOX_NOSELECT; } if (*path == '\0') break; name = path+1; parent = (*node)->name; node = &(*node)->children; } t_pop(); return *node; } static void list_func(MailStorage *storage __attr_unused__, const char *name, MailboxFlags flags, void *context) { ListContext *ctx = context; ListNode *node; node = list_node_get(ctx->pool, &ctx->nodes, name, ctx->storage->hierarchy_sep); /* set the flags, this also nicely overrides the NOSELECT flag set by list_node_get() */ node->flags = flags; } static void list_send(Client *client, ListNode *node, const char *cmd, const char *path, const char *sep, const ImapMatchGlob *glob) { const char *name; for (; node != NULL; node = node->next) { t_push(); name = path == NULL ? node->name : t_strconcat(path, sep, node->name, NULL); if (node->children != NULL) list_send(client, node->children, cmd, name, sep, glob); if ((node->flags & MAILBOX_NOSELECT) && imap_match(glob, name, 0, NULL) < 0) { /* doesn't match the mask */ t_pop(); continue; } /* node->name should already be escaped */ client_send_line(client, t_strdup_printf("* %s (%s) \"%s\" \"%s\"", cmd, mailbox_flags2str(node->flags), sep, name)); t_pop(); } } int cmd_list_full(Client *client, int subscribed) { ListContext ctx; const char *ref, *pattern; char sep_chr, sep[3]; sep_chr = client->storage->hierarchy_sep; if (IS_ESCAPED_CHAR(sep_chr)) { sep[0] = '\\'; sep[1] = sep_chr; sep[2] = '\0'; } else { sep[0] = sep_chr; sep[1] = '\0'; } /* <reference> <mailbox wildcards> */ if (!client_read_string_args(client, 2, &ref, &pattern)) return FALSE; if (*pattern == '\0' && !subscribed) { /* special request to return the hierarchy delimiter */ client_send_line(client, t_strconcat( "* LIST (\\Noselect) \"", sep, "\" \"\"", NULL)); } else { if (*ref != '\0') { /* join reference + pattern */ if (*pattern == sep_chr && ref[strlen(ref)-1] == sep_chr) { /* LIST A. .B -> A.B */ pattern++; } pattern = t_strconcat(ref, pattern, NULL); } ctx.pool = pool_create("ListCtx", 10240, FALSE); ctx.nodes = NULL; ctx.storage = client->storage; if (!subscribed) { client->storage->find_mailboxes(client->storage, pattern, list_func, &ctx); } else { client->storage->find_subscribed(client->storage, pattern, list_func, &ctx); } list_send(client, ctx.nodes, subscribed ? "LSUB" : "LIST", NULL, sep, imap_match_init(pattern, TRUE, sep_chr)); pool_unref(ctx.pool); } client_send_tagline(client, subscribed ? "OK Lsub completed." : "OK List completed."); return TRUE; } int cmd_list(Client *client) { return cmd_list_full(client, FALSE); }