Example #1
0
static int cmd_test_config_unset_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{
    string_t *setting;
    int ret;

    /*
     * Read operands
     */

    /* Setting */
    if ( (ret=sieve_opr_string_read(renv, address, "setting", &setting)) <= 0 )
        return ret;

    /*
     * Perform operation
     */

    if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) {
        sieve_runtime_trace(renv, 0,
                            "testsuite: test_config_unset command");
        sieve_runtime_trace_descend(renv);
        sieve_runtime_trace(renv, 0, "unset config `%s'", str_c(setting));
    }

    testsuite_setting_unset(str_c(setting));

    return SIEVE_EXEC_OK;
}
static int cmd_test_set_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{
	struct testsuite_object tobj;
	string_t *value;
	int member_id;
	int ret;

	if ( !testsuite_object_read_member
		(renv->sblock, address, &tobj, &member_id) ) {
		sieve_runtime_trace_error(renv, "invalid testsuite object member");
		return SIEVE_EXEC_BIN_CORRUPT;
	}

	if ( (ret=sieve_opr_string_read(renv, address, "string", &value)) <= 0 )
		return ret;

	if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) {
		sieve_runtime_trace(renv, 0, "testsuite: test_set command");
		sieve_runtime_trace_descend(renv);
		sieve_runtime_trace(renv, 0,
			"set test parameter '%s' = \"%s\"",
				testsuite_object_member_name(&tobj, member_id), str_c(value));
	}

	if ( tobj.def == NULL || tobj.def->set_member == NULL ) {
		sieve_runtime_trace_error(renv, "unimplemented testsuite object");
		return SIEVE_EXEC_FAILURE;
	}

	tobj.def->set_member(renv, member_id, value);
	return SIEVE_EXEC_OK;
}
int sieve_match_value
(struct sieve_match_context *mctx, const char *value, size_t value_size,
	struct sieve_stringlist *key_list)
{
	const struct sieve_match_type *mcht = mctx->match_type;
	const struct sieve_runtime_env *renv = mctx->runenv;
	int match, ret;

	if ( mctx->trace ) {
		sieve_runtime_trace(renv, 0,
			"matching value `%s'", str_sanitize(value, 80));
	}

	/* Match to key values */

	sieve_stringlist_reset(key_list);

	if ( mctx->trace )
		sieve_stringlist_set_trace(key_list, TRUE);

	sieve_runtime_trace_descend(renv);

	if ( mcht->def->match_keys != NULL ) {
		/* Call match-type's own key match handler */
		match = mcht->def->match_keys(mctx, value, value_size, key_list);
	} else {
		string_t *key_item = NULL;

		/* Default key match loop */
		match = 0;
		while ( match == 0 &&
			(ret=sieve_stringlist_next_item(key_list, &key_item)) > 0 ) {
			T_BEGIN {
				match = mcht->def->match_key
					(mctx, value, value_size, str_c(key_item), str_len(key_item));

				if ( mctx->trace ) {
					sieve_runtime_trace(renv, 0,
						"with key `%s' => %d", str_sanitize(str_c(key_item), 80),
						match);
				}
			} T_END;
		}

		if ( ret < 0 ) {
			mctx->exec_status = key_list->exec_status;
			match = -1;
		}
	}

	sieve_runtime_trace_ascend(renv);

