cmd-append.c revision c96eb61168670cfdd7596baba18856d3f086a093
/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
#include "common.h"
#include "ioloop.h"
#include "istream.h"
#include "ostream.h"
#include "str.h"
#include "commands.h"
#include "imap-parser.h"
#include "imap-date.h"
#include "mail-storage.h"
struct cmd_append_context {
struct client_command_context *cmd;
struct mail_storage *storage;
struct mailbox_transaction_context *t;
struct imap_parser *save_parser;
struct mail_save_context *save_ctx;
unsigned int count;
unsigned int message_input:1;
unsigned int failed:1;
};
{
bool finished;
case -1:
/* disconnected */
/* Reset command so that client_destroy() doesn't try to call
cmd_append_continue_message() anymore. */
return;
case -2:
if (ctx->message_input) {
/* message data, this is handled internally by
mailbox_save_continue() */
break;
}
/* parameter word is longer than max. input buffer size.
this is most likely an error, so skip the new data
until newline is found. */
return;
}
(void)client_handle_unfinished_cmd(cmd);
else
if (cmd_sync_delayed(client))
}
/* 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. */
bool *nonsync_r)
{
/* [<flags>] */
else {
args++;
}
/* [<internal date>] */
*internal_date_r = NULL;
else {
args++;
}
return FALSE;
}
return TRUE;
}
{
/* we must put back the original flush callback before beginning to
sync (the command is still unfinished at that point) */
}
{
return TRUE;
}
return TRUE;
}
/* finished, but with MULTIAPPEND and LITERAL+ we may get
more messages. */
return cmd_append_continue_parsing(cmd);
}
return FALSE;
}
{
if (!nonsync) {
return TRUE;
}
/* we have to read the nonsynced literal so we don't treat the message
data as commands. */
}
{
const struct imap_arg *flags_list;
enum mail_flags flags;
const char *const *keywords_list;
struct mail_keywords *keywords;
const char *internal_date_str;
int ret, timezone_offset;
bool nonsync;
return TRUE;
}
/* if error occurs, the CRLF is already read. */
/* [<flags>] [<internal date>] <message literal> */
return TRUE;
}
if (ret < 0) {
/* need more data */
return FALSE;
}
/* last message */
enum mailbox_sync_flags sync_flags;
enum imap_sync_flags imap_flags;
const char *msg;
/* eat away the trailing CRLF */
/* we failed earlier, error message is sent */
return TRUE;
}
if (ret < 0) {
return TRUE;
}
"Append completed.",
uid_validity, uid1);
} else {
"Append completed.",
}
sync_flags = 0;
} else {
imap_flags = 0;
}
}
}
/* we failed earlier, make sure we just eat nonsync-literal
if it's given. */
}
if (flags_list != NULL) {
&flags, &keywords_list))
if (keywords_list == NULL)
&keywords) < 0) {
}
} else {
flags = 0;
}
if (internal_date_str == NULL) {
/* no time given, default to now. */
timezone_offset = 0;
} else if (!imap_parse_datetime(internal_date_str,
&internal_date, &timezone_offset)) {
}
/* no message data, abort */
}
/* save the mail */
if (ret < 0) {
/* save initialization failed */
}
/* after literal comes CRLF, if we fail make sure we eat it away */
if (!nonsync) {
}
return cmd_append_continue_message(cmd);
}
{
int ret;
return TRUE;
}
/* we still have to finish reading the message
from client */
break;
}
break;
}
}
}
/* finished */
/* failed above */
} else if (!all_written) {
/* client disconnected before it finished sending the
whole message. */
}
return TRUE;
}
/* prepare for next message */
return cmd_append_continue_parsing(cmd);
}
return FALSE;
}
static struct mailbox *
{
struct mail_storage *storage;
return NULL;
return NULL;
return NULL;
}
return box;
}
{
struct cmd_append_context *ctx;
const char *mailbox;
/* if transaction is created while its view is synced,
appends aren't allowed for it. */
return FALSE;
}
/* <mailbox> */
return FALSE;
/* we keep the input locked all the time */
else {
}
/* append is special because we're only waiting on client input, not
client output, so disable the standard output handler until we're
finished */
return cmd_append_continue_parsing(cmd);
}