Coverage Report

Created: 2026-08-13 06:41

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