Пример #1
0
static bool tag_comparator_validate
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
	struct sieve_command *cmd)
{
	struct sieve_ast_argument *tag = *arg;
	const struct sieve_comparator *cmp;

	/* Skip tag */
	*arg = sieve_ast_argument_next(*arg);

	/* Check syntax:
	 *   ":comparator" <comparator-name: string>
	 */
	if ( !sieve_validate_tag_parameter
		(valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING, FALSE) ) {
		return FALSE;
	}

	/* FIXME: We can currently only handle string literal argument, so
	 * variables are not allowed.
	 */
	if ( !sieve_argument_is_string_literal(*arg) ) {
		sieve_argument_validate_error(valdtr, *arg,
			"this Sieve implementation currently only supports "
			"a literal string argument for the :comparator tag");
		return FALSE;
	}

	/* Get comparator from registry */
	cmp = sieve_comparator_create(valdtr, cmd, sieve_ast_argument_strc(*arg));

	if ( cmp == NULL ) {
		sieve_argument_validate_error(valdtr, *arg,
			"unknown comparator '%s'",
			str_sanitize(sieve_ast_argument_strc(*arg),80));

		return FALSE;
	}

	/* String argument not needed during code generation, so detach it from
	 * argument list
	 */
	*arg = sieve_ast_arguments_detach(*arg, 1);

	/* Store comparator in context */
	tag->argument->data = (void *) cmp;

	return TRUE;
}
Пример #2
0
static bool cmd_execute_validate_output_tag
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, 
	struct sieve_command *cmd)
{
	struct sieve_ast_argument *tag = *arg;
	struct sieve_extprograms_config *ext_config =
		(struct sieve_extprograms_config *) cmd->ext->context;

	if ( ext_config == NULL || ext_config->var_ext == NULL ||
		!sieve_ext_variables_is_active(ext_config->var_ext, valdtr) )	{
		sieve_argument_validate_error(valdtr,*arg, 
			"the %s %s only allows for the specification of an "
			":output argument when the variables extension is active",
			sieve_command_identifier(cmd), sieve_command_type_name(cmd));
		return FALSE;
	}

	/* Detach the tag itself */
	*arg = sieve_ast_arguments_detach(*arg, 1);
	
	if ( !sieve_variable_argument_activate
		(ext_config->var_ext, valdtr, cmd, *arg, TRUE) )
		return FALSE;

	(*arg)->argument->id_code = tag->argument->id_code;

	/* Skip parameter */
	*arg = sieve_ast_argument_next(*arg);
					
	return TRUE;
}		
Пример #3
0
static bool cmd_include_validate_location_tag
(struct sieve_validator *valdtr,	struct sieve_ast_argument **arg,
	struct sieve_command *cmd)
{
	struct cmd_include_context_data *ctx_data =
		(struct cmd_include_context_data *) cmd->data;

	if ( ctx_data->location_assigned) {
		sieve_argument_validate_error(valdtr, *arg,
			"include: cannot use location tags ':personal' and ':global' "
			"multiple times");
		return FALSE;
	}

	if ( sieve_argument_is(*arg, include_personal_tag) )
		ctx_data->location = EXT_INCLUDE_LOCATION_PERSONAL;
	else if ( sieve_argument_is(*arg, include_global_tag) )
		ctx_data->location = EXT_INCLUDE_LOCATION_GLOBAL;
	else
		return FALSE;

	ctx_data->location_assigned = TRUE;

	/* Delete this tag (for now) */
	*arg = sieve_ast_arguments_detach(*arg, 1);

	return TRUE;
}
Пример #4
0
static bool cmd_execute_validate_input_tag
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
    struct sieve_command *cmd)
{
	struct sieve_ast_argument *tag = *arg;

	if ( (bool) cmd->data ) {
		sieve_argument_validate_error(valdtr, *arg,
			"multiple :input or :pipe arguments specified for the %s %s",
			sieve_command_identifier(cmd), sieve_command_type_name(cmd));
		return FALSE;
	}

	cmd->data = (void *) TRUE;

	/* Skip tag */
 	*arg = sieve_ast_argument_next(*arg);

	if ( sieve_argument_is(tag, execute_input_tag) ) {
		/* Check syntax:
		 *   :input <input-data: string>
		 */
		if ( !sieve_validate_tag_parameter
			(valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING, FALSE) ) {
			return FALSE;
		}

		/* Assign tag parameters */
		tag->parameters = *arg;
		*arg = sieve_ast_arguments_detach(*arg,1);
	}

	return TRUE;
}
Пример #5
0
static bool tag_body_transform_validate
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, 
	struct sieve_command *cmd)
{
	enum tst_body_transform transform;
	struct sieve_ast_argument *tag = *arg;

	/* BODY-TRANSFORM:
	 *   :raw
	 *     / :content <content-types: string-list>
	 *     / :text
	 */
	if ( (bool) cmd->data ) {
		sieve_argument_validate_error(valdtr, *arg, 
			"the :raw, :content and :text arguments for the body test are mutually "
			"exclusive, but more than one was specified");
		return FALSE;
	}

	/* Skip tag */
	*arg = sieve_ast_argument_next(*arg);

	/* :content tag has a string-list argument */
	if ( sieve_argument_is(tag, body_raw_tag) ) 
		transform = TST_BODY_TRANSFORM_RAW;
		
	else if ( sieve_argument_is(tag, body_text_tag) )
		transform = TST_BODY_TRANSFORM_TEXT;
		
	else if ( sieve_argument_is(tag, body_content_tag) ) {
		/* Check syntax:
		 *   :content <content-types: string-list>
		 */
		if ( !sieve_validate_tag_parameter
			(valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING_LIST, FALSE) ) {
			return FALSE;
		}
		
		/* Assign tag parameters */
		tag->parameters = *arg;
		*arg = sieve_ast_arguments_detach(*arg,1);
		
		transform = TST_BODY_TRANSFORM_CONTENT;
	} else 
		return FALSE;
	
	/* Signal the presence of this tag */
	cmd->data = (void *) TRUE;
		
	/* Assign context data */
	tag->argument->data = (void *) transform;	
		
	return TRUE;
}
Пример #6
0
static bool tag_match_type_validate
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
	struct sieve_command *cmd)
{
	struct cmd_denotify_context_data *cmd_data =
        (struct cmd_denotify_context_data *) cmd->data;
	struct sieve_ast_argument *tag = *arg;

	if ( !match_type_tag.validate(valdtr, arg, cmd) )
		return FALSE;

	if ( *arg == NULL ) {
		sieve_argument_validate_error(valdtr, tag,
			"the MATCH-TYPE argument (:%s) for the denotify command requires "
			"an additional key-string parameter, but no more arguments were found",
			sieve_ast_argument_tag(tag));
		return FALSE;
	}

	if ( sieve_ast_argument_type(*arg) != SAAT_STRING )
	{
		sieve_argument_validate_error(valdtr, *arg,
			"the MATCH-TYPE argument (:%s) for the denotify command requires "
			"an additional key-string parameter, but %s was found",
			sieve_ast_argument_tag(tag), sieve_ast_argument_name(*arg));
		return FALSE;
	}

	if ( !sieve_validator_argument_activate(valdtr, cmd, *arg, FALSE) )
		return FALSE;

	tag->argument->def = &match_type_tag;
	tag->argument->ext = NULL;

	(*arg)->argument->id_code = OPT_MATCH_KEY;
	cmd_data->match_key_arg = *arg;

	*arg = sieve_ast_argument_next(*arg);

	return TRUE;
}
Пример #7
0
static bool tst_spamtest_validate_percent_tag
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
	struct sieve_command *tst)
{
	if ( !sieve_extension_is(tst->ext, spamtestplus_extension) ) {
		sieve_argument_validate_error(valdtr, *arg,
			"the spamtest test only accepts the :percent argument when "
			"the spamtestplus extension is active");
		return FALSE;
	}

	/* Skip tag */
	*arg = sieve_ast_argument_next(*arg);

