1
1
/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
5
6
#include "commands.h"
6
#include "imap-search.h"
7
#include "imap-thread.h"
7
#include "imap-search-args.h"
8
#include "mail-thread.h"
10
static int imap_thread_write(struct mail_thread_iterate_context *iter,
11
string_t *str, bool root)
13
const struct mail_thread_child_node *node;
14
struct mail_thread_iterate_context *child_iter;
18
count = mail_thread_iterate_count(iter);
22
if (count == 1 && !root) {
23
/* only one child - special case to avoid extra paranthesis */
24
node = mail_thread_iterate_next(iter, &child_iter);
25
str_printfa(str, "%u", node->uid);
26
if (child_iter != NULL) {
27
str_append_c(str, ' ');
29
ret = imap_thread_write(child_iter, str, FALSE);
31
if (mail_thread_iterate_deinit(&child_iter) < 0)
37
while ((node = mail_thread_iterate_next(iter, &child_iter)) != NULL) {
38
if (child_iter == NULL) {
40
str_printfa(str, "(%u)", node->uid);
42
/* node with children */
43
str_append_c(str, '(');
45
str_printfa(str, "%u ", node->uid);
47
ret = imap_thread_write(child_iter, str, FALSE);
49
if (mail_thread_iterate_deinit(&child_iter) < 0 ||
52
str_append_c(str, ')');
59
imap_thread_write_reply(struct mail_thread_context *ctx, string_t *str,
60
enum mail_thread_type thread_type, bool write_seqs)
62
struct mail_thread_iterate_context *iter;
65
iter = mail_thread_iterate_init(ctx, thread_type, write_seqs);
66
str_append(str, "* THREAD ");
68
ret = imap_thread_write(iter, str, TRUE);
70
if (mail_thread_iterate_deinit(&iter) < 0)
73
str_append(str, "\r\n");
77
static int imap_thread(struct client_command_context *cmd,
78
struct mail_search_args *search_args,
79
enum mail_thread_type thread_type)
81
struct mail_thread_context *ctx;
85
i_assert(thread_type == MAIL_THREAD_REFERENCES ||
86
thread_type == MAIL_THREAD_REFS);
88
str = str_new(default_pool, 1024);
89
ret = mail_thread_init(cmd->client->mailbox,
92
ret = imap_thread_write_reply(ctx, str, thread_type,
94
mail_thread_deinit(&ctx);
98
(void)o_stream_send(cmd->client->output,
99
str_data(str), str_len(str));
9
105
bool cmd_thread(struct client_command_context *cmd)
11
107
struct client *client = cmd->client;
12
enum mail_thread_type threading;
13
struct mail_search_arg *sargs;
108
enum mail_thread_type thread_type;
109
struct mail_search_args *sargs;
14
110
const struct imap_arg *args;
17
const char *error, *charset, *str;
111
const char *charset, *str;
19
args_count = imap_parser_read_args(cmd->parser, 0, 0, &args);
114
if (!client_read_args(cmd, 0, 0, &args))
22
client->input_lock = NULL;
25
client_send_command_error(cmd, args_count < 0 ? NULL :
26
"Missing or invalid arguments.");
30
117
if (!client_verify_open_mailbox(cmd))
53
134
if (args->type != IMAP_ARG_ATOM && args->type != IMAP_ARG_STRING) {
54
client_send_command_error(cmd,
55
"Invalid charset argument.");
135
client_send_command_error(cmd, "Invalid charset argument.");
58
138
charset = IMAP_ARG_STR(args);
61
pool = pool_alloconly_create("mail_search_args", 2048);
141
ret = imap_search_args_build(cmd, args, charset, &sargs);
63
sargs = imap_search_args_build(pool, client->mailbox, args, &error);
65
/* error in search arguments */
66
client_send_tagline(cmd, t_strconcat("BAD ", error, NULL));
67
} else if (imap_thread(cmd, charset, sargs, threading) == 0) {
69
return cmd_sync(cmd, MAILBOX_SYNC_FLAG_FAST |
70
(cmd->uid ? 0 : MAILBOX_SYNC_FLAG_NO_EXPUNGES),
71
0, "OK Thread completed.");
145
ret = imap_thread(cmd, sargs, thread_type);
146
mail_search_args_unref(&sargs);
73
148
client_send_storage_error(cmd,
74
149
mailbox_get_storage(client->mailbox));
153
return cmd_sync(cmd, MAILBOX_SYNC_FLAG_FAST |
154
(cmd->uid ? 0 : MAILBOX_SYNC_FLAG_NO_EXPUNGES),
155
0, "OK Thread completed.");