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;
}
예제 #2
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;
}