Coverage Report

Created: 2026-06-15 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pigeonhole/src/lib-sieve/plugins/environment/tst-environment.c
Line
Count
Source
1
/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file
2
 */
3
4
#include "lib.h"
5
#include "str-sanitize.h"
6
7
#include "sieve-common.h"
8
#include "sieve-commands.h"
9
#include "sieve-stringlist.h"
10
#include "sieve-code.h"
11
#include "sieve-comparators.h"
12
#include "sieve-match-types.h"
13
#include "sieve-validator.h"
14
#include "sieve-generator.h"
15
#include "sieve-interpreter.h"
16
#include "sieve-dump.h"
17
#include "sieve-match.h"
18
19
#include "ext-environment-common.h"
20
21
/*
22
 * Environment test
23
 *
24
 * Syntax:
25
 *   environment [COMPARATOR] [MATCH-TYPE]
26
 *      <name: string> <key-list: string-list>
27
 */
28
29
static bool
30
tst_environment_registered(struct sieve_validator *valdtr,
31
         const struct sieve_extension *ext,
32
         struct sieve_command_registration *cmd_reg);
33
static bool
34
tst_environment_validate(struct sieve_validator *valdtr,
35
       struct sieve_command *tst);
36
static bool
37
tst_environment_generate(const struct sieve_codegen_env *cgenv,
38
       struct sieve_command *cmd);
39
40
const struct sieve_command_def tst_environment = {
41
  .identifier = "environment",
42
  .type = SCT_TEST,
43
  .positional_args = 2,
44
  .subtests = 0,
45
  .block_allowed = FALSE,
46
  .block_required = FALSE,
47
  .registered = tst_environment_registered,
48
  .validate = tst_environment_validate,
49
  .generate = tst_environment_generate,
50
};
51
52
/*
53
 * Environment operation
54
 */
55
56
static bool
57
tst_environment_operation_dump(const struct sieve_dumptime_env *denv,
58
             sieve_size_t *address);
59
static int
60
tst_environment_operation_execute(const struct sieve_runtime_env *renv,
61
          sieve_size_t *address);
62
63
const struct sieve_operation_def tst_environment_operation = {
64
  .mnemonic = "ENVIRONMENT",
65
  .ext_def = &environment_extension,
66
  .dump = tst_environment_operation_dump,
67
  .execute = tst_environment_operation_execute,
68
};
69
70
/*
71
 * Test registration
72
 */
73
74
static bool
75
tst_environment_registered(struct sieve_validator *valdtr,
76
         const struct sieve_extension *ext ATTR_UNUSED,
77
         struct sieve_command_registration *cmd_reg)
78
0
{
79
  /* The order of these is not significant */
80
0
  sieve_comparators_link_tag(valdtr, cmd_reg,
81
0
           SIEVE_MATCH_OPT_COMPARATOR);
82
0
  sieve_match_types_link_tags(valdtr, cmd_reg,
83
0
            SIEVE_MATCH_OPT_MATCH_TYPE);
84
85
0
  return TRUE;
86
0
}
87
88
/*
89
 * Test validation
90
 */
91
92
static bool
93
tst_environment_validate(struct sieve_validator *valdtr,
94
       struct sieve_command *tst)
95
0
{
96
0
  struct sieve_ast_argument *arg = tst->first_positional;
97
0
  const struct sieve_match_type mcht_default =
98
0
    SIEVE_MATCH_TYPE_DEFAULT(is_match_type);
99
0
  const struct sieve_comparator cmp_default =
100
0
    SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator);
101
102
0
  if (!sieve_validate_positional_argument(valdtr, tst, arg,
103
0
            "name", 1, SAAT_STRING))
104
0
    return FALSE;
105
0
  if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE))
106
0
    return FALSE;
107
108
0
  arg = sieve_ast_argument_next(arg);
109
110
0
  if (!sieve_validate_positional_argument(valdtr, tst, arg, "key list", 2,
111
0
            SAAT_STRING_LIST))
112
0
    return FALSE;
113
0
  if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE))
114
0
    return FALSE;
115
116
  /* Validate the key argument to a specified match type */
117
0
  return sieve_match_type_validate(valdtr, tst, arg,
118
0
           &mcht_default, &cmp_default);
119
0
}
120
121
/*
122
 * Test generation
123
 */
124
125
static bool
126
tst_environment_generate(const struct sieve_codegen_env *cgenv,
127
       struct sieve_command *cmd)
128
0
{
129
0
  sieve_operation_emit(cgenv->sblock, cmd->ext,
130
0
           &tst_environment_operation);
131
132
  /* Generate arguments */
133
0
  return sieve_generate_arguments(cgenv, cmd, NULL);
134
0
}
135
136
/*
137
 * Code dump
138
 */
139
140
static bool
141
tst_environment_operation_dump(const struct sieve_dumptime_env *denv,
142
             sieve_size_t *address)
143
0
{
144
0
  sieve_code_dumpf(denv, "ENVIRONMENT");
145
0
  sieve_code_descend(denv);
146
147
  /* Optional operands */
148
0
  if (sieve_match_opr_optional_dump(denv, address, NULL) != 0)
149
0
    return FALSE;
150
151
0
  return (sieve_opr_string_dump(denv, address, "name") &&
152
0
    sieve_opr_stringlist_dump(denv, address, "key list"));
153
0
}
154
155
/*
156
 * Code execution
157
 */
158
159
static int
160
tst_environment_operation_execute(const struct sieve_runtime_env *renv,
161
          sieve_size_t *address)
162
0
{
163
0
  const struct sieve_extension *this_ext = renv->oprtn->ext;
164
0
  struct sieve_match_type mcht =
165
0
    SIEVE_MATCH_TYPE_DEFAULT(is_match_type);
166
0
  struct sieve_comparator cmp =
167
0
    SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator);
168
0
  string_t *name;
169
0
  struct sieve_stringlist *value_list, *key_list;
170
0
  const char *env_item;
171
0
  int match, ret;
172
173
  /*
174
   * Read operands
175
   */
176
177
  /* Handle match-type and comparator operands */
178
0
  if (sieve_match_opr_optional_read(renv, address, NULL,
179
0
            &ret, &cmp, &mcht) < 0)
180
0
    return ret;
181
182
  /* Read source */
183
0
  ret = sieve_opr_string_read(renv, address, "name", &name);
184
0
  if (ret <= 0)
185
0
    return ret;
186
187
  /* Read key-list */
188
0
  ret = sieve_opr_stringlist_read(renv, address, "key-list", &key_list);
189
0
  if (ret <= 0)
190
0
    return ret;
191
192
  /*
193
   * Perform operation
194
   */
195
196
0
  sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "environment test");
197
198
0
  env_item = ext_environment_item_get_value(this_ext, renv, str_c(name));
199
200
0
  if (env_item != NULL) {
201
    /* Construct value list */
202
0
    value_list = sieve_single_stringlist_create_cstr(
203
0
      renv, env_item, FALSE);
204
205
    /* Perform match */
206
0
    match = sieve_match(renv, &mcht, &cmp, value_list, key_list,
207
0
            &ret);
208
0
    if (ret < 0)
209
0
      return ret;
210
0
  } else {
211
0
    match = 0;
212
213
0
    sieve_runtime_trace_descend(renv);
214
0
    sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS,
215
0
            "environment item '%s' not found",
216
0
            str_sanitize(str_c(name), 128));
217
0
  }
218
219
  /* Set test result for subsequent conditional jump */
220
0
  sieve_interpreter_set_test_result(renv->interp, match > 0);
221
0
  return SIEVE_EXEC_OK;
222
0
}