<commit_before>/* Copyright (c) 2002-2012 Dovecot authors, see the included COPYING file */

#include "imap-common.h"
#include "ostream.h"
#include "imap-resp-code.h"
#include "imap-commands.h"
#include "imap-fetch.h"
#include "imap-search-args.h"
#include "mail-search.h"

#include <stdlib.h>

static const char *all_macro[] = {
	"FLAGS", "INTERNALDATE", "RFC822.SIZE", "ENVELOPE", NULL
};
static const char *fast_macro[] = {
	"FLAGS", "INTERNALDATE", "RFC822.SIZE", NULL
};
static const char *full_macro[] = {
	"FLAGS", "INTERNALDATE", "RFC822.SIZE", "ENVELOPE", "BODY", NULL
};

static bool
fetch_parse_args(struct imap_fetch_context *ctx,
		 struct client_command_context *cmd,
		 const struct imap_arg *arg, const struct imap_arg **next_arg_r)
{
	const char *str, *const *macro;

	if (cmd->uid) {
		if (!imap_fetch_cmd_init_handler(ctx, cmd, "UID", &arg))
			return FALSE;
	}
	if (imap_arg_get_atom(arg, &str)) {
		str = t_str_ucase(str);
		arg++;

		/* handle macros first */
		if (strcmp(str, "ALL") == 0)
			macro = all_macro;
		else if (strcmp(str, "FAST") == 0)
			macro = fast_macro;
		else if (strcmp(str, "FULL") == 0)
			macro = full_macro;
		else {
			macro = NULL;
			if (!imap_fetch_cmd_init_handler(ctx, cmd, str, &arg))
				return FALSE;
		}
		if (macro != NULL) {
			while (*macro != NULL) {
				if (!imap_fetch_cmd_init_handler(ctx, cmd, *macro, &arg))
					return FALSE;
				macro++;
			}
		}
		*next_arg_r = arg;
	} else {
		*next_arg_r = arg + 1;
		arg = imap_arg_as_list(arg);
		if (IMAP_ARG_IS_EOL(arg)) {
			client_send_command_error(cmd,
						  "FETCH list is empty.");
			return FALSE;
		}
		while (imap_arg_get_atom(arg, &str)) {
			str = t_str_ucase(str);
			arg++;
			if (!imap_fetch_cmd_init_handler(ctx, cmd, str, &arg))
				return FALSE;
		}
		if (!IMAP_ARG_IS_EOL(arg)) {
			client_send_command_error(cmd,
				"FETCH list contains non-atoms.");
			return FALSE;
		}
	}
	return TRUE;
}

static bool
fetch_parse_modifier(struct imap_fetch_context *ctx,
		     struct client_command_context *cmd,
		     const char *name, const struct imap_arg **args)
{
	const char *str;
	uint64_t modseq;

	if (strcmp(name, "CHANGEDSINCE") == 0) {
		if (!imap_arg_get_atom(*args, &str) ||
		    str_to_uint64(str, &modseq) < 0) {
			client_send_command_error(cmd,
				"Invalid CHANGEDSINCE modseq.");
			return FALSE;
		}
		*args += 1;
		imap_fetch_add_changed_since(ctx, modseq);
		return TRUE;
	}
	if (strcmp(name, "VANISHED") == 0 && cmd->uid) {
		if ((ctx->client->enabled_features &
		     MAILBOX_FEATURE_QRESYNC) == 0) {
			client_send_command_error(cmd, "QRESYNC not enabled");
			return FALSE;
		}
		ctx->send_vanished = TRUE;
		return TRUE;
	}

	client_send_command_error(cmd, "Unknown FETCH modifier");
	return FALSE;
}