	return TRUE;
}
Пример #8
0
static bool cmd_vacation_validate_string_tag
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
	struct sieve_command *cmd)
{
	struct sieve_ast_argument *tag = *arg;
	struct cmd_vacation_context_data *ctx_data =
		(struct cmd_vacation_context_data *) cmd->data;

	/* Detach the tag itself */
	*arg = sieve_ast_arguments_detach(*arg,1);

	/* Check syntax:
	 *   :subject string
	 *   :from string
	 *   :handle string
	 */
	if ( !sieve_validate_tag_parameter
		(valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING, FALSE) ) {
		return FALSE;
	}

	if ( sieve_argument_is(tag, vacation_from_tag) ) {
		if ( sieve_argument_is_string_literal(*arg) ) {
			string_t *address = sieve_ast_argument_str(*arg);
			const char *error;
	 		bool result;

	 		T_BEGIN {
	 			result = sieve_address_validate(address, &error);

				if ( !result ) {
					sieve_argument_validate_error(valdtr, *arg,
						"specified :from address '%s' is invalid for vacation action: %s",
						str_sanitize(str_c(address), 128), error);
				}
			} T_END;

			if ( !result )
				return FALSE;
		}

		ctx_data->from = sieve_ast_argument_str(*arg);

		/* Skip parameter */
		*arg = sieve_ast_argument_next(*arg);

	} else if ( sieve_argument_is(tag, vacation_subject_tag) ) {
Пример #9
0
static bool tst_size_validate_over_tag
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
	struct sieve_command *tst)
{
	struct tst_size_context_data *ctx_data =
		(struct tst_size_context_data *) tst->data;

	if ( ctx_data->type != SIZE_UNASSIGNED ) {
		sieve_argument_validate_error(valdtr, *arg, TST_SIZE_ERROR_DUP_TAG);
		return FALSE;
	}

	ctx_data->type = SIZE_OVER;

	/* Delete this tag */
	*arg = sieve_ast_arguments_detach(*arg, 1);

	return TRUE;
}
Пример #10
0
static int _arg_validate
(void *context, struct sieve_ast_argument *item)
{
	struct _arg_validate_context *actx = (struct _arg_validate_context *) context;

	if ( sieve_argument_is_string_literal(item) ) {
		string_t *arg = sieve_ast_argument_str(item);

		if ( !sieve_extprogram_arg_is_valid(arg) ) {
			sieve_argument_validate_error(actx->valdtr, item,
				"%s %s: specified external program argument `%s' is invalid",
				sieve_command_identifier(actx->cmd), sieve_command_type_name(actx->cmd),
				str_sanitize(str_c(arg), 128));

			return FALSE;
		}
	}

	return TRUE;
}
static bool ext_variables_variable_argument_activate
(const struct sieve_extension *this_ext, struct sieve_validator *valdtr,
	struct sieve_ast_argument *arg, const char *variable)
{
	struct sieve_ast *ast = arg->ast;
	struct sieve_variable *var;

	var = ext_variables_validator_get_variable(this_ext, valdtr, variable, TRUE);

	if ( var == NULL ) {
		sieve_argument_validate_error(valdtr, arg,
			"(implicit) declaration of new variable '%s' exceeds the limit "
			"(max variables: %u)", variable,
			EXT_VARIABLES_MAX_SCOPE_SIZE);
		return FALSE;
	}

	arg->argument = sieve_argument_create(ast, &variable_argument, this_ext, 0);
	arg->argument->data = (void *) var;
	return TRUE;
}
bool ext_imap4flags_command_validate
(struct sieve_validator *valdtr, struct sieve_command *cmd)
{
	struct sieve_ast_argument *arg = cmd->first_positional;
	struct sieve_ast_argument *arg2;
	const struct sieve_extension *var_ext;

	/* Check arguments */

	if ( arg == NULL ) {
		sieve_command_validate_error(valdtr, cmd,
			"the %s %s expects at least one argument, but none was found",
			sieve_command_identifier(cmd), sieve_command_type_name(cmd));
		return FALSE;
	}

	if ( sieve_ast_argument_type(arg) != SAAT_STRING &&
		sieve_ast_argument_type(arg) != SAAT_STRING_LIST )
	{
		sieve_argument_validate_error(valdtr, arg,
			"the %s %s expects either a string (variable name) or "
			"a string-list (list of flags) as first argument, but %s was found",
			sieve_command_identifier(cmd), sieve_command_type_name(cmd),
			sieve_ast_argument_name(arg));
		return FALSE;
	}

	arg2 = sieve_ast_argument_next(arg);
	if ( arg2 != NULL ) {
		/* First, check syntax sanity */

		if ( sieve_ast_argument_type(arg) != SAAT_STRING )
		{
			if ( sieve_command_is(cmd, tst_hasflag) ) {
				if ( sieve_ast_argument_type(arg) != SAAT_STRING_LIST ) {
					sieve_argument_validate_error(valdtr, arg,
						"if a second argument is specified for the hasflag, the first "
						"must be a string-list (variable-list), but %s was found",
						sieve_ast_argument_name(arg));
					return FALSE;
				}
			} else {
				sieve_argument_validate_error(valdtr, arg,
					"if a second argument is specified for the %s %s, the first "
					"must be a string (variable name), but %s was found",
					sieve_command_identifier(cmd), sieve_command_type_name(cmd),
					sieve_ast_argument_name(arg));
				return FALSE;
			}
		}

		/* Then, check whether the second argument is permitted */

		var_ext = sieve_ext_variables_get_extension(cmd->ext->svinst);

		if ( var_ext == NULL || !sieve_ext_variables_is_active(var_ext, valdtr) )
			{
			sieve_argument_validate_error(valdtr,arg,
				"the %s %s only allows for the specification of a "
				"variable name when the variables extension is active",
				sieve_command_identifier(cmd), sieve_command_type_name(cmd));
			return FALSE;
		}

		if ( !sieve_variable_argument_activate
			(var_ext, valdtr, cmd, arg, !sieve_command_is(cmd, tst_hasflag) ) )
			return FALSE;

		if ( sieve_ast_argument_type(arg2) != SAAT_STRING &&
			sieve_ast_argument_type(arg2) != SAAT_STRING_LIST )
		{
			sieve_argument_validate_error(valdtr, arg2,
				"the %s %s expects a string list (list of flags) as "
				"second argument when two arguments are specified, "
				"but %s was found",
				sieve_command_identifier(cmd), sieve_command_type_name(cmd),
				sieve_ast_argument_name(arg2));
			return FALSE;
		}
	} else
		arg2 = arg;

	if ( !sieve_validator_argument_activate(valdtr, cmd, arg2, FALSE) )
		return FALSE;

	if ( !sieve_command_is(cmd, tst_hasflag) &&
		sieve_argument_is_string_literal(arg2) ) {
		struct ext_imap4flags_iter fiter;
		const char *flag;

		/* Warn the user about validity of verifiable flags */
		ext_imap4flags_iter_init(&fiter, sieve_ast_argument_str(arg));

		while ( (flag=ext_imap4flags_iter_get_flag(&fiter)) != NULL ) {
			if ( !sieve_ext_imap4flags_flag_is_valid(flag) ) {
				sieve_argument_validate_warning(valdtr, arg,
					"IMAP flag '%s' specified for the %s command is invalid "
					"and will be ignored (only first invalid is reported)",
					str_sanitize(flag, 64), sieve_command_identifier(cmd));
				break;
			}
		}
	}

	return TRUE;
}
Пример #13
0
static bool cmd_global_validate
(struct sieve_validator *valdtr, struct sieve_command *cmd)
{
	const struct sieve_extension *this_ext = cmd->ext;
	struct sieve_ast_argument *arg = cmd->first_positional;
	struct sieve_command *prev = sieve_command_prev(cmd);

	/* DEPRECATED: Check valid command placement */
	if ( !sieve_command_is(cmd, cmd_global) ) {
		if ( !sieve_command_is_toplevel(cmd) ||
			( !sieve_command_is_first(cmd) && prev != NULL &&
				!sieve_command_is(prev, cmd_require) &&
				!sieve_command_is(prev, cmd_import) &&
				!sieve_command_is(prev, cmd_export) ) ) {
			sieve_command_validate_error(valdtr, cmd,
				"the DEPRECATED %s command can only be placed at top level "
				"at the beginning of the file after any require or "
				"import/export commands",
				sieve_command_identifier(cmd));
			return FALSE;
		}
	}

	/* Check for use of variables extension */
	if ( !ext_include_validator_have_variables(this_ext, valdtr) ) {
		sieve_command_validate_error(valdtr, cmd,
			"%s command requires that variables extension is active",
			sieve_command_identifier(cmd));
		return FALSE;
	}

	/* Register global variable */
	if ( sieve_ast_argument_type(arg) == SAAT_STRING ) {
		/* Single string */
		const char *identifier = sieve_ast_argument_strc(arg);
		struct sieve_variable *var;

		if ( (var=ext_include_variable_import_global
			(valdtr, cmd, identifier)) == NULL )
			return FALSE;

		arg->argument = _create_variable_argument(cmd, var);

	} else if ( sieve_ast_argument_type(arg) == SAAT_STRING_LIST ) {
		/* String list */
		struct sieve_ast_argument *stritem = sieve_ast_strlist_first(arg);

		while ( stritem != NULL ) {
			const char *identifier = sieve_ast_argument_strc(stritem);
			struct sieve_variable *var;

			if ( (var=ext_include_variable_import_global
				(valdtr, cmd, identifier)) == NULL )
				return FALSE;

			stritem->argument = _create_variable_argument(cmd, var);

			stritem = sieve_ast_strlist_next(stritem);
		}
	} else {
		/* Something else */
		sieve_argument_validate_error(valdtr, arg,
			"the %s command accepts a single string or string list argument, "
			"but %s was found", sieve_command_identifier(cmd),
			sieve_ast_argument_name(arg));
		return FALSE;
	}

	/* Join global commands with predecessors if possible */
	if ( sieve_commands_equal(prev, cmd) ) {
		/* Join this command's string list with the previous one */
		prev->first_positional = sieve_ast_stringlist_join
			(prev->first_positional, cmd->first_positional);

		if ( prev->first_positional == NULL ) {
			/* Not going to happen unless MAXINT stringlist items are specified */
			sieve_command_validate_error(valdtr, cmd,
				"compiler reached AST limit (script too complex)");
			return FALSE;
		}

		/* Detach this command node */
		sieve_ast_node_detach(cmd->ast_node);
	}

	return TRUE;
}
Пример #14
0
bool ext_enotify_compile_check_arguments
(struct sieve_validator *valdtr, struct sieve_command *cmd,
	struct sieve_ast_argument *uri_arg, struct sieve_ast_argument *msg_arg,
	struct sieve_ast_argument *from_arg, struct sieve_ast_argument *options_arg)
{
	const struct sieve_extension *this_ext = cmd->ext;
	struct sieve_instance *svinst = this_ext->svinst;
	const char *uri = sieve_ast_argument_strc(uri_arg);
	const char *scheme;
	const struct sieve_enotify_method *method;
	struct sieve_enotify_env nenv;
	bool result = TRUE;

