cmd-sort.c revision def516ea503a60f20d510c14d5070b7ff5bbddf4
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (C) 2002 Timo Sirainen */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "common.h"
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen#include "buffer.h"
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen#include "commands.h"
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen#include "mail-search.h"
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen#include "mail-sort.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c2cda8cd0043443566efc5da30f79865508a1947Timo Sirainentypedef struct {
c2cda8cd0043443566efc5da30f79865508a1947Timo Sirainen MailSortType type;
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen const char *name;
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen} SortName;
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainenstatic SortName sort_names[] = {
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen { MAIL_SORT_ARRIVAL, "arrival" },
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen { MAIL_SORT_CC, "cc" },
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen { MAIL_SORT_DATE, "date" },
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen { MAIL_SORT_FROM, "from" },
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen { MAIL_SORT_SIZE, "size" },
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen { MAIL_SORT_SUBJECT, "subject" },
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen { MAIL_SORT_TO, "to" },
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen { MAIL_SORT_REVERSE, "reverse" },
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen { MAIL_SORT_END, NULL }
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen};
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainenstatic MailSortType *get_sort_program(Client *client, ImapArg *args)
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen{
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen MailSortType type;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen Buffer *buf;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen int i;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen buf = buffer_create_dynamic(data_stack_pool, 32 * sizeof(MailSortType),
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen (size_t)-1);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen while (args->type == IMAP_ARG_ATOM || args->type == IMAP_ARG_STRING) {
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen const char *arg = args->data.str;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen for (i = 0; sort_names[i].type != MAIL_SORT_END; i++) {
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen if (strcasecmp(arg, sort_names[i].name) == 0)
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen break;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen if (sort_names[i].type == MAIL_SORT_END) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client_send_command_error(client, t_strconcat(
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Unknown sort argument: ", arg, NULL));
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return NULL;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen buffer_append(buf, &sort_names[i].type, sizeof(MailSortType));
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen args++;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen type = MAIL_SORT_END;
5a1b498b646b5c5dbd1b3f3861df766f560578c5Timo Sirainen buffer_append(buf, &type, sizeof(type));
5a1b498b646b5c5dbd1b3f3861df766f560578c5Timo Sirainen
5a1b498b646b5c5dbd1b3f3861df766f560578c5Timo Sirainen if (args->type != IMAP_ARG_EOL) {
5a1b498b646b5c5dbd1b3f3861df766f560578c5Timo Sirainen client_send_command_error(client,
5a1b498b646b5c5dbd1b3f3861df766f560578c5Timo Sirainen "Invalid sort list argument.");
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return NULL;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen return buffer_free_without_data(buf);
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen}
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainenint cmd_sort(Client *client)
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen{
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen MailSearchArg *sargs;
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen MailSortType *sorting;
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen ImapArg *args;
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen int args_count;
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen Pool pool;
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen const char *error, *charset;
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen args_count = imap_parser_read_args(client->parser, 0, 0, &args);
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen if (args_count == -2)
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen return FALSE;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (args_count < 3) {
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen client_send_command_error(client,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Missing or invalid arguments.");
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return TRUE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen if (!client_verify_open_mailbox(client))
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen return TRUE;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen /* sort program */
46ce4d9273e6df12ef1912bbdb1c8b84b104f394Timo Sirainen if (args->type != IMAP_ARG_LIST) {
46ce4d9273e6df12ef1912bbdb1c8b84b104f394Timo Sirainen client_send_command_error(client, "Invalid sort argument.");
46ce4d9273e6df12ef1912bbdb1c8b84b104f394Timo Sirainen return TRUE;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen }
46ce4d9273e6df12ef1912bbdb1c8b84b104f394Timo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen sorting = get_sort_program(client, args->data.list->args);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen if (sorting == NULL)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen return TRUE;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen args++;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen /* charset */
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen if (args->type != IMAP_ARG_ATOM && args->type != IMAP_ARG_STRING) {
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen client_send_command_error(client,
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen "Invalid charset argument.");
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen }
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen charset = args->data.str;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen args++;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen pool = pool_create("MailSortArgs", 2048, FALSE);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen sargs = mail_search_args_build(pool, args, &error);
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen if (sargs == NULL) {
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen /* error in search arguments */
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen client_send_tagline(client, t_strconcat("NO ", error, NULL));
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen } else {
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen if (client->mailbox->search(client->mailbox, charset,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen sargs, sorting,
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen client->output, client->cmd_uid)) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* NOTE: syncing is allowed when returning UIDs */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (client->cmd_uid)
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen client_sync_full(client);
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen else
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen client_sync_without_expunges(client);
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen client_send_tagline(client, "OK Search completed.");
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen } else {
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen client_send_storage_error(client);
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen }
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen }
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen pool_unref(pool);
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainen return TRUE;
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainen}
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainen