コード例 #1
0
ファイル: client-authenticate.c プロジェクト: bdraco/core
int cmd_login(struct imap_client *imap_client, const struct imap_arg *args)
{
	struct client *client = &imap_client->common;
	const char *user, *pass;
	string_t *plain_login, *base64;

	/* two arguments: username and password */
	if (!imap_arg_get_astring(&args[0], &user) ||
	    !imap_arg_get_astring(&args[1], &pass) ||
	    !IMAP_ARG_IS_EOL(&args[2]))
		return -1;

	if (!client_check_plaintext_auth(client, TRUE)) {
		if (client->virtual_user == NULL)
			client->virtual_user = i_strdup(user);
		return 1;
	}

	/* authorization ID \0 authentication ID \0 pass */
	plain_login = t_buffer_create(64);
	buffer_append_c(plain_login, '\0');
	buffer_append(plain_login, user, strlen(user));
	buffer_append_c(plain_login, '\0');
	buffer_append(plain_login, pass, strlen(pass));

	base64 = t_buffer_create(MAX_BASE64_ENCODED_SIZE(plain_login->used));
	base64_encode(plain_login->data, plain_login->used, base64);
	return imap_client_auth_begin(imap_client, "PLAIN", str_c(base64));
}
コード例 #2
0
ファイル: cmd-store.c プロジェクト: jkerihuel/dovecot
static bool
store_parse_modifiers(struct imap_store_context *ctx,
		      const struct imap_arg *args)
{
	const char *name, *value;

	for (; !IMAP_ARG_IS_EOL(args); args += 2) {
		if (!imap_arg_get_atom(&args[0], &name) ||
		    !imap_arg_get_atom(&args[1], &value)) {
			client_send_command_error(ctx->cmd,
				"Invalid STORE modifiers.");
			return FALSE;
		}

		if (strcasecmp(name, "UNCHANGEDSINCE") == 0) {
			if (str_to_uint64(value, &ctx->max_modseq) < 0) {
				client_send_command_error(ctx->cmd,
							  "Invalid modseq");
				return FALSE;
			}
			(void)client_enable(ctx->cmd->client,
					    MAILBOX_FEATURE_CONDSTORE);
		} else {
			client_send_command_error(ctx->cmd,
						  "Unknown STORE modifier");
			return FALSE;
		}
	}
	return TRUE;
}
コード例 #3
0
ファイル: cmd-cancelupdate.c プロジェクト: LTD-Beget/dovecot
bool cmd_cancelupdate(struct client_command_context *cmd)
{
	const struct imap_arg *args;
	const char *tag;
	unsigned int i;

	if (!client_read_args(cmd, 0, 0, &args))
		return FALSE;

	for (i = 0; args[i].type == IMAP_ARG_STRING; i++) ;
	if (!IMAP_ARG_IS_EOL(&args[i]) || i == 0) {
		client_send_command_error(cmd, "Invalid parameters.");
		return TRUE;
	}

	while (imap_arg_get_quoted(args, &tag)) {
		if (!client_search_update_cancel(cmd->client, tag)) {
			client_send_tagline(cmd, "NO Unknown tag.");
			return TRUE;
		}
		args++;
	}
	client_send_tagline(cmd, "OK Updates cancelled.");
	return TRUE;
}
コード例 #4
0
ファイル: cmd-enable.c プロジェクト: LTD-Beget/dovecot
bool cmd_enable(struct client_command_context *cmd)
{
	const struct imap_arg *args;
	const char *str;
	string_t *reply;

	if (!client_read_args(cmd, 0, 0, &args))
		return FALSE;

	reply = t_str_new(64);
	str_append(reply, "* ENABLED");
	for (; !IMAP_ARG_IS_EOL(args); args++) {
		if (!imap_arg_get_atom(args, &str)) {
			client_send_command_error(cmd, "Invalid arguments.");
			return TRUE;
		}
		str = t_str_ucase(str);
		if (strcmp(str, "CONDSTORE") == 0) {
			if (client_enable(cmd->client,
					  MAILBOX_FEATURE_CONDSTORE) == 0)
				str_append(reply, " CONDSTORE");
		} else if (strcmp(str, "QRESYNC") == 0) {
			if (client_enable(cmd->client, MAILBOX_FEATURE_QRESYNC |
					  MAILBOX_FEATURE_CONDSTORE) == 0)
				str_append(reply, " QRESYNC");
		}
	}
	if (str_len(reply) > 9)
		client_send_line(cmd->client, str_c(reply));
	client_send_tagline(cmd, "OK Enabled.");
	return TRUE;
}
コード例 #5
0
bool client_read_string_args(struct client_command_context *cmd,
			     unsigned int count, ...)
{
	const struct imap_arg *imap_args;
	va_list va;
	const char *str;
	unsigned int i;

	if (!client_read_args(cmd, count, 0, &imap_args))
		return FALSE;

	va_start(va, count);
	for (i = 0; i < count; i++) {
		const char **ret = va_arg(va, const char **);

		if (IMAP_ARG_IS_EOL(&imap_args[i])) {
			client_send_command_error(cmd, "Missing arguments.");
			break;
		}

		if (!imap_arg_get_astring(&imap_args[i], &str)) {
			client_send_command_error(cmd, "Invalid arguments.");
			break;
		}

		if (ret != NULL)
			*ret = str;
	}
	va_end(va);

	return i == count;
}
コード例 #6
0
ファイル: imap-id.c プロジェクト: LTD-Beget/dovecot
static const char *
imap_id_reply_generate_from_imap_args(const struct imap_arg *args)
{
	string_t *str;
	const char *key, *value;

	if (IMAP_ARG_IS_EOL(args))
		return "NIL";

	str = t_str_new(256);
	str_append_c(str, '(');
	for (; !IMAP_ARG_IS_EOL(args); args++) {
		if (!imap_arg_get_astring(args, &key)) {
			/* broken input */
			if (IMAP_ARG_IS_EOL(&args[1]))
				break;
			args++;
		} else {
			/* key */
			if (str_len(str) > 1)
				str_append_c(str, ' ');
			imap_append_quoted(str, key);
			str_append_c(str, ' ');
			/* value */
			if (IMAP_ARG_IS_EOL(&args[1])) {
				str_append(str, "NIL");
				break;
			}
			args++;
			if (!imap_arg_get_astring(args, &value))
				value = NULL;
			else {
				if (strcmp(value, "*") == 0)
					value = imap_id_get_default(key);
			}
			imap_append_nstring(str, value);
		}
	}
	if (str_len(str) == 1) {
		/* broken */
		return "NIL";
	}
	str_append_c(str, ')');
	return str_c(str);
}
コード例 #7
0
const char *imap_id_args_get_log_reply(const struct imap_arg *args,
				       const char *settings)
{
	const char *const *keys, *key, *value;
	string_t *reply;
	bool log_all;

	if (settings == NULL || *settings == '\0')
		return NULL;
	if (!imap_arg_get_list(args, &args))
		return NULL;

	log_all = strcmp(settings, "*") == 0;
	reply = t_str_new(256);
	keys = t_strsplit_spaces(settings, " ");
	while (!IMAP_ARG_IS_EOL(&args[0]) &&
	       !IMAP_ARG_IS_EOL(&args[1])) {
		if (!imap_arg_get_string(args, &key)) {
			/* broken input */
			args += 2;
			continue;
		}
		args++;
		if (strlen(key) > 30) {
			/* broken: ID spec requires fields to be max. 30
			   octets */
			args++;
			continue;
		}

		if (log_all || str_array_icase_find(keys, key)) {
			if (!imap_arg_get_nstring(args, &value))
				value = "";
			else if (value == NULL)
				value = "NIL";
			if (str_len(reply) > 0)
				str_append(reply, ", ");
			str_append(reply, str_sanitize(key, 30));
			str_append_c(reply, '=');
			str_append(reply, str_sanitize(value, 80));
		}
		args++;
	}
	return str_len(reply) == 0 ? NULL : str_c(reply);
}
コード例 #8
0
ファイル: cmd-append.c プロジェクト: bsmr-dovecot/core
static int
cmd_append_catenate(struct client_command_context *cmd,
		    const struct imap_arg *args, bool *nonsync_r)
{
	struct cmd_append_context *ctx = cmd->context;
	const char *catpart;

	*nonsync_r = FALSE;

	/* Handle URLs until a TEXT literal is encountered */
	while (imap_arg_get_atom(args, &catpart)) {
		const char *caturl;

		if (strcasecmp(catpart, "URL") == 0 ) {
			/* URL <url> */ 
			args++;
			if (!imap_arg_get_astring(args, &caturl))
				break;
			if (cmd_append_catenate_url(cmd, caturl) < 0) {
				/* delay failure until we can stop
				   parsing input */
				ctx->failed = TRUE;
			}
		} else if (strcasecmp(catpart, "TEXT") == 0) {
			/* TEXT <literal> */
			args++;
			if (!imap_arg_get_literal_size(args, &ctx->literal_size))
				break;
			if (args->literal8 && !ctx->binary_input &&
			    !ctx->failed) {
				client_send_tagline(cmd,
					"NO ["IMAP_RESP_CODE_UNKNOWN_CTE"] "
					"Binary input allowed only when the first part is binary.");
				ctx->failed = TRUE;
			}
			*nonsync_r = args->type == IMAP_ARG_LITERAL_SIZE_NONSYNC;
			cmd_append_catenate_text(cmd);
			return 1;
		} else {
			break;
		}
		args++;
	}

	if (IMAP_ARG_IS_EOL(args)) {
		/* ")" */
		return 0;
	}
	if (!ctx->failed)
		client_send_command_error(cmd, "Invalid arguments.");
	return -1;
}
コード例 #9
0
bool client_parse_mail_flags(struct client_command_context *cmd,
			     const struct imap_arg *args,
			     enum mail_flags *flags_r,
			     const char *const **keywords_r)
{
	const char *atom;
	enum mail_flags flag;
	ARRAY(const char *) keywords;

	*flags_r = 0;
	*keywords_r = NULL;
	p_array_init(&keywords, cmd->pool, 16);

	while (!IMAP_ARG_IS_EOL(args)) {
		if (!imap_arg_get_atom(args, &atom)) {
			client_send_command_error(cmd,
				"Flags list contains non-atoms.");
			return FALSE;
		}

		if (*atom == '\\') {
			/* system flag */
			atom = t_str_ucase(atom);
			flag = imap_parse_system_flag(atom);
			if (flag != 0 && flag != MAIL_RECENT)
				*flags_r |= flag;
			else {
				client_send_command_error(cmd, t_strconcat(
					"Invalid system flag ", atom, NULL));
				return FALSE;
			}
		} else {
			/* keyword validity checks are done by lib-storage */
			array_append(&keywords, &atom, 1);
		}

		args++;
	}

	if (array_count(&keywords) == 0)
		*keywords_r = NULL;
	else {
		array_append_zero(&keywords); /* NULL-terminate */
		*keywords_r = array_idx(&keywords, 0);
	}
	return TRUE;
}
コード例 #10
0
bool cmd_genurlauth(struct client_command_context *cmd)
{
	const struct imap_arg *args;
	string_t *response;
	int ret;

	if (cmd->client->urlauth_ctx == NULL) {
		client_send_command_error(cmd, "URLAUTH disabled.");
		return TRUE;
	}

	if (!client_read_args(cmd, 0, 0, &args))
		return FALSE;

	response = t_str_new(1024);
	str_append(response, "* GENURLAUTH");
	for (;;) {
		const char *url_rump, *mechanism, *url, *error;

		if (IMAP_ARG_IS_EOL(args))
			break;
		if (!imap_arg_get_astring(args++, &url_rump) ||
		    !imap_arg_get_atom(args++, &mechanism)) {
			client_send_command_error(cmd, "Invalid arguments.");
			return FALSE;
		}

		ret = imap_urlauth_generate(cmd->client->urlauth_ctx,
					    mechanism, url_rump, &url, &error);
		if (ret <= 0) {
			if (ret < 0)
				client_send_internal_error(cmd);
			else
				client_send_command_error(cmd, error);
			return TRUE;
		}

		str_append_c(response, ' ');
		imap_append_astring(response, url);
	}

	client_send_line(cmd->client, str_c(response));
	client_send_tagline(cmd, "OK GENURLAUTH completed.");
	return TRUE;
}
コード例 #11
0
static int xaps_register(const char *aps_account_id, const char *aps_device_token, const char *aps_subtopic, const char *dovecot_username, const struct imap_arg *dovecot_mailboxes)
{
  /*
   * Construct our request.
   */

  string_t *req = t_str_new(2048);
  str_append(req, "XAPS REGISTER ");
  str_append(req, "{\"aps-account-id\":\"");
  json_append_escaped(req, aps_account_id);
  str_append(req, "\",\"aps-device-token\":\"");
  json_append_escaped(req, aps_device_token);
  str_append(req, "\",\"aps-subtopic\":\"");
  json_append_escaped(req, aps_subtopic);
  str_append(req, "\",\"dovecot-username\":\"");
  json_append_escaped(req, dovecot_username);
  str_append(req, "\",");

  if (dovecot_mailboxes == NULL) {
    str_append(req, "\"dovecot-mailboxes\":[\"INBOX\"]");
  } else {
    str_append(req, "\"dovecot-mailboxes\":[");
    int next = 0;
    for (; !IMAP_ARG_IS_EOL(dovecot_mailboxes); dovecot_mailboxes++) {
      const char *mailbox;
      if (!imap_arg_get_astring(&dovecot_mailboxes[0], &mailbox)) {
        return -1;
      }
      if (next) {
        str_append(req, ",");
      }
      str_append(req, "\"");
      json_append_escaped(req, mailbox);
      str_append(req, "\"");
      next = 1;
    }
    str_append(req, "]");
  }
  str_append(req, "}");
  i_info(str_c(req));
  return 0;
}
コード例 #12
0
static bool cmd_setquota(struct client_command_context *cmd)
{
	struct quota_root *root;
        const struct imap_arg *args, *list_args;
	const char *root_name, *name, *value_str, *error;
	uint64_t value;

	/* <quota root> <resource limits> */
	if (!client_read_args(cmd, 2, 0, &args))
		return FALSE;

	if (!imap_arg_get_astring(&args[0], &root_name) ||
	    !imap_arg_get_list(&args[1], &list_args)) {
		client_send_command_error(cmd, "Invalid arguments.");
		return TRUE;
	}

	root = quota_root_lookup(cmd->client->user, root_name);
	if (root == NULL) {
		client_send_tagline(cmd, "NO Quota root doesn't exist.");
		return TRUE;
	}

	for (; !IMAP_ARG_IS_EOL(list_args); list_args += 2) {
		if (!imap_arg_get_atom(&list_args[0], &name) ||
		    !imap_arg_get_atom(&list_args[1], &value_str) ||
		    str_to_uint64(value_str, &value) < 0) {
			client_send_command_error(cmd, "Invalid arguments.");
			return TRUE;
		}

		if (quota_set_resource(root, name, value, &error) < 0) {
			client_send_command_error(cmd, error);
			return TRUE;
		}
	}

	client_send_tagline(cmd, "OK Setquota completed.");
	return TRUE;
}
コード例 #13
0
ファイル: imap-search-args.c プロジェクト: Distrotech/dovecot
int imap_search_args_build(struct client_command_context *cmd,
			   const struct imap_arg *args, const char *charset,
			   struct mail_search_args **search_args_r)
{
	struct mail_search_parser *parser;
	struct mail_search_args *sargs;
	const char *error;
	int ret;