	/* If the uri string is not a constant literal, we cannot determine which
	 * method is used, so we bail out successfully and defer checking to runtime.
	 */
	if ( !sieve_argument_is_string_literal(uri_arg) )
		return TRUE;

	/* Parse scheme part of URI */
	if ( (scheme=ext_enotify_uri_scheme_parse(&uri)) == NULL ) {
		sieve_argument_validate_error(valdtr, uri_arg,
			"notify command: invalid scheme part for method URI '%s'",
			str_sanitize(sieve_ast_argument_strc(uri_arg), 80));
		return FALSE;
	}

	/* Find used method with the parsed scheme identifier */
	if ( (method=ext_enotify_method_find(this_ext, scheme)) == NULL ) {
		sieve_argument_validate_error(valdtr, uri_arg,
			"notify command: invalid method '%s'", scheme);
		return FALSE;
	}

	if ( method->def == NULL ) return TRUE;

	/* Compose log structure */
	memset(&nenv, 0, sizeof(nenv));
	nenv.svinst = svinst;
	nenv.method = method;

	/* Check URI itself */
	if ( result && method->def->compile_check_uri != NULL ) {
		/* Set log location to location of URI argument */
		nenv.ehandler = sieve_prefix_ehandler_create
		(sieve_validator_error_handler(valdtr),
			sieve_error_script_location
				(sieve_validator_script(valdtr), uri_arg->source_line),
			"notify command");

		/* Execute method check function */
		result = method->def->compile_check_uri
			(&nenv, sieve_ast_argument_strc(uri_arg), uri);
	}

