Coverage Report

Created: 2026-07-30 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pigeonhole/src/testsuite/cmd-test-imap-metadata.c
Line
Count
Source
1
/* Copyright (c) Pigeonhole authors, see top-level COPYING file */
2
3
#include "lib.h"
4
#include "str-sanitize.h"
5
6
#include "sieve-common.h"
7
#include "sieve-commands.h"
8
#include "sieve-validator.h"
9
#include "sieve-generator.h"
10
#include "sieve-interpreter.h"
11
#include "sieve-code.h"
12
#include "sieve-binary.h"
13
#include "sieve-dump.h"
14
#include "sieve-actions.h"
15
16
#include "testsuite-common.h"
17
#include "testsuite-mailstore.h"
18
19
/*
20
 * Commands
21
 */
22
23
static bool
24
cmd_test_imap_metadata_registered(struct sieve_validator *valdtr,
25
          const struct sieve_extension *ext,
26
          struct sieve_command_registration *cmd_reg);
27
static bool
28
cmd_test_imap_metadata_validate(struct sieve_validator *valdtr,
29
        struct sieve_command *cmd);
30
static bool
31
cmd_test_imap_metadata_generate(const struct sieve_codegen_env *cgenv,
32
        struct sieve_command *ctx);
33
34
/* Test_mailbox_create command
35
36
   Syntax:
37
     test_imap_metadata_set
38
       <mailbox: string> <annotation: string> <value:string>
39
 */
40
41
const struct sieve_command_def cmd_test_imap_metadata_set = {
42
  .identifier = "test_imap_metadata_set",
43
  .type = SCT_COMMAND,
44
  .positional_args = 2,
45
  .subtests = 0,
46
  .block_allowed = FALSE,
47
  .block_required = FALSE,
48
  .registered = cmd_test_imap_metadata_registered,
49
  .validate = cmd_test_imap_metadata_validate,
50
  .generate = cmd_test_imap_metadata_generate,
51
};
52
53
/*
54
 * Command tags
55
 */
56
57
static bool
58
cmd_test_imap_metadata_validate_mailbox_tag(struct sieve_validator *valdtr,
59
              struct sieve_ast_argument **arg,
60
              struct sieve_command *cmd);
61
62
static const struct sieve_argument_def test_imap_metadata_mailbox_tag = {
63
  .identifier = "mailbox",
64
  .validate = cmd_test_imap_metadata_validate_mailbox_tag
65
};
66
67
/*
68
 * Operations
69
 */
70
71
static bool
72
cmd_test_imap_metadata_operation_dump(const struct sieve_dumptime_env *denv,
73
              sieve_size_t *address);
74
static int
75
cmd_test_imap_metadata_operation_execute(const struct sieve_runtime_env *renv,
76
           sieve_size_t *address);
77
78
/* Test_mailbox_create operation */
79
80
const struct sieve_operation_def test_imap_metadata_set_operation = {
81
  .mnemonic = "TEST_IMAP_METADATA_SET",
82
  .ext_def = &testsuite_extension,
83
  .code = TESTSUITE_OPERATION_TEST_IMAP_METADATA_SET,
84
  .dump = cmd_test_imap_metadata_operation_dump,
85
  .execute = cmd_test_imap_metadata_operation_execute,
86
};
87
88
/* Codes for optional arguments */
89
90
enum cmd_vacation_optional {
91
  OPT_END,
92
  OPT_MAILBOX,
93
};
94
95
/*
96
 * Tag validation
97
 */
98
99
static bool
100
cmd_test_imap_metadata_validate_mailbox_tag(struct sieve_validator *valdtr,
101
              struct sieve_ast_argument **arg,
102
              struct sieve_command *cmd)
103
0
{
104
0
  struct sieve_ast_argument *tag = *arg;
105
106
  /* Delete this tag */
107
0
  *arg = sieve_ast_arguments_detach(*arg, 1);
108
109
  /* Check syntax:
110
       :mailbox string
111
   */
112
0
  if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL,
113
0
            0, SAAT_STRING, FALSE))
