Coverage Report

Created: 2026-08-08 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dovecot/src/lib-var-expand/expansion-parameter.c
Line
Count
Source
1
/* Copyright (c) Dovecot authors, see top-level COPYING file */
2
3
#include "lib.h"
4
#include "str.h"
5
#include "strnum.h"
6
#include "var-expand-private.h"
7
#include "expansion.h"
8
9
struct var_expand_parameter_iter_context {
10
  const struct var_expand_parameter *ptr;
11
};
12
13
const char *var_expand_parameter_key(const struct var_expand_parameter *param)
14
0
{
15
0
  return param->key;
16
0
}
17
18
int var_expand_parameter_idx(const struct var_expand_parameter *param)
19
0
{
20
0
  return param->idx;
21
0
}
22
23
int var_expand_parameter_number_or_var(const struct var_expand_state *state,
24
               const struct var_expand_parameter *param,
25
               intmax_t *value_r, const char **error_r)
26
0
{
27
0
  if (param == NULL) {
28
0
    *error_r = "Missing parameter";
29
0
    return -1;
30
0
  }
31
32
0
  if (param->value_type == VAR_EXPAND_PARAMETER_VALUE_TYPE_VARIABLE) {
33
0
    const char *result;
34
0
    if (var_expand_state_lookup_variable(state, param->value.str,
35
0
                 &result, error_r) < 0)
36
0
      return -1;
37
0
    else if (str_to_intmax(result, value_r) < 0) {
38
0
      *error_r = t_strdup_printf("'%s' (in %s) is not a number",
39
0
               result, param->value.str);
40
0
      return -1;
41
0
    }
42
0
  } else if (param->value_type != VAR_EXPAND_PARAMETER_VALUE_TYPE_INT) {
43
0
    *error_r = t_strdup_printf("'%s' is not a number", param->value.str);
44
0
    return -1;
45
0
  } else {
46
0
    *value_r = param->value.num;
47
0
  }
48
0
  return 0;
49
0
}
50
51
int var_expand_parameter_bool_or_var(const struct var_expand_state *state,
52
             const struct var_expand_parameter *param,
53
             bool *value_r, const char **error_r)
54
0
{
55
0
  intmax_t value;
56
0
  if (var_expand_parameter_number_or_var(state, param, &value, error_r) < 0)
57
0
    return -1;
58
0
  if (value == 0) {
59
0
    *value_r = FALSE;
60
0
  } else if (value == 1) {
61
0
    *value_r = TRUE;
62
0
  } else {
63
0
    *error_r = t_strdup_printf("'%jd' is not 0 or 1", value);
64
0
    return -1;
65
0
  }
66
0
  return 0;
67
0
}
68
69
int var_expand_parameter_string_or_var(const struct var_expand_state *state,
70
               const struct var_expand_parameter *param,
71
               const char **value_r, const char **error_r)
72
0
{
73
0
  if (param == NULL) {
74
0
    *error_r = "Missing parameter";
75
0
    return -1;
76
0
  }
77
0
  if (param->value_type == VAR_EXPAND_PARAMETER_VALUE_TYPE_VARIABLE) {
78
0
    if (var_expand_state_lookup_variable(state, param->value.str,
79
0
                 value_r, error_r) < 0)
80
0
      return -1;
81
0
  } else if (param->value_type == VAR_EXPAND_PARAMETER_VALUE_TYPE_INT) {
82
0
    *error_r = t_strdup_printf("%jd is not a string",
83
0
             param->value.num);
84
0
    return -1;
85
0
  } else {
86
0
    *value_r = param->value.str;
87
0
  }
88
0
  return 0;
89
0
}
90
91
int var_expand_parameter_any_or_var(const struct var_expand_state *state,
92
            const struct var_expand_parameter *param,
93
            const char **value_r, const char **error_r)
