<commit_before>/* Copyright (C) 2002 <NAME> */

#include "common.h"
#include "ioloop.h"
#include "istream.h"
#include "ostream.h"
#include "commands.h"
#include "imap-parser.h"
#include "imap-date.h"
#include "mail-storage.h"

#include <sys/time.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(struct imap_arg *args, struct imap_arg_list **flags,
			 const char **internal_date, uoff_t *msg_size,
			 int *nonsync)
{
	/* [<flags>] */
	if (args->type != IMAP_ARG_LIST)
		*flags = NULL;
	else {
		*flags = IMAP_ARG_LIST(args);
		args++;
	}

	/* [<internal date>] */
	if (args->type != IMAP_ARG_STRING)
		*internal_date = NULL;
	else {
		*internal_date = IMAP_ARG_STR(args);
		args++;
	}

	if (args->type != IMAP_ARG_LITERAL_SIZE &&
	    args->type != IMAP_ARG_LITERAL_SIZE_NONSYNC)
		return FALSE;

	*nonsync = args->type == IMAP_ARG_LITERAL_SIZE_NONSYNC;
	*msg_size = IMAP_ARG_LITERAL_SIZE(args);
	return TRUE;
}

int cmd_append(struct client *client)
{
	struct mail_storage *storage;
	struct mailbox *box;
	struct mailbox_status status;
	struct mail_save_context *ctx;
	struct imap_parser *save_parser;
	struct imap_arg *args;
	struct imap_arg_list *flags_list;
        struct mailbox_custom_flags old_flags;
	struct mail_full_flags flags;
	time_t internal_date;
	const char *mailbox, *internal_date_str, *error;
	uoff_t msg_size;
	unsigned int count;
	int ret, failed, timezone_offset, nonsync, fatal_error;

	/* <mailbox> */
	if (!client_read_string_args(client, 1, &mailbox))
		return FALSE;

	if (!client_verify_mailbox_name(client, mailbox, TRUE, FALSE))
		return TRUE;

	storage = client_find_storage(client, mailbox);
	if (storage == NULL)
		return TRUE;

	box = storage->open_mailbox(storage, mailbox,
				    mailbox_open_flags | MAILBOX_OPEN_FAST);
	if (box == NULL) {
		client_send_storage_error(client, storage);
		return TRUE;
	}

	if (!box->get_status(box, STATUS_CUSTOM_FLAGS, &status)) {
		client_send_storage_error(client, storage);
		box->close(box);
		return TRUE;
	}
	memset(&old_flags, 0, sizeof(old_flags));
        old_flags.pool = pool_datastack_create();
	client_save_custom_flags(&old_flags, status.custom_flags,
				 status.custom_flags_count);

	ctx = box->save_init(box, TRUE);
	if (ctx == NULL) {
		client_send_storage_error(client, storage);
		return TRUE;
	}

	/* if error occurs, the CRLF is already read. */
	client->input_skip_line = FALSE;

	count = 0;
	failed = TRUE;
	save_parser = imap_parser_create(client->input, client->output,
					 imap_max_line_length);

	for (;;) {
		/* [<flags>] [<internal date>] <message literal> */
		imap_parser_reset(save_parser);
		for (;;) {
			ret = imap_parser_read_args(save_parser, 0,
						   IMAP_PARSE_FLAG_LITERAL_SIZE,
						   &args);
			if (ret >= 0)
				break;
			if (ret == -1) {
				error = imap_parser_get_error(save_parser,
							      &fatal_error);
				if (fatal_error) {
					client_disconnect_with_error(client,
								     error);
				} else {
					client_send_command_error(client,
								  error);
				}
				break;
			}

			/* need more data */
			ret = i_stream_read(client->input);
			if (ret == -2) {
				client_send_command_error(client,
							  "Too long argument.");
				break;
			}
			if (ret < 0) {
				/* disconnected */
				client->cmd_error = TRUE;
				break;
			}
		}

		if (client->cmd_error)
			break;

		if (args->type == IMAP_ARG_EOL) {
			/* last one */
			if (count > 0)
				failed = FALSE;
			client->input_skip_line = TRUE;
			break;
		}

		if (!validate_args(args, &flags_list, &internal_date_str,
				   &msg_size, &nonsync)) {
			/* error */<commit_msg>cleanup<commit_after>/* Copyright (C) 2002 <NAME> */

#include "common.h"
#include "ioloop.h"
#include "istream.h"
#include "ostream.h"
#include "commands.h"
#include "imap-parser.h"
#include "imap-date.h"
#include "mail-storage.h"

#include <sys/time.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(struct imap_arg *args, struct imap_arg_list **flags,
			 const char **internal_date, uoff_t *msg_size,
			 int *nonsync)
{
	/* [<flags>] */
	if (args->type != IMAP_ARG_LIST)
		*flags = NULL;
	else {
		*flags = IMAP_ARG_LIST(args);
		args++;
	}

	/* [<internal date>] */
	if (args->type != IMAP_ARG_STRING)
		*internal_date = NULL;
	else {
		*internal_date = IMAP_ARG_STR(args);
		args++;
	}

	if (args->type != IMAP_ARG_LITERAL_SIZE &&
	    args->type != IMAP_ARG_LITERAL_SIZE_NONSYNC)
		return FALSE;

	*nonsync = args->type == IMAP_ARG_LITERAL_SIZE_NONSYNC;
	*msg_size = IMAP_ARG_LITERAL_SIZE(args);
	return TRUE;
}

int cmd_append(struct client *client)
{
	struct mail_storage *storage;
	struct mailbox *box;
	struct mailbox_status status;
	struct mail_save_context *ctx;
	struct imap_parser *save_parser;
	struct imap_arg *args;
	struct imap_arg_list *flags_list;
        struct mailbox_custom_flags old_flags;
	struct mail_full_flags flags;
	time_t internal_date;
	const char *mailbox, *internal_date_str;
	uoff_t msg_size;
	unsigned int count;
	int ret, failed, timezone_offset, nonsync;

	/* <mailbox> */
	if (!client_read_string_args(client, 1, &mailbox))
		return FALSE;

	if (!client_verify_mailbox_name(client, mailbox, TRUE, FALSE))
		return TRUE;

	storage = client_find_storage(client, mailbox);
	if (storage == NULL)
		return TRUE;

	box = storage->open_mailbox(storage, mailbox,
				    mailbox_open_flags | MAILBOX_OPEN_FAST);
	if (box == NULL) {
		client_send_storage_error(client, storage);
		return TRUE;
	}

	if (!box->get_status(box, STATUS_CUSTOM_FLAGS, &status)) {
		client_send_storage_error(client, storage);
		box->close(box);
		return TRUE;
	}
	memset(&old_flags, 0, sizeof(old_flags));
        old_flags.pool = pool_datastack_create();
	client_save_custom_flags(&old_flags, status.custom_flags,
				 status.custom_flags_count);

	ctx = box->save_init(box, TRUE);
	if (ctx == NULL) {
		client_send_storage_error(client, storage);
		return TRUE;
	}

	/* if error occurs, the CRLF is already read. */
	client->input_skip_line = FALSE;

	count = 0;
	failed = TRUE;
	save_parser = imap_parser_create(client->input, client->output,
					 imap_max_line_length);

	for (;;) {
		/* [<flags>] [<internal date>] <message literal> */
		imap_parser_reset(save_parser);
		for (;;) {
			ret = imap_parser_read_args(save_parser, 0,
						   IMAP_PARSE_FLAG_LITERAL_SIZE,
						   &args);
			if (ret >= 0)
				break;
			if (ret == -1) {
				client_send_command_error(client, NULL);
				break;
			}

			/* need more data */
			ret = i_stream_read(client->input);
			if (ret == -2) {
				client_send_command_error(client,
							  "Too long argument.");
				break;
			}
			if (ret < 0) {
				/* disconnected */
				client->cmd_error = TRUE;
				break;
			}
		}

		if (client->cmd_error)
			break;

		if (args->type == IMAP_ARG_EOL) {
			/* last one */
			if (count > 0)
				failed = FALSE;
			client->input_skip_line = TRUE;
			break;
		}

		if (!validate_args(args, &flags_list, &internal_date_str,
				   &msg_size, &nonsync)) {
			/* error */
{'fraction_non_alphanumeric': 0.1310954551733665, 'fraction_numerical': 0.004420500069070314, 'mean_word_length': 3.738219895287958, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3268356', 'n_tokens_mistral': 3020, 'n_tokens_neox': 2649, 'n_words': 594}