Coverage Report

Created: 2026-04-12 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-namespaces.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-code.h"
7
#include "sieve-binary.h"
8
#include "sieve-dump.h"
9
10
#include "ext-variables-common.h"
11
#include "ext-variables-namespaces.h"
12
13
#include <ctype.h>
14
15
/*
16
 * Namespace registry
17
 */
18
19
void sieve_variables_namespace_register(
20
  const struct sieve_extension *var_ext, struct sieve_validator *valdtr,
21
  const struct sieve_extension *ext,
22
  const struct sieve_variables_namespace_def *nspc_def)
23
0
{
24
0
  struct ext_variables_validator_context *ctx =
25
0
    ext_variables_validator_context_get(var_ext, valdtr);
26
27
0
  sieve_validator_object_registry_add(ctx->namespaces, ext,
28
0
              &nspc_def->obj_def);
29
0
}
30
31
bool ext_variables_namespace_exists(const struct sieve_extension *var_ext,
32
            struct sieve_validator *valdtr,
33
            const char *identifier)
34
0
{
35
0
  struct ext_variables_validator_context *ctx =
36
0
    ext_variables_validator_context_get(var_ext, valdtr);
37
38
0
  return sieve_validator_object_registry_find(ctx->namespaces, identifier,
39
0
                NULL);
40
0
}
41
42
const struct sieve_variables_namespace *
43
ext_variables_namespace_create_instance(const struct sieve_extension *var_ext,
44
          struct sieve_validator *valdtr,
45
          struct sieve_command *cmd,
46
          const char *identifier)
47
0
{
48
0
  struct ext_variables_validator_context *ctx =
49
0
    ext_variables_validator_context_get(var_ext, valdtr);
50
0
  struct sieve_object object;
51
0
  struct sieve_variables_namespace *nspc;
52
0
  pool_t pool;
53
54
0
  if (!sieve_validator_object_registry_find(ctx->namespaces, identifier,
55
0
              &object))
56
0
    return NULL;
57
58
0
  pool = sieve_command_pool(cmd);
59
0
  nspc = p_new(pool, struct sieve_variables_namespace, 1);
60
0
  nspc->object = object;
61
0
  nspc->def = (const struct sieve_variables_namespace_def *) object.def;
62
63
0
  return nspc;
64
0
}
65
66
/*
67
 * Namespace variable argument
68
 */
69
70
struct arg_namespace_variable {
71
  const struct sieve_variables_namespace *namespace;
72
73
  void *data;
74
};
75
76
static bool
77
arg_namespace_generate(const struct sieve_codegen_env *cgenv,
78
           struct sieve_ast_argument *arg,
79
           struct sieve_command *context ATTR_UNUSED);
80
81
const struct sieve_argument_def namespace_argument = {
82
  .identifier = "@namespace",
83
  .generate = arg_namespace_generate,
84
};
85
86
bool ext_variables_namespace_argument_activate(
87
  const struct sieve_extension *this_ext, struct sieve_validator *valdtr,
88
  struct sieve_ast_argument *arg, struct sieve_command *cmd,
89
  ARRAY_TYPE(sieve_variable_name) *var_name, bool assignment)
90
0
{
91
0
  pool_t pool = sieve_command_pool(cmd);
92
0
  struct sieve_ast *ast = arg->ast;
93
0
  const struct sieve_variables_namespace *nspc;
94
0
  struct arg_namespace_variable *var;
95
0
  const struct sieve_variable_name *name_element = array_idx(var_name, 0);
96
0
  void *var_data = NULL;
97
98
0
  nspc = ext_variables_namespace_create_instance(
99
0
    this_ext, valdtr, cmd, str_c(name_element->identifier));
100
0
  if (nspc == NULL) {
101
0
    sieve_argument_validate_error(
102
0
      valdtr, arg,
103
0
      "referring to variable in unknown namespace '%s'",
104
0
      str_c(name_element->identifier));
105
0
    return FALSE;
106
0
  }
107
108
0
  if (nspc->def != NULL && nspc->def->validate != NULL &&
109
0
      !nspc->def->validate(valdtr, nspc, arg, cmd, var_name, &var_data,
110
0
         assignment))
111
0
    return FALSE;
112
113
0
  var = p_new(pool, struct arg_namespace_variable, 1);
114
0
  var->namespace = nspc;
115
0
  var->data = var_data;
116
117
0
  arg->argument = sieve_argument_create(ast, &namespace_argument,
118
0
                this_ext, 0);
119
0
  arg->argument->data = var;
120
121
0
  return TRUE;
122
0
}
123
124
struct sieve_ast_argument *
125
ext_variables_namespace_argument_create(
126
  const struct sieve_extension *this_ext, struct sieve_validator *valdtr,
127
  struct sieve_ast_argument *parent_arg, struct sieve_command *cmd,
128
  ARRAY_TYPE(sieve_variable_name) *var_name)