static bool
fetch_parse_modifiers(struct imap_fetch_context *ctx,
		      struct client_command_context *cmd,
		      const struct imap_arg *args)
{
	const char *name;

	while (!IMAP_ARG_IS_EOL(args)) {
		if (!imap_arg_get_atom(args, &name)) {
			client_send_command_error(cmd,
				"FETCH modifiers contain non-atoms.");
			return FALSE;
		}
		args++;
		if (!fetch_parse_modifier(ctx, cmd, t_str_ucase(name), &args))
			return FALSE;
	}
	if (ctx->send_vanished &&
	    (ctx->search_args->args->next == NULL ||
	     ctx->search_args->args->next->type != SEARCH_MODSEQ)) {
		client_send_command_error(cmd,
			"VANISHED used without CHANGEDSINCE");
		return FALSE;
	}
	return TRUE;
}

static bool cmd_fetch_finish(struct imap_fetch_context *ctx,
			     struct client_command_context *cmd)
{
	static const char *ok_message = "OK Fetch completed.";
	const char *tagged_reply = ok_message;

	if (ctx->partial_fetch) {
		tagged_reply = "OK ["IMAP_RESP_CODE_EXPUNGEISSUED"] "
			"Some messages were already expunged.";
	}

	if (imap_fetch_deinit(ctx) < 0)
		ctx->failed = TRUE;

	if (ctx->failed) {
		const char *errstr;

		if (ctx->client->output->closed) {
			client_disconnect(cmd->client, "Disconnected");
			return TRUE;
		}

		errstr = mailbox_get_last_error(cmd->client->mailbox, NULL);

		/* We never want to reply NO to FETCH requests,
		   BYE is preferrable (see imap-ml for reasons). */
		client_disconnect_with_error(cmd->client, errstr);
		return TRUE;
	}

	return cmd_sync(cmd,
			(ctx->seen_flags_changed ? 0 : MAILBOX_SYNC_FLAG_FAST) |
			(cmd->uid ? 0 : MAILBOX_SYNC_FLAG_NO_EXPUNGES), 0,
			tagged_reply);
}

