diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-12-11 18:10:47 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-12-11 18:10:47 +0200 |
commit | 57e0b97994f04b8d3f36ef3c45a99941b4f011bc (patch) | |
tree | 58a1de1ec129d4ebf98b95fa59715c30cc7289b8 /libmu_sieve | |
parent | 44f87939efa0a33e8d1f26b9d9fa3e15c32d808a (diff) | |
download | mailutils-57e0b97994f04b8d3f36ef3c45a99941b4f011bc.tar.gz mailutils-57e0b97994f04b8d3f36ef3c45a99941b4f011bc.tar.bz2 |
Support for environment extension (RFC 5183).
* include/mailutils/sieve.h (mu_sieve_require_environment): New proto.
* libmu_sieve/Makefile.am: Add environment.c
* libmu_sieve/environment.c: New file.
* libmu_sieve/require.c: Handle "environment" keyword.
* libmu_sieve/sieve-priv.h (mu_sieve_machine) <exenv>: New member.
* libmu_sieve/sieve.l: Bugfixes
* libmu_sieve/variables.c: Add missing static qualifiers
* sieve/sieve.c: New option --environment
Diffstat (limited to 'libmu_sieve')
-rw-r--r-- | libmu_sieve/Makefile.am | 1 | ||||
-rw-r--r-- | libmu_sieve/environment.c | 226 | ||||
-rw-r--r-- | libmu_sieve/require.c | 2 | ||||
-rw-r--r-- | libmu_sieve/sieve-priv.h | 4 | ||||
-rw-r--r-- | libmu_sieve/sieve.l | 30 | ||||
-rw-r--r-- | libmu_sieve/variables.c | 4 |
6 files changed, 251 insertions, 16 deletions
diff --git a/libmu_sieve/Makefile.am b/libmu_sieve/Makefile.am index a0ce50b65..fd96ac505 100644 --- a/libmu_sieve/Makefile.am +++ b/libmu_sieve/Makefile.am @@ -31,6 +31,7 @@ libmu_sieve_la_SOURCES = \ conf.c\ comparator.c\ encoded.c\ + environment.c\ load.c\ mem.c\ prog.c\ diff --git a/libmu_sieve/environment.c b/libmu_sieve/environment.c new file mode 100644 index 000000000..9de486271 --- /dev/null +++ b/libmu_sieve/environment.c @@ -0,0 +1,226 @@ +/* The Sieve "environment" extension for GNU Mailutils + Copyright (C) 2016 Free Software Foundation, Inc. + + GNU Mailutils is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GNU Mailutils is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with GNU Mailutils. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <sieve-priv.h> + +int +retrieve_env (void *item, void *data, size_t idx, char **pval) +{ + mu_sieve_machine_t mach; + + if (idx) + return MU_ERR_NOENT; + mach = data; + return mu_sieve_get_environ (mach, item, pval); +} + +static int +sieve_test_environment (mu_sieve_machine_t mach) +{ + mu_sieve_value_t *name, *key_list; + + name = mu_sieve_get_arg_untyped (mach, 0); + key_list = mu_sieve_get_arg_untyped (mach, 1); + + return mu_sieve_vlist_compare (mach, name, key_list, retrieve_env, NULL, + mach); +} + +static mu_sieve_data_type environ_args[] = { + SVT_STRING, + SVT_STRING_LIST, + SVT_VOID +}; + +static mu_sieve_tag_group_t environ_tag_groups[] = { + { mu_sieve_match_part_tags, mu_sieve_match_part_checker }, + { NULL } +}; + +int +mu_sieve_require_environment (mu_sieve_machine_t mach) +{ + mu_sieve_register_test (mach, "environment", sieve_test_environment, + environ_args, environ_tag_groups, 1); + return 0; +} + +static char * +std_name_get (mu_sieve_machine_t mach) +{ + return strdup (PACKAGE_NAME); +} + +static char * +std_version_get (mu_sieve_machine_t mach) +{ + return strdup (PACKAGE_VERSION); +} + +/* "host" => The fully-qualified domain name of the host where + the Sieve script is executing. +*/ +static char * +std_host_get (mu_sieve_machine_t mach) +{ + char *host; + int rc; + + rc = mu_get_host_name (&host); + if (rc == 0) + return host; + return NULL; +} + + +/* "domain" => The primary DNS domain associated with the Sieve + execution context, usually but not always a proper + suffix of the host name. +*/ +static char * +std_domain_get (mu_sieve_machine_t mach) +{ + char *host; + int rc; + + rc = mu_get_host_name (&host); + if (rc == 0) + { + char *p = strchr (host, '.'); + if (p) + { + p = strdup (p + 1); + free (host); + return p; + } + return host; + } + return NULL; +} + +/* FIXME: do we need set? If so, mu_set_host_name is also needed */ + +struct stdenviron +{ + char *name; + char *(*get) (mu_sieve_machine_t); + int (*set) (mu_sieve_machine_t, char const *, char const *value); +}; + +static struct stdenviron stdenv[] = +{ + { "domain", std_domain_get, NULL }, + { "host", std_host_get, NULL }, + { "name", std_name_get, NULL }, + { "version", std_version_get, NULL }, + { NULL } +}; + +static struct stdenviron const * +stdenv_find (char const *name) +{ + struct stdenviron const *p; + + for (p = stdenv; p->name; p++) + if (strcmp (p->name, name) == 0) + return p; + return NULL; +} + +static char * +stdenv_get (mu_sieve_machine_t mach, char const *name) +{ + struct stdenviron const *p = stdenv_find (name); + if (!p) + return NULL; + return p->get (mach); +} + +static int +stdenv_set (mu_sieve_machine_t mach, char const *name, char const *value) +{ + struct stdenviron const *p = stdenv_find (name); + if (!p) + return MU_ERR_NOENT; + if (!p->set) + return EACCES; + return p->set (mach, name, value); +} + +int +mu_sieve_get_environ (mu_sieve_machine_t mach, char const *name, char **retval) +{ + char *p; + + p = stdenv_get (mach, name); + if (p) + { + *retval = p; + return 0; + } + + if (!mach->exenv) + return MU_ERR_NOENT; + + p = mu_assoc_ref (mach->exenv, name); + if (p) + { + *retval = strdup (*(char**)p); + if (!*retval) + return errno; + } + else + return MU_ERR_NOENT; + return 0; +} + +int +mu_sieve_set_environ (mu_sieve_machine_t mach, char const *name, + char const *value) +{ + int rc; + + rc = stdenv_set (mach, name, value); + if (rc == MU_ERR_NOENT) + { + char **pptr; + + if (!mach->exenv) + { + int rc = mu_assoc_create (&mach->exenv, sizeof (char *), 0); + if (rc) + return rc; + } + rc = mu_assoc_ref_install (mach->exenv, name, (void **) &pptr); + if (rc == 0 || rc == MU_ERR_EXISTS) + { + char *copy = strdup (value); + if (!copy) + rc = errno; + else + { + *pptr = copy; + rc = 0; + } + } + } + return rc; +} + diff --git a/libmu_sieve/require.c b/libmu_sieve/require.c index f0ff27c77..c8f5b62b9 100644 --- a/libmu_sieve/require.c +++ b/libmu_sieve/require.c @@ -43,6 +43,8 @@ mu_sieve_require (mu_sieve_machine_t mach, mu_sieve_slice_t list) rc = mu_sieve_require_relational (mach, name); else if (strcmp (name, "encoded-character") == 0) /* RFC 5228, 2.4.2.4 */ rc = mu_sieve_require_encoded_character (mach, name); + else if (strcmp (name, "environment") == 0) /* RFC 5183 */ + rc = mu_sieve_require_environment (mach); else if (strncmp (name, "comparator-", 11) == 0) rc = mu_sieve_registry_require (mach, name + 11, mu_sieve_record_comparator); diff --git a/libmu_sieve/sieve-priv.h b/libmu_sieve/sieve-priv.h index f5fb38a45..b288f213a 100644 --- a/libmu_sieve/sieve-priv.h +++ b/libmu_sieve/sieve-priv.h @@ -107,7 +107,9 @@ struct mu_sieve_machine int dry_run; /* Dry-run mode */ jmp_buf errbuf; /* Target location for non-local exits */ - + + mu_assoc_t exenv; /* Execution environment (RFC 5183) */ + mu_mailbox_t mailbox; /* Mailbox to operate upon */ size_t msgno; /* Current message number */ mu_message_t msg; /* Current message */ diff --git a/libmu_sieve/sieve.l b/libmu_sieve/sieve.l index b18cd4ae6..ffc7a4ab8 100644 --- a/libmu_sieve/sieve.l +++ b/libmu_sieve/sieve.l @@ -41,10 +41,11 @@ static int strip_tabs; static int number (void); static int string (void); static void line_begin (void); -static void line_add (char *text, size_t len); +static void line_add (char const *text, size_t len); +static void line_addz (char const *text); static void line_finish (void); static void multiline_begin (void); -static void multiline_add (char *); +static void multiline_add (void); static void multiline_finish (void); static char *multiline_strip_tabs (char *text); static void ident (const char *text); @@ -286,8 +287,8 @@ true return TRUE; \"[^\\"\n]*\" { return string (); } \"[^\\"\n]*\\. { BEGIN(STR); line_begin (); - line_add (str_unescape (yytext + 1, yyleng - 1), 0); } -<STR>[^\\"\n]*\\. { line_add (str_unescape (yytext, yyleng), 0); } + line_addz (str_unescape (yytext + 1, yyleng - 1)); } +<STR>[^\\"\n]*\\. { line_addz (str_unescape (yytext, yyleng)); } <STR>[^\\"\n]*\" { BEGIN(INITIAL); if (yyleng > 1) line_add (yytext, yyleng - 1); @@ -303,7 +304,7 @@ text:-?\\?{IDENT}[ \t]*#.*\n { BEGIN(ML); text:-?\\?{IDENT}[ \t]*\n { BEGIN(ML); multiline_begin (); } <ML>#[ \t]*include.*\n { if (multiline_delimiter[0] == '\\') - multiline_add (NULL); + multiline_add (); else sieve_include (); } <ML>.*\n { char *p = multiline_strip_tabs (yytext); @@ -318,7 +319,7 @@ text:-?\\?{IDENT}[ \t]*\n { BEGIN(ML); multiline_finish (); return MULTILINE; } - multiline_add (NULL); } + multiline_add (); } {WS} ; /* Other tokens */ \n ; @@ -527,19 +528,22 @@ multiline_strip_tabs (char *text) } static void -line_add (char *text, size_t len) +line_add (char const *text, size_t len) { - if (len == 0) - len = strlen (text); mu_opool_append (mu_sieve_machine->string_pool, text, len); } static void -multiline_add (char *s) +line_addz (char const *text) { - if (!s) - s = multiline_strip_tabs (yytext); - mu_opool_appendz (mu_sieve_machine->string_pool, s); + mu_opool_appendz (mu_sieve_machine->string_pool, text); +} + +static void +multiline_add (void) +{ + mu_opool_appendz (mu_sieve_machine->string_pool, + multiline_strip_tabs (yytext)); } static void diff --git a/libmu_sieve/variables.c b/libmu_sieve/variables.c index 347457782..c73b7e8d0 100644 --- a/libmu_sieve/variables.c +++ b/libmu_sieve/variables.c @@ -284,13 +284,13 @@ sieve_test_string (mu_sieve_machine_t mach) retrieve_string, fold_string, mach); } -mu_sieve_data_type string_args[] = { +static mu_sieve_data_type string_args[] = { SVT_STRING_LIST, SVT_STRING_LIST, SVT_VOID }; -mu_sieve_tag_group_t string_tag_groups[] = { +static mu_sieve_tag_group_t string_tag_groups[] = { { mu_sieve_match_part_tags, mu_sieve_match_part_checker }, { NULL } }; |