summaryrefslogtreecommitdiff
path: root/libmu_sieve
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2016-12-11 18:10:47 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2016-12-11 18:10:47 +0200
commit57e0b97994f04b8d3f36ef3c45a99941b4f011bc (patch)
tree58a1de1ec129d4ebf98b95fa59715c30cc7289b8 /libmu_sieve
parent44f87939efa0a33e8d1f26b9d9fa3e15c32d808a (diff)
downloadmailutils-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.am1
-rw-r--r--libmu_sieve/environment.c226
-rw-r--r--libmu_sieve/require.c2
-rw-r--r--libmu_sieve/sieve-priv.h4
-rw-r--r--libmu_sieve/sieve.l30
-rw-r--r--libmu_sieve/variables.c4
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 }
};

Return to:

Send suggestions and report system problems to the System administrator.