From 1ce4c883b64ba8acfb0f5d08dbeda4b8214db309 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Wed, 23 Sep 2015 20:06:15 +0200 Subject: [PATCH] Sieve extprograms plugin: Made line endings configurable for the input passed to the external program. --- doc/plugins/sieve_extprograms.txt | 9 ++++- .../sieve-extprograms-common.c | 31 +++++++++++++---- .../sieve-extprograms-common.h | 7 ++++ tests/plugins/extprograms/bin/crlf | 3 ++ .../extprograms/execute/execute.svtest | 33 ++++++++++++++++++- 5 files changed, 74 insertions(+), 9 deletions(-) create mode 100755 tests/plugins/extprograms/bin/crlf diff --git a/doc/plugins/sieve_extprograms.txt b/doc/plugins/sieve_extprograms.txt index d2b59a668..4110fce85 100644 --- a/doc/plugins/sieve_extprograms.txt +++ b/doc/plugins/sieve_extprograms.txt @@ -106,9 +106,16 @@ sieve_<extension>_bin_dir = execute directly and pipe messages to. sieve_<extension>_exec_timeout = 10s - Configures the maximum execution time after which the program is forcefully + Configures the maximum execution time after which the program is forcibly terminated. +sieve_<extension>_input_eol = crlf + Determines the end-of-line character sequence used for the data piped to + external programs. The default is currently "crlf", which represents a + sequence of the carriage return (CR) and line feed (LF) characters. This + matches the Internet Message Format (RFC5322) and what Sieve itself uses as a + line ending. Set this setting to "lf" to use a single LF character instead. + Examples -------- diff --git a/src/plugins/sieve-extprograms/sieve-extprograms-common.c b/src/plugins/sieve-extprograms/sieve-extprograms-common.c index 1619f095e..cf52b80a9 100644 --- a/src/plugins/sieve-extprograms/sieve-extprograms-common.c +++ b/src/plugins/sieve-extprograms/sieve-extprograms-common.c @@ -62,7 +62,7 @@ struct sieve_extprograms_config *sieve_extprograms_config_init struct sieve_instance *svinst = ext->svinst; struct sieve_extprograms_config *ext_config; const char *extname = sieve_extension_name(ext); - const char *bin_dir, *socket_dir; + const char *bin_dir, *socket_dir, *input_eol; sieve_number_t execute_timeout; extname = strrchr(extname, '.'); @@ -73,6 +73,8 @@ struct sieve_extprograms_config *sieve_extprograms_config_init (svinst, t_strdup_printf("sieve_%s_bin_dir", extname)); socket_dir = sieve_setting_get (svinst, t_strdup_printf("sieve_%s_socket_dir", extname)); + input_eol = sieve_setting_get + (svinst, t_strdup_printf("sieve_%s_input_eol", extname)); ext_config = i_new(struct sieve_extprograms_config, 1); ext_config->execute_timeout = @@ -94,6 +96,10 @@ struct sieve_extprograms_config *sieve_extprograms_config_init &execute_timeout)) { ext_config->execute_timeout = execute_timeout; } + + ext_config->default_input_eol = SIEVE_EXTPROGRAMS_EOL_CRLF; + if (input_eol != NULL && strcasecmp(input_eol, "lf") == 0) + ext_config->default_input_eol = SIEVE_EXTPROGRAMS_EOL_LF; } if ( sieve_extension_is(ext, vnd_pipe_extension) ) @@ -366,6 +372,8 @@ int sieve_extprogram_command_read_operands struct sieve_extprogram { struct sieve_instance *svinst; + const struct sieve_extprograms_config *ext_config; + const struct sieve_script_env *scriptenv; struct program_client_settings set; struct program_client *program_client; @@ -515,6 +523,7 @@ struct sieve_extprogram *sieve_extprogram_create sprog = i_new(struct sieve_extprogram, 1); sprog->svinst = ext->svinst; + sprog->ext_config = ext_config; sprog->scriptenv = senv; sprog->set.client_connect_timeout_msecs = @@ -574,7 +583,20 @@ void sieve_extprogram_set_output void sieve_extprogram_set_input (struct sieve_extprogram *sprog, struct istream *input) { + switch (sprog->ext_config->default_input_eol) { + case SIEVE_EXTPROGRAMS_EOL_LF: + input = i_stream_create_lf(input); + break; + case SIEVE_EXTPROGRAMS_EOL_CRLF: + input = i_stream_create_crlf(input); + break; + default: + i_unreached(); + } + program_client_set_input(sprog->program_client, input); + + i_stream_unref(&input); } void sieve_extprogram_set_output_seekable @@ -601,12 +623,7 @@ int sieve_extprogram_set_input_mail if (mail_get_stream(mail, NULL, NULL, &input) < 0) return -1; - /* Make sure the message contains CRLF consistently */ - input = i_stream_create_crlf(input); - - program_client_set_input(sprog->program_client, input); - i_stream_unref(&input); - + sieve_extprogram_set_input(sprog, input); return 1; } diff --git a/src/plugins/sieve-extprograms/sieve-extprograms-common.h b/src/plugins/sieve-extprograms/sieve-extprograms-common.h index d769e3607..1c09d96ee 100644 --- a/src/plugins/sieve-extprograms/sieve-extprograms-common.h +++ b/src/plugins/sieve-extprograms/sieve-extprograms-common.h @@ -10,6 +10,11 @@ * Extension configuration */ +enum sieve_extprograms_eol { + SIEVE_EXTPROGRAMS_EOL_CRLF = 0, + SIEVE_EXTPROGRAMS_EOL_LF +}; + struct sieve_extprograms_config { const struct sieve_extension *copy_ext; const struct sieve_extension *var_ext; @@ -17,6 +22,8 @@ struct sieve_extprograms_config { char *socket_dir; char *bin_dir; + enum sieve_extprograms_eol default_input_eol; + unsigned int execute_timeout; }; diff --git a/tests/plugins/extprograms/bin/crlf b/tests/plugins/extprograms/bin/crlf new file mode 100755 index 000000000..a0028cf55 --- /dev/null +++ b/tests/plugins/extprograms/bin/crlf @@ -0,0 +1,3 @@ +#!/bin/sh + +tr -s '\r' '#' diff --git a/tests/plugins/extprograms/execute/execute.svtest b/tests/plugins/extprograms/execute/execute.svtest index f8fde2698..5e671c571 100644 --- a/tests/plugins/extprograms/execute/execute.svtest +++ b/tests/plugins/extprograms/execute/execute.svtest @@ -4,6 +4,7 @@ require "vnd.dovecot.debug"; require "variables"; require "relational"; require "environment"; +require "encoded-character"; test_set "message" text: From: stephan@example.com @@ -115,4 +116,34 @@ test "Execute - used as test" { } } - +test_config_set "sieve_execute_input_eol" "crlf"; +test_config_reload :extension "vnd.dovecot.execute"; +test_result_reset; +set "out" ""; + +test "Execute - CRLF" { + execute + :input "FROP${hex:0A}FRIEP${hex:0a}" + :output "out" + "crlf"; + + if not string "${out}" "FROP#${hex:0A}FRIEP#${hex:0a}" { + test_fail "wrong string returned: '${out}'"; + } +} + +test_config_set "sieve_execute_input_eol" "lf"; +test_config_reload :extension "vnd.dovecot.execute"; +test_result_reset; +set "out" ""; + +test "Execute - LF" { + execute + :input "FROP${hex:0D 0A}FRIEP${hex:0d 0a}" + :output "out" + "crlf"; + + if not string "${out}" "FROP${hex:0A}FRIEP${hex:0a}" { + test_fail "wrong string returned: '${out}'"; + } +} -- GitLab