129
0
{
130
0
  struct sieve_ast *ast = parent_arg->ast;
131
0
  struct sieve_ast_argument *new_arg;
132
133
0
  new_arg = sieve_ast_argument_create(
134
0
    ast, sieve_ast_argument_line(parent_arg));
135
0
  new_arg->type = SAAT_STRING;
136
137
0
  if (!ext_variables_namespace_argument_activate(
138
0
    this_ext, valdtr, new_arg, cmd, var_name, FALSE))
139
0
    return NULL;
140
141
0
  return new_arg;
142
0
}
143
144
static bool
145
arg_namespace_generate(const struct sieve_codegen_env *cgenv,
146
           struct sieve_ast_argument *arg,
147
           struct sieve_command *cmd)
148
0
{
149
0
  struct sieve_argument *argument = arg->argument;
150
0
  struct arg_namespace_variable *var =
151
0
    (struct arg_namespace_variable *)argument->data;
152
0
  const struct sieve_variables_namespace *nspc = var->namespace;
153
154
0
  if (nspc->def != NULL && nspc->def->generate != NULL)
155
0
    return nspc->def->generate(cgenv, nspc, arg, cmd, var->data);
156
157
0
  return TRUE;
158
0
}
159
160
/*
161
 * Namespace variable operands
162
 */
163
164
const struct sieve_operand_class sieve_variables_namespace_operand_class =
165
  { "variable-namespace" };
166
167
static bool
168
opr_namespace_variable_dump(const struct sieve_dumptime_env *denv,
169
          const struct sieve_operand *oprnd,
170
          sieve_size_t *address);
171
static int
172
opr_namespace_variable_read(const struct sieve_runtime_env *renv,
173
          const struct sieve_operand *oprnd,
174
          sieve_size_t *address, string_t **str_r);
175
176
static const struct sieve_opr_string_interface namespace_variable_interface = {
177
  opr_namespace_variable_dump,
178
  opr_namespace_variable_read,
179
};
180
181
const struct sieve_operand_def namespace_variable_operand = {
182
  .name = "namespace",
183
  .ext_def = &variables_extension,
184
  .code = EXT_VARIABLES_OPERAND_NAMESPACE_VARIABLE,
185
  .class = &string_class,
186
  .interface = &namespace_variable_interface,
187
};
188
189
void sieve_variables_opr_namespace_variable_emit(
190
  struct sieve_binary_block *sblock,
191
  const struct sieve_extension *var_ext,
192
  const struct sieve_extension *ext,
193
  const struct sieve_variables_namespace_def *nspc_def)
194
0
{
195
0
  i_assert(sieve_extension_is(var_ext, variables_extension));
196
0
  sieve_operand_emit(sblock, var_ext, &namespace_variable_operand);
197
0
  sieve_opr_object_emit(sblock, ext, &nspc_def->obj_def);
198
0
}
199
200
static bool
201
opr_namespace_variable_dump(const struct sieve_dumptime_env *denv,
202
          const struct sieve_operand *oprnd,
203
          sieve_size_t *address)
204
0
{
205
0
  struct sieve_variables_namespace nspc;
206
0
  struct sieve_operand nsoprnd;
207
208
0
  if (!sieve_operand_read(denv->sblock, address, NULL, &nsoprnd))
209
0
    return FALSE;
210
0
  if (!sieve_opr_object_read_data(
211
0
    denv->sblock, &nsoprnd,
212
0
    &sieve_variables_namespace_operand_class, address,
213
0
    &nspc.object))
214
0
    return FALSE;
215
216
0
  nspc.def = (const struct sieve_variables_namespace_def *)
217
0
    nspc.object.def;
218
219
0
  if (nspc.def == NULL || nspc.def->dump_variable == NULL)
220
0
    return FALSE;
221
222
0
  return nspc.def->dump_variable(denv, &nspc, oprnd, address);
223
0
}
224
225
static int
226
opr_namespace_variable_read(const struct sieve_runtime_env *renv,
227
          const struct sieve_operand *oprnd,
228
          sieve_size_t *address, string_t **str_r)
229
0
{
230
0
  struct sieve_variables_namespace nspc;
231
232
0
  if (!sieve_opr_object_read(
233
0
    renv, &sieve_variables_namespace_operand_class, address,
234
0
    &nspc.object)) {
235
0
    sieve_runtime_trace_operand_error(renv, oprnd,
236
0
      "variable namespace operand corrupt: failed to read");
237
0
    return SIEVE_EXEC_BIN_CORRUPT;
238
0
  }
239
240
0
  nspc.def = (const struct sieve_variables_namespace_def *)
241
0
    nspc.object.def;
242
243
0
  if (nspc.def == NULL || nspc.def->read_variable == NULL)
244
0
    return SIEVE_EXEC_FAILURE;
245
246
0
  return nspc.def->read_variable(renv, &nspc, oprnd, address, str_r);
247
0
}