Mercurial > dovecot > original-hg > dovecot-1.2
diff src/imap/cmd-sort.c @ 761:d3bd41a56309 HEAD
First implementation of SORT extension. String comparing still not up to
spec, so we don't advertise it in capability string yet. The code supports
getting the data partially pre-sorted to reduce memory usage and make it
faster. So, in future we could use this by creating sorted binary trees.
Also moved mail-storage-register.c into it's own .a lib to fix circular
dependencies.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 04 Dec 2002 20:28:37 +0200 |
parents | |
children | f57c52738f90 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/imap/cmd-sort.c Wed Dec 04 20:28:37 2002 +0200 @@ -0,0 +1,137 @@ +/* Copyright (C) 2002 Timo Sirainen */ + +#include "common.h" +#include "commands.h" +#include "mail-search.h" +#include "mail-sort.h" + +typedef struct { + MailSortType type; + const char *name; +} SortName; + +static SortName sort_names[] = { + { MAIL_SORT_ARRIVAL, "arrival" }, + { MAIL_SORT_CC, "cc" }, + { MAIL_SORT_DATE, "date" }, + { MAIL_SORT_FROM, "from" }, + { MAIL_SORT_SIZE, "size" }, + { MAIL_SORT_SUBJECT, "subject" }, + { MAIL_SORT_TO, "to" }, + + { MAIL_SORT_REVERSE, "reverse" }, + { MAIL_SORT_END, NULL } +}; + +static MailSortType *get_sort_program(Client *client, ImapArg *args) +{ + MailSortType *program, *temp_prog; + size_t program_alloc, program_size; + int i; + + program_alloc = 32; program_size = 0; + program = t_new(MailSortType, program_alloc+1); + + while (args->type == IMAP_ARG_ATOM || args->type == IMAP_ARG_STRING) { + const char *arg = args->data.str; + + for (i = 0; sort_names[i].type != MAIL_SORT_END; i++) { + if (strcasecmp(arg, sort_names[i].name) == 0) + break; + } + + if (sort_names[i].type == MAIL_SORT_END) { + client_send_command_error(client, t_strconcat( + "Unknown sort argument: ", arg, NULL)); + return NULL; + } + + if (program_size == program_alloc) { + program_alloc *= 2; + if (!t_try_realloc(program, program_alloc+1)) { + temp_prog = t_new(MailSortType, program_alloc); + memcpy(temp_prog, program, + sizeof(MailSortType) * program_size); + program = temp_prog; + } + } + program[program_size++] = sort_names[i].type; + args++; + } + + program[program_size] = MAIL_SORT_END; + + if (args->type != IMAP_ARG_EOL) { + client_send_command_error(client, + "Invalid sort list argument."); + return NULL; + } + + return program; +} + +int cmd_sort(Client *client) +{ + MailSearchArg *sargs; + MailSortType *sorting; + ImapArg *args; + int args_count; + Pool pool; + const char *error, *charset; + + args_count = imap_parser_read_args(client->parser, 0, 0, &args); + if (args_count == -2) + return FALSE; + + if (args_count < 3) { + client_send_command_error(client, + "Missing or invalid arguments."); + return TRUE; + } + + if (!client_verify_open_mailbox(client)) + return TRUE; + + /* sort program */ + if (args->type != IMAP_ARG_LIST) { + client_send_command_error(client, "Invalid sort argument."); + return TRUE; + } + + sorting = get_sort_program(client, args->data.list->args); + if (sorting == NULL) + return TRUE; + args++; + + /* charset */ + if (args->type != IMAP_ARG_ATOM && args->type != IMAP_ARG_STRING) { + client_send_command_error(client, + "Invalid charset argument."); + } + charset = args->data.str; + args++; + + pool = pool_create("MailSortArgs", 2048, FALSE); + + sargs = mail_search_args_build(pool, args, &error); + if (sargs == NULL) { + /* error in search arguments */ + client_send_tagline(client, t_strconcat("NO ", error, NULL)); + } else { + if (client->mailbox->search(client->mailbox, charset, + sargs, sorting, + client->outbuf, client->cmd_uid)) { + /* NOTE: syncing is allowed when returning UIDs */ + if (client->cmd_uid) + client_sync_full(client); + else + client_sync_without_expunges(client); + client_send_tagline(client, "OK Search completed."); + } else { + client_send_storage_error(client); + } + } + + pool_unref(pool); + return TRUE; +}