1
/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
3
/* Implementation of draft-ietf-imapext-sort-10 sorting algorithm.
4
Pretty messy code actually, adding any sort types requires care.
5
This is pretty fast however and takes only as much memory as needed to be
13
#include "imap-base-subject.h"
14
#include "mail-storage.h"
15
#include "message-address.h"
16
#include "imap-sort.h"
20
#define MAX_WANTED_HEADERS 10
21
#define STRBUF_SIZE 1024
23
#define IS_SORT_STRING(type) \
24
((type) == MAIL_SORT_CC || (type) == MAIL_SORT_FROM || \
25
(type) == MAIL_SORT_SUBJECT || (type) == MAIL_SORT_TO)
27
#define IS_SORT_TIME(type) \
28
((type) == MAIL_SORT_ARRIVAL || (type) == MAIL_SORT_DATE)
31
enum mail_sort_type sort_program[MAX_SORT_PROGRAM_SIZE];
34
struct ostream *output;
40
int imap_sort(struct client_command_context *cmd, const char *charset,
41
struct mail_search_arg *args,
42
const enum mail_sort_type *sort_program)
44
struct client *client = cmd->client;
45
const char *wanted_headers[2];
46
enum mail_fetch_field wanted_fields;
47
struct mail_search_context *search_ctx;
48
struct mailbox_transaction_context *t;
49
struct mailbox_header_lookup_ctx *headers_ctx;
56
wanted_headers[0] = wanted_headers[1] = NULL;
57
switch (*sort_program & MAIL_SORT_MASK) {
58
case MAIL_SORT_ARRIVAL:
59
wanted_fields = MAIL_FETCH_RECEIVED_DATE;
62
wanted_headers[0] = "Cc";
65
wanted_fields = MAIL_FETCH_DATE;
68
wanted_headers[0] = "From";
71
wanted_fields = MAIL_FETCH_VIRTUAL_SIZE;
73
case MAIL_SORT_SUBJECT:
74
wanted_headers[0] = "Subject";
77
wanted_headers[0] = "To";
81
headers_ctx = wanted_headers[0] == NULL ? NULL :
82
mailbox_header_lookup_init(client->mailbox, wanted_headers);
84
t = mailbox_transaction_begin(client->mailbox, 0);
85
search_ctx = mailbox_search_init(t, charset, args, sort_program);
87
str = t_str_new(STRBUF_SIZE);
88
str_append(str, "* SORT");
90
mail = mail_alloc(t, wanted_fields, headers_ctx);
91
while (mailbox_search_next(search_ctx, mail) > 0) {
92
if (str_len(str) >= STRBUF_SIZE-MAX_INT_STRLEN) {
93
o_stream_send(client->output, str_data(str),
98
str_printfa(str, " %u", cmd->uid ? mail->uid : mail->seq);
100
ret = mailbox_search_deinit(&search_ctx);
103
if (mailbox_transaction_commit(&t) < 0)
106
if (written || ret == 0) {
107
str_append(str, "\r\n");
108
o_stream_send(client->output, str_data(str), str_len(str));
111
if (headers_ctx != NULL)
112
mailbox_header_lookup_deinit(&headers_ctx);