94
0
{
95
0
  if (param == NULL) {
96
0
    *error_r = "Missing parameter";
97
0
    return -1;
98
0
  }
99
0
  if (param->value_type == VAR_EXPAND_PARAMETER_VALUE_TYPE_VARIABLE) {
100
0
    if (var_expand_state_lookup_variable(state, param->value.str,
101
0
                 value_r, error_r) < 0)
102
0
      return -1;
103
0
  } else if (param->value_type == VAR_EXPAND_PARAMETER_VALUE_TYPE_INT) {
104
0
    *value_r = t_strdup_printf("%jd", param->value.num);
105
0
  } else {
106
0
    *value_r = param->value.str;
107
0
  }
108
0
  return 0;
109
0
}
110
111
struct var_expand_parameter_iter_context *
112
var_expand_parameter_iter_init(const struct var_expand_statement *stmt)
113
0
{
114
0
  struct var_expand_parameter_iter_context *ctx =
115
0
    t_new(struct var_expand_parameter_iter_context, 1);
116
0
  ctx->ptr = stmt->params;
117
0
  return ctx;
118
0
}
119
120
bool var_expand_parameter_iter_more(struct var_expand_parameter_iter_context *ctx)
121
0
{
122
0
  return ctx->ptr != NULL;
123
0
}
124
125
const struct var_expand_parameter *
126
var_expand_parameter_iter_next(struct var_expand_parameter_iter_context *ctx)
127
0
{
128
0
  i_assert(ctx->ptr != NULL);
129
0
  const struct var_expand_parameter *par = ctx->ptr;
130
0
  ctx->ptr = ctx->ptr->next;
131
0
  return par;
132
0
}
133
134
void var_expand_parameter_dump(string_t *dest, const struct var_expand_parameter *par)
135
0
{
136
0
  if (par->idx > -1)
137
0
    str_printfa(dest, "\t - %d ", par->idx);
138
0
  else
139
0
    str_printfa(dest, "\t - %s ", par->key);
140
0
  switch (par->value_type) {
141
0
  case VAR_EXPAND_PARAMETER_VALUE_TYPE_STRING:
142
0
    str_printfa(dest, "'%s'", par->value.str);
143
0
    break;
144
0
  case VAR_EXPAND_PARAMETER_VALUE_TYPE_INT:
145
0
    str_printfa(dest, "%jd", par->value.num);
146
0
    break;
147
0
  case VAR_EXPAND_PARAMETER_VALUE_TYPE_VARIABLE:
148
0
    str_append(dest, par->value.str);
149
0
    break;
150
0
  case VAR_EXPAND_PARAMETER_VALUE_TYPE_COUNT:
151
0
    i_unreached();
152
0
  }
153
0
  str_append_c(dest, '\n');
154
0
}
155
156
157
int var_expand_parameter_number(const struct var_expand_parameter *param,
158
        bool convert, intmax_t *value_r)
159
0
{
160
0
  if (param->value_type == VAR_EXPAND_PARAMETER_VALUE_TYPE_INT) {
161
0
    *value_r = param->value.num;
162
0
    return 0;
163
0
  } else if (convert && param->value_type == VAR_EXPAND_PARAMETER_VALUE_TYPE_STRING)
164
0
    return str_to_intmax(param->value.str, value_r);
165
166
0
  return -1;
167
0
}
168
169
int var_expand_parameter_string(const struct var_expand_parameter *param,
170
        bool convert, const char **value_r)
171
0
{
172
0
  if (param->value_type == VAR_EXPAND_PARAMETER_VALUE_TYPE_STRING) {
173
0
    *value_r = param->value.str;
174
0
    return 0;
175
0
  } else if (convert && param->value_type == VAR_EXPAND_PARAMETER_VALUE_TYPE_INT) {
176
0
    *value_r = t_strdup_printf("%jd", param->value.num);
177
0
    return 0;
178
0
  }
179
0
  return -1;
180
0
}
181
182
int
183
var_expand_parameter_from_state(struct var_expand_state *state, bool number,
184
        const struct var_expand_parameter **param_r)
185
0
{
186
0
  if (!state->transfer_set)
187
0
    return -1;
188
0
  struct var_expand_parameter *par = t_new(struct var_expand_parameter, 1);
189
0
  par->idx = -1;
190
0
  if (number) {
191
0
    par->value_type = VAR_EXPAND_PARAMETER_VALUE_TYPE_INT;
192
0
    if (str_to_intmax(str_c(state->transfer), &par->value.num) < 0)
193
0
      return -1;
194
0
  } else {
195
0
    par->value_type = VAR_EXPAND_PARAMETER_VALUE_TYPE_STRING;
196
0
    par->value.str = t_strdup(str_c(state->transfer));
197
0
  }
198
0
  *param_r = par;
199
0
  return 0;
200
0
}