static int _ext_enotify_option_check
(void *context, struct sieve_ast_argument *arg)
{
	struct _ext_enotify_option_check_context *optn_context =
		(struct _ext_enotify_option_check_context *) context;
	struct sieve_validator *valdtr = optn_context->valdtr;
	const struct sieve_enotify_method *method = optn_context->method;
	struct sieve_enotify_env nenv;
	const char *option = sieve_ast_argument_strc(arg);
	const char *opt_name = NULL, *opt_value = NULL;
	bool check = TRUE;
	int result = 1;

	/* Compose log structure */
	memset(&nenv, 0, sizeof(nenv));
	nenv.svinst = optn_context->svinst;
	nenv.method = method;
	nenv.ehandler = sieve_prefix_ehandler_create
		(sieve_validator_error_handler(valdtr),
			sieve_error_script_location
				(sieve_validator_script(valdtr), arg->source_line),
			"notify command");

	/* Parse option */
	if ( !sieve_argument_is_string_literal(arg) ) {
		/* Variable string: partial option parse
		 *
		 * If the string item is not a string literal, it cannot be validated fully
		 * at compile time. We can however check whether the '=' is in the string
		 * specification and whether the part before the '=' is a valid option name.
		 * In that case, the method option check function is called with the value
		 * parameter equal to NULL, meaning that it should only check the validity
		 * of the option itself and not the assigned value.
		 */
		if ( !ext_enotify_option_parse(NULL, option, TRUE, &opt_name, &opt_value) )
			check = FALSE;
	} else {
		/* Literal string: full option parse */
		if ( !ext_enotify_option_parse
			(&nenv, option, FALSE, &opt_name, &opt_value) )
			result = -1;
	}

	/* Call method's option check function */
	if ( result > 0 && check && method->def != NULL &&
		method->def->compile_check_option != NULL ) {
		result = ( method->def->compile_check_option
			(&nenv, opt_name, opt_value) ? 1 : -1 );
	}

	sieve_error_handler_unref(&nenv.ehandler);

	return result;
}
Beispiel #2
0
void sieve_generator_critical
(struct sieve_generator *gentr, unsigned int source_line,
	const char *fmt, ...)
{
	va_list args;

	va_start(args, fmt);
	sieve_vwarning(gentr->ehandler,
        sieve_error_script_location(gentr->genenv.script, source_line),
        fmt, args);
	va_end(args);
}
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;
}