	if (IMAP_ARG_IS_EOL(args)) {
		client_send_command_error(cmd, "Missing search parameters");
		return -1;
	}

	parser = mail_search_parser_init_imap(args);
	ret = mail_search_build(mail_search_register_get_imap(),
				parser, &charset, &sargs, &error);
	mail_search_parser_deinit(&parser);
	if (ret < 0) {
		if (charset == NULL) {
			client_send_tagline(cmd, t_strconcat(
				"BAD [BADCHARSET] ", error, NULL));
		} else {
			client_send_command_error(cmd, error);
		}
		return -1;
	}

	if (search_args_have_searchres(sargs->args)) {
		if (client_handle_search_save_ambiguity(cmd))
			return 0;
	}

	mail_search_args_init(sargs, cmd->client->mailbox, TRUE,
			      &cmd->client->search_saved_uidset);
	*search_args_r = sargs;
	return 1;
}
コード例 #14
0
ファイル: cmd-append.c プロジェクト: bsmr-dovecot/core
static bool cmd_append_parse_new_msg(struct client_command_context *cmd)
{
	struct client *client = cmd->client;
	struct cmd_append_context *ctx = cmd->context;
	const struct imap_arg *args;
	const char *msg;
	unsigned int arg_min_count;
	bool fatal, nonsync, last_literal;
	int ret;

	/* this function gets called 1) after parsing APPEND <mailbox> and
	   2) with MULTIAPPEND extension after already saving one or more
	   mails. */
	if (cmd->cancel) {
		/* cancel the command immediately (disconnection) */
		cmd_append_finish(ctx);
		return TRUE;
	}

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

	/* parse the entire line up to the first message literal, or in case
	   the input buffer is full of MULTIAPPEND CATENATE URLs, parse at
	   least until the beginning of the next message */
	arg_min_count = 0; last_literal = FALSE;
	do {
		if (!last_literal)
			arg_min_count++;
		else {
			/* we only read the literal size. now we read the
			   literal itself. */
		}
		ret = imap_parser_read_args(ctx->save_parser, arg_min_count,
					    IMAP_PARSE_FLAG_LITERAL_SIZE |
					    IMAP_PARSE_FLAG_LITERAL8, &args);
	} while (ret >= (int)arg_min_count &&
		 !cmd_append_args_can_stop(ctx, args, &last_literal));
	if (ret == -1) {
		if (!ctx->failed) {
			msg = imap_parser_get_error(ctx->save_parser, &fatal);
			if (fatal)
				client_disconnect_with_error(client, msg);
			else
				client_send_command_error(cmd, msg);
		}
		cmd_append_finish(ctx);
		return TRUE;
	}
	if (ret < 0) {
		/* need more data */
		return FALSE;
	}

	if (IMAP_ARG_IS_EOL(args)) {
		/* last message */
		return cmd_append_finish_parsing(cmd);
	}

	ret = cmd_append_handle_args(cmd, args, &nonsync);
	if (ret < 0) {
		/* invalid parameters, abort immediately */
		cmd_append_finish(ctx);
		return TRUE;
	}
	if (ret == 0) {
		/* CATENATE contained only URLs. Finish it and see if there
		   are more messsages. */
		cmd_append_finish_catenate(cmd);
		imap_parser_reset(ctx->save_parser);
		return cmd_append_parse_new_msg(cmd);
	}

	if (!nonsync) {
		if (!cmd_append_send_literal_continue(ctx)) {
			cmd_append_finish(ctx);
			return TRUE;
		}
	}

	i_assert(ctx->litinput != NULL);
	ctx->message_input = TRUE;
	cmd->func = cmd_append_continue_message;
	return cmd_append_continue_message(cmd);
}
コード例 #15
0
ファイル: cmd-append.c プロジェクト: bsmr-dovecot/core
static int
cmd_append_handle_args(struct client_command_context *cmd,
		       const struct imap_arg *args, bool *nonsync_r)
{
	struct client *client = cmd->client;
	struct cmd_append_context *ctx = cmd->context;
	const struct imap_arg *flags_list;
	const struct imap_arg *cat_list = NULL;
	enum mail_flags flags;
	const char *const *keywords_list;
	struct mail_keywords *keywords;
	struct istream *input;
	const char *internal_date_str;
	time_t internal_date;
	int ret, timezone_offset;
	bool valid;

	/* [<flags>] */
	if (!imap_arg_get_list(args, &flags_list))
		flags_list = NULL;
	else
		args++;

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

	/* <message literal> | CATENATE (..) */
	valid = FALSE;
	*nonsync_r = FALSE;
	ctx->catenate = FALSE;
	if (imap_arg_get_literal_size(args, &ctx->literal_size)) {
		*nonsync_r = args->type == IMAP_ARG_LITERAL_SIZE_NONSYNC;
		ctx->binary_input = args->literal8;
		valid = TRUE;
	} else if (!imap_arg_atom_equals(args, "CATENATE")) {
		/* invalid */
	} else if (!imap_arg_get_list(++args, &cat_list)) {
		/* invalid */
	} else {
		valid = TRUE;
		ctx->catenate = TRUE;
		/* We'll do BINARY conversion only if the CATENATE's first
		   part is a literal8. If it doesn't and a literal8 is seen
		   later we'll abort the append with UNKNOWN-CTE. */
		ctx->binary_input = imap_arg_atom_equals(&cat_list[0], "TEXT") &&
			cat_list[1].literal8;

	}
	if (!IMAP_ARG_IS_EOL(&args[1]))
		valid = FALSE;
	if (!valid) {
		client->input_skip_line = TRUE;
		if (!ctx->failed)
			client_send_command_error(cmd, "Invalid arguments.");
		return -1;
	}

	if (flags_list == NULL || ctx->failed) {
		flags = 0;
		keywords = NULL;
	} else {
		if (!client_parse_mail_flags(cmd, flags_list,
					     &flags, &keywords_list))
			return -1;
		if (keywords_list == NULL)
			keywords = NULL;
		else if (mailbox_keywords_create(ctx->box, keywords_list,
						 &keywords) < 0) {
			/* invalid keywords - delay failure */
			client_send_box_error(cmd, ctx->box);
			ctx->failed = TRUE;
			keywords = NULL;
		}
	}

	if (internal_date_str == NULL || ctx->failed) {
		/* no time given, default to now. */
		internal_date = (time_t)-1;
		timezone_offset = 0;
	} else if (!imap_parse_datetime(internal_date_str,
					&internal_date, &timezone_offset)) {
		client_send_command_error(cmd, "Invalid internal date.");
		if (keywords != NULL)
			mailbox_keywords_unref(&keywords);
		return -1;
	}

	if (internal_date != (time_t)-1 &&
	    internal_date > ioloop_time + INTERNALDATE_MAX_FUTURE_SECS) {
		/* the client specified a time in the future, set it to now. */
		internal_date = (time_t)-1;
		timezone_offset = 0;
	}

	if (cat_list != NULL) {
		ctx->cat_msg_size = 0;
		ctx->input = i_stream_create_chain(&ctx->catchain);
	} else {
		if (ctx->literal_size == 0) {
			/* no message data, abort */
			if (!ctx->failed) {
				client_send_tagline(cmd,
					"NO Can't save a zero byte message.");
				ctx->failed = TRUE;
			}
			if (!*nonsync_r) {
				if (keywords != NULL)
					mailbox_keywords_unref(&keywords);
				return -1;
			}
			/* {0+} used. although there isn't any point in using
			   MULTIAPPEND here and adding more messages, it is
			   technically valid so we'll continue parsing.. */
		}
		ctx->litinput = i_stream_create_limit(client->input, ctx->literal_size);
		ctx->input = ctx->litinput;
		i_stream_ref(ctx->input);
	}
	if (ctx->binary_input) {
		input = i_stream_create_binary_converter(ctx->input);
		i_stream_unref(&ctx->input);
		ctx->input = input;
	}

	if (!ctx->failed) {
		/* save the mail */
		ctx->save_ctx = mailbox_save_alloc(ctx->t);
		mailbox_save_set_flags(ctx->save_ctx, flags, keywords);
		mailbox_save_set_received_date(ctx->save_ctx,
					       internal_date, timezone_offset);
		if (mailbox_save_begin(&ctx->save_ctx, ctx->input) < 0) {
			/* save initialization failed */
			client_send_box_error(cmd, ctx->box);
			ctx->failed = TRUE;
		}
	}
	if (keywords != NULL)
		mailbox_keywords_unref(&keywords);
	ctx->count++;

	if (cat_list == NULL) {
		/* normal APPEND */
		return 1;
	} else if (cat_list->type == IMAP_ARG_EOL) {
		/* zero parts */
		if (!ctx->failed)
			client_send_command_error(cmd, "Empty CATENATE list.");
		client->input_skip_line = TRUE;
		return -1;
	} else if ((ret = cmd_append_catenate(cmd, cat_list, nonsync_r)) < 0) {
		/* invalid parameters, abort immediately */
		return -1;
	} else if (ret == 0) {
		/* CATENATE consisted only of URLs */
		return 0;
	} else {
		/* TEXT part found from CATENATE */
		return 1;
	}
}
コード例 #16
0
static bool cmd_compress(struct client_command_context *cmd)
{
	struct client *client = cmd->client;
	struct zlib_client *zclient = IMAP_ZLIB_IMAP_CONTEXT(client);
	const struct compression_handler *handler;
	const struct imap_arg *args;
	struct istream *old_input;
	struct ostream *old_output;
	const char *mechanism, *value;
	unsigned int level;

	/* <mechanism> */
	if (!client_read_args(cmd, 0, 0, &args))
		return FALSE;

	if (!imap_arg_get_atom(args, &mechanism) ||
	    !IMAP_ARG_IS_EOL(&args[1])) {
		client_send_command_error(cmd, "Invalid arguments.");
		return TRUE;
	}
	if (zclient->handler != NULL) {
		client_send_tagline(cmd, t_strdup_printf(
			"NO [COMPRESSIONACTIVE] COMPRESSION=%s already enabled.",
			t_str_ucase(zclient->handler->name)));
		return TRUE;
	}
	if (client->tls_compression) {
		client_send_tagline(cmd,
			"NO [COMPRESSIONACTIVE] TLS compression already enabled.");
		return TRUE;
	}

	handler = compression_lookup_handler(t_str_lcase(mechanism));
	if (handler == NULL || handler->create_istream == NULL) {
		client_send_tagline(cmd, "NO Unknown compression mechanism.");
		return TRUE;
	}

	imap_zlib_client_skip_line(client);
	client_send_tagline(cmd, "OK Begin compression.");

	value = mail_user_plugin_getenv(client->user,
					"imap_zlib_compress_level");
	if (value == NULL || str_to_uint(value, &level) < 0 ||
	    level <= 0 || level > 9)
		level = IMAP_COMPRESS_DEFAULT_LEVEL;

	old_input = client->input;
	old_output = client->output;
	client->input = handler->create_istream(old_input, FALSE);
	client->output = handler->create_ostream(old_output, level);
	/* preserve output offset so that the bytes out counter in logout
	   message doesn't get reset here */
	client->output->offset = old_output->offset;
	i_stream_unref(&old_input);
	o_stream_unref(&old_output);

	client_update_imap_parser_streams(client);
	zclient->handler = handler;
	return TRUE;
}
コード例 #17
0
ファイル: cmd-fetch.c プロジェクト: Distrotech/dovecot
bool cmd_fetch(struct client_command_context *cmd)
{
	struct client *client = cmd->client;
	struct imap_fetch_context *ctx;
	const struct imap_arg *args, *next_arg, *list_arg;
	struct mail_search_args *search_args;
	struct imap_fetch_qresync_args qresync_args;
	const char *messageset;
	bool send_vanished = FALSE;
	int ret;

	if (!client_read_args(cmd, 0, 0, &args))
		return FALSE;

	if (!client_verify_open_mailbox(cmd))
		return TRUE;

	/* <messageset> <field(s)> [(modifiers)] */
	if (!imap_arg_get_atom(&args[0], &messageset) ||
	    (args[1].type != IMAP_ARG_LIST && args[1].type != IMAP_ARG_ATOM) ||
	    (!IMAP_ARG_IS_EOL(&args[2]) && args[2].type != IMAP_ARG_LIST)) {
		client_send_command_error(cmd, "Invalid arguments.");
		return TRUE;
	}

	/* UID FETCH VANISHED needs the uidset, so convert it to
	   sequence set later */
	ret = imap_search_get_anyset(cmd, messageset, cmd->uid, &search_args);
	if (ret <= 0)
		return ret < 0;

	ctx = imap_fetch_alloc(client, cmd->pool);

	if (!fetch_parse_args(ctx, cmd, &args[1], &next_arg) ||
	    (imap_arg_get_list(next_arg, &list_arg) &&
	     !fetch_parse_modifiers(ctx, cmd, search_args, list_arg,
				    &send_vanished))) {
		imap_fetch_free(&ctx);
		mail_search_args_unref(&search_args);
		return TRUE;
	}

	if (send_vanished) {
		memset(&qresync_args, 0, sizeof(qresync_args));
		if (imap_fetch_send_vanished(client, client->mailbox,
					     search_args, &qresync_args) < 0) {
			mail_search_args_unref(&search_args);
			return cmd_fetch_finish(ctx, cmd);
		}
	}

	imap_fetch_begin(ctx, client->mailbox, search_args);
	mail_search_args_unref(&search_args);

	if (imap_fetch_more(ctx, cmd) == 0) {
		/* unfinished */
		cmd->state = CLIENT_COMMAND_STATE_WAIT_OUTPUT;

		cmd->func = cmd_fetch_continue;
		cmd->context = ctx;
		return FALSE;
	}
	return cmd_fetch_finish(ctx, cmd);
}
コード例 #18
0
ファイル: cmd-setmetadata.c プロジェクト: LTD-Beget/dovecot
static int
cmd_setmetadata_parse_entryvalue(struct imap_setmetadata_context *ctx,
				 const char **entry_r,
				 const struct imap_arg **value_r)
{
	const struct imap_arg *args;
	const char *name, *error;
	int ret;
	bool fatal;

	/* parse the entry name */
	ret = imap_parser_read_args(ctx->parser, 1,
				    IMAP_PARSE_FLAG_INSIDE_LIST, &args);
	if (ret >= 0) {
		if (ret == 0) {
			/* ')' found */
			*entry_r = NULL;
			return 1;
		}
		if (!imap_arg_get_astring(args, &name)) {
			client_send_command_error(ctx->cmd,
						  "Entry name isn't astring");
			return -1;
		}

		ret = imap_parser_read_args(ctx->parser, 2,
					    IMAP_PARSE_FLAG_INSIDE_LIST |
					    IMAP_PARSE_FLAG_LITERAL_SIZE |
					    IMAP_PARSE_FLAG_LITERAL8, &args);
	}
	if (ret < 0) {
		if (ret == -2)
			return 0;
		error = imap_parser_get_error(ctx->parser, &fatal);
		if (fatal) {
			client_disconnect_with_error(ctx->cmd->client, error);
			return -1;
		}
		client_send_command_error(ctx->cmd, error);
		return -1;
	}
	i_assert(!IMAP_ARG_IS_EOL(&args[1]));
	if (args[1].type == IMAP_ARG_LIST) {
		client_send_command_error(ctx->cmd, "Entry value can't be a list");
		return -1;
	}
	if (!ctx->cmd_error_sent &&
	    !imap_metadata_verify_entry_name(name, &error)) {
		client_send_command_error(ctx->cmd, error);
		ctx->cmd_error_sent = TRUE;
	}
	if (ctx->cmd_error_sent) {
		ctx->cmd->param_error = FALSE;
		ctx->cmd->state = CLIENT_COMMAND_STATE_WAIT_INPUT;

		ctx->failed = TRUE;
		if (args[1].type == IMAP_ARG_LITERAL_SIZE) {
			/* client won't see "+ OK", so we can abort
			   immediately */
			ctx->cmd->client->input_skip_line = FALSE;
			return -1;
		}
	}

	/* entry names are case-insensitive. handle this by using only
	   lowercase names. */
	*entry_r = t_str_lcase(name);
	*value_r = &args[1];
	return 1;
}