	/* Check :message argument */
	if ( result && msg_arg != NULL && sieve_argument_is_string_literal(msg_arg)
		&& method->def->compile_check_message != NULL ) {
		/* Set log location to location of :message argument */
		sieve_error_handler_unref(&nenv.ehandler);
		nenv.ehandler = sieve_prefix_ehandler_create
		(sieve_validator_error_handler(valdtr),
			sieve_error_script_location
				(sieve_validator_script(valdtr), msg_arg->source_line),
			"notify command");

		/* Execute method check function */
		result = method->def->compile_check_message
			(&nenv, sieve_ast_argument_str(msg_arg));
	}

	/* Check :from argument */
	if ( result && from_arg != NULL && sieve_argument_is_string_literal(from_arg)
		&& method->def->compile_check_from != NULL ) {
		/* Set log location to location of :from argument */
		sieve_error_handler_unref(&nenv.ehandler);
		nenv.ehandler = sieve_prefix_ehandler_create
		(sieve_validator_error_handler(valdtr),
			sieve_error_script_location
				(sieve_validator_script(valdtr), from_arg->source_line),
				"notify command");

		/* Execute method check function */
		result = method->def->compile_check_from
			(&nenv, sieve_ast_argument_str(from_arg));
	}

	sieve_error_handler_unref(&nenv.ehandler);

	/* Check :options argument */
	if ( result && options_arg != NULL ) {
		struct sieve_ast_argument *option = options_arg;
		struct _ext_enotify_option_check_context optn_context =
			{ svinst, valdtr, method };

		/* Parse and check options */
		result = ( sieve_ast_stringlist_map
			(&option, (void *) &optn_context, _ext_enotify_option_check) > 0 );

		/* Discard argument if options are not accepted by method */
		if ( result && method->def->compile_check_option == NULL ) {
			sieve_argument_validate_warning(valdtr, options_arg,
				"notify command: method '%s' accepts no options", scheme);
			(void)sieve_ast_arguments_detach(options_arg,1);
		}
	}

