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; }
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; }