diff src/imap/cmd-append.c @ 0:3b1985cbc908 HEAD

Initial revision
author Timo Sirainen <tss@iki.fi>
date Fri, 09 Aug 2002 12:15:38 +0300
parents
children 97d0b9fcc18a
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/imap/cmd-append.c	Fri Aug 09 12:15:38 2002 +0300
@@ -0,0 +1,132 @@
+/* Copyright (C) 2002 Timo Sirainen */
+
+#include "common.h"
+#include "commands.h"
+#include "imap-parser.h"
+#include "rfc822-date.h"
+
+/* Returns -1 = error, 0 = need more data, 1 = successful. flags and
+   internal_date may be NULL as a result, but mailbox and msg_size are always
+   set when successful. */
+static int validate_args(Client *client, const char **mailbox,
+			 ImapArgList **flags, const char **internal_date,
+			 unsigned int *msg_size, unsigned int count)
+{
+	ImapArg *args;
+	int ret;
+
+	i_assert(count >= 2 && count <= 4);
+
+	*flags = NULL;
+	*internal_date = NULL;
+
+	ret = client_read_args(client, count, IMAP_PARSE_FLAG_LITERAL_SIZE,
+			       &args);
+	i_assert((unsigned int) ret == count);
+
+	switch (count) {
+	case 2:
+		/* do we have flags or internal date parameter? */
+		if (args[1].type == IMAP_ARG_LIST ||
+		    args[1].type == IMAP_ARG_STRING)
+			return validate_args(client, mailbox, flags,
+					     internal_date, msg_size, 3);
+
+		break;
+	case 3:
+		/* do we have both flags and internal date? */
+		if (args[1].type == IMAP_ARG_LIST &&
+		    args[2].type == IMAP_ARG_STRING)
+			return validate_args(client, mailbox, flags,
+					     internal_date, msg_size, 4);
+
+		if (args[1].type == IMAP_ARG_LIST)
+			*flags = args[1].data.list;
+		else if (args[1].type == IMAP_ARG_STRING)
+			*internal_date = args[1].data.str;
+		else
+			return -1;
+		break;
+	case 4:
+		/* we have all parameters */
+		*flags = args[1].data.list;
+		*internal_date = args[2].data.str;
+		break;
+	default:
+		i_assert(0);
+	}
+
+	/* check that mailbox and message arguments are ok */
+	*mailbox = imap_arg_string(&args[0]);
+	if (*mailbox == NULL)
+		return -1;
+
+	if (args[ret-1].type != IMAP_ARG_LITERAL_SIZE)
+		return -1;
+
+	*msg_size = args[ret-1].data.literal_size;
+	return 1;
+}
+
+int cmd_append(Client *client)
+{
+	ImapArgList *flags_list;
+	Mailbox *box;
+	MailFlags flags;
+	time_t internal_date;
+	const char *custom_flags[MAIL_CUSTOM_FLAGS_COUNT];
+	const char *mailbox, *internal_date_str;
+	unsigned int msg_size;
+	int failed;
+
+	/* <mailbox> [<flags>] [<internal date>] <message literal> */
+	switch (validate_args(client, &mailbox, &flags_list,
+			      &internal_date_str, &msg_size, 2)) {
+	case -1:
+		/* error */
+		client_send_command_error(client, "Invalid APPEND arguments.");
+		return TRUE;
+	case 0:
+		/* need more data */
+		return FALSE;
+	default:
+	}
+
+	if (!client_parse_mail_flags(client, flags_list, &flags, custom_flags))
+		return TRUE;
+
+	if (!rfc822_parse_date(internal_date_str, &internal_date)) {
+		client_send_tagline(client, "BAD Invalid internal date.");
+		return TRUE;
+	}
+
+	if (client->mailbox != NULL &&
+	    strcmp(client->mailbox->name, mailbox) == 0) {
+		/* this mailbox is selected */
+		box = client->mailbox;
+	} else {
+		/* open the mailbox */
+		if (!client_verify_mailbox_name(client, mailbox, TRUE))
+			return TRUE;
+
+		box = client->storage->open_mailbox(client->storage,
+						    mailbox, FALSE);
+		if (box == NULL) {
+			client_send_storage_error(client);
+			return TRUE;
+		}
+	}
+
+	/* save the mail */
+	failed = !box->save(box, flags, custom_flags, internal_date,
+			    client->inbuf, msg_size);
+	if (box != client->mailbox)
+		box->close(box);
+
+	if (failed)
+		return FALSE;
+
+	client_sync_mailbox(client);
+	client_send_tagline(client, "OK Append completed.");
+	return TRUE;
+}