	return result;
}
Пример #15
0
bool sieve_extprogram_command_validate
(struct sieve_validator *valdtr, struct sieve_command *cmd)
{
	struct sieve_ast_argument *arg = cmd->first_positional;
	struct sieve_ast_argument *stritem;
	struct _arg_validate_context actx;
	string_t *program_name;

	if ( arg == NULL ) {
		sieve_command_validate_error(valdtr, cmd, 
			"the %s %s expects at least one positional argument, but none was found", 
			sieve_command_identifier(cmd), sieve_command_type_name(cmd));
		return FALSE;
	}

	/* <program-name: string> argument */

	if ( !sieve_validate_positional_argument
		(valdtr, cmd, arg, "program-name", 1, SAAT_STRING) ) {
		return FALSE;
	}
	
	if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) )
		return FALSE;

	/* Variables are not allowed */
	if ( !sieve_argument_is_string_literal(arg) ) {
		sieve_argument_validate_error(valdtr, arg, 
			"the %s %s requires a constant string "
			"for its program-name argument",
			sieve_command_identifier(cmd), sieve_command_type_name(cmd));
		return FALSE;
	}

	/* Check program name */
	program_name = sieve_ast_argument_str(arg);
	if ( !sieve_extprogram_name_is_valid(program_name) ) {
 		sieve_argument_validate_error(valdtr, arg,
			"%s %s: invalid program name '%s'",
			sieve_command_identifier(cmd), sieve_command_type_name(cmd),
			str_sanitize(str_c(program_name), 80));
		return FALSE;
	}

	/* Optional <arguments: string-list> argument */

	arg = sieve_ast_argument_next(arg);
	if ( arg == NULL )
		return TRUE;

	if ( !sieve_validate_positional_argument
		(valdtr, cmd, arg, "arguments", 2, SAAT_STRING_LIST) ) {
		return FALSE;
	}

	if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) )
		return FALSE;

	/* Check arguments */
	actx.valdtr = valdtr;
	actx.cmd = cmd;
	stritem = arg;
	if ( sieve_ast_stringlist_map
		(&stritem, (void *)&actx, _arg_validate) <= 0 ) {
		return FALSE;
	}

	if ( sieve_ast_argument_next(arg) != NULL ) {
		sieve_command_validate_error(valdtr, cmd, 
			"the %s %s expects at most two positional arguments, but more were found", 
			sieve_command_identifier(cmd), sieve_command_type_name(cmd));
		return FALSE;
	}

	return TRUE;
}
Пример #16
0
static bool arg_testsuite_string_validate
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
	struct sieve_command *cmd)
{
	enum { ST_NONE, ST_OPEN, ST_SUBSTITUTION, ST_PARAM, ST_CLOSE } state =
		ST_NONE;
	pool_t pool = sieve_ast_pool((*arg)->ast);
	struct sieve_arg_catenated_string *catstr = NULL;
	string_t *str = sieve_ast_argument_str(*arg);
	const char *p, *strstart, *substart = NULL;
	const char *strval = (const char *) str_data(str);
	const char *strend = strval + str_len(str);
	bool result = TRUE;
	string_t *subs_name = t_str_new(256);
	string_t *subs_param = t_str_new(256);

	T_BEGIN {
		/* Initialize substitution structure */

		p = strval;
		strstart = p;
		while ( result && p < strend ) {
			switch ( state ) {

			/* Nothing found yet */
			case ST_NONE:
				if ( *p == '%' ) {
					substart = p;
					state = ST_OPEN;
					str_truncate(subs_name, 0);
					str_truncate(subs_param, 0);
				}
				p++;
				break;

			/* Got '%' */
			case ST_OPEN:
				if ( *p == '{' ) {
					state = ST_SUBSTITUTION;
					p++;
				} else
					state = ST_NONE;
				break;

			/* Got '%{' */
			case ST_SUBSTITUTION:
				state = ST_PARAM;

				while ( *p != '}' && *p != ':' ) {
					if ( !i_isalnum(*p) ) {
						state = ST_NONE;
						break;
					}
					str_append_c(subs_name, *p);
					p++;
				}
				break;

			/* Got '%{name' */
			case ST_PARAM:
				if ( *p == ':' ) {
					p++;
					while ( *p != '}' ) {
						str_append_c(subs_param, *p);
						p++;
					}
				}
				state = ST_CLOSE;
				break;

			/* Finished parsing param, expecting '}' */
			case ST_CLOSE:
				if ( *p == '}' ) {
					struct sieve_ast_argument *strarg;

					/* We now know that the substitution is valid */

					if ( catstr == NULL ) {
						catstr = sieve_arg_catenated_string_create(*arg);
					}

					/* Add the substring that is before the substitution to the
					 * variable-string AST.
					 */
					if ( substart > strstart ) {
						string_t *newstr = str_new(pool, substart - strstart);
						str_append_n(newstr, strstart, substart - strstart);

						strarg = sieve_ast_argument_string_create_raw
							((*arg)->ast, newstr, (*arg)->source_line);
						sieve_arg_catenated_string_add_element(catstr, strarg);

						/* Give other substitution extensions a chance to do their work */
						if ( !sieve_validator_argument_activate_super
							(valdtr, cmd, strarg, FALSE) ) {
							result = FALSE;
							break;
						}
					}

					strarg = testsuite_substitution_argument_create
						(valdtr, (*arg)->ast, (*arg)->source_line, str_c(subs_name),
							str_c(subs_param));

					if ( strarg != NULL )
						sieve_arg_catenated_string_add_element(catstr, strarg);
					else {
						sieve_argument_validate_error(valdtr, *arg,
							"unknown testsuite substitution type '%s'", str_c(subs_name));
					}

					strstart = p + 1;
					substart = strstart;

					p++;
				}

				/* Finished, reset for the next substitution */
				state = ST_NONE;
			}
		}
	} T_END;