	if ( mctx->match_status < 0 || match < 0 )
		mctx->match_status = -1;
	else
		mctx->match_status =
			( mctx->match_status > match ? mctx->match_status : match );
	return match;
}
static int tst_exists_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{
	struct sieve_stringlist *hdr_list;
	struct mail *mail = sieve_message_get_mail(renv->msgctx);
	string_t *hdr_item;
	bool matched;
	int ret;

	/*
	 * Read operands
	 */

	/* Read header-list */
	if ( (ret=sieve_opr_stringlist_read(renv, address, "header-list", &hdr_list))
		<= 0 )
		return ret;

	/*
	 * Perfrom test
	 */

	sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "exists test");
	sieve_runtime_trace_descend(renv);

	/* Iterate through all requested headers to match (must find all specified) */
	hdr_item = NULL;
	matched = TRUE;
	while ( matched &&
		(ret=sieve_stringlist_next_item(hdr_list, &hdr_item)) > 0 ) {
		const char *const *headers;

		if ( mail_get_headers(mail, str_c(hdr_item), &headers) < 0 ||
			headers[0] == NULL ) {
			matched = FALSE;
		}

		sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING,
        	"header `%s' %s", str_sanitize(str_c(hdr_item), 80),
			( matched ? "exists" : "is missing" ));
	}

	if ( matched )
		sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, "all headers exist");
	else
		sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, "headers are missing");

	/* Set test result for subsequent conditional jump */
	if ( ret >= 0 ) {
		sieve_interpreter_set_test_result(renv->interp, matched);
		return SIEVE_EXEC_OK;
	}

	sieve_runtime_trace_error(renv, "invalid header-list item");
	return SIEVE_EXEC_BIN_CORRUPT;
}
Example #5
0
static int ext_fileinto_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{
	struct sieve_side_effects_list *slist = NULL;
	string_t *folder;
	bool folder_literal;
	bool trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_ACTIONS);
	int ret = 0;

	/*
	 * Read operands
	 */

	/* Optional operands (side effects only) */
	if ( sieve_action_opr_optional_read(renv, address, NULL, &ret, &slist) != 0 )
		return ret;

	/* Folder operand */
	if ( (ret=sieve_opr_string_read_ex
		(renv, address, "folder", FALSE, &folder, &folder_literal)) <= 0 )
		return ret;

	/*
	 * Perform operation
	 */

	if ( trace ) {
		sieve_runtime_trace(renv, 0, "fileinto action");
		sieve_runtime_trace_descend(renv);
	}

	if ( !folder_literal && !uni_utf8_str_is_valid(str_c(folder)) ) {
		sieve_runtime_error(renv, NULL,
			"folder name specified for fileinto command is not utf-8: %s",
			str_c(folder));
		return SIEVE_EXEC_FAILURE;
	}


	if ( trace ) {
		sieve_runtime_trace(renv, 0, "store message in mailbox `%s'",
			str_sanitize(str_c(folder), 80));
	}

	/* Add action to result */
	if ( sieve_act_store_add_to_result
		(renv, slist, str_c(folder)) < 0 )
		return SIEVE_EXEC_FAILURE;

	sieve_message_snapshot(renv->msgctx);

	return SIEVE_EXEC_OK;
}
Example #6
0
static int mcht_count_match
(struct sieve_match_context *mctx, struct sieve_stringlist *value_list,
	struct sieve_stringlist *key_list)
{
	const struct sieve_runtime_env *renv = mctx->runenv;
	bool trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING);
	int count;
	string_t *key_item;
	int match, ret;

	if ( (count=sieve_stringlist_get_length(value_list)) < 0 ) {
		mctx->exec_status = value_list->exec_status;
		return -1;
	}

	sieve_stringlist_reset(key_list);

	string_t *value = t_str_new(20);
	str_printfa(value, "%d", count);

	if ( trace ) {
		sieve_runtime_trace(renv, 0,
			"matching count value `%s'", str_sanitize(str_c(value), 80));
	}

	sieve_runtime_trace_descend(renv);

  /* Match to all key values */
  key_item = NULL;
	match = 0;
  while ( match == 0 &&
		(ret=sieve_stringlist_next_item(key_list, &key_item)) > 0 )
  {
		match = mcht_value_match_key
			(mctx, str_c(value), str_len(value), str_c(key_item), str_len(key_item));

		if ( trace ) {
			sieve_runtime_trace(renv, 0,
				"with key `%s' => %d", str_sanitize(str_c(key_item), 80), ret);
		}
	}

	sieve_runtime_trace_ascend(renv);

	if ( ret < 0 ) {
		mctx->exec_status = key_list->exec_status;
		match = -1;
	}

	return match;
}
Example #7
0
static int cmd_error_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{
	string_t *message;
	int ret;

	/*
	 * Read operands
	 */

	/* Read message */

	if ( (ret=sieve_opr_string_read(renv, address, "message", &message)) <= 0 )
		return ret;

	/*
	 * Perform operation
	 */

	sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "error \"%s\"",
		str_sanitize(str_c(message), 80));

	sieve_runtime_error(renv, NULL, "%s", str_c(message));

	return SIEVE_EXEC_FAILURE;
}
Example #8
0
static int opc_global_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{
	const struct sieve_extension *this_ext = renv->oprtn->ext;
	struct sieve_variable_scope_binary *global_vars;
	struct sieve_variable_scope *global_scope;
	struct sieve_variable_storage *storage;
	struct sieve_variable * const *vars;
	unsigned int var_count, count, i;

	if ( !sieve_binary_read_unsigned(renv->sblock, address, &count) ) {
		sieve_runtime_trace_error(renv,
			"global: count operand invalid");
		return SIEVE_EXEC_BIN_CORRUPT;
	}

	global_vars = ext_include_binary_get_global_scope(this_ext, renv->sbin);
	global_scope = sieve_variable_scope_binary_get(global_vars);
	vars = sieve_variable_scope_get_variables(global_scope, &var_count);
	storage = ext_include_interpreter_get_global_variables
		(this_ext, renv->interp);

	for ( i = 0; i < count; i++ ) {
		unsigned int index;

		if ( !sieve_binary_read_unsigned(renv->sblock, address, &index) ) {
			sieve_runtime_trace_error(renv,
				"global: variable index operand invalid");
			return SIEVE_EXEC_BIN_CORRUPT;
		}

		if ( index >= var_count ) {
			sieve_runtime_trace_error(renv,
				"global: variable index %u is invalid in global storage (> %u)",
				index, var_count);
			return SIEVE_EXEC_BIN_CORRUPT;
		}

		sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS,
			"global: exporting variable '%s' [gvid: %u, vid: %u]",
			vars[index]->identifier, i, index);

		/* Make sure variable is initialized (export) */
		(void)sieve_variable_get_modifiable(storage, index, NULL);
	}

	return SIEVE_EXEC_OK;
}
static int tst_test_multiscript_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{
	struct sieve_stringlist *scripts_list;
	string_t *script_name;
	ARRAY_TYPE (const_string) scriptfiles;
	bool result = TRUE;
	int ret;

	/*
	 * Read operands
	 */

	if ( (ret=sieve_opr_stringlist_read(renv, address, "scripts", &scripts_list))
		<= 0 )
		return ret;

	/*
	 * Perform operation
	 */

	sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS,
		"testsuite: test_multiscript test");
	sieve_runtime_trace_descend(renv);

	t_array_init(&scriptfiles, 16);

	script_name = NULL;
	while ( result &&
		(ret=sieve_stringlist_next_item(scripts_list, &script_name)) > 0 ) {
		const char *script = t_strdup(str_c(script_name));

		array_append(&scriptfiles, &script, 1);
	}

	result = result && (ret >= 0) &&
		testsuite_script_multiscript(renv, &scriptfiles);

	/* Set result */
	sieve_interpreter_set_test_result(renv->interp, result);

	return SIEVE_EXEC_OK;
}
Example #10
0
int sieve_match_end(struct sieve_match_context **mctx, int *exec_status)
{
	const struct sieve_match_type *mcht = (*mctx)->match_type;
	const struct sieve_runtime_env *renv = (*mctx)->runenv;
	int match = (*mctx)->match_status;

	if ( mcht->def != NULL && mcht->def->match_deinit != NULL )
		mcht->def->match_deinit(*mctx);

	if ( exec_status != NULL )
		*exec_status = (*mctx)->exec_status;

	pool_unref(&(*mctx)->pool);

	sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING,
		"finishing match with result: %s",
		( match > 0 ? "matched" : ( match < 0 ? "error" : "not matched" ) ));
	sieve_runtime_trace_ascend(renv);

	return match;
}
static int tst_vnotifym_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{
	struct sieve_stringlist *notify_uris;
	string_t *uri_item;
	bool all_valid = TRUE;
	int ret;

	/*
	 * Read operands
	 */

	/* Read notify uris */
	if ( (ret=sieve_opr_stringlist_read
		(renv, address, "notify-uris", &notify_uris)) <= 0 )
		return ret;

	/*
	 * Perform operation
	 */

	sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "valid_notify_method test");

	uri_item = NULL;
	while ( (ret=sieve_stringlist_next_item(notify_uris, &uri_item)) > 0 ) {
		if ( !ext_enotify_runtime_method_validate(renv, uri_item) ) {
			all_valid = FALSE;
			break;
		}
	}

	if ( ret < 0 ) {
		sieve_runtime_trace_error(renv, "invalid method uri item");
		return SIEVE_EXEC_BIN_CORRUPT;
	}

	sieve_interpreter_set_test_result(renv->interp, all_valid);
	return SIEVE_EXEC_OK;
}
Example #12
0
struct sieve_match_context *sieve_match_begin
(const struct sieve_runtime_env *renv,
	const struct sieve_match_type *mcht,
	const struct sieve_comparator *cmp)
{
	struct sieve_match_context *mctx;
	pool_t pool;

	/* Reject unimplemented match-type */
	if ( mcht->def == NULL || (mcht->def->match == NULL &&
			mcht->def->match_keys == NULL && mcht->def->match_key == NULL) )
			return NULL;

	/* Create match context */
	pool = pool_alloconly_create("sieve_match_context", 1024);
	mctx = p_new(pool, struct sieve_match_context, 1);
	mctx->pool = pool;
	mctx->runenv = renv;
	mctx->match_type = mcht;
	mctx->comparator = cmp;
	mctx->exec_status = SIEVE_EXEC_OK;
	mctx->trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING);

	/* Trace */
	if ( mctx->trace ) {
		sieve_runtime_trace_descend(renv);
		sieve_runtime_trace(renv, 0,
			"starting `:%s' match with `%s' comparator:",
			sieve_match_type_name(mcht), sieve_comparator_name(cmp));
	}

	/* Initialize match type */
	if ( mcht->def != NULL && mcht->def->match_init != NULL ) {
		mcht->def->match_init(mctx);
	}

	return mctx;
}
static int tst_mailboxexists_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{
	struct sieve_stringlist *mailbox_names;
	string_t *mailbox_item;
	bool trace = FALSE;
	bool all_exist = TRUE;
	int ret;

	/*
	 * Read operands
	 */

	/* Read notify uris */
	if ( (ret=sieve_opr_stringlist_read
		(renv, address, "mailbox-names", &mailbox_names)) <= 0 )
		return ret;

	/*
	 * Perform operation
	 */

	if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_TESTS) ) {
		sieve_runtime_trace(renv, 0, "mailboxexists test");
		sieve_runtime_trace_descend(renv);

		trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING);
	}

	if ( renv->scriptenv->user != NULL ) {
		int ret;

		mailbox_item = NULL;
		while ( (ret=sieve_stringlist_next_item(mailbox_names, &mailbox_item)) > 0 )
			{
			struct mail_namespace *ns;
			const char *mailbox = str_c(mailbox_item);
			struct mailbox *box;

			/* Find the namespace */
			ns = mail_namespace_find(renv->scriptenv->user->namespaces, mailbox);
			if ( ns == NULL) {
				if ( trace ) {
					sieve_runtime_trace(renv, 0, "mailbox `%s' not found",
						str_sanitize(mailbox, 80));
				}

				all_exist = FALSE;
				break;
			}

			/* Open the box */
			box = mailbox_alloc(ns->list, mailbox, 0);
			if ( mailbox_open(box) < 0 ) {
				if ( trace ) {
					sieve_runtime_trace(renv, 0, "mailbox `%s' cannot be opened",
						str_sanitize(mailbox, 80));
				}

				all_exist = FALSE;
				mailbox_free(&box);
				break;
			}

			/* Also fail when it is readonly */
			if ( mailbox_is_readonly(box) ) {
				if ( trace ) {
					sieve_runtime_trace(renv, 0, "mailbox `%s' is read-only",
						str_sanitize(mailbox, 80));
				}

				all_exist = FALSE;
				mailbox_free(&box);
				break;
			}

			/* FIXME: check acl for 'p' or 'i' ACL permissions as required by RFC */

			if ( trace ) {
				sieve_runtime_trace(renv, 0, "mailbox `%s' exists",
					str_sanitize(mailbox, 80));
			}

			/* Close mailbox */
			mailbox_free(&box);
		}

		if ( ret < 0 ) {
			sieve_runtime_trace_error(renv, "invalid mailbox name item");
			return SIEVE_EXEC_BIN_CORRUPT;
		}
	}

	if ( trace ) {
		if ( all_exist )
			sieve_runtime_trace(renv, 0, "all mailboxes are available");
		else
			sieve_runtime_trace(renv, 0, "some mailboxes are unavailable");
	}

	sieve_interpreter_set_test_result(renv->interp, all_exist);
	return SIEVE_EXEC_OK;
}
Example #14
0
static int cmd_test_config_reload_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{
    const struct sieve_extension *ext;
    int opt_code = 0;
    string_t *extension = NULL;
    int ret;

    /*
     * Read operands
     */

    /* Optional operands */
    for (;;) {
        int opt;

        if ( (opt=sieve_opr_optional_read(renv, address, &opt_code)) < 0 )
            return SIEVE_EXEC_BIN_CORRUPT;

        if ( opt == 0 ) break;

        switch ( opt_code ) {
        case OPT_EXTENSION:
            ret = sieve_opr_string_read(renv, address, "extension", &extension);
            break;
        default:
            sieve_runtime_trace_error(renv, "unknown optional operand");
            ret = SIEVE_EXEC_BIN_CORRUPT;
        }

        if ( ret <= 0 ) return ret;
    }

    /*
     * Perform operation
     */

    if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) {
        sieve_runtime_trace(renv, 0,
                            "testsuite: test_config_reload command");
        sieve_runtime_trace_descend(renv);
    }

    if ( extension == NULL ) {
        if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) {
            sieve_runtime_trace(renv, 0,
                                "reload configuration for sieve engine");
        }

        sieve_settings_load(renv->svinst);

    } else {
        if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) {
            sieve_runtime_trace(renv, 0,
                                "reload configuration for extension `%s'",
                                str_c(extension));
        }

        ext = sieve_extension_get_by_name(renv->svinst, str_c(extension));
        if ( ext == NULL ) {
            testsuite_test_failf("test_config_reload: "
                                 "unknown extension '%s'", str_c(extension));
            return SIEVE_EXEC_OK;
        }

        sieve_extension_reload(ext);
    }

    return SIEVE_EXEC_OK;
}
Example #15
0
static int tst_spamvirustest_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{
	const struct sieve_operation *op = renv->oprtn;
	const struct sieve_extension *this_ext = op->ext;
	int opt_code = 0;
	struct sieve_match_type mcht =
		SIEVE_MATCH_TYPE_DEFAULT(is_match_type);
	struct sieve_comparator cmp =
		SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator);
	bool percent = FALSE;
	struct sieve_stringlist *value_list, *key_list;
	const char *score_value;
	int match, ret;

	/* Read optional operands */
	for (;;) {
		int opt;

		if ( (opt=sieve_match_opr_optional_read
			(renv, address, &opt_code, &ret, &cmp, &mcht)) < 0 )
			return ret;

		if ( opt == 0 ) break;

		switch ( opt_code ) {
		case OPT_SPAMTEST_PERCENT:
			percent = TRUE;
			break;
		default:
			sieve_runtime_trace_error(renv, "unknown optional operand");
			return SIEVE_EXEC_BIN_CORRUPT;
		}
	}

	/* Read value part */
	if ( (ret=sieve_opr_stringlist_read(renv, address, "value", &key_list)) <= 0 )
		return ret;

	/* Perform test */

	if ( sieve_operation_is(op, spamtest_operation) ) {
		sieve_runtime_trace
			(renv, SIEVE_TRLVL_TESTS, "spamtest test [percent=%s]",
				( percent ? "true" : "false" ));
	} else {
		sieve_runtime_trace
			(renv, SIEVE_TRLVL_TESTS, "virustest test");
	}

	/* Get score value */
	sieve_runtime_trace_descend(renv);
	if ( (ret=ext_spamvirustest_get_value
		(renv, this_ext, percent, &score_value)) <= 0 )
		return ret;
	sieve_runtime_trace_ascend(renv);

	/* Construct value list */
	value_list = sieve_single_stringlist_create_cstr(renv, score_value, TRUE);

	/* Perform match */
	if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 )
		return ret;

	/* Set test result for subsequent conditional jump */
	sieve_interpreter_set_test_result(renv->interp, match > 0);
	return SIEVE_EXEC_OK;
}
Example #16
0
static int cmd_report_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{
	struct act_report_data *act;
	string_t *fbtype, *message, *to_address;
	const char *norm_address, *feedback_type, *error;
	int opt_code = 0, ret = 0;
	bool headers_only = FALSE;
	pool_t pool;

	/*
	 * Read operands
	 */

	/* Optional operands */

	for (;;) {
		int opt;

		if ( (opt=sieve_opr_optional_read(renv, address, &opt_code)) < 0 )
			return SIEVE_EXEC_BIN_CORRUPT;

		if ( opt == 0 ) break;

		switch ( opt_code ) {
		case OPT_HEADERS_ONLY:
			headers_only = TRUE;
			break;
		default:
			sieve_runtime_trace_error(renv, "unknown optional operand");
			return SIEVE_EXEC_BIN_CORRUPT;
		}
	}

	/* Fixed operands */

	if ( (ret=sieve_opr_string_read
		(renv, address, "feedback-type", &fbtype)) <= 0 )
		return ret;

	if ( (ret=sieve_opr_string_read
		(renv, address, "message", &message)) <= 0 )
		return ret;

	if ( (ret=sieve_opr_string_read
		(renv, address, "address", &to_address)) <= 0 )
		return ret;

	/*
	 * Perform operation
	 */

	/* Verify and trim feedback type */
	feedback_type = ext_vnd_report_parse_feedback_type(str_c(fbtype));
	if ( feedback_type == NULL ) {
		sieve_runtime_error(renv, NULL,
			"specified report feedback type `%s' is invalid",
			str_sanitize(str_c(fbtype), 256));
		return SIEVE_EXEC_FAILURE;
	}

	/* Verify and normalize the address to 'local_part@domain' */
	norm_address = sieve_address_normalize(to_address, &error);
	if ( norm_address == NULL ) {
		sieve_runtime_error(renv, NULL,
			"specified report address `%s' is invalid: %s",
			str_sanitize(str_c(to_address), 256), error);
		return SIEVE_EXEC_FAILURE;
	}

	/* Trace */
	if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_ACTIONS) ) {
		sieve_runtime_trace(renv, 0, "report action");
		sieve_runtime_trace_descend(renv);
		sieve_runtime_trace(renv, 0,
			"report incoming message as `%s' to address `%s'",
			str_sanitize(str_c(fbtype), 32),
			str_sanitize(norm_address, 80));
	}

	/* Add report action to the result */

	pool = sieve_result_pool(renv->result);
	act = p_new(pool, struct act_report_data, 1);
	act->headers_only = headers_only;
	act->feedback_type = p_strdup(pool, feedback_type);
	act->message = p_strdup(pool, str_c(message));
	act->to_address = p_strdup(pool, norm_address);

	if ( sieve_result_add_action(renv,
		NULL, &act_report, NULL, (void *) act, 0, TRUE) < 0 )
		return SIEVE_EXEC_FAILURE;

	return SIEVE_EXEC_OK;
}
Example #17
0
static int cmd_test_binary_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{
	const struct sieve_operation *oprtn = renv->oprtn;
	string_t *binary_name = NULL;
	int ret;

	/* 
	 * Read operands 
	 */

	/* Binary Name */

	if ( (ret=sieve_opr_string_read(renv, address, "binary-name", &binary_name))
		<= 0 )
		return ret;

	/*
	 * Perform operation
	 */

	if ( sieve_operation_is(oprtn, test_binary_load_operation) ) {
		struct sieve_binary *sbin = testsuite_binary_load(str_c(binary_name));

		if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) {
			sieve_runtime_trace(renv, 0, "testsuite: test_binary_load command");
			sieve_runtime_trace_descend(renv);
			sieve_runtime_trace(renv, 0, "load binary `%s'", str_c(binary_name));
		}

		if ( sbin != NULL ) {
			testsuite_script_set_binary(sbin);

			sieve_binary_unref(&sbin);
		} else {
			sieve_sys_error(testsuite_sieve_instance,
				"failed to load binary %s", str_c(binary_name));
			return SIEVE_EXEC_FAILURE;
		}

	} else if ( sieve_operation_is(oprtn, test_binary_save_operation) ) {
		struct sieve_binary *sbin = testsuite_script_get_binary();

		if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) {
			sieve_runtime_trace(renv, 0, "testsuite: test_binary_save command");
			sieve_runtime_trace_descend(renv);
			sieve_runtime_trace(renv, 0, "save binary `%s'", str_c(binary_name));
		}

		if ( sbin != NULL ) 
			testsuite_binary_save(sbin, str_c(binary_name));
		else {
			sieve_sys_error(testsuite_sieve_instance,
				"no compiled binary to save as %s", str_c(binary_name));
			return SIEVE_EXEC_FAILURE;
		}
	} else {
		i_unreached();
	}

	return SIEVE_EXEC_OK;
}
Example #18
0
static int cmd_filter_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{	
	const struct sieve_extension *this_ext = renv->oprtn->ext;
	unsigned int is_test = 0;
	struct sieve_stringlist *args_list = NULL;
	enum sieve_error error = SIEVE_ERROR_NONE;
	string_t *pname = NULL;
	const char *program_name = NULL;
	const char *const *args = NULL;
	struct istream *newmsg = NULL;
	struct sieve_extprogram *sprog;
	int ret;

	/*
	 * Read operands
	 */

	/* The is_test flag */

	if ( !sieve_binary_read_byte(renv->sblock, address, &is_test) ) {
		sieve_runtime_trace_error(renv, "invalid is_test flag");
		return SIEVE_EXEC_BIN_CORRUPT;
	}

	/* Optional operands */	

	if ( sieve_action_opr_optional_read(renv, address, NULL, &ret, NULL) != 0 ) 
		return ret;

	/* Fixed operands */

	if ( (ret=sieve_extprogram_command_read_operands
		(renv, address, &pname, &args_list)) <= 0 )
		return ret;

	program_name = str_c(pname);
	if ( args_list != NULL &&
		sieve_stringlist_read_all(args_list, pool_datastack_create(), &args) < 0 ) {
		sieve_runtime_trace_error(renv, "failed to read args operand");
		return args_list->exec_status;
	}

	/*
	 * Perform operation
	 */

	/* Trace */

	sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "filter action");
	sieve_runtime_trace_descend(renv);
	sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS,
		"execute program `%s'", str_sanitize(program_name, 128));

	sprog = sieve_extprogram_create
		(this_ext, renv->scriptenv, renv->msgdata, "filter", program_name, args,
			&error);

	if ( sprog != NULL ) {
		struct mail *mail = sieve_message_get_mail(renv->msgctx);

		if ( sieve_extprogram_set_input_mail(sprog, mail) < 0 ) {
			sieve_extprogram_destroy(&sprog);
			return sieve_runtime_mail_error(renv, mail,
				"filter action: failed to read input message");
		}
		sieve_extprogram_set_output_seekable(sprog);
		ret = sieve_extprogram_run(sprog);
	} else {
		ret = -1;
	}

	if ( ret > 0 )
		newmsg = sieve_extprogram_get_output_seekable(sprog);
	if ( sprog != NULL )
		sieve_extprogram_destroy(&sprog);

	if ( ret > 0 && newmsg != NULL ) {
		sieve_runtime_trace(renv,	SIEVE_TRLVL_ACTIONS,
			"executed program successfully");

		i_stream_set_name(newmsg,
			t_strdup_printf("filter %s output", program_name));
		newmsg->blocking = TRUE;
		if ( (ret=sieve_message_substitute(renv->msgctx, newmsg)) >= 0 ) {
			sieve_runtime_trace(renv,	SIEVE_TRLVL_ACTIONS,
				"changed message");
		} else {
			sieve_runtime_critical(renv, NULL, "filter action",
				"filter action: failed to substitute message"); 
		}

		i_stream_unref(&newmsg);

	} else if ( ret < 0 ) {
		if ( error == SIEVE_ERROR_NOT_FOUND ) {
			sieve_runtime_error(renv, NULL,
				"filter action: program `%s' not found",
				str_sanitize(program_name, 80));
		} else {
			sieve_extprogram_exec_error(renv->ehandler,
				sieve_runtime_get_full_command_location(renv),
				"filter action: failed to execute to program `%s'",
				str_sanitize(program_name, 80));
		}

	} else {
		sieve_runtime_trace(renv,	SIEVE_TRLVL_ACTIONS,
			"filter action: program indicated false result");
	}

	if ( is_test > 0 ) {
		sieve_interpreter_set_test_result(renv->interp, ( ret > 0 ));

		return SIEVE_EXEC_OK;
	}

	return ( ret >= 0 ? SIEVE_EXEC_OK : SIEVE_EXEC_FAILURE );
}
static int cmd_test_imap_metadata_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{
	const struct sieve_operation *oprtn = renv->oprtn;
	int opt_code = 0;
	string_t *mailbox = NULL, *annotation = NULL, *value = NULL;
	int ret;

	/*
	 * Read operands
	 */

	/* Optional operands */

	for (;;) {
		int opt;

		if ( (opt=sieve_opr_optional_read(renv, address, &opt_code)) < 0 )
			return SIEVE_EXEC_BIN_CORRUPT;

		if ( opt == 0 ) break;

		switch ( opt_code ) {
		case OPT_MAILBOX:
			ret = sieve_opr_string_read(renv, address, "mailbox", &mailbox);
			break;
		default:
			sieve_runtime_trace_error(renv, "unknown optional operand");
			ret = SIEVE_EXEC_BIN_CORRUPT;
		}

		if ( ret <= 0 ) return ret;
	}

	/* Fixed operands */

	if ( (ret=sieve_opr_string_read
		(renv, address, "annotation", &annotation)) <= 0 )
		return ret;
	if ( (ret=sieve_opr_string_read
		(renv, address, "value", &value)) <= 0 )
		return ret;

	/*
	 * Perform operation
	 */

	if ( sieve_operation_is(oprtn, test_imap_metadata_set_operation) ) {
		if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) {
			sieve_runtime_trace(renv, 0, "testsuite/test_imap_metadata_set command");
			sieve_runtime_trace_descend(renv);
			if (mailbox == NULL) {
				sieve_runtime_trace(renv, 0,
					"set server annotation `%s'", str_c(annotation));
			} else {
				sieve_runtime_trace(renv, 0,
					"set annotation `%s' for mailbox `%s'",
					str_c(annotation), str_c(mailbox));
			}
		}

		if (testsuite_mailstore_set_imap_metadata
			(( mailbox == NULL ? NULL : str_c(mailbox) ),
				str_c(annotation), str_c(value)) < 0)
			return SIEVE_EXEC_FAILURE;
	}

	return SIEVE_EXEC_OK;
}
Example #20
0
static int cmd_execute_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{	
	const struct sieve_extension *this_ext = renv->oprtn->ext;
	struct sieve_side_effects_list *slist = NULL;
	int opt_code = 0;
	unsigned int is_test = 0;
	struct sieve_stringlist *args_list = NULL;
	string_t *pname = NULL, *input = NULL;
	struct sieve_variable_storage *var_storage = NULL;
	unsigned int var_index;
	bool have_input = FALSE;
	const char *program_name = NULL;
	const char *const *args = NULL;
	enum sieve_error error = SIEVE_ERROR_NONE;
	buffer_t *outbuf = NULL;
	struct sieve_extprogram *sprog = NULL;
	int ret;

	/*
	 * Read operands
	 */

	/* The is_test flag */
	if ( !sieve_binary_read_byte(renv->sblock, address, &is_test) ) {
		sieve_runtime_trace_error(renv, "invalid is_test flag");
		return SIEVE_EXEC_BIN_CORRUPT;
	}

	/* Optional operands */	

	for (;;) {
		int opt;

		if ( (opt=sieve_action_opr_optional_read
			(renv, address, &opt_code, &ret, &slist)) < 0 )
			return ret;

		if ( opt == 0 ) break;

		switch ( opt_code ) {
		case OPT_INPUT:
			ret = sieve_opr_string_read_ex
				(renv, address, "input", TRUE, &input, NULL);
			have_input = TRUE;
			break;
		case OPT_OUTPUT:
			ret = sieve_variable_operand_read
				(renv, address, "output", &var_storage, &var_index);
			break;
		default:
			sieve_runtime_trace_error(renv, "unknown optional operand");
			return SIEVE_EXEC_BIN_CORRUPT;
		}

		if ( ret <= 0 ) return ret;
	}

	/* Fixed operands */

	if ( (ret=sieve_extprogram_command_read_operands
		(renv, address, &pname, &args_list)) <= 0 )
		return ret;

	program_name = str_c(pname);
	if ( args_list != NULL &&
		sieve_stringlist_read_all(args_list, pool_datastack_create(), &args) < 0 ) {
		sieve_runtime_trace_error(renv, "failed to read args operand");
		return args_list->exec_status;
	}

	/*
	 * Perform operation
	 */

	/* Trace */

	sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "execute action");
	sieve_runtime_trace_descend(renv);
	sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS,
		"execute program `%s'", str_sanitize(program_name, 128));

	sprog = sieve_extprogram_create
		(this_ext, renv->scriptenv, renv->msgdata, "execute", program_name, args,
			&error);
	if ( sprog != NULL ) {
		if ( var_storage != NULL ) {
			// FIXME: limit output size
			struct ostream *outdata;

			outbuf = buffer_create_dynamic(pool_datastack_create(), 1024);
			outdata = o_stream_create_buffer(outbuf);
			sieve_extprogram_set_output(sprog, outdata);
			o_stream_unref(&outdata);
		}

		if ( input == NULL && have_input ) {
			struct mail *mail = sieve_message_get_mail(renv->msgctx);

			if ( sieve_extprogram_set_input_mail(sprog, mail) < 0 ) {
				sieve_extprogram_destroy(&sprog);
				return sieve_runtime_mail_error(renv, mail,
					"execute action: failed to read input message");
			}
			ret = 1;
		} else if ( input != NULL ) {
			struct istream *indata =
				i_stream_create_from_data(str_data(input), str_len(input));
			sieve_extprogram_set_input(sprog, indata);
			i_stream_unref(&indata);
			ret = 1;
		}

		if ( ret >= 0 ) 
			ret = sieve_extprogram_run(sprog);
		sieve_extprogram_destroy(&sprog);
	} else {
		ret = -1;
	}

	if ( ret > 0 ) {
		sieve_runtime_trace(renv,	SIEVE_TRLVL_ACTIONS,
			"executed program successfully");

		if ( var_storage != NULL ) {
			string_t *var;

			if ( sieve_variable_get_modifiable(var_storage, var_index, &var) ) {
				str_truncate(var, 0);
				str_append_str(var, outbuf); 

				sieve_runtime_trace(renv,	SIEVE_TRLVL_ACTIONS,
					"assigned output variable");
			} // FIXME: handle failure
		}

	} else if ( ret < 0 ) {
		if ( error == SIEVE_ERROR_NOT_FOUND ) {
			sieve_runtime_error(renv, NULL,
				"execute action: program `%s' not found",
				str_sanitize(program_name, 80));
		} else {
			sieve_extprogram_exec_error(renv->ehandler,
				sieve_runtime_get_full_command_location(renv),
				"execute action: failed to execute to program `%s'",
				str_sanitize(program_name, 80));
		}
	} else {
		sieve_runtime_trace(renv,	SIEVE_TRLVL_ACTIONS,
			"execute action: program indicated false result");
	}

	if ( outbuf != NULL ) 
		buffer_free(&outbuf);

	if ( is_test )
		sieve_interpreter_set_test_result(renv->interp, ( ret > 0 ));

	return SIEVE_EXEC_OK;
}