view src/imap/cmd-sort.c @ 765:553f050c8313 HEAD

Added buffer API. Point is to hide all buffer writing behind this API which verifies that nothing overflows. Much better than doing the same checks all around the code, even if it is slightly slower. Buffer reading is still mostly done directly, that isn't such a big security risk and I can't think of a reasonable API for it anyway.
author Timo Sirainen <tss@iki.fi>
date Sun, 08 Dec 2002 07:23:07 +0200
parents f57c52738f90
children 8b3518bb327e
line wrap: on
line source

/* Copyright (C) 2002 Timo Sirainen */

#include "common.h"
#include "buffer.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 type;
	Buffer *buf;
	int i;

	buf = buffer_create_dynamic(data_stack_pool, 32 * sizeof(MailSortType),
				    (size_t)-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;
		}

		buffer_append(buf, &sort_names[i].type, sizeof(MailSortType));
		args++;
	}

	type = MAIL_SORT_END;
	buffer_append(buf, &type, sizeof(type));

	if (args->type != IMAP_ARG_EOL) {
		client_send_command_error(client,
					  "Invalid sort list argument.");
		return NULL;
	}

	return buffer_free_without_data(buf);
}

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->output, 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;
}