	/* Bail out early if substitution is invalid */
	if ( !result ) return FALSE;

	/* Check whether any substitutions were found */
	if ( catstr == NULL ) {
		/* No substitutions in this string, pass it on to any other substution
		 * extension.
		 */
		return sieve_validator_argument_activate_super(valdtr, cmd, *arg, TRUE);
	}

	/* Add the final substring that comes after the last substitution to the
	 * variable-string AST.
	 */
	if ( strend > strstart ) {
		struct sieve_ast_argument *strarg;
		string_t *newstr = str_new(pool, strend - strstart);
		str_append_n(newstr, strstart, strend - strstart);

		strarg = sieve_ast_argument_string_create_raw
			((*arg)->ast, newstr, (*arg)->source_line);
		sieve_arg_catenated_string_add_element(catstr, strarg);

		/* Give other substitution extensions a chance to do their work */
		if ( !sieve_validator_argument_activate_super
			(valdtr, cmd, strarg, FALSE) )
			return FALSE;
	}

	return TRUE;
}
Пример #17
0
static bool cmd_report_validate
(struct sieve_validator *valdtr, struct sieve_command *cmd)
{
	struct sieve_ast_argument *arg = cmd->first_positional;

	/* type */
	if ( !sieve_validate_positional_argument
		(valdtr, cmd, arg, "feedback-type", 1, SAAT_STRING) ) {
		return FALSE;
	}
	if ( !sieve_validator_argument_activate
		(valdtr, cmd, arg, FALSE) )
		return FALSE;

	if ( sieve_argument_is_string_literal(arg) ) {
		string_t *fbtype = sieve_ast_argument_str(arg);
		const char *feedback_type;

		T_BEGIN {
			/* Check feedback type */
			feedback_type = ext_vnd_report_parse_feedback_type
				(str_c(fbtype));

			if ( feedback_type == NULL ) {
				sieve_argument_validate_error(valdtr, arg,
					"specified feedback type `%s' is invalid",
					str_sanitize(str_c(fbtype),128));
			}
		} T_END;

		if ( feedback_type == NULL )
			return FALSE;
	}
	arg = sieve_ast_argument_next(arg);

	/* message */
	if ( !sieve_validate_positional_argument
		(valdtr, cmd, arg, "message", 2, SAAT_STRING) ) {
		return FALSE;
	}
	if ( !sieve_validator_argument_activate
		(valdtr, cmd, arg, FALSE) )
		return FALSE;
	arg = sieve_ast_argument_next(arg);

	/* address */
	if ( !sieve_validate_positional_argument
		(valdtr, cmd, arg, "address", 3, SAAT_STRING) ) {
		return FALSE;
	}
	if ( !sieve_validator_argument_activate
		(valdtr, cmd, arg, FALSE) )
		return FALSE;

	/* We can only assess the validity of the outgoing address when it is
	 * a string literal. For runtime-generated strings this needs to be
	 * done at runtime.
	 */
	if ( sieve_argument_is_string_literal(arg) ) {
		string_t *address = sieve_ast_argument_str(arg);
		const char *error;
		const char *norm_address;

		T_BEGIN {
			/* Verify and normalize the address to 'local_part@domain' */
			norm_address = sieve_address_normalize(address, &error);

			if ( norm_address == NULL ) {
				sieve_argument_validate_error(valdtr, arg,
					"specified redirect address `%s' is invalid: %s",
					str_sanitize(str_c(address),128), error);
			} else {
				/* Replace string literal in AST */
				sieve_ast_argument_string_setc(arg, norm_address);
			}
		} T_END;

		return ( norm_address != NULL );
	}

	return TRUE;
}