114
0
    return FALSE;
115
116
  /* Check name validity when mailbox argument is not a variable */
117
0
  if (sieve_argument_is_string_literal(*arg)) {
118
0
    const char *mailbox = sieve_ast_argument_strc(*arg), *error;
119
120
0
    if (!sieve_mailbox_check_name(mailbox, &error)) {
121
0
      sieve_command_validate_error(
122
0
        valdtr, cmd, "test_imap_metadata_set command: "
123
0
        "invalid mailbox name '%s' specified: %s",
124
0
        str_sanitize(mailbox, 256), error);
125
0
      return FALSE;
126
0
    }
127
0
  }
128
129
  /* Skip parameter */
130
0
  *arg = sieve_ast_argument_next(*arg);
131
0
  return TRUE;
132
0
}
133
134
/*
135
 * Command registration
136
 */
137
138
static bool
139
cmd_test_imap_metadata_registered(struct sieve_validator *valdtr,
140
          const struct sieve_extension *ext,
141
          struct sieve_command_registration *cmd_reg)
142
0
{
143
0
  sieve_validator_register_tag(valdtr, cmd_reg, ext,
144
0
             &test_imap_metadata_mailbox_tag,
145
0
             OPT_MAILBOX);
146
0
  return TRUE;
147
0
}
148
149
150
/*
151
 * Validation
152
 */
153
154
static bool
155
cmd_test_imap_metadata_validate(struct sieve_validator *valdtr,
156
        struct sieve_command *cmd)
157
0
{
158
0
  struct sieve_ast_argument *arg = cmd->first_positional;
159
160
0
  if (!sieve_validate_positional_argument(valdtr, cmd, arg, "annotation",
161
0
            2, SAAT_STRING))
162
0
    return FALSE;
163
0
  if (!sieve_validator_argument_activate(valdtr, cmd, arg, FALSE))
164
0
    return FALSE;
165
166
0
  arg = sieve_ast_argument_next(arg);
167
168
0
  if (!sieve_validate_positional_argument(valdtr, cmd, arg, "value",
169
0
            3, SAAT_STRING))
170
0
    return FALSE;
171
0
  if (!sieve_validator_argument_activate(valdtr, cmd, arg, FALSE))
172
0
    return FALSE;
173
0
  return TRUE;
174
0
}
175
176
/*
177
 * Code generation
178
 */
179
180
static bool
181
cmd_test_imap_metadata_generate(const struct sieve_codegen_env *cgenv,
182
        struct sieve_command *cmd)
183
0
{
184
  /* Emit operation */
185
0
  if (sieve_command_is(cmd, cmd_test_imap_metadata_set)) {
186
0
    sieve_operation_emit(cgenv->sblock, cmd->ext,
187
0
             &test_imap_metadata_set_operation);
188
0
  } else {
189
0
    i_unreached();
190
0
  }
191
192
  /* Generate arguments */
193
0
  if (!sieve_generate_arguments(cgenv, cmd, NULL))
194
0
    return FALSE;
195
0
  return TRUE;
196
0
}
197
198
/*
199
 * Code dump
200
 */
201
202
static bool
203
cmd_test_imap_metadata_operation_dump(const struct sieve_dumptime_env *denv,
204
              sieve_size_t *address)
