48
48
* Binary context management
51
51
struct ext_include_binary_context {
52
52
struct sieve_binary *binary;
53
53
unsigned int dependency_block;
55
55
struct hash_table *included_scripts;
56
56
ARRAY_DEFINE(include_index, struct ext_include_script_info *);
58
58
struct sieve_variable_scope *global_vars;
62
62
static struct ext_include_binary_context *ext_include_binary_create_context
63
63
(const struct sieve_extension *this_ext, struct sieve_binary *sbin)
65
65
pool_t pool = sieve_binary_pool(sbin);
67
struct ext_include_binary_context *ctx =
67
struct ext_include_binary_context *ctx =
68
68
p_new(pool, struct ext_include_binary_context, 1);
71
ctx->included_scripts = hash_table_create(default_pool, pool, 0,
72
(hash_callback_t *) sieve_script_hash,
71
ctx->included_scripts = hash_table_create(default_pool, pool, 0,
72
(hash_callback_t *) sieve_script_hash,
73
73
(hash_cmp_callback_t *) sieve_script_cmp);
74
74
p_array_init(&ctx->include_index, pool, 128);
81
81
struct ext_include_binary_context *ext_include_binary_get_context
82
82
(const struct sieve_extension *this_ext, struct sieve_binary *sbin)
84
84
struct ext_include_binary_context *ctx = (struct ext_include_binary_context *)
85
85
sieve_binary_extension_get_context(sbin, this_ext);
88
88
ctx = ext_include_binary_create_context(this_ext, sbin);
93
93
struct ext_include_binary_context *ext_include_binary_init
94
(const struct sieve_extension *this_ext, struct sieve_binary *sbin,
94
(const struct sieve_extension *this_ext, struct sieve_binary *sbin,
95
95
struct sieve_ast *ast)
97
97
struct ext_include_ast_context *ast_ctx =
98
98
ext_include_get_ast_context(this_ext, ast);
99
99
struct ext_include_binary_context *ctx;
101
101
/* Get/create our context from the binary we are working on */
102
102
ctx = ext_include_binary_get_context(this_ext, sbin);
104
104
/* Create dependency block */
105
105
if ( ctx->dependency_block == 0 )
106
ctx->dependency_block =
106
ctx->dependency_block =
107
107
sieve_binary_extension_create_block(sbin, this_ext);
109
109
if ( ctx->global_vars == NULL ) {
110
110
ctx->global_vars = ast_ctx->global_vars;
111
111
sieve_variable_scope_ref(ctx->global_vars);
148
148
struct ext_include_script_info *incscript = (struct ext_include_script_info *)
149
149
hash_table_lookup(binctx->included_scripts, script);
151
151
if ( incscript == NULL )
154
154
*script_info_r = incscript;
158
158
const struct ext_include_script_info *ext_include_binary_script_get_included
159
159
(struct ext_include_binary_context *binctx, unsigned int include_id)
161
if ( include_id > 0 &&
161
if ( include_id > 0 &&
162
162
(include_id - 1) < array_count(&binctx->include_index) ) {
163
163
struct ext_include_script_info *const *sinfo =
164
164
array_idx(&binctx->include_index, include_id - 1);
202
202
static bool ext_include_binary_save
203
(const struct sieve_extension *ext ATTR_UNUSED, struct sieve_binary *sbin,
203
(const struct sieve_extension *ext ATTR_UNUSED, struct sieve_binary *sbin,
206
struct ext_include_binary_context *binctx =
206
struct ext_include_binary_context *binctx =
207
207
(struct ext_include_binary_context *) context;
208
208
struct ext_include_script_info *const *scripts;
209
209
unsigned int script_count, i;
210
210
unsigned int prvblk;
211
211
bool result = TRUE;
213
213
sieve_binary_block_clear(sbin, binctx->dependency_block);
214
if ( !sieve_binary_block_set_active(sbin, binctx->dependency_block, &prvblk) )
214
if ( !sieve_binary_block_set_active(sbin, binctx->dependency_block, &prvblk) )
217
217
scripts = array_get(&binctx->include_index, &script_count);
236
236
static bool ext_include_binary_open
237
237
(const struct sieve_extension *ext, struct sieve_binary *sbin, void *context)
239
struct ext_include_binary_context *binctx =
239
struct ext_include_binary_context *binctx =
240
240
(struct ext_include_binary_context *) context;
241
241
unsigned int block, prvblk, depcount, i;
242
242
sieve_size_t offset;
244
244
block = sieve_binary_extension_get_block(sbin, ext);
246
246
if ( !sieve_binary_block_set_active(sbin, block, &prvblk) )
251
251
if ( !sieve_binary_read_unsigned(sbin, &offset, &depcount) ) {
252
252
sieve_sys_error("include: failed to read include count "
253
"for dependency block %d of binary %s", block, sieve_binary_path(sbin));
253
"for dependency block %d of binary %s", block, sieve_binary_path(sbin));
257
/* Check include limit */
257
/* Check include limit */
258
258
if ( depcount > EXT_INCLUDE_MAX_INCLUDES ) {
259
259
sieve_sys_error("include: binary %s includes too many scripts (%u > %u)",
260
sieve_binary_path(sbin), depcount, EXT_INCLUDE_MAX_INCLUDES);
260
sieve_binary_path(sbin), depcount, EXT_INCLUDE_MAX_INCLUDES);
264
264
/* Read dependencies */
265
265
for ( i = 0; i < depcount; i++ ) {
266
266
unsigned int block_id;
268
268
string_t *script_name;
269
269
const char *script_dir;
270
270
struct sieve_script *script;
273
273
!sieve_binary_read_unsigned(sbin, &offset, &block_id) ||
274
274
!sieve_binary_read_byte(sbin, &offset, &location) ||
275
275
!sieve_binary_read_string(sbin, &offset, &script_name) ) {
276
276
/* Binary is corrupt, recompile */
277
277
sieve_sys_error("include: failed to read included script "
278
"from dependency block %d of binary %s", block, sieve_binary_path(sbin));
278
"from dependency block %d of binary %s", block, sieve_binary_path(sbin));
282
282
if ( location >= EXT_INCLUDE_LOCATION_INVALID ) {
283
283
/* Binary is corrupt, recompile */
284
284
sieve_sys_error("include: dependency block %d of binary %s "
285
"reports invalid script location (id %d)",
286
block, sieve_binary_path(sbin), location);
285
"reports invalid script location (id %d)",
286
block, sieve_binary_path(sbin), location);
290
290
/* Can we find/open the script dependency ? */
291
291
script_dir = ext_include_get_script_directory
292
(ext, location, str_c(script_name));
293
if ( script_dir == NULL ||
292
(ext, location, str_c(script_name));
293
if ( script_dir == NULL ||
294
294
!(script=sieve_script_create_in_directory
295
295
(ext->svinst, script_dir, str_c(script_name), NULL, NULL)) ) {
296
296
/* No, recompile */
300
300
(void)ext_include_binary_script_include(binctx, script, location, block_id);
302
302
sieve_script_unref(&script);
305
305
if ( !ext_include_variables_load
306
306
(ext, sbin, &offset, block, &binctx->global_vars) )
309
309
/* Restore previously active block */
310
310
(void)sieve_binary_block_set_active(sbin, prvblk, NULL);
315
315
static bool ext_include_binary_up_to_date
316
(const struct sieve_extension *ext ATTR_UNUSED, struct sieve_binary *sbin,
316
(const struct sieve_extension *ext ATTR_UNUSED, struct sieve_binary *sbin,
319
struct ext_include_binary_context *binctx =
319
struct ext_include_binary_context *binctx =
320
320
(struct ext_include_binary_context *) context;
321
321
struct hash_iterate_context *hctx;
322
322
void *key, *value;
324
324
/* Check all included scripts for changes */
325
325
hctx = hash_table_iterate_init(binctx->included_scripts);
326
326
while ( hash_table_iterate(hctx, &key, &value) ) {
327
struct ext_include_script_info *incscript =
327
struct ext_include_script_info *incscript =
328
328
(struct ext_include_script_info *) value;
330
330
/* Is the binary old than this dependency? */
331
331
if ( sieve_binary_script_newer(sbin, incscript->script) ) {
332
332
/* No, recompile */
341
341
static void ext_include_binary_free
342
(const struct sieve_extension *ext ATTR_UNUSED,
342
(const struct sieve_extension *ext ATTR_UNUSED,
343
343
struct sieve_binary *sbin ATTR_UNUSED, void *context)
345
struct ext_include_binary_context *binctx =
345
struct ext_include_binary_context *binctx =
346
346
(struct ext_include_binary_context *) context;
347
347
struct hash_iterate_context *hctx;
348
348
void *key, *value;
350
350
/* Release references to all included script objects */
351
351
hctx = hash_table_iterate_init(binctx->included_scripts);
352
352
while ( hash_table_iterate(hctx, &key, &value) ) {
353
struct ext_include_script_info *incscript =
353
struct ext_include_script_info *incscript =
354
354
(struct ext_include_script_info *) value;
356
356
sieve_script_unref(&incscript->script);
358
358
hash_table_iterate_deinit(&hctx);
360
360
hash_table_destroy(&binctx->included_scripts);
362
if ( binctx->global_vars != NULL )
362
if ( binctx->global_vars != NULL )
363
363
sieve_variable_scope_unref(&binctx->global_vars);
370
370
bool ext_include_binary_dump
371
371
(const struct sieve_extension *ext, struct sieve_dumptime_env *denv)
373
373
struct sieve_binary *sbin = denv->sbin;
374
struct ext_include_binary_context *binctx =
374
struct ext_include_binary_context *binctx =
375
375
ext_include_binary_get_context(ext, sbin);
376
376
struct hash_iterate_context *hctx;
377
377
void *key, *value;
380
380
if ( !ext_include_variables_dump(denv, binctx->global_vars) )
383
hctx = hash_table_iterate_init(binctx->included_scripts);
383
hctx = hash_table_iterate_init(binctx->included_scripts);
384
384
while ( hash_table_iterate(hctx, &key, &value) ) {
385
struct ext_include_script_info *incscript =
385
struct ext_include_script_info *incscript =
386
386
(struct ext_include_script_info *) value;
388
sieve_binary_dump_sectionf(denv, "Included %s script '%s' (block: %d)",
389
ext_include_script_location_name(incscript->location),
388
sieve_binary_dump_sectionf(denv, "Included %s script '%s' (block: %d)",
389
ext_include_script_location_name(incscript->location),
390
390
sieve_script_name(incscript->script), incscript->block_id);
392
392
if ( prvblk == 0 ) {
393
if ( !sieve_binary_block_set_active(sbin, incscript->block_id, &prvblk) )
393
if ( !sieve_binary_block_set_active(sbin, incscript->block_id, &prvblk) )
396
if ( !sieve_binary_block_set_active(sbin, incscript->block_id, NULL) )
396
if ( !sieve_binary_block_set_active(sbin, incscript->block_id, NULL) )
400
400
denv->cdumper = sieve_code_dumper_create(denv);
402
402
if ( denv->cdumper == NULL )
405
405
sieve_code_dumper_run(denv->cdumper);
406
406
sieve_code_dumper_free(&(denv->cdumper));
409
if ( !sieve_binary_block_set_active(sbin, prvblk, NULL) )
409
if ( !sieve_binary_block_set_active(sbin, prvblk, NULL) )
412
412
hash_table_iterate_deinit(&hctx);
417
417
bool ext_include_code_dump
418
(const struct sieve_extension *ext, const struct sieve_dumptime_env *denv,
418
(const struct sieve_extension *ext, const struct sieve_dumptime_env *denv,
419
419
sieve_size_t *address ATTR_UNUSED)
421
421
struct sieve_binary *sbin = denv->sbin;
422
struct ext_include_binary_context *binctx =
422
struct ext_include_binary_context *binctx =
423
423
ext_include_binary_get_context(ext, sbin);
424
424
struct ext_include_context *ectx = ext_include_get_context(ext);
426
426
sieve_ext_variables_dump_set_scope
427
427
(ectx->var_ext, denv, ext, binctx->global_vars);