static bool cmd_putscript_continue_parsing(struct client_command_context *cmd)
{
	struct client *client = cmd->client;
	struct cmd_putscript_context *ctx = cmd->context;
	const struct managesieve_arg *args;
	int ret;

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

	/* <script literal> */
	ret = managesieve_parser_read_args(ctx->save_parser, 0,
				    MANAGESIEVE_PARSE_FLAG_STRING_STREAM, &args);
	if (ret == -1 || client->output->closed) {
		cmd_putscript_finish(ctx);
		client_send_command_error(cmd, "Invalid arguments.");
		client->input_skip_line = TRUE;
		return TRUE;
	}
	if (ret < 0) {
		/* need more data */
		return FALSE;
	}

	/* Validate the script argument */
	if ( !managesieve_arg_get_string_stream(args,&ctx->input) ) {
		client_send_command_error(cmd, "Invalid arguments.");
		return cmd_putscript_cancel(ctx, FALSE);
	}

	if ( i_stream_get_size(ctx->input, FALSE, &ctx->script_size) > 0 ) {
		if ( ctx->script_size == 0 ) {
			/* no script content, abort */
			if ( ctx->scriptname != NULL )
				client_send_no(client, "PUTSCRIPT aborted (empty script).");
			else
				client_send_no(client, "CHECKSCRIPT aborted (empty script).");

			cmd_putscript_finish(ctx);
			return TRUE;

		/* Check quota */
		} else if ( ctx->scriptname == NULL ) {
			if ( !managesieve_quota_check_validsize(client, ctx->script_size) )
				return cmd_putscript_cancel(ctx, TRUE);
		} else {
			if ( !managesieve_quota_check_all
				(client, ctx->scriptname, ctx->script_size) )
				return cmd_putscript_cancel(ctx, TRUE);
		}

	} else {
		ctx->max_script_size = managesieve_quota_max_script_size(client);
	}

	/* save the script */
	ctx->save_ctx = sieve_storage_save_init
		(ctx->storage, ctx->scriptname, ctx->input);

	if ( ctx->save_ctx == NULL ) {
		/* save initialization failed */
		client_send_storage_error(client, ctx->storage);
		return cmd_putscript_cancel(ctx, TRUE);
	}

	/* after literal comes CRLF, if we fail make sure we eat it away */
	client->input_skip_line = TRUE;

	client->command_pending = TRUE;
	cmd->func = cmd_putscript_continue_script;
	return cmd_putscript_continue_script(cmd);
}
示例#2
0
static int
sieve_attribute_set_sieve(struct mail_storage *storage,
			  const char *key,
			  const struct mail_attribute_value *value)
{
	struct sieve_storage *svstorage;
	struct sieve_storage_save_context *save_ctx;
	struct istream *input;
	const char *scriptname;
	int ret;

	if ((ret = mail_sieve_user_init(storage->user, &svstorage)) <= 0) {
		if (ret == 0) {
			mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
					       "Sieve not enabled for user");
		}
		return -1;
	}

	if (strcmp(key, MAILBOX_ATTRIBUTE_SIEVE_DEFAULT) == 0)
		return sieve_attribute_set_default(storage, svstorage, value);
	if (strncmp(key, MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES,
		    strlen(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES)) != 0) {
		mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
				       "Nonexistent sieve attribute");
		return -1;
	}
	scriptname = key + strlen(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES);

	if (value->value != NULL) {
		input = i_stream_create_from_data(value->value,
						  strlen(value->value));
		save_ctx = sieve_storage_save_init(svstorage, scriptname, input);
		i_stream_unref(&input);
	} else if (value->value_stream != NULL) {
		input = value->value_stream;
		save_ctx = sieve_storage_save_init(svstorage, scriptname, input);
	} else {
		return sieve_attribute_unset_script(storage, svstorage, scriptname);
	}

	if (save_ctx == NULL) {
		/* save initialization failed */
		mail_storage_set_critical(storage,
			"Failed to save sieve script '%s': %s", scriptname,
			sieve_storage_get_last_error(svstorage, NULL));
		return -1;
	}

	sieve_storage_save_set_mtime(save_ctx, value->last_change);

	ret = 0;
	while (i_stream_read(input) > 0) {
		if (sieve_storage_save_continue(save_ctx) < 0) {
			mail_storage_set_critical(storage,
				"Failed to save sieve script '%s': %s", scriptname,
				sieve_storage_get_last_error(svstorage, NULL));
			ret = -1;
			break;
		}
	}
	i_assert(input->eof || ret < 0);
	if (input->stream_errno != 0) {
		errno = input->stream_errno;
		mail_storage_set_critical(storage,
			"Saving sieve script: read(%s) failed: %m",
			i_stream_get_name(input));
		ret = -1;
	}
	if (ret == 0 && sieve_storage_save_finish(save_ctx) < 0) {
		mail_storage_set_critical(storage,
			"Failed to save sieve script '%s': %s", scriptname,
			sieve_storage_get_last_error(svstorage, NULL));
		ret = -1;
	}
	if (ret < 0)
		sieve_storage_save_cancel(&save_ctx);
	else if (sieve_storage_save_commit(&save_ctx) < 0) {
		mail_storage_set_critical(storage,
			"Failed to save sieve script '%s': %s", scriptname,
			sieve_storage_get_last_error(svstorage, NULL));
		ret = -1;
	}
	return ret;
}