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