var-expand-if.c revision 9ab2df665ed6bd5043c3334853fcb008aecbf315
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi/* Copyright (c) 2003-2017 Dovecot authors, see the included COPYING file */
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi#include "lib.h"
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi#include "array.h"
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi#include "str.h"
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi#include "var-expand.h"
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi#include "var-expand-private.h"
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi#include "wildcard-match.h"
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi#include <regex.h>
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomienum var_expand_if_op {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi OP_UNKNOWN,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi OP_NUM_EQ,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi OP_NUM_LT,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi OP_NUM_LE,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi OP_NUM_GT,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi OP_NUM_GE,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi OP_NUM_NE,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi/* put all numeric comparisons before this line */
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi OP_STR_EQ,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi OP_STR_LT,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi OP_STR_LE,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi OP_STR_GT,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi OP_STR_GE,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi OP_STR_NE,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi OP_STR_LIKE,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi OP_STR_NOT_LIKE,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi OP_STR_REGEXP,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi OP_STR_NOT_REGEXP,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi/* keep this as last */
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi OP_COUNT
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi};
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomistatic enum var_expand_if_op var_expand_if_str_to_comp(const char *op)
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi{
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi const char *ops[OP_COUNT] = {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi NULL,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi "==",
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi "<",
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi "<=",
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi ">",
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi ">=",
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi "!=",
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi "eq",
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi "lt",
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi "le",
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi "gt",
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi "ge",
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi "ne",
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi "*",
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi "!*",
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi "~",
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi "!~",
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi };
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi for(enum var_expand_if_op i = 1; i < OP_COUNT; i++) {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi i_assert(ops[i] != NULL);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi if (strcmp(op, ops[i]) == 0)
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return i;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi }
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return OP_UNKNOWN;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi}
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomistatic int var_expand_if_comp(const char *lhs, const char *_op, const char *rhs,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi bool *result_r, const char **error_r)
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi{
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi bool neg = FALSE;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi enum var_expand_if_op op = var_expand_if_str_to_comp(_op);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi if (op == OP_UNKNOWN) {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *error_r = t_strdup_printf("if: Unsupported comparator '%s'", _op);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return -1;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi }
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi if (op < OP_STR_EQ) {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi intmax_t a;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi intmax_t b;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi if (str_to_intmax(lhs, &a) < 0) {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *error_r = t_strdup_printf("if: %s (lhs) is not a number", lhs);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return -1;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi }
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi if (str_to_intmax(rhs, &b) < 0) {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *error_r = t_strdup_printf("if: %s (rhs) is not a number", rhs);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return -1;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi }
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi switch(op) {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi case OP_NUM_EQ:
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *result_r = a==b;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return 0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi case OP_NUM_LT:
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *result_r = a<b;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return 0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi case OP_NUM_LE:
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *result_r = a<=b;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return 0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi case OP_NUM_GT:
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *result_r = a>b;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return 0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi case OP_NUM_GE:
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *result_r = a>=b;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return 0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi case OP_NUM_NE:
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *result_r = a!=b;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return 0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi default:
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi i_panic("Missing numeric comparator %u", op);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi }
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi }
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi switch(op) {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi case OP_STR_EQ:
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *result_r = strcmp(lhs,rhs)==0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return 0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi case OP_STR_LT:
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *result_r = strcmp(lhs,rhs)<0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return 0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi case OP_STR_LE:
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *result_r = strcmp(lhs,rhs)<=0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return 0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi case OP_STR_GT:
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *result_r = strcmp(lhs,rhs)>0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return 0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi case OP_STR_GE:
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *result_r = strcmp(lhs,rhs)>=0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return 0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi case OP_STR_NE:
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *result_r = strcmp(lhs,rhs)!=0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return 0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi case OP_STR_LIKE:
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *result_r = wildcard_match(lhs, rhs);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return 0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi case OP_STR_NOT_LIKE:
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *result_r = !wildcard_match(lhs, rhs);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return 0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi case OP_STR_NOT_REGEXP:
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi neg = TRUE;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi case OP_STR_REGEXP: {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi int ec;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi bool res;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi regex_t reg;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi if ((ec = regcomp(&reg, rhs, REG_EXTENDED)) != 0) {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi size_t siz;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi char *errbuf;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi siz = regerror(ec, &reg, NULL, 0);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi errbuf = t_malloc_no0(siz);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi (void)regerror(ec, &reg, errbuf, siz);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *error_r = t_strdup_printf("if: regex failed: %s",
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi errbuf);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return -1;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi }
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi if ((ec = regexec(&reg, lhs, 0, 0, 0)) != 0) {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi i_assert(ec == REG_NOMATCH);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi res = FALSE;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi } else {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi res = TRUE;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi }
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi regfree(&reg);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi /* this should be same as neg.
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi if NOT_REGEXP, neg == TRUE and res should be FALSE
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi if REGEXP, ned == FALSE, and res should be TRUE
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi */
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *result_r = !res == neg;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return 0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi }
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi default:
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi i_panic("Missing generic comparator %u", op);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi }
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi}
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomiint var_expand_if(struct var_expand_context *ctx,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi const char *key, const char *field,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi const char **result_r, const char **error_r)
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi{
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi /* in case the original input had :, we need to fix that
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi by concatenating the key and field together. */
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi const char *input = t_strconcat(key, ":", field, NULL);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi const char *p = strchr(input, ';');
9ab2df665ed6bd5043c3334853fcb008aecbf315Aki Tuomi const char *par_end;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi string_t *parbuf;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi const char *const *parms;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi unsigned int depth = 0;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi int ret;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi bool result, escape = FALSE, maybe_var = FALSE;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi if (p == NULL) {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *error_r = "if: missing parameter(s)";
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return -1;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi }
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi ARRAY_TYPE(const_string) params;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi t_array_init(&params, 6);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi parbuf = t_str_new(64);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi /* we need to skip any %{} parameters here, so we can split the string
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi correctly from , without breaking any inner expansions */
9ab2df665ed6bd5043c3334853fcb008aecbf315Aki Tuomi for(par_end = p+1; *par_end != '\0'; par_end++) {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi if (*par_end == '\\') {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi escape = TRUE;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi continue;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi } else if (escape) {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi str_append_c(parbuf, *par_end);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi escape = FALSE;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi continue;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi }
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi if (*par_end == '%') {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi maybe_var = TRUE;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi } else if (maybe_var && *par_end == '{') {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi depth++;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi maybe_var = FALSE;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi } else if (depth > 0 && *par_end == '}') {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi depth--;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi } else if (depth == 0 && *par_end == ';') {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi const char *par = str_c(parbuf);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi array_append(&params, &par, 1);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi parbuf = t_str_new(64);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi continue;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi /* if there is a unescaped : at top level it means
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi that the key + arguments end here. it's probably
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi a by-product of the t_strconcat at top of function,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi which is best handled here. */
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi } else if (depth == 0 && *par_end == ':') {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi break;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi }
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi str_append_c(parbuf, *par_end);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi }
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi if (str_len(parbuf) > 0) {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi const char *par = str_c(parbuf);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi array_append(&params, &par, 1);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi }
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi if (array_count(&params) != 5) {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi if (array_count(&params) == 4) {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi const char *empty = "";
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi array_append(&params, &empty, 1);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi } else {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *error_r = t_strdup_printf("if: requires four or five parameters, got %u",
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi array_count(&params));
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return -1;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi }
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi }
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi array_append_zero(&params);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi parms = array_idx(&params, 0);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi t_array_init(&params, 6);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi for(;*parms != NULL; parms++) {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi /* expand the parameters */
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi string_t *param = t_str_new(64);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi if ((ret = var_expand_with_funcs(param, *parms, ctx->table,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi ctx->func_table, ctx->context,
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi error_r)) <= 0) {
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return ret;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi }
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi const char *p = str_c(param);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi array_append(&params, &p, 1);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi }
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi i_assert(array_count(&params) == 5);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi /* execute comparison */
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi const char *const *args = array_idx(&params, 0);
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi if (var_expand_if_comp(args[0], args[1], args[2], &result, error_r)<0)
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return -1;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi *result_r = result ? args[3] : args[4];
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi return 1;
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi}
b3e71425659780a58cba2f1d84eceef5b4616762Aki Tuomi