1
/* Copyright (c) 2002-2009 Dovecot Sieve authors, see the included COPYING file
9
#include "sieve-common.h"
11
#include "sieve-ast.h"
12
#include "sieve-binary.h"
13
#include "sieve-code.h"
14
#include "sieve-objects.h"
15
#include "sieve-match-types.h"
17
#include "sieve-commands.h"
18
#include "sieve-validator.h"
19
#include "sieve-generator.h"
20
#include "sieve-dump.h"
21
#include "sieve-interpreter.h"
23
#include "ext-variables-common.h"
24
#include "ext-variables-name.h"
25
#include "ext-variables-modifiers.h"
31
struct sieve_variable_scope {
35
struct sieve_variable *error_var;
37
const struct sieve_extension *ext;
39
struct hash_table *variables;
40
ARRAY_DEFINE(variable_index, struct sieve_variable *);
43
struct sieve_variable_scope_iter {
44
struct sieve_variable_scope *scope;
45
struct hash_iterate_context *hctx;
48
struct sieve_variable_scope *sieve_variable_scope_create
49
(const struct sieve_extension *ext)
51
struct sieve_variable_scope *scope;
54
pool = pool_alloconly_create("sieve_variable_scope", 4096);
55
scope = p_new(pool, struct sieve_variable_scope, 1);
60
scope->variables = hash_table_create
61
(default_pool, pool, 0, strcase_hash, (hash_cmp_callback_t *)strcasecmp);
62
p_array_init(&scope->variable_index, pool, 128);
67
void sieve_variable_scope_ref(struct sieve_variable_scope *scope)
72
void sieve_variable_scope_unref(struct sieve_variable_scope **scope)
74
i_assert((*scope)->refcount > 0);
76
if (--(*scope)->refcount != 0)
79
hash_table_destroy(&(*scope)->variables);
81
pool_unref(&(*scope)->pool);
85
pool_t sieve_variable_scope_pool(struct sieve_variable_scope *scope)
90
struct sieve_variable *sieve_variable_scope_declare
91
(struct sieve_variable_scope *scope, const char *identifier)
93
struct sieve_variable *new_var;
95
new_var = p_new(scope->pool, struct sieve_variable, 1);
96
new_var->ext = scope->ext;
98
if ( array_count(&scope->variable_index) >= SIEVE_VARIABLES_MAX_SCOPE_SIZE ) {
99
if ( scope->error_var == NULL ) {
100
new_var->identifier = "@ERROR@";
103
scope->error_var = new_var;
107
return scope->error_var;
110
new_var->identifier = p_strdup(scope->pool, identifier);
111
new_var->index = array_count(&scope->variable_index);
113
hash_table_insert(scope->variables, (void *) new_var->identifier, (void *) new_var);
114
array_append(&scope->variable_index, &new_var, 1);
119
struct sieve_variable *sieve_variable_scope_get_variable
120
(struct sieve_variable_scope *scope, const char *identifier, bool declare)
122
struct sieve_variable *var =
123
(struct sieve_variable *) hash_table_lookup(scope->variables, identifier);
125
if ( var == NULL && declare ) {
126
var = sieve_variable_scope_declare(scope, identifier);
132
struct sieve_variable *sieve_variable_scope_import
133
(struct sieve_variable_scope *scope, struct sieve_variable *var)
135
struct sieve_variable *new_var = p_new(scope->pool, struct sieve_variable, 1);
136
memcpy(new_var, var, sizeof(struct sieve_variable));
138
hash_table_insert(scope->variables, (void *) new_var->identifier, (void *) new_var);
140
/* Not entered into the index because it is an external variable
141
* (This can be done unlimited; only limited by the size of the external scope)
147
struct sieve_variable_scope_iter *sieve_variable_scope_iterate_init
148
(struct sieve_variable_scope *scope)
150
struct sieve_variable_scope_iter *iter = t_new(struct sieve_variable_scope_iter, 1);
152
iter->hctx = hash_table_iterate_init(scope->variables);
157
bool sieve_variable_scope_iterate
158
(struct sieve_variable_scope_iter *iter, struct sieve_variable **var_r)
162
if ( !hash_table_iterate(iter->hctx, &key, &value) )
165
*var_r = (struct sieve_variable *) value;
169
void sieve_variable_scope_iterate_deinit
170
(struct sieve_variable_scope_iter **iter)
172
hash_table_iterate_deinit(&(*iter)->hctx);
176
unsigned int sieve_variable_scope_declarations
177
(struct sieve_variable_scope *scope)
179
return hash_table_count(scope->variables);
182
unsigned int sieve_variable_scope_size
183
(struct sieve_variable_scope *scope)
185
return array_count(&scope->variable_index);
188
struct sieve_variable * const *sieve_variable_scope_get_variables
189
(struct sieve_variable_scope *scope, unsigned int *size_r)
191
return array_get(&scope->variable_index, size_r);
194
struct sieve_variable *sieve_variable_scope_get_indexed
195
(struct sieve_variable_scope *scope, unsigned int index)
197
struct sieve_variable * const *var;
199
if ( index >= array_count(&scope->variable_index) )
202
var = array_idx(&scope->variable_index, index);
211
struct sieve_variable_storage {
213
struct sieve_variable_scope *scope;
214
unsigned int max_size;
215
ARRAY_DEFINE(var_values, string_t *);
218
struct sieve_variable_storage *sieve_variable_storage_create
219
(pool_t pool, struct sieve_variable_scope *scope, unsigned int max_size)
221
struct sieve_variable_storage *storage;
223
storage = p_new(pool, struct sieve_variable_storage, 1);
224
storage->pool = pool;
225
storage->scope = scope;
228
storage->max_size = sieve_variable_scope_size(scope);
230
storage->max_size = max_size;
232
p_array_init(&storage->var_values, pool, 4);
237
static inline bool sieve_variable_valid
238
(struct sieve_variable_storage *storage, unsigned int index)
240
if ( storage->scope == NULL ) return TRUE;
242
return ( index < storage->max_size );
245
bool sieve_variable_get_identifier
246
(struct sieve_variable_storage *storage, unsigned int index, const char **identifier)
248
struct sieve_variable * const *var;
251
if ( storage->scope == NULL ) return TRUE;
253
/* FIXME: direct invasion of the scope object is a bit ugly */
254
if ( index >= array_count(&storage->scope->variable_index) )
257
var = array_idx(&storage->scope->variable_index, index);
260
*identifier = (*var)->identifier;
265
bool sieve_variable_get
266
(struct sieve_variable_storage *storage, unsigned int index, string_t **value)
270
if ( index < array_count(&storage->var_values) ) {
271
string_t * const *varent;
273
varent = array_idx(&storage->var_values, index);
276
} else if ( !sieve_variable_valid(storage, index) )
282
bool sieve_variable_get_modifiable
283
(struct sieve_variable_storage *storage, unsigned int index, string_t **value)
287
if ( value == NULL ) value = &dummy;
289
if ( !sieve_variable_get(storage, index, value) )
292
if ( *value == NULL ) {
293
*value = str_new(storage->pool, 256);
294
array_idx_set(&storage->var_values, index, value);
300
bool sieve_variable_assign
301
(struct sieve_variable_storage *storage, unsigned int index,
302
const string_t *value)
306
if ( !sieve_variable_get_modifiable(storage, index, &varval) )
309
str_truncate(varval, 0);
310
str_append_str(varval, value);
312
/* Just a precaution, caller should prevent this in the first place */
313
if ( str_len(varval) > SIEVE_VARIABLES_MAX_VARIABLE_SIZE )
314
str_truncate(varval, SIEVE_VARIABLES_MAX_VARIABLE_SIZE);
323
static void ext_variables_ast_free
324
(struct sieve_ast *ast ATTR_UNUSED, void *context)
326
struct sieve_variable_scope *main_scope =
327
(struct sieve_variable_scope *) context;
329
/* Unreference main variable scope */
330
sieve_variable_scope_unref(&main_scope);
333
static const struct sieve_ast_extension variables_ast_extension = {
334
&variables_extension,
335
ext_variables_ast_free
338
static struct sieve_variable_scope *ext_variables_create_main_scope
339
(struct sieve_ast *ast)
341
struct sieve_variable_scope *scope;
343
scope = sieve_variable_scope_create(NULL);
345
sieve_ast_extension_register(ast, &variables_ast_extension, (void *) scope);
350
static struct sieve_variable_scope *ext_variables_ast_get_main_scope
351
(struct sieve_ast *ast)
353
struct sieve_variable_scope *main_scope =
354
(struct sieve_variable_scope *) sieve_ast_extension_get_context
355
(ast, &variables_extension);
364
static struct ext_variables_validator_context *
365
ext_variables_validator_context_create(struct sieve_validator *valdtr)
367
pool_t pool = sieve_validator_pool(valdtr);
368
struct ext_variables_validator_context *ctx;
369
struct sieve_ast *ast = sieve_validator_ast(valdtr);
371
ctx = p_new(pool, struct ext_variables_validator_context, 1);
372
ctx->modifiers = sieve_validator_object_registry_create(valdtr);
373
ctx->main_scope = ext_variables_create_main_scope(ast);
375
sieve_validator_extension_set_context
376
(valdtr, &variables_extension, (void *) ctx);
381
struct ext_variables_validator_context *ext_variables_validator_context_get
382
(struct sieve_validator *valdtr)
384
struct ext_variables_validator_context *ctx =
385
(struct ext_variables_validator_context *)
386
sieve_validator_extension_get_context(valdtr, &variables_extension);
389
ctx = ext_variables_validator_context_create(valdtr);
395
void ext_variables_validator_initialize(struct sieve_validator *validator)
397
struct ext_variables_validator_context *ctx;
399
/* Create our context */
400
ctx = ext_variables_validator_context_get(validator);
402
ext_variables_register_core_modifiers(ctx);
407
struct sieve_variable *ext_variables_validator_get_variable
408
(struct sieve_validator *validator, const char *variable, bool declare)
410
struct ext_variables_validator_context *ctx =
411
ext_variables_validator_context_get(validator);
413
return sieve_variable_scope_get_variable(ctx->main_scope, variable, declare);
416
struct sieve_variable_scope *sieve_ext_variables_get_main_scope
417
(struct sieve_validator *validator)
419
struct ext_variables_validator_context *ctx =
420
ext_variables_validator_context_get(validator);
422
return ctx->main_scope;
425
bool sieve_ext_variables_is_active(struct sieve_validator *valdtr)
427
struct ext_variables_validator_context *ctx =
428
ext_variables_validator_context_get(valdtr);
430
return ( ctx != NULL && ctx->active );
437
bool ext_variables_generator_load(const struct sieve_codegen_env *cgenv)
439
struct sieve_variable_scope *main_scope =
440
ext_variables_ast_get_main_scope(cgenv->ast);
441
unsigned int count = sieve_variable_scope_size(main_scope);
444
sieve_binary_emit_unsigned(cgenv->sbin, count);
446
jump = sieve_binary_emit_offset(cgenv->sbin, 0);
449
unsigned int size, i;
450
struct sieve_variable *const *vars =
451
sieve_variable_scope_get_variables(main_scope, &size);
453
for ( i = 0; i < size; i++ ) {
454
sieve_binary_emit_cstring(cgenv->sbin, vars[i]->identifier);
458
sieve_binary_resolve_offset(cgenv->sbin, jump);
464
* Interpreter context
467
struct ext_variables_interpreter_context {
468
struct sieve_variable_storage *local_storage;
469
ARRAY_DEFINE(ext_storages, struct sieve_variable_storage *);
472
static struct ext_variables_interpreter_context *
473
ext_variables_interpreter_context_create
474
(struct sieve_interpreter *interp, unsigned int max_size)
476
pool_t pool = sieve_interpreter_pool(interp);
477
struct ext_variables_interpreter_context *ctx;
479
ctx = p_new(pool, struct ext_variables_interpreter_context, 1);
480
ctx->local_storage = sieve_variable_storage_create(pool, NULL, max_size);
481
p_array_init(&ctx->ext_storages, pool, sieve_extensions_get_count());
483
sieve_interpreter_extension_set_context
484
(interp, &variables_extension, (void *) ctx);
489
bool ext_variables_interpreter_load
490
(const struct sieve_runtime_env *renv, sieve_size_t *address)
492
struct ext_variables_interpreter_context *ctx;
493
unsigned int scope_size;
497
if ( !sieve_binary_read_unsigned(renv->sbin, address, &scope_size) ) {
498
sieve_sys_error("variables: failed to read main scope size");
502
if ( scope_size > SIEVE_VARIABLES_MAX_SCOPE_SIZE ) {
503
sieve_sys_error("variables: scope size exceeds the limit (%u > %u)",
504
scope_size, SIEVE_VARIABLES_MAX_SCOPE_SIZE );
509
if ( !sieve_binary_read_offset(renv->sbin, address, &end_offset) )
511
*address = pc + end_offset;
513
/* Create our context */
514
ctx = ext_variables_interpreter_context_create(renv->interp, scope_size);
516
/* Enable support for match values */
517
(void) sieve_match_values_set_enabled(renv->interp, TRUE);
522
static inline struct ext_variables_interpreter_context *
523
ext_variables_interpreter_context_get(struct sieve_interpreter *interp)
525
return (struct ext_variables_interpreter_context *)
526
sieve_interpreter_extension_get_context(interp, &variables_extension);
529
struct sieve_variable_storage *sieve_ext_variables_get_storage
530
(struct sieve_interpreter *interp, const struct sieve_extension *ext)
532
struct ext_variables_interpreter_context *ctx =
533
ext_variables_interpreter_context_get(interp);
534
struct sieve_variable_storage * const *storage;
538
return ctx->local_storage;
540
ext_id = SIEVE_EXT_ID(ext);
541
if ( ext_id >= (int) array_count(&ctx->ext_storages) ) {
544
storage = array_idx(&ctx->ext_storages, ext_id);
547
if ( storage == NULL || *storage == NULL )
553
void sieve_ext_variables_set_storage
554
(struct sieve_interpreter *interp, struct sieve_variable_storage *storage,
555
const struct sieve_extension *ext)
557
struct ext_variables_interpreter_context *ctx =
558
ext_variables_interpreter_context_get(interp);
560
if ( ctx == NULL || ext == NULL || storage == NULL )
563
array_idx_set(&ctx->ext_storages, (unsigned int) SIEVE_EXT_ID(ext), &storage);