예제 #1
0
static const struct sieve_enotify_method *ext_enotify_get_method
(const struct sieve_runtime_env *renv, string_t *method_uri,
	const char **uri_body_r)
{
	const struct sieve_extension *this_ext = renv->oprtn->ext;
	const struct sieve_enotify_method *method;
	const char *uri = str_c(method_uri);
	const char *scheme;

	/* Parse part before ':' of the uri (the scheme) and use it to identify
	 * notify method.
	 */
	if ( (scheme=ext_enotify_uri_scheme_parse(&uri)) == NULL ) {
		sieve_runtime_error(renv, NULL,
			"invalid scheme part for method URI '%s'",
			str_sanitize(str_c(method_uri), 80));
		return NULL;
	}

	/* Find the notify method */
	if ( (method=ext_enotify_method_find(this_ext, scheme)) == NULL ) {
		sieve_runtime_error(renv, NULL,
			"invalid notify method '%s'", scheme);
		return NULL;
	}

	/* Return the parse pointer and the found method */
	*uri_body_r = uri;
	return method;
}
예제 #2
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;
}
예제 #3
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;
}
bool testsuite_result_execute(const struct sieve_runtime_env *renv)
{
	int ret;

	if ( _testsuite_result == NULL ) {
		sieve_runtime_error(renv, NULL,
			"testsuite: trying to execute result, but no result evaluated yet");
		return FALSE;
	}

	testsuite_log_clear_messages();

	/* Execute the result */
	ret=sieve_result_execute(_testsuite_result, NULL);

	return ( ret > 0 );
}
int sieve_extprogram_command_read_operands
(const struct sieve_runtime_env *renv, sieve_size_t *address,
	string_t **pname_r, struct sieve_stringlist **args_list_r)
{	
	string_t *arg;
	int ret;

	/*
	 * Read fixed operands
	 */

	if ( (ret=sieve_opr_string_read
		(renv, address, "program-name", pname_r)) <= 0 )
		return ret;

	if ( (ret=sieve_opr_stringlist_read_ex
		(renv, address, "arguments", TRUE, args_list_r)) <= 0 )
		return ret;
		
	/*
	 * Check operands
	 */

	arg = NULL;
	while ( *args_list_r != NULL &&
		(ret=sieve_stringlist_next_item(*args_list_r, &arg)) > 0 ) {
		if ( !sieve_extprogram_arg_is_valid(arg) ) {
			sieve_runtime_error(renv, NULL,
				"specified :args item `%s' is invalid",
				str_sanitize(str_c(arg), 128));
			return SIEVE_EXEC_FAILURE;
		}
	}

	if ( ret < 0 ) {
		sieve_runtime_trace_error(renv, "invalid args-list item");
		return SIEVE_EXEC_BIN_CORRUPT;
	}

	return SIEVE_EXEC_OK;
}
예제 #6
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 );
}
예제 #7
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;
}
예제 #8
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;
}