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