[dovecot-cvs] dovecot/src/imap cmd-list.c,1.16,1.17 commands.h,1.10,1.11
cras at procontrol.fi
cras at procontrol.fi
Mon Feb 24 19:39:34 EET 2003
Update of /home/cvs/dovecot/src/imap
In directory danu:/tmp/cvs-serv5915/src/imap
Modified Files:
cmd-list.c commands.h
Log Message:
Added support for CHILDREN and LISTEXT extensions.
Index: cmd-list.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-list.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- cmd-list.c 20 Feb 2003 16:41:16 -0000 1.16
+++ cmd-list.c 24 Feb 2003 17:39:32 -0000 1.17
@@ -19,14 +19,36 @@
struct mail_storage *storage;
};
-static const char *mailbox_flags2str(enum mailbox_flags flags)
+struct list_send_context {
+ struct client *client;
+ const char *response_name;
+ const char *sep;
+ struct imap_match_glob *glob;
+ int listext;
+};
+
+static const char *mailbox_flags2str(enum mailbox_flags flags, int listext)
{
const char *str;
- if (flags == MAILBOX_PLACEHOLDER)
- flags = MAILBOX_NOSELECT;
+ if (flags & MAILBOX_PLACEHOLDER) {
+ if (flags == MAILBOX_PLACEHOLDER) {
+ if (!listext)
+ flags = MAILBOX_NOSELECT;
+ } else {
+ /* it was at one point, but then we got better specs */
+ flags &= ~MAILBOX_PLACEHOLDER;
+ }
+ flags |= MAILBOX_CHILDREN;
+ }
+ if ((flags & MAILBOX_NONEXISTENT) != 0 && !listext)
+ flags |= MAILBOX_NOSELECT;
str = t_strconcat((flags & MAILBOX_NOSELECT) ? " \\Noselect" : "",
+ (flags & MAILBOX_NONEXISTENT) ? " \\NonExistent" : "",
+ (flags & MAILBOX_PLACEHOLDER) ? " \\PlaceHolder" : "",
+ (flags & MAILBOX_CHILDREN) ? " \\Children" : "",
+ (flags & MAILBOX_NOCHILDREN) ? " \\NoChildren" : "",
(flags & MAILBOX_NOINFERIORS) ? " \\NoInferiors" : "",
(flags & MAILBOX_MARKED) ? " \\Marked" : "",
(flags & MAILBOX_UNMARKED) ? " \\UnMarked" : "",
@@ -35,8 +57,9 @@
return *str == '\0' ? "" : str+1;
}
-static struct list_node *list_node_get(pool_t pool, struct list_node **node,
- const char *path, char separator)
+static void list_node_update(pool_t pool, struct list_node **node,
+ const char *path, char separator,
+ enum mailbox_flags flags)
{
const char *name, *parent;
@@ -64,7 +87,11 @@
/* not found, create it */
*node = p_new(pool, struct list_node, 1);
(*node)->name = p_strdup(pool, name);
- (*node)->flags = MAILBOX_PLACEHOLDER;
+ (*node)->flags = *path == '\0' ?
+ flags : MAILBOX_PLACEHOLDER;
+ } else {
+ if (*path == '\0')
+ (*node)->flags |= flags;
}
t_pop();
@@ -76,15 +103,12 @@
parent = (*node)->name;
node = &(*node)->children;
}
-
- return *node;
}
-static void list_send(struct client *client, struct list_node *node,
- const char *cmd, const char *path, const char *sep,
- struct imap_match_glob *glob)
+static void list_send(struct list_send_context *ctx, struct list_node *node,
+ const char *path)
{
- const char *name, *send_name, *str;
+ const char *name, *send_name, *str, *flagstr;
enum imap_match_result match;
for (; node != NULL; node = node->next) {
@@ -92,7 +116,7 @@
/* Send INBOX always uppercased */
if (path != NULL)
- name = t_strconcat(path, sep, node->name, NULL);
+ name = t_strconcat(path, ctx->sep, node->name, NULL);
else if (strcasecmp(node->name, "INBOX") == 0)
name = "INBOX";
else
@@ -106,24 +130,25 @@
const char *buf;
buf = str_unescape(t_strdup_noconst(name));
- match = imap_match(glob, buf);
+ match = imap_match(ctx->glob, buf);
if (match == IMAP_MATCH_CHILDREN) {
- send_name = t_strconcat(name, sep, NULL);
+ send_name = t_strconcat(name, ctx->sep, NULL);
buf = str_unescape(t_strdup_noconst(send_name));
- match = imap_match(glob, buf);
+ match = imap_match(ctx->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);
+ flagstr = mailbox_flags2str(node->flags, ctx->listext);
+ str = t_strdup_printf("* %s (%s) \"%s\" \"%s\"",
+ ctx->response_name, flagstr,
+ ctx->sep, send_name);
+ client_send_line(ctx->client, str);
}
if (node->children != NULL)
- list_send(client, node->children, cmd, name, sep, glob);
+ list_send(ctx, node->children, name);
t_pop();
}
@@ -131,32 +156,38 @@
static void list_and_sort(struct client *client,
struct mailbox_list_context *ctx,
- const char *cmd, const char *sep, const char *mask)
+ const char *response_name,
+ const char *sep, const char *mask, int listext)
{
struct mailbox_list *list;
- struct list_node *nodes, *node;
- struct imap_match_glob *glob;
+ struct list_node *nodes;
+ struct list_send_context send_ctx;
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;
+ list_node_update(pool, &nodes, list->name,
+ client->storage->hierarchy_sep,
+ 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);
+ send_ctx.client = client;
+ send_ctx.response_name = response_name;
+ send_ctx.sep = sep;
+ send_ctx.glob = imap_match_init(data_stack_pool, mask, TRUE,
+ client->storage->hierarchy_sep);
+ send_ctx.listext = listext;
+
+ list_send(&send_ctx, nodes, NULL);
+ imap_match_deinit(send_ctx.glob);
pool_unref(pool);
}
static void list_unsorted(struct client *client,
struct mailbox_list_context *ctx,
- const char *cmd, const char *sep)
+ const char *reply, const char *sep, int listext)
{
struct mailbox_list *list;
const char *name, *str;
@@ -167,42 +198,50 @@
name = "INBOX";
else
name = str_escape(list->name);
- str = t_strdup_printf("* %s (%s) \"%s\" \"%s\"", cmd,
- mailbox_flags2str(list->flags),
+ str = t_strdup_printf("* %s (%s) \"%s\" \"%s\"", reply,
+ mailbox_flags2str(list->flags, listext),
sep, name);
client_send_line(client, str);
t_pop();
}
}
-static int list_mailboxes(struct client *client, const char *mask,
- int subscribed, const char *sep)
+static int parse_list_flags(struct client *client, struct imap_arg *args,
+ enum mailbox_list_flags *list_flags)
{
- struct mailbox_list_context *ctx;
- const char *cmd;
- int sorted;
+ const char *atom;
- ctx = client->storage->
- list_mailbox_init(client->storage, mask,
- subscribed ? MAILBOX_LIST_SUBSCRIBED : 0,
- &sorted);
- if (ctx == NULL)
- return FALSE;
+ while (args->type != IMAP_ARG_EOL) {
+ if (args->type != IMAP_ARG_ATOM) {
+ client_send_command_error(client,
+ "List options contains non-atoms.");
+ return FALSE;
+ }
- cmd = subscribed ? "LSUB" : "LIST";
- if (sorted)
- list_unsorted(client, ctx, cmd, sep);
- else
- list_and_sort(client, ctx, cmd, sep, mask);
+ atom = IMAP_ARG_STR(args);
- return client->storage->list_mailbox_deinit(ctx);
+ if (strcasecmp(atom, "SUBSCRIBED") == 0)
+ *list_flags |= MAILBOX_LIST_SUBSCRIBED;
+ else if (strcasecmp(atom, "CHILDREN") == 0)
+ *list_flags |= MAILBOX_LIST_CHILDREN;
+ else {
+ client_send_tagline(client, t_strconcat(
+ "BAD Invalid list option ", atom, NULL));
+ return FALSE;
+ }
+ args++;
+ }
+ return TRUE;
}
-int _cmd_list_full(struct client *client, int subscribed)
+int _cmd_list_full(struct client *client, int lsub)
{
+ struct imap_arg *args;
+ enum mailbox_list_flags list_flags;
+ struct mailbox_list_context *ctx;
const char *ref, *mask;
char sep_chr, sep[3];
- int failed;
+ int failed, sorted, listext;
sep_chr = client->storage->hierarchy_sep;
if (IS_ESCAPED_CHAR(sep_chr)) {
@@ -214,11 +253,34 @@
sep[1] = '\0';
}
- /* <reference> <mailbox wildcards> */
- if (!client_read_string_args(client, 2, &ref, &mask))
+ /* [(<options>)] <reference> <mailbox wildcards> */
+ if (!client_read_args(client, 0, 0, &args))
return FALSE;
- if (*mask == '\0' && !subscribed) {
+ listext = FALSE;
+ if (lsub)
+ list_flags = MAILBOX_LIST_SUBSCRIBED | MAILBOX_LIST_FAST_FLAGS;
+ else {
+ list_flags = 0;
+ if (args[0].type == IMAP_ARG_LIST) {
+ listext = TRUE;
+ if (!parse_list_flags(client,
+ IMAP_ARG_LIST(&args[0])->args,
+ &list_flags))
+ return TRUE;
+ args++;
+ }
+ }
+
+ ref = imap_arg_string(&args[0]);
+ mask = imap_arg_string(&args[1]);
+
+ if (ref == NULL || mask == NULL) {
+ client_send_command_error(client, "Invalid FETCH arguments.");
+ return TRUE;
+ }
+
+ if (*mask == '\0' && !lsub) {
/* special request to return the hierarchy delimiter */
client_send_line(client, t_strconcat(
"* LIST (\\Noselect) \"", sep, "\" \"\"", NULL));
@@ -240,13 +302,29 @@
}
}
- failed = !list_mailboxes(client, mask, subscribed, sep);
+ ctx = client->storage->list_mailbox_init(client->storage, mask,
+ list_flags, &sorted);
+ if (ctx == NULL)
+ failed = TRUE;
+ else {
+ const char *response_name = lsub ? "LSUB" : "LIST";
+
+ if (sorted) {
+ list_unsorted(client, ctx, response_name, sep,
+ listext);
+ } else {
+ list_and_sort(client, ctx, response_name, sep,
+ mask, listext);
+ }
+
+ failed = !client->storage->list_mailbox_deinit(ctx);
+ }
}
if (failed)
client_send_storage_error(client);
else {
- client_send_tagline(client, subscribed ?
+ client_send_tagline(client, lsub ?
"OK Lsub completed." :
"OK List completed.");
}
Index: commands.h
===================================================================
RCS file: /home/cvs/dovecot/src/imap/commands.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- commands.h 14 Feb 2003 10:46:44 -0000 1.10
+++ commands.h 24 Feb 2003 17:39:32 -0000 1.11
@@ -47,7 +47,7 @@
int cmd_idle(struct client *client);
/* private: */
-int _cmd_list_full(struct client *client, int subscribed);
+int _cmd_list_full(struct client *client, int lsub);
int _cmd_select_full(struct client *client, int readonly);
int _cmd_subscribe_full(struct client *client, int subscribe);
More information about the dovecot-cvs
mailing list