diff --git a/src/lib-sieve/plugins/include/Makefile.am b/src/lib-sieve/plugins/include/Makefile.am index 89e93524b1d6eaaa8316d1086c119cf8ec82128c..2e7b9b1040a641324e0613f793e2a29c46656e35 100644 --- a/src/lib-sieve/plugins/include/Makefile.am +++ b/src/lib-sieve/plugins/include/Makefile.am @@ -9,7 +9,9 @@ AM_CPPFLAGS = \ cmds = \ cmd-include.c \ - cmd-return.c + cmd-return.c \ + cmd-import.c \ + cmd-export.c libsieve_ext_include_la_SOURCES = \ $(cmds) \ diff --git a/src/lib-sieve/plugins/include/cmd-export.c b/src/lib-sieve/plugins/include/cmd-export.c new file mode 100644 index 0000000000000000000000000000000000000000..47ebe809fab0f00b4e1cbfb73fa19c59299ea9e8 --- /dev/null +++ b/src/lib-sieve/plugins/include/cmd-export.c @@ -0,0 +1,107 @@ +#include "lib.h" + +#include "sieve-code.h" +#include "sieve-commands.h" +#include "sieve-commands-private.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "ext-include-common.h" + +/* Forward declarations */ + +static bool cmd_export_validate + (struct sieve_validator *validator, struct sieve_command_context *cmd); +static bool cmd_export_generate + (struct sieve_generator *generator, + struct sieve_command_context *ctx ATTR_UNUSED); + +static bool opc_export_execute + (const struct sieve_operation *op, + const struct sieve_runtime_env *renv, sieve_size_t *address); + +/* Export command + * + * Syntax + * export + */ +const struct sieve_command cmd_export = { + "export", + SCT_COMMAND, + 1, 0, FALSE, FALSE, + NULL, NULL, + cmd_export_validate, + cmd_export_generate, + NULL +}; + +/* Export operation */ + +const struct sieve_operation export_operation = { + "export", + &include_extension, + EXT_INCLUDE_OPERATION_EXPORT, + NULL, + opc_export_execute +}; + +/* + * Validation + */ + +static bool cmd_export_validate + (struct sieve_validator *validator, struct sieve_command_context *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + struct sieve_command_context *prev_context = + sieve_command_prev_context(cmd); + + /* Check valid command placement */ + if ( !sieve_command_is_toplevel(cmd) || + ( !sieve_command_is_first(cmd) && prev_context != NULL && + prev_context->command != &cmd_require && + prev_context->command != &cmd_import && + prev_context->command != &cmd_export) ) + { + sieve_command_validate_error(validator, cmd, + "export commands can only be placed at top level " + "at the beginning of the file after any require or import commands"); + return FALSE; + } + + if ( !sieve_validate_positional_argument + (validator, cmd, arg, "value", 1, SAAT_STRING_LIST) ) { + return FALSE; + } + + //return sieve_validator_argument_activate(validator, cmd, arg, FALSE); + return TRUE; +} + +/* + * Generation + */ + +static bool cmd_export_generate +(struct sieve_generator *gentr, struct sieve_command_context *ctx ATTR_UNUSED) +{ + sieve_generator_emit_operation_ext + (gentr, &export_operation, ext_include_my_id); + + return TRUE; +} + +/* + * Interpretation + */ + +static bool opc_export_execute +(const struct sieve_operation *op ATTR_UNUSED, + const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + return TRUE; +} + + diff --git a/src/lib-sieve/plugins/include/cmd-import.c b/src/lib-sieve/plugins/include/cmd-import.c new file mode 100644 index 0000000000000000000000000000000000000000..5ac6b9d67c8a62641072c5b4136ed0e3afc290f2 --- /dev/null +++ b/src/lib-sieve/plugins/include/cmd-import.c @@ -0,0 +1,106 @@ +#include "lib.h" + +#include "sieve-code.h" +#include "sieve-commands.h" +#include "sieve-commands-private.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "ext-include-common.h" + +/* Forward declarations */ + +static bool cmd_import_validate + (struct sieve_validator *validator, struct sieve_command_context *cmd); +static bool cmd_import_generate + (struct sieve_generator *generator, + struct sieve_command_context *ctx ATTR_UNUSED); + +static bool opc_import_execute + (const struct sieve_operation *op, + const struct sieve_runtime_env *renv, sieve_size_t *address); + +/* Import command + * + * Syntax + * import + */ +const struct sieve_command cmd_import = { + "import", + SCT_COMMAND, + 1, 0, FALSE, FALSE, + NULL, NULL, + cmd_import_validate, + cmd_import_generate, + NULL +}; + +/* Import operation */ + +const struct sieve_operation import_operation = { + "import", + &include_extension, + EXT_INCLUDE_OPERATION_IMPORT, + NULL, + opc_import_execute +}; + +/* + * Validation + */ + +static bool cmd_import_validate + (struct sieve_validator *validator, struct sieve_command_context *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + struct sieve_command_context *prev_context = + sieve_command_prev_context(cmd); + + /* Check valid command placement */ + if ( !sieve_command_is_toplevel(cmd) || + ( !sieve_command_is_first(cmd) && prev_context != NULL && + prev_context->command != &cmd_require && + prev_context->command != &cmd_import) ) + { + sieve_command_validate_error(validator, cmd, + "import commands can only be placed at top level " + "at the beginning of the file after any require commands"); + return FALSE; + } + + if ( !sieve_validate_positional_argument + (validator, cmd, arg, "value", 1, SAAT_STRING_LIST) ) { + return FALSE; + } + + //return sieve_validator_argument_activate(validator, cmd, arg, FALSE); + return TRUE; +} + +/* + * Generation + */ + +static bool cmd_import_generate +(struct sieve_generator *gentr, struct sieve_command_context *ctx ATTR_UNUSED) +{ + sieve_generator_emit_operation_ext + (gentr, &import_operation, ext_include_my_id); + + return TRUE; +} + +/* + * Interpretation + */ + +static bool opc_import_execute +(const struct sieve_operation *op ATTR_UNUSED, + const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + return TRUE; +} + + diff --git a/src/lib-sieve/plugins/include/cmd-include.c b/src/lib-sieve/plugins/include/cmd-include.c index 3e9b03a13ea2dd215e25b17399fb8328b27d4244..75c95e00b8f297765944807673aa29ae6e5c4d56 100644 --- a/src/lib-sieve/plugins/include/cmd-include.c +++ b/src/lib-sieve/plugins/include/cmd-include.c @@ -191,7 +191,7 @@ static bool cmd_include_generate * This yields the id of the binary block containing the compiled byte code. */ if ( !ext_include_generate_include - (gentr, cmd, ctx_data->location, ctx_data->script_name, &block_id) ) + (gentr, cmd, ctx_data->location, ctx_data->script_name, &block_id) ) return FALSE; sieve_generator_emit_operation_ext diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c index 5b3aa59d88b3b2e8cb1a1bc1bff7400ab49fc6ff..ddb874b6f9e5ce7f9e94ec250cad41dd4803f20f 100644 --- a/src/lib-sieve/plugins/include/ext-include-common.c +++ b/src/lib-sieve/plugins/include/ext-include-common.c @@ -462,7 +462,7 @@ bool ext_include_generate_include /* Create script object */ if ( (script = sieve_script_create(script_path, script_name, ehandler, NULL)) - == NULL ) + == NULL ) return FALSE; /* Check for circular include */ diff --git a/src/lib-sieve/plugins/include/ext-include-common.h b/src/lib-sieve/plugins/include/ext-include-common.h index 107367faaeb710e4cc1a6304f7ed26ac4e08b80c..4c924a7486354c6ed0299555e7e95540bbd0b021 100644 --- a/src/lib-sieve/plugins/include/ext-include-common.h +++ b/src/lib-sieve/plugins/include/ext-include-common.h @@ -15,11 +15,20 @@ extern int ext_include_my_id; extern const struct sieve_extension include_extension; +/* Commands */ + +extern const struct sieve_command cmd_include; +extern const struct sieve_command cmd_return; +extern const struct sieve_command cmd_import; +extern const struct sieve_command cmd_export; + /* Types */ enum ext_include_opcode { EXT_INCLUDE_OPERATION_INCLUDE, - EXT_INCLUDE_OPERATION_RETURN + EXT_INCLUDE_OPERATION_RETURN, + EXT_INCLUDE_OPERATION_IMPORT, + EXT_INCLUDE_OPERATION_EXPORT }; enum ext_include_script_location { diff --git a/src/lib-sieve/plugins/include/ext-include.c b/src/lib-sieve/plugins/include/ext-include.c index b914869e75c7d67cf16b2e569a4374dc1f94d089..999aaa3e83f416c3d88e5b179f8444124e16fe29 100644 --- a/src/lib-sieve/plugins/include/ext-include.c +++ b/src/lib-sieve/plugins/include/ext-include.c @@ -37,18 +37,19 @@ static bool ext_include_generator_load(struct sieve_generator *gentr); static bool ext_include_binary_load(struct sieve_binary *sbin); static bool ext_include_interpreter_load(struct sieve_interpreter *interp); -/* Commands */ - -extern const struct sieve_command cmd_include; -extern const struct sieve_command cmd_return; - /* Operations */ extern const struct sieve_operation include_operation; extern const struct sieve_operation return_operation; - -static const struct sieve_operation *ext_include_operations[] = - { &include_operation, &return_operation }; +extern const struct sieve_operation import_operation; +extern const struct sieve_operation export_operation; + +static const struct sieve_operation *ext_include_operations[] = { + &include_operation, + &return_operation, + &import_operation, + &export_operation +}; /* Extension definitions */ @@ -87,6 +88,8 @@ static bool ext_include_validator_load(struct sieve_validator *validator) /* Register new commands */ sieve_validator_register_command(validator, &cmd_include); sieve_validator_register_command(validator, &cmd_return); + sieve_validator_register_command(validator, &cmd_import); + sieve_validator_register_command(validator, &cmd_export); return TRUE; } diff --git a/src/lib-sieve/plugins/include/include-variables.sieve b/src/lib-sieve/plugins/include/include-variables.sieve new file mode 100644 index 0000000000000000000000000000000000000000..996c81aa6392522d3632c517b04c6d2553d8e46f --- /dev/null +++ b/src/lib-sieve/plugins/include/include-variables.sieve @@ -0,0 +1,13 @@ +require "include"; +require "variables"; + +export ["value1", "value2"]; +export ["value3", "value4"]; + +set "value1" "Works"; +set "value2" "fine."; +set "value3" "Yeah"; +set "value4" "it does."; + +include "include-variables1"; +include "include-variables2"; diff --git a/src/lib-sieve/plugins/include/include-variables1.sieve b/src/lib-sieve/plugins/include/include-variables1.sieve new file mode 100644 index 0000000000000000000000000000000000000000..6bb7436bc45b7a27431d1cbbbd86c0cf86cdd297 --- /dev/null +++ b/src/lib-sieve/plugins/include/include-variables1.sieve @@ -0,0 +1,5 @@ +require "include"; +require "variables"; +require "fileinto"; + +fileinto "${value1} ${value2}"; diff --git a/src/lib-sieve/plugins/include/include-variables2.sieve b/src/lib-sieve/plugins/include/include-variables2.sieve new file mode 100644 index 0000000000000000000000000000000000000000..1c97235a6cb5695ceaf54841db4cff5f46b09cdf --- /dev/null +++ b/src/lib-sieve/plugins/include/include-variables2.sieve @@ -0,0 +1,5 @@ +require "include"; +require "variables"; +require "fileinto"; + +fileinto "${value3} ${value4}"; diff --git a/src/lib-sieve/sieve-generator.c b/src/lib-sieve/sieve-generator.c index edc87c55ff5fadca8a3b3cf3bcb67e3915e706ed..27d70874b532fa6b723a3c24811f025283f72173 100644 --- a/src/lib-sieve/sieve-generator.c +++ b/src/lib-sieve/sieve-generator.c @@ -368,6 +368,11 @@ bool sieve_generator_run generator->binary = NULL; sieve_binary_unref(sbin); + + if ( topmost && !result ) { + sieve_binary_unref(sbin); + *sbin = NULL; + } return result; } diff --git a/src/lib-sieve/sieve-script.c b/src/lib-sieve/sieve-script.c index 02f95b2097be9fd0846f7d0ab913cfd8b8aa4d85..025a0cabbe1ca1b47b080162218099738736d608 100644 --- a/src/lib-sieve/sieve-script.c +++ b/src/lib-sieve/sieve-script.c @@ -25,68 +25,66 @@ struct sieve_script *sieve_script_init if ( exists_r != NULL ) *exists_r = FALSE; -// t_push(); - - /* Extract filename from path */ - filename = strrchr(path, '/'); - if ( filename == NULL ) { - dirpath = ""; - filename = path; - } else { - dirpath = t_strdup_until(path, filename); - filename++; - } - - if ( name == NULL || *name == '\0' ) { - const char *ext; + T_BEGIN { + /* Extract filename from path */ + filename = strrchr(path, '/'); + if ( filename == NULL ) { + dirpath = ""; + filename = path; + } else { + dirpath = t_strdup_until(path, filename); + filename++; + } - /* Extract the script name */ - ext = strrchr(filename, '.'); - if ( ext == NULL || ext == filename || strncmp(ext,".sieve",6) != 0 ) - name = filename; - else - name = t_strdup_until(filename, ext); - } + if ( name == NULL || *name == '\0' ) { + const char *ext; + + /* Extract the script name */ + ext = strrchr(filename, '.'); + if ( ext == NULL || ext == filename || strncmp(ext,".sieve",6) != 0 ) + name = filename; + else + name = t_strdup_until(filename, ext); + } + + /* First obtain stat data from the system */ - /* First obtain stat data from the system */ - - if ( (ret=stat(path, &st)) != 0 && (errno != ENOENT || exists_r == NULL) ) { - if ( errno == ENOENT ) - sieve_error(ehandler, name, "sieve script does not exist"); - else - sieve_critical(ehandler, name, "failed to stat sieve script file '%s': %m", path); - script = NULL; - } else { - /* Only create/init the object if it stat()s without problems */ - - if ( ret == 0 && !S_ISREG(st.st_mode) ) { - sieve_critical(ehandler, name, - "sieve script file '%s' is not a regular file.", path); + if ( (ret=stat(path, &st)) != 0 && (errno != ENOENT || exists_r == NULL) ) { + if ( errno == ENOENT ) + sieve_error(ehandler, name, "sieve script does not exist"); + else + sieve_critical(ehandler, name, "failed to stat sieve script file '%s': %m", path); script = NULL; } else { - if ( exists_r != NULL ) - *exists_r = ( ret == 0 ); - - if ( script == NULL ) { - pool = pool_alloconly_create("sieve_script", 1024); - script = p_new(pool, struct sieve_script, 1); - script->pool = pool; - } else - pool = script->pool; - - script->refcount = 1; - script->ehandler = ehandler; - sieve_error_handler_ref(ehandler); - - script->st = st; - script->path = p_strdup(pool, path); - script->filename = p_strdup(pool, filename); - script->dirpath = p_strdup(pool, dirpath); - script->name = p_strdup(pool, name); + /* Only create/init the object if it stat()s without problems */ + + if ( ret == 0 && !S_ISREG(st.st_mode) ) { + sieve_critical(ehandler, name, + "sieve script file '%s' is not a regular file.", path); + script = NULL; + } else { + if ( exists_r != NULL ) + *exists_r = ( ret == 0 ); + + if ( script == NULL ) { + pool = pool_alloconly_create("sieve_script", 1024); + script = p_new(pool, struct sieve_script, 1); + script->pool = pool; + } else + pool = script->pool; + + script->refcount = 1; + script->ehandler = ehandler; + sieve_error_handler_ref(ehandler); + + script->st = st; + script->path = p_strdup(pool, path); + script->filename = p_strdup(pool, filename); + script->dirpath = p_strdup(pool, dirpath); + script->name = p_strdup(pool, name); + } } - } - -// t_pop(); + } T_END; return script; }