bool sieve_generate_argument_parameters (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd, struct sieve_ast_argument *arg) { struct sieve_ast_argument *param = arg->parameters; /* Generate all parameters with assigned generator function */ while ( param != NULL ) { if ( param->argument != NULL && param->argument->def != NULL ) { const struct sieve_argument_def *parameter = param->argument->def; /* Call the generation function for the parameter */ if ( parameter->generate != NULL ) { sieve_generate_debug_from_ast_argument(cgenv, param); if ( !parameter->generate(cgenv, param, cmd) ) return FALSE; } } param = sieve_ast_argument_next(param); } 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_test_config_set_validate (struct sieve_validator *valdtr, struct sieve_command *cmd) { struct sieve_ast_argument *arg = cmd->first_positional; /* Check syntax: * <setting: string> <value: string> */ if ( !sieve_validate_positional_argument (valdtr, cmd, arg, "setting", 1, SAAT_STRING) ) { return FALSE; } if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) ) return FALSE; arg = sieve_ast_argument_next(arg); if ( !sieve_validate_positional_argument (valdtr, cmd, arg, "value", 2, SAAT_STRING) ) { return FALSE; } return sieve_validator_argument_activate(valdtr, cmd, arg, FALSE); }
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 cmd_vacation_validate_number_tag (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, struct sieve_command *cmd) { const struct sieve_extension *ext = sieve_argument_ext(*arg); const struct ext_vacation_config *config = (const struct ext_vacation_config *) ext->context; struct sieve_ast_argument *tag = *arg; sieve_number_t period, seconds; /* Detach the tag itself */ *arg = sieve_ast_arguments_detach(*arg,1); /* Check syntax: * :days number */ if ( !sieve_validate_tag_parameter (valdtr, cmd, tag, *arg, NULL, 0, SAAT_NUMBER, FALSE) ) { return FALSE; } period = sieve_ast_argument_number(*arg); if ( sieve_argument_is(tag, vacation_days_tag) ) { seconds = period * (24*60*60); } else if ( sieve_argument_is(tag, vacation_seconds_tag) ) { seconds = period; } else { i_unreached(); } /* Enforce :seconds >= min_period */ if ( seconds < config->min_period ) { seconds = config->min_period; sieve_argument_validate_warning(valdtr, *arg, "specified :%s value '%lu' is under the minimum", sieve_argument_identifier(tag), (unsigned long) period); /* Enforce :days <= max_period */ } else if ( config->max_period > 0 && seconds > config->max_period ) { seconds = config->max_period; sieve_argument_validate_warning(valdtr, *arg, "specified :%s value '%lu' is over the maximum", sieve_argument_identifier(tag), (unsigned long) period); } sieve_ast_argument_number_set(*arg, seconds); /* Skip parameter */ *arg = sieve_ast_argument_next(*arg); 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_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 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 cmd_filter_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { sieve_operation_emit(cgenv->sblock, cmd->ext, &cmd_filter_operation); /* Emit is_test flag */ sieve_binary_emit_byte(cgenv->sblock, ( cmd->ast_node->type == SAT_TEST )); /* Generate arguments */ if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) return FALSE; /* Emit a placeholder when the <arguments> argument is missing */ if ( sieve_ast_argument_next(cmd->first_positional) == NULL ) sieve_opr_omitted_emit(cgenv->sblock); 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 cmd_test_imap_metadata_validate_mailbox_tag (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, struct sieve_command *cmd) { struct sieve_ast_argument *tag = *arg; /* Delete this tag */ *arg = sieve_ast_arguments_detach(*arg, 1); /* Check syntax: * :mailbox string */ if ( !sieve_validate_tag_parameter (valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING, FALSE) ) { return FALSE; } /* Skip parameter */ *arg = sieve_ast_argument_next(*arg); return TRUE; }
static bool tst_test_error_validate_index_tag (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, struct sieve_command *cmd) { struct sieve_ast_argument *tag = *arg; /* Detach the tag itself */ *arg = sieve_ast_arguments_detach(*arg,1); /* Check syntax: * :index number */ if ( !sieve_validate_tag_parameter (valdtr, cmd, tag, *arg, NULL, 0, SAAT_NUMBER, FALSE) ) { return FALSE; } /* Skip parameter */ *arg = sieve_ast_argument_next(*arg); return TRUE; }
static bool cmd_test_imap_metadata_validate (struct sieve_validator *valdtr, struct sieve_command *cmd) { struct sieve_ast_argument *arg = cmd->first_positional; if ( !sieve_validate_positional_argument (valdtr, cmd, arg, "annotation", 2, SAAT_STRING) ) return FALSE; if (!sieve_validator_argument_activate(valdtr, cmd, arg, FALSE)) return FALSE; arg = sieve_ast_argument_next(arg); if ( !sieve_validate_positional_argument (valdtr, cmd, arg, "value", 3, SAAT_STRING) ) return FALSE; if (!sieve_validator_argument_activate(valdtr, cmd, arg, FALSE)) return FALSE; return TRUE; }
static bool cmd_test_config_reload_validate_tag (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, struct sieve_command *cmd) { struct sieve_ast_argument *tag = *arg; /* Detach the tag itself */ *arg = sieve_ast_arguments_detach(*arg,1); /* Check syntax: * :extension <extension: string> */ if ( !sieve_validate_tag_parameter (valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING, TRUE) ) { return FALSE; } /* Skip parameter */ *arg = sieve_ast_argument_next(*arg); return TRUE; }
static bool cmd_test_set_validate (struct sieve_validator *valdtr, struct sieve_command *cmd) { struct sieve_ast_argument *arg = cmd->first_positional; /* Check arguments */ if ( !sieve_validate_positional_argument (valdtr, cmd, arg, "object", 1, SAAT_STRING) ) { return FALSE; } if ( !testsuite_object_argument_activate(valdtr, arg, cmd) ) return FALSE; arg = sieve_ast_argument_next(arg); if ( !sieve_validate_positional_argument (valdtr, cmd, arg, "value", 2, SAAT_STRING) ) { return FALSE; } return sieve_validator_argument_activate(valdtr, cmd, arg, FALSE); }
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_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; }
bool sieve_generate_arguments (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd, struct sieve_ast_argument **last_arg_r) { enum { ARG_START, ARG_OPTIONAL, ARG_POSITIONAL } state = ARG_START; struct sieve_ast_argument *arg = sieve_ast_argument_first(cmd->ast_node); /* Generate all arguments with assigned generator function */ while ( arg != NULL ) { const struct sieve_argument *argument; const struct sieve_argument_def *arg_def; if ( arg->argument == NULL || arg->argument->def == NULL ) return FALSE; argument = arg->argument; arg_def = argument->def; switch ( state ) { case ARG_START: if ( argument->id_code == 0 ) state = ARG_POSITIONAL; else { /* Mark start of optional operands with 0 operand identifier */ sieve_binary_emit_byte(cgenv->sblock, SIEVE_OPERAND_OPTIONAL); /* Emit argument id for optional operand */ sieve_binary_emit_byte (cgenv->sblock, (unsigned char) argument->id_code); state = ARG_OPTIONAL; } break; case ARG_OPTIONAL: if ( argument->id_code == 0 ) state = ARG_POSITIONAL; /* Emit argument id for optional operand (0 marks the end of the optionals) */ sieve_binary_emit_byte (cgenv->sblock, (unsigned char) argument->id_code); break; case ARG_POSITIONAL: if ( argument->id_code != 0 ) return FALSE; break; } /* Call the generation function for the argument */ if ( arg_def->generate != NULL ) { sieve_generate_debug_from_ast_argument(cgenv, arg); if ( !arg_def->generate(cgenv, arg, cmd) ) return FALSE; } else if ( state == ARG_POSITIONAL ) break; arg = sieve_ast_argument_next(arg); } /* Mark end of optional list if it is still open */ if ( state == ARG_OPTIONAL ) sieve_binary_emit_byte(cgenv->sblock, 0); if ( last_arg_r != NULL ) *last_arg_r = arg; return TRUE; }
"create operand", &mailbox_extension, 0, &sieve_side_effect_operand_class, &ext_side_effects }; /* * Tag validation */ static bool tag_mailbox_create_validate (struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_ast_argument **arg, struct sieve_command *cmd ATTR_UNUSED) { *arg = sieve_ast_argument_next(*arg); return TRUE; } /* * Code generation */ static bool tag_mailbox_create_generate (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, struct sieve_command *context ATTR_UNUSED) { if ( sieve_ast_argument_type(arg) != SAAT_TAG ) { return FALSE; }
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; }