205
0
{
206
0
  int opt_code = 0;
207
208
0
  sieve_code_dumpf(denv, "%s:", sieve_operation_mnemonic(denv->oprtn));
209
0
  sieve_code_descend(denv);
210
211
  /* Dump optional operands */
212
213
0
  for (;;) {
214
0
    int opt;
215
0
    bool opok = TRUE;
216
217
0
    opt = sieve_opr_optional_dump(denv, address, &opt_code);
218
0
    if (opt < 0)
219
0
      return FALSE;
220
0
    if (opt == 0)
221
0
      break;
222
223
0
    switch (opt_code) {
224
0
    case OPT_MAILBOX:
225
0
      opok = sieve_opr_string_dump(denv, address, "mailbox");
226
0
      break;
227
0
    default:
228
0
      return FALSE;
229
0
    }
230
231
0
    if (!opok)
232
0
      return FALSE;
233
0
  }
234
235
0
  return (sieve_opr_string_dump(denv, address, "annotation") &&
236
0
    sieve_opr_string_dump(denv, address, "value"));
237
0
}
238
239
/*
240
 * Intepretation
241
 */
242
243
static int
244
cmd_test_imap_metadata_operation_execute(const struct sieve_runtime_env *renv,
245
           sieve_size_t *address)
246
0
{
247
0
  const struct sieve_operation *oprtn = renv->oprtn;
248
0
  int opt_code = 0;
249
0
  string_t *mailbox = NULL, *annotation = NULL, *value = NULL;
250
0
  const char *error;
251
0
  int ret;
252
253
  /*
254
   * Read operands
255
   */
256
257
  /* Optional operands */
258
259
0
  for (;;) {
260
0
    int opt;
261
262
0
    opt = sieve_opr_optional_read(renv, address, &opt_code);
263
0
    if (opt < 0)
264
0
      return SIEVE_EXEC_BIN_CORRUPT;
265
0
    if (opt == 0)
266
0
      break;
267
268
0
    switch (opt_code) {
269
0
    case OPT_MAILBOX:
270
0
      ret = sieve_opr_string_read(renv, address, "mailbox",
271
0
                &mailbox);
272
0
      if (ret > 0 &&
273
0
          !sieve_mailbox_check_name(str_c(mailbox), &error)) {
274
0
        sieve_runtime_error(
275
0
          renv, NULL,
276
0
          "test_imap_metadata_set command: "
277
0
          "invalid mailbox name '%s' specified: %s",
278
0
          str_c(mailbox), error);
279
0
        ret = SIEVE_EXEC_FAILURE;
280
0
      }
281
0
      break;
282
0
    default:
283
0
      sieve_runtime_trace_error(
284
0
        renv, "unknown optional operand");
285
0
      ret = SIEVE_EXEC_BIN_CORRUPT;
286
0
    }
287
288
0
    if (ret <= 0)
289
0
      return ret;
290
0
  }
291
292
  /* Fixed operands */
293
294
0
  ret = sieve_opr_string_read(renv, address, "annotation", &annotation);
295
0
  if (ret <= 0)
296
0
    return ret;
297
0
  ret = sieve_opr_string_read(renv, address, "value", &value);
298
0
  if (ret <= 0)
299
0
    return ret;
300
301
  /*
302
   * Perform operation
303
   */
304
305
0
  if (sieve_operation_is(oprtn, test_imap_metadata_set_operation)) {
306
0
    if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS)) {
307
0
      sieve_runtime_trace(renv, 0,
308
0
        "testsuite/test_imap_metadata_set command");
309
0
      sieve_runtime_trace_descend(renv);
310
0
      if (mailbox == NULL) {
311
0
        sieve_runtime_trace(renv, 0,
312
0
          "set server annotation '%s'",
313
0
          str_c(annotation));
314
0
      } else {
315
0
        sieve_runtime_trace(renv, 0,
316
0
          "set annotation '%s' for mailbox '%s'",
317
0
          str_c(annotation), str_c(mailbox));
318
0
      }
319
0
    }
320
321
0
    if (testsuite_mailstore_set_imap_metadata(
322
0
      (mailbox == NULL ? NULL : str_c(mailbox)),
323
0
      str_c(annotation), str_c(value)) < 0)
324
0
      return SIEVE_EXEC_FAILURE;
325
0
  }
326
0
  return SIEVE_EXEC_OK;
327
0
}