static bool cmd_fetch_continue(struct client_command_context *cmd)
{<commit_msg>imap: Compile fix due to recent changes<commit_after>/* Copyright (c) 2002-2012 Dovecot authors, see the included COPYING file */

#include "imap-common.h"
#include "ostream.h"
#include "imap-resp-code.h"
#include "imap-commands.h"
#include "imap-fetch.h"
#include "imap-search-args.h"
#include "mail-search.h"

#include <stdlib.h>

static const char *all_macro[] = {
	"FLAGS", "INTERNALDATE", "RFC822.SIZE", "ENVELOPE", NULL
};
static const char *fast_macro[] = {
	"FLAGS", "INTERNALDATE", "RFC822.SIZE", NULL
};
static const char *full_macro[] = {
	"FLAGS", "INTERNALDATE", "RFC822.SIZE", "ENVELOPE", "BODY", NULL
};

static bool
fetch_parse_args(struct imap_fetch_context *ctx,
		 struct client_command_context *cmd,
		 const struct imap_arg *arg, const struct imap_arg **next_arg_r)
{
	const char *str, *const *macro;

	if (cmd->uid) {
		if (!imap_fetch_cmd_init_handler(ctx, cmd, "UID", &arg))
			return FALSE;
	}
	if (imap_arg_get_atom(arg, &str)) {
		str = t_str_ucase(str);
		arg++;

		/* handle macros first */
		if (strcmp(str, "ALL") == 0)
			macro = all_macro;
		else if (strcmp(str, "FAST") == 0)
			macro = fast_macro;
		else if (strcmp(str, "FULL") == 0)
			macro = full_macro;
		else {
			macro = NULL;
			if (!imap_fetch_cmd_init_handler(ctx, cmd, str, &arg))
				return FALSE;
		}
		if (macro != NULL) {
			while (*macro != NULL) {
				if (!imap_fetch_cmd_init_handler(ctx, cmd, *macro, &arg))
					return FALSE;
				macro++;
			}
		}
		*next_arg_r = arg;
	} else {
		*next_arg_r = arg + 1;
		arg = imap_arg_as_list(arg);
		if (IMAP_ARG_IS_EOL(arg)) {
			client_send_command_error(cmd,
						  "FETCH list is empty.");
			return FALSE;
		}
		while (imap_arg_get_atom(arg, &str)) {
			str = t_str_ucase(str);
			arg++;
			if (!imap_fetch_cmd_init_handler(ctx, cmd, str, &arg))
				return FALSE;
		}
		if (!IMAP_ARG_IS_EOL(arg)) {
			client_send_command_error(cmd,
				"FETCH list contains non-atoms.");
			return FALSE;
		}
	}
	return TRUE;
}

static bool
fetch_parse_modifier(struct imap_fetch_context *ctx,
		     struct client_command_context *cmd,
		     const char *name, const struct imap_arg **args)
{
	const char *str;
	uint64_t modseq;

	if (strcmp(name, "CHANGEDSINCE") == 0) {
		if (!imap_arg_get_atom(*args, &str) ||
		    str_to_uint64(str, &modseq) < 0) {
			client_send_command_error(cmd,
				"Invalid CHANGEDSINCE modseq.");
			return FALSE;
		}
		*args += 1;
		imap_fetch_add_changed_since(ctx, modseq);
		return TRUE;
	}
	if (strcmp(name, "VANISHED") == 0 && cmd->uid) {
		if ((ctx->client->enabled_features &
		     MAILBOX_FEATURE_QRESYNC) == 0) {
			client_send_command_error(cmd, "QRESYNC not enabled");
			return FALSE;
		}
		ctx->send_vanished = TRUE;
		return TRUE;
	}

	client_send_command_error(cmd, "Unknown FETCH modifier");
	return FALSE;
}

static bool
fetch_parse_modifiers(struct imap_fetch_context *ctx,
		      struct client_command_context *cmd,
		      const struct imap_arg *args)
{
	const char *name;

	while (!IMAP_ARG_IS_EOL(args)) {
		if (!imap_arg_get_atom(args, &name)) {
			client_send_command_error(cmd,
				"FETCH modifiers contain non-atoms.");
			return FALSE;
		}
		args++;
		if (!fetch_parse_modifier(ctx, cmd, t_str_ucase(name), &args))
			return FALSE;
	}
	if (ctx->send_vanished &&
	    (ctx->search_args->args->next == NULL ||
	     ctx->search_args->args->next->type != SEARCH_MODSEQ)) {
		client_send_command_error(cmd,
			"VANISHED used without CHANGEDSINCE");
		return FALSE;
	}
	return TRUE;
}

static bool cmd_fetch_finish(struct imap_fetch_context *ctx,
			     struct client_command_context *cmd)
{
	static const char *ok_message = "OK Fetch completed.";
	const char *tagged_reply = ok_message;

	if (ctx->skipped_expunged_msgs) {
		tagged_reply = "OK ["IMAP_RESP_CODE_EXPUNGEISSUED"] "
			"Some messages were already expunged.";
	}

	if (imap_fetch_deinit(ctx) < 0)
		ctx->failed = TRUE;

	if (ctx->failed) {
		const char *errstr;

		if (ctx->client->output->closed) {
			client_disconnect(cmd->client, "Disconnected");
			return TRUE;
		}

		errstr = mailbox_get_last_error(cmd->client->mailbox, NULL);

		/* We never want to reply NO to FETCH requests,
		   BYE is preferrable (see imap-ml for reasons). */
		client_disconnect_with_error(cmd->client, errstr);
		return TRUE;
	}

	return cmd_sync(cmd,
			(ctx->seen_flags_changed ? 0 : MAILBOX_SYNC_FLAG_FAST) |
			(cmd->uid ? 0 : MAILBOX_SYNC_FLAG_NO_EXPUNGES), 0,
			tagged_reply);
}

static bool cmd_fetch_continue(struct client_command_context *cmd)
{
{'fraction_non_alphanumeric': 0.13903803131991052, 'fraction_numerical': 0.007606263982102908, 'mean_word_length': 4.059988681380871, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 55, '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': '4513268', 'n_tokens_mistral': 3842, 'n_tokens_neox': 3417, 'n_words': 762}