Commit 1528dfde 1528dfded819e3c8ccba459425b0dc18b1f3a722 by Sergey Poznyakoff

sieve: improve argument/tag runtime access API

* include/mailutils/sieve.h (mu_sieve_data_type): Remove SVT_VALUE_LIST.
(mu_sieve_value_storage): Named union for use in mu_sieve_value_t; remove
the tag field.
(mu_sieve_tag_lookup): Change prototype.
(mu_sieve_value_get): Change prototype.
(mu_sieve_value_get_optional)
(mu_sieve_value_get_untyped): New functions.
(mu_sieve_arg_error): Removed proto.

* libmu_sieve/sieve.y: Remove SVT_VALUE_LIST support.
* libmu_sieve/util.c (mu_sieve_value_create)
(mu_sieve_type_str,mu_sieve_vlist_do): Remove SVT_VALUE_LIST support.
(mu_sieve_value_get): Rewrite.
(mu_sieve_value_get_untyped)
(mu_sieve_value_get_optional): New functions.
(mu_sieve_arg_error): Remove.
(mu_sieve_tag_lookup): Rewrite.
(mu_sieve_tag_lookup_untyped): New function.

* doc/texinfo/libmu_sieve.texi: Update.

libmu_sieve/tests.c
libmu_sieve/actions.c
libmu_sieve/extensions/editheader.c
libmu_sieve/extensions/list.c
libmu_sieve/extensions/moderator.c
libmu_sieve/extensions/pipe.c
libmu_sieve/extensions/spamd.c
libmu_sieve/extensions/timestamp.c
libmu_sieve/extensions/vacation.c
libmu_sieve/relational.c

examples/numaddr.c
1 parent 56217f1e
......@@ -85,9 +85,6 @@ A sieve tag. See @code{mu_sieve_runtime_tag_t} below.
@item SVT_IDENT
A character string representing an identifier.
@item SVT_VALUE_LIST
A @code{mu_list_t}. Each item in this list is of @code{mu_sieve_value_t} type.
@item SVT_POINTER
An opaque pointer.
@end table
......@@ -128,7 +125,6 @@ The numeric value is kept in @code{number} member.
The string is kept in @code{string} member.
@item SVT_STRING_LIST
@itemx SVT_VALUE_LIST
The list itself is pointed to by @code{list} member
@item SVT_TAG
......
......@@ -80,37 +80,26 @@ _count_items (void *item, void *data)
static int
numaddr_test (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
{
mu_sieve_value_t *h, *v;
mu_sieve_value_t *h;
struct val_ctr vc;
int rc;
/* Retrieve required arguments: */
/* First argument: list of header names */
h = mu_sieve_value_get (args, 0);
if (!h)
{
mu_sieve_error (mach, "numaddr: can't get argument 1");
mu_sieve_abort (mach);
}
h = mu_sieve_value_get_untyped (mach, args, 0);
/* Second argument: Limit on the number of addresses */
v = mu_sieve_value_get (args, 1);
if (!v)
{
mu_sieve_error (mach, "numaddr: can't get argument 2");
mu_sieve_abort (mach);
}
mu_sieve_value_get (mach, args, 1, SVT_NUMBER, &vc.limit);
/* Fill in the val_ctr structure */
mu_message_get_header (mu_sieve_get_message (mach), &vc.hdr);
vc.count = 0;
vc.limit = v->v.number;
/* Count the addresses */
rc = mu_sieve_vlist_do (h, _count_items, &vc);
/* Here rc >= 1 iff the counted number of addresses is greater or equal
to vc.limit. If `:under' tag was given we reverse the return value */
if (mu_sieve_tag_lookup (tags, "under", NULL))
if (mu_sieve_tag_lookup (mach, tags, "under", SVT_VOID, NULL))
rc = !rc;
return rc;
......
......@@ -57,24 +57,24 @@ typedef enum
SVT_STRING_LIST,
SVT_TAG,
SVT_IDENT,
SVT_VALUE_LIST,
SVT_POINTER
}
mu_sieve_data_type;
typedef struct mu_sieve_runtime_tag mu_sieve_runtime_tag_t;
union mu_sieve_value_storage
{
char *string;
size_t number;
mu_list_t list;
void *ptr;
};
typedef struct
{
mu_sieve_data_type type;
union
{
char *string;
size_t number;
mu_list_t list;
mu_sieve_runtime_tag_t *tag;
void *ptr;
} v;
union mu_sieve_value_storage v;
} mu_sieve_value_t;
typedef struct
......@@ -184,8 +184,12 @@ mu_sieve_relcmp_t mu_sieve_get_relcmp (mu_sieve_machine_t mach,
void mu_sieve_require (mu_sieve_machine_t mach, mu_list_t slist);
int mu_sieve_tag_lookup (mu_list_t taglist, char *name,
mu_sieve_value_t ** arg);
int mu_sieve_tag_lookup (mu_sieve_machine_t mach,
mu_list_t taglist, char *name,
mu_sieve_data_type type, void *ret);
int mu_sieve_tag_lookup_untyped (mu_sieve_machine_t mach, mu_list_t taglist,
char *name, mu_sieve_value_t **ret);
int mu_sieve_load_ext (mu_sieve_machine_t mach, const char *name);
int mu_sieve_match_part_checker (mu_sieve_machine_t mach,
const char *name, mu_list_t tags,
......@@ -193,8 +197,16 @@ int mu_sieve_match_part_checker (mu_sieve_machine_t mach,
int mu_sieve_match_part_checker (mu_sieve_machine_t mach,
const char *name, mu_list_t tags,
mu_list_t args);
/* Operations in value lists */
mu_sieve_value_t *mu_sieve_value_get (mu_list_t vlist, size_t index);
/* Operations on value lists */
mu_sieve_value_t *mu_sieve_value_get_optional (mu_sieve_machine_t mach,
mu_list_t vlist,
size_t index);
mu_sieve_value_t *mu_sieve_value_get_untyped (mu_sieve_machine_t mach,
mu_list_t vlist,
size_t index);
int mu_sieve_value_get (mu_sieve_machine_t mach, mu_list_t vlist,
size_t index,
mu_sieve_data_type type, void *ret);
int mu_sieve_vlist_do (mu_sieve_value_t *val, mu_list_action_t ac,
void *data);
int mu_sieve_vlist_compare (mu_sieve_value_t *a, mu_sieve_value_t *b,
......@@ -251,7 +263,6 @@ void mu_sieve_log_action (mu_sieve_machine_t mach, const char *action,
const char *fmt, ...)
MU_PRINTFLIKE(3,4);
void mu_sieve_abort (mu_sieve_machine_t mach);
void mu_sieve_arg_error (mu_sieve_machine_t mach, int n);
int mu_sieve_is_dry_run (mu_sieve_machine_t mach);
const char *mu_sieve_type_str (mu_sieve_data_type type);
......
......@@ -79,32 +79,29 @@ sieve_action_fileinto (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
{
int rc;
int mbflags = 0;
mu_sieve_value_t *opt;
mu_sieve_value_t *val = mu_sieve_value_get (args, 0);
if (!val)
{
mu_sieve_error (mach, _("cannot get filename!"));
mu_sieve_abort (mach);
}
char *filename;
char *perms;
if (mu_sieve_tag_lookup (tags, "permissions", &opt))
mu_sieve_value_get (mach, args, 0, SVT_STRING, &filename);
if (mu_sieve_tag_lookup (mach, tags, "permissions", SVT_STRING, &perms))
{
const char *p;
if (mu_parse_stream_perm_string (&mbflags, opt->v.string, &p))
if (mu_parse_stream_perm_string (&mbflags, perms, &p))
{
/* Should not happen, but anyway... */
mu_sieve_error (mach, _("invalid permissions (near %s)"), p);
return 1;
mu_sieve_abort (mach);
}
}
mu_sieve_log_action (mach, "FILEINTO",
_("delivering into %s"), val->v.string);
_("delivering into %s"), filename);
if (mu_sieve_is_dry_run (mach))
return 0;
rc = mu_message_save_to_mailbox (mach->msg, val->v.string, mbflags);
rc = mu_message_save_to_mailbox (mach->msg, filename, mbflags);
if (rc)
mu_sieve_error (mach, _("cannot save to mailbox: %s"),
mu_strerror (rc));
......@@ -293,18 +290,14 @@ sieve_action_reject (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
char *addrtext;
mu_address_t from, to;
mu_header_t hdr;
char *text;
mu_sieve_value_t *val = mu_sieve_value_get (args, 0);
if (!val)
{
mu_sieve_error (mach, _("reject: cannot get text!"));
mu_sieve_abort (mach);
}
mu_sieve_value_get (mach, args, 0, SVT_STRING, &text);
mu_sieve_log_action (mach, "REJECT", NULL);
if (mu_sieve_is_dry_run (mach))
return 0;
rc = build_mime (&mime, mach->msg, val->v.string);
rc = build_mime (&mime, mach->msg, text);
mu_mime_get_message (mime, &newmsg);
mu_message_unref (newmsg);
......@@ -413,25 +406,21 @@ sieve_action_redirect (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
int rc;
char *fromaddr, *p;
mu_mailer_t mailer = mu_sieve_get_mailer (mach);
char *addrstr;
mu_sieve_value_t *val = mu_sieve_value_get (args, 0);
if (!val)
{
mu_sieve_error (mach, _("cannot get address!"));
mu_sieve_abort (mach);
}
mu_sieve_value_get (mach, args, 0, SVT_STRING, &addrstr);
rc = mu_address_create (&addr, val->v.string);
rc = mu_address_create (&addr, addrstr);
if (rc)
{
mu_sieve_error (mach,
_("%lu: parsing recipient address `%s' failed: %s"),
(unsigned long) mu_sieve_get_message_num (mach),
val->v.string, mu_strerror (rc));
addrstr, mu_strerror (rc));
return 1;
}
mu_sieve_log_action (mach, "REDIRECT", _("to %s"), val->v.string);
mu_sieve_log_action (mach, "REDIRECT", _("to %s"), addrstr);
if (mu_sieve_is_dry_run (mach))
return 0;
......
......@@ -288,8 +288,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach,
matchtype = MU_SIEVE_MATCH_LAST; /* to not leave it undefined */
compfun = comp_false;
val = mu_sieve_value_get (args, 1);
if (!val)
if (mu_list_get (args, 1, (void**) &val))
return 1; /* shouldn't happen */
/* NOTE: Type of v is always SVT_STRING_LIST */
mu_list_count (val->v.list, &count);
......
......@@ -33,32 +33,14 @@
int
sieve_addheader (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
{
mu_sieve_value_t *val;
const char *field_name;
const char *field_value;
mu_message_t msg;
mu_header_t hdr;
int rc;
val = mu_sieve_value_get (args, 0);
if (!val)
{
mu_sieve_error (mach, "%lu: %s",
(unsigned long) mu_sieve_get_message_num (mach),
_("cannot get field name"));
mu_sieve_abort (mach);
}
field_name = val->v.string;
val = mu_sieve_value_get (args, 1);
if (!val)
{
mu_sieve_error (mach, "%lu: %s",
(unsigned long) mu_sieve_get_message_num (mach),
_("cannot get field value"));
mu_sieve_abort (mach);
}
field_value = val->v.string;
mu_sieve_value_get (mach, args, 0, SVT_STRING, &field_name);
mu_sieve_value_get (mach, args, 1, SVT_STRING, &field_value);
mu_sieve_log_action (mach, "ADDHEADER", "%s: %s", field_name, field_value);
......@@ -76,7 +58,7 @@ sieve_addheader (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
mu_sieve_abort (mach);
}
rc = (mu_sieve_tag_lookup (tags, "last", NULL) ?
rc = (mu_sieve_tag_lookup (mach, tags, "last", SVT_VOID, NULL) ?
mu_header_append : mu_header_prepend) (hdr, field_name, field_value);
if (rc)
{
......@@ -105,19 +87,10 @@ sieve_deleteheader (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
int rc;
mu_sieve_comparator_t comp;
mu_iterator_t itr;
unsigned long i, idx = 0;
size_t i, idx = 0;
val = mu_sieve_value_get (args, 0);
if (!val)
{
mu_sieve_error (mach, "%lu: %s",
(unsigned long) mu_sieve_get_message_num (mach),
_("cannot get field name"));
mu_sieve_abort (mach);
}
field_name = val->v.string;
val = mu_sieve_value_get (args, 1);
mu_sieve_value_get (mach, args, 0, SVT_STRING, &field_name);
val = mu_sieve_value_get_optional (mach, args, 1);
if (!val)
{
field_pattern = NULL;
......@@ -169,15 +142,14 @@ sieve_deleteheader (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
}
mu_header_get_iterator (hdr, &itr);
if (mu_sieve_tag_lookup (tags, "last", NULL))
if (mu_sieve_tag_lookup (mach, tags, "last", SVT_VOID, NULL))
{
int backwards = 1;
mu_iterator_ctl (itr, mu_itrctl_set_direction, &backwards);
}
comp = mu_sieve_get_comparator (mach, tags);
if (mu_sieve_tag_lookup (tags, "index", &val))
idx = val->v.number;
mu_sieve_tag_lookup (mach, tags, "index", SVT_NUMBER, &idx);
for (i = 0, mu_iterator_first (itr); !mu_iterator_is_done (itr);
mu_iterator_next (itr))
......
......@@ -147,30 +147,17 @@ list_retrieve_header (void *item, void *data, int idx, char **pval)
static int
list_test (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
{
mu_sieve_value_t *h, *v, *arg;
mu_sieve_value_t *h, *v;
mu_sieve_comparator_t comp = mu_sieve_get_comparator (mach, tags);
struct header_closure clos;
int result;
memset (&clos, 0, sizeof clos);
if (mu_sieve_tag_lookup (tags, "delim", &arg))
clos.delim = arg->v.string;
else
if (!mu_sieve_tag_lookup (mach, tags, "delim", SVT_STRING, &clos.delim))
clos.delim = ",";
h = mu_sieve_value_get (args, 0);
if (!h)
{
mu_sieve_arg_error (mach, 1);
mu_sieve_abort (mach);
}
v = mu_sieve_value_get (args, 1);
if (!v)
{
mu_sieve_arg_error (mach, 2);
mu_sieve_abort (mach);
}
h = mu_sieve_value_get_untyped (mach, args, 0);
v = mu_sieve_value_get_untyped (mach, args, 1);
mu_message_get_header (mu_sieve_get_message (mach), &clos.header);
result = mu_sieve_vlist_compare (h, v, comp,
mu_sieve_get_relcmp (mach, tags),
......
......@@ -80,9 +80,9 @@ moderator_filter_message (mu_sieve_machine_t mach, mu_list_t tags,
int rc;
mu_sieve_machine_t newmach;
mu_attribute_t attr;
mu_sieve_value_t *arg;
char *arg;
if (mu_sieve_tag_lookup (tags, "source", &arg))
if (mu_sieve_tag_lookup (mach, tags, "source", SVT_STRING, &arg))
{
rc = mu_sieve_machine_inherit (mach, &newmach);
if (rc)
......@@ -97,11 +97,11 @@ moderator_filter_message (mu_sieve_machine_t mach, mu_list_t tags,
...
*/
rc = mu_sieve_compile (newmach, arg->v.string);
rc = mu_sieve_compile (newmach, arg);
if (rc)
mu_sieve_error (mach, _("cannot compile source `%s'"), arg->v.string);
mu_sieve_error (mach, _("cannot compile source `%s'"), arg);
}
else if (mu_sieve_tag_lookup (tags, "program", &arg))
else if (mu_sieve_tag_lookup (mach, tags, "program", SVT_STRING, &arg))
{
struct mu_locus locus;
......@@ -114,7 +114,7 @@ moderator_filter_message (mu_sieve_machine_t mach, mu_list_t tags,
}
mu_sieve_get_locus (mach, &locus);
rc = mu_sieve_compile_buffer (newmach,
arg->v.string, strlen (arg->v.string),
arg, strlen (arg),
locus.mu_file, locus.mu_line);
if (rc)
mu_sieve_error (mach, _("cannot compile subprogram"));
......@@ -303,7 +303,6 @@ moderator_action (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
{
mu_message_t request;
char *from = NULL;
mu_sieve_value_t *arg;
if ((rc = moderator_message_get_part (mach, msg, 3, &request)))
{
......@@ -312,14 +311,13 @@ moderator_action (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
mu_sieve_abort (mach);
}
if (mu_sieve_tag_lookup (tags, "address", &arg))
from = arg->v.string;
mu_sieve_tag_lookup (mach, tags, "address", SVT_STRING, &from);
if (moderator_discard_message (mach, request, from))
discard = 0;
else
{
if (!mu_sieve_tag_lookup (tags, "keep", NULL))
if (!mu_sieve_tag_lookup (mach, tags, "keep", SVT_VOID, NULL))
{
mu_attribute_t attr = 0;
......
......@@ -87,7 +87,6 @@ sieve_pipe (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags, int test)
int retval = 0;
int rc, result;
mu_message_t msg;
mu_sieve_value_t *val;
char *cmd;
mu_stream_t pstr;
mu_envelope_t env;
......@@ -95,15 +94,7 @@ sieve_pipe (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags, int test)
const char *error_arg = NULL;
int pipe_mask = 0;
val = mu_sieve_value_get (args, 0);
if (!val)
{
mu_sieve_error (mach, "%lu: %s",
(unsigned long) mu_sieve_get_message_num (mach),
_("cannot get command!"));
mu_sieve_abort (mach);
}
cmd = val->v.string;
mu_sieve_value_get (mach, args, 0, SVT_STRING, &cmd);
if (mu_sieve_is_dry_run (mach))
return 0;
......@@ -111,11 +102,11 @@ sieve_pipe (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags, int test)
msg = mu_sieve_get_message (mach);
mu_message_get_envelope (msg, &env);
if (mu_sieve_tag_lookup (tags, "envelope", NULL))
if (mu_sieve_tag_lookup (mach, tags, "envelope", SVT_VOID, NULL))
pipe_mask |= PIPE_ENVELOPE;
if (mu_sieve_tag_lookup (tags, "header", NULL))
if (mu_sieve_tag_lookup (mach, tags, "header", SVT_VOID, NULL))
pipe_mask |= PIPE_HEADERS;
if (mu_sieve_tag_lookup (tags, "body", NULL))
if (mu_sieve_tag_lookup (mach, tags, "body", SVT_VOID, NULL))
pipe_mask |= PIPE_BODY;
if (pipe_mask == 0)
pipe_mask = PIPE_ALL;
......@@ -193,6 +184,7 @@ sieve_pipe (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags, int test)
{
int code = 0;
int status;
size_t n;
rc = mu_stream_ioctl (pstr, MU_IOCTL_PROGSTREAM,
MU_IOCTL_PROG_STATUS, &status);
......@@ -202,8 +194,8 @@ sieve_pipe (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags, int test)
mu_sieve_abort (mach);
}
if (mu_sieve_tag_lookup (tags, "exit", &val))
code = val->v.number;
if (mu_sieve_tag_lookup (mach, tags, "exit", SVT_NUMBER, &n))
code = n;
if (result == 0)
retval = code == 0;
else if (result == MU_ERR_PROCESS_EXITED)
......@@ -211,8 +203,9 @@ sieve_pipe (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags, int test)
else if (result == MU_ERR_PROCESS_SIGNALED)
{
int signo = WTERMSIG (status);
if (mu_sieve_tag_lookup (tags, "signal", &val))
retval = signo == val->v.number;
size_t n;
if (mu_sieve_tag_lookup (mach, tags, "signal", SVT_NUMBER, &n))
retval = signo == n;
else
{
mu_stream_destroy (&pstr);
......
......@@ -362,9 +362,10 @@ spamd_test (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
int result;
long score, threshold, limit;
mu_stream_t stream = NULL, null;
mu_sieve_value_t *arg;
mu_message_t msg;
char *host;
size_t num;
char *str;
mu_header_t hdr;
mu_debug_handle_t lev = 0;
......@@ -380,15 +381,13 @@ spamd_test (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
mu_sieve_abort (mach);
}
if (mu_sieve_tag_lookup (tags, "host", &arg))
host = arg->v.string;
else
if (!mu_sieve_tag_lookup (mach, tags, "host", SVT_STRING, &host))
host = "127.0.0.1";
if (mu_sieve_tag_lookup (tags, "port", &arg))
result = spamd_connect_tcp (mach, &stream, host, arg->v.number);
else if (mu_sieve_tag_lookup (tags, "socket", &arg))
result = spamd_connect_socket (mach, &stream, arg->v.string);
if (mu_sieve_tag_lookup (mach, tags, "port", SVT_NUMBER, &num))
result = spamd_connect_tcp (mach, &stream, host, num);
else if (mu_sieve_tag_lookup (mach, tags, "socket", SVT_STRING, &str))
result = spamd_connect_socket (mach, &stream, str);
else
result = spamd_connect_tcp (mach, &stream, host, DEFAULT_SPAMD_PORT);
if (result) /* spamd_connect_ already reported error */
......@@ -422,8 +421,8 @@ spamd_test (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
spamd_send_command (stream, "SYMBOLS SPAMC/1.2");
spamd_send_command (stream, "Content-length: %lu", (u_long) size);
if (mu_sieve_tag_lookup (tags, "user", &arg))
spamd_send_command (stream, "User: %s", arg);
if (mu_sieve_tag_lookup (mach, tags, "user", SVT_STRING, &str))
spamd_send_command (stream, "User: %s", str);
else
{
struct mu_auth_data *auth = mu_get_auth_by_uid (geteuid ());
......@@ -465,14 +464,14 @@ spamd_test (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
if (!result)
{
if (mu_sieve_tag_lookup (tags, "over", &arg))
if (mu_sieve_tag_lookup (mach, tags, "over", SVT_STRING, &str))
{
decode_float (&limit, arg->v.string, 3, NULL);
decode_float (&limit, str, 3, NULL);
result = score >= limit;
}
else if (mu_sieve_tag_lookup (tags, "under", &arg))
else if (mu_sieve_tag_lookup (mach, tags, "under", SVT_STRING, &str))
{
decode_float (&limit, arg->v.string, 3, NULL);
decode_float (&limit, str, 3, NULL);
result = score <= limit;
}
}
......
......@@ -50,7 +50,8 @@
static int
timestamp_test (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
{
mu_sieve_value_t *h, *v;
char const *hname;
char const *date;
mu_header_t hdr;
char *val;
time_t now = time (NULL);
......@@ -59,24 +60,14 @@ timestamp_test (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
/* Retrieve required arguments: */
/* First argument: header name */
h = mu_sieve_value_get (args, 0);
if (!h)
{
mu_sieve_arg_error (mach, 1);
mu_sieve_abort (mach);
}
mu_sieve_value_get (mach, args, 0, SVT_STRING, &hname);
/* Second argument: date displacement */
v = mu_sieve_value_get (args, 1);
if (!v)
{
mu_sieve_arg_error (mach, 2);
mu_sieve_abort (mach);
}
mu_sieve_value_get (mach, args, 1, SVT_STRING, &date);
if (mu_parse_date (v->v.string, &tlimit, &now))
if (mu_parse_date (date, &tlimit, &now))
{
mu_sieve_error (mach, _("cannot parse date specification (%s)"),
v->v.string);
date);
mu_sieve_abort (mach);
}
......@@ -87,7 +78,7 @@ timestamp_test (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
mu_sieve_abort (mach);
}
if (mu_header_aget_value (hdr, h->v.string, &val))
if (mu_header_aget_value (hdr, hname, &val))
return 0;
if (mu_parse_date (val, &tval, &now))
......@@ -102,7 +93,7 @@ timestamp_test (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
rc = tval > tlimit;
if (mu_sieve_tag_lookup (tags, "before", NULL))
if (mu_sieve_tag_lookup (mach, tags, "before", SVT_VOID, NULL))
rc = !rc;
return rc;
......
......@@ -78,7 +78,7 @@ build_mime (mu_sieve_machine_t mach, mu_list_t tags, mu_mime_t *pmime,
return 1;
}
if (mu_sieve_tag_lookup (tags, "mime", NULL))
if (mu_sieve_tag_lookup (mach, tags, "mime", SVT_VOID, NULL))
{
mu_stream_t fstr;
rc = mu_filter_create (&fstr, input, "base64",
......@@ -249,7 +249,7 @@ noreply_address_p (mu_sieve_machine_t mach, mu_list_t tags, char *email)
for (i = 0; rc == 0 && noreply_sender[i]; i++)
rc = regex_comparator (noreply_sender[i], &rd);
if (!rc && mu_sieve_tag_lookup (tags, "noreply", &arg))
if (!rc && mu_sieve_tag_lookup_untyped (mach, tags, "noreply", &arg))
rc = mu_sieve_vlist_do (arg, regex_comparator, &rd);
return rc;
......@@ -341,24 +341,23 @@ check_db (mu_sieve_machine_t mach, mu_list_t tags, char *from)
{
mu_property_t prop;
char *file;
mu_sieve_value_t *arg;
unsigned int days;
int rc;
mu_stream_t str;
mu_locker_t locker;
const char *dbfile = "~/.vacation";
size_t n;
if (mu_sieve_tag_lookup (tags, "days", &arg))
if (mu_sieve_tag_lookup (mach, tags, "days", SVT_NUMBER, &n))
{
days = arg->v.number;
days = n;
if (days > DAYS_MAX)
days = DAYS_MAX;
}
else
days = DAYS_DEFAULT;
if (mu_sieve_tag_lookup (tags, "database", &arg))
dbfile = arg->v.string;
mu_sieve_tag_lookup (mach, tags, "database", SVT_STRING, &dbfile);
file = mu_tilde_expansion (dbfile, MU_HIERARCHY_DELIMITER, NULL);
if (!file)
......@@ -433,13 +432,9 @@ static void
re_subject (mu_sieve_machine_t mach, mu_list_t tags, char **psubject)
{
char *subject;
mu_sieve_value_t *arg;
char *prefix = "Re";
if (mu_sieve_tag_lookup (tags, "reply_prefix", &arg))
{
prefix = arg->v.string;
}
mu_sieve_tag_lookup (mach, tags, "reply_prefix", SVT_STRING, &prefix);
subject = malloc (strlen (*psubject) + strlen (prefix) + 3);
if (!subject)
......@@ -467,20 +462,19 @@ static void
vacation_subject (mu_sieve_machine_t mach, mu_list_t tags,
mu_message_t msg, mu_header_t newhdr)
{
mu_sieve_value_t *arg;
char *value;
char *subject;
int subject_allocated = 0;
mu_header_t hdr;
if (mu_sieve_tag_lookup (tags, "subject", &arg))
subject = arg->v.string;
if (mu_sieve_tag_lookup (mach, tags, "subject", SVT_STRING, &subject))
/* nothing */;
else if (mu_message_get_header (msg, &hdr) == 0
&& mu_header_aget_value_unfold (hdr, MU_HEADER_SUBJECT,
&value) == 0)
{
char *p;
int rc = mu_rfc2047_decode (MU_SIEVE_CHARSET, value, &p);
subject_allocated = 1;
......@@ -494,11 +488,11 @@ vacation_subject (mu_sieve_machine_t mach, mu_list_t tags,
subject = p;
}
if (mu_sieve_tag_lookup (tags, "reply_regex", &arg))
if (mu_sieve_tag_lookup (mach, tags, "reply_regex", SVT_STRING, &p))
{
char *err = NULL;
rc = mu_unre_set_regex (arg->v.string, 0, &err);
rc = mu_unre_set_regex (p, 0, &err);
if (rc)
{
mu_sieve_error (mach,
......@@ -619,7 +613,7 @@ vacation_reply (mu_sieve_machine_t mach, mu_list_t tags, mu_message_t msg,
int rc;
mu_sieve_value_t *val;
if (mu_sieve_tag_lookup (tags, "file", NULL))
if (mu_sieve_tag_lookup (mach, tags, "file", SVT_VOID, NULL))
{
mu_stream_t instr;
......@@ -634,7 +628,7 @@ vacation_reply (mu_sieve_machine_t mach, mu_list_t tags, mu_message_t msg,
return -1;
}
if (mu_sieve_tag_lookup (tags, "rfc2822", NULL))
if (mu_sieve_tag_lookup (mach, tags, "rfc2822", SVT_VOID, NULL))
{
rc = mu_stream_to_message (instr, &newmsg);
mu_stream_unref (instr);
......@@ -722,7 +716,7 @@ vacation_reply (mu_sieve_machine_t mach, mu_list_t tags, mu_message_t msg,
{
mu_header_set_value (newhdr, MU_HEADER_TO, to, 0);
if (mu_sieve_tag_lookup (tags, "header", &val))
if (mu_sieve_tag_lookup_untyped (mach, tags, "header", &val))
{
struct header_closure hc;
hc.mach = mach;
......@@ -774,7 +768,6 @@ sieve_action_vacation (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
int rc;
char *text, *from = NULL;
char const *return_address;
mu_sieve_value_t *val;
mu_message_t msg;
mu_header_t hdr;
char *my_address;
......@@ -782,22 +775,15 @@ sieve_action_vacation (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
if (diag (mach))
return 0;
val = mu_sieve_value_get (args, 0);
if (!val)
{
mu_sieve_error (mach, _("cannot get text!"));
mu_sieve_abort (mach);
}
else
text = val->v.string;
mu_sieve_value_get (mach, args, 0, SVT_STRING, &text);
msg = mu_sieve_get_message (mach);
mu_message_get_header (msg, &hdr);
if (mu_sieve_tag_lookup (tags, "sender", &val))
if (mu_sieve_tag_lookup (mach, tags, "sender", SVT_STRING, &from))
{
/* Debugging hook: :sender sets fake reply address */
from = strdup (val->v.string);
from = strdup (from);
if (!from)
{
mu_sieve_error (mach, "%lu: %s",
......@@ -817,12 +803,12 @@ sieve_action_vacation (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
my_address = mu_get_user_email (NULL);
if (mu_sieve_tag_lookup (tags, "always_reply", NULL))
if (mu_sieve_tag_lookup (mach, tags, "always_reply", SVT_VOID, NULL))
return_address = my_address;
else
{
val = NULL;
mu_sieve_tag_lookup (tags, "aliases", &val);
mu_sieve_value_t *val = NULL;
mu_sieve_tag_lookup_untyped (mach, tags, "aliases", &val);
if (match_addresses (hdr, my_address, val, &return_address) == 0)
{
free (my_address);
......@@ -839,8 +825,8 @@ sieve_action_vacation (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
return 0;
}
if (mu_sieve_tag_lookup (tags, "return_address", &val))
return_address = val->v.string;
mu_sieve_tag_lookup (mach, tags, "return_address", SVT_STRING,
&return_address);
rc = vacation_reply (mach, tags, msg, text, from, return_address);
free (from);
......
......@@ -83,12 +83,12 @@ mu_sieve_str_to_relcmp (const char *str,
mu_sieve_relcmp_t
mu_sieve_get_relcmp (mu_sieve_machine_t mach, mu_list_t tags)
{
mu_sieve_value_t *arg;
char *str;
mu_sieve_relcmp_t test = NULL;
if (mu_sieve_tag_lookup (tags, "value", &arg) == 0)
if (mu_sieve_tag_lookup (mach, tags, "value", SVT_STRING, &str) == 0)
return op_ne;
mu_sieve_str_to_relcmp (arg->v.string, &test, NULL);
mu_sieve_str_to_relcmp (str, &test, NULL);
return test;
}
......
......@@ -539,12 +539,6 @@ mu_i_sv_valf (mu_stream_t str, mu_sieve_value_t *val)
mu_stream_printf (str, "%s", val->v.string);
break;
case SVT_VALUE_LIST:
mu_stream_printf (str, "[");
mu_i_sv_argf (str, val->v.list);
mu_stream_printf (str, "]");
break;
case SVT_POINTER:
mu_stream_printf (str, "%p", val->v.ptr);
break;
......
......@@ -64,22 +64,23 @@ struct address_closure
};
static int
do_count (mu_list_t args, mu_list_t tags, size_t count, int retval)
do_count (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags,
size_t count, int retval)
{
mu_sieve_value_t *arg;
char *relcmp;
if (mu_sieve_tag_lookup (tags, "count", &arg))
if (mu_sieve_tag_lookup (mach, tags, "count", SVT_STRING, &relcmp))
{
size_t limit;
char *str;
mu_sieve_value_t *val;
mu_list_t list;
mu_sieve_relcmpn_t stest;
val = mu_sieve_value_get (args, 1);
mu_list_get (val->v.list, 0, (void **) &str);
mu_sieve_value_get (mach, args, 1, SVT_STRING_LIST, &list);
mu_list_get (list, 0, (void **) &str);
limit = strtoul (str, &str, 10);
mu_sieve_str_to_relcmp (arg->v.string, NULL, &stest);
mu_sieve_str_to_relcmp (relcmp, NULL, &stest);
return stest (count, limit);
}
return retval;
......@@ -119,18 +120,8 @@ sieve_test_address (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
int rc;
size_t count;
h = mu_sieve_value_get (args, 0);
if (!h)
{
mu_sieve_arg_error (mach, 1);
mu_sieve_abort (mach);
}
v = mu_sieve_value_get (args, 1);
if (!v)
{
mu_sieve_arg_error (mach, 2);
mu_sieve_abort (mach);
}
h = mu_sieve_value_get_untyped (mach, args, 0);
v = mu_sieve_value_get_untyped (mach, args, 1);
mu_message_get_header (mu_sieve_get_message (mach), &header);
clos.data = header;
......@@ -139,10 +130,11 @@ sieve_test_address (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
rc = mu_sieve_vlist_compare (h, v, comp, test, retrieve_address, &clos, &count);
mu_address_destroy (&clos.addr);
return do_count (args, tags, count, rc);
return do_count (mach, args, tags, count, rc);
}
struct header_closure {
struct header_closure
{
mu_header_t header;
int index;
};
......@@ -180,20 +172,10 @@ sieve_test_header (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
size_t count, mcount = 0;
struct header_closure clos;
h = mu_sieve_value_get (args, 0);
if (!h)
{
mu_sieve_arg_error (mach, 1);
mu_sieve_abort (mach);
}
v = mu_sieve_value_get (args, 1);
if (!v)
{
mu_sieve_arg_error (mach, 2);
mu_sieve_abort (mach);
}
h = mu_sieve_value_get_untyped (mach, args, 0);
v = mu_sieve_value_get_untyped (mach, args, 1);
if (mu_sieve_tag_lookup (tags, "mime", NULL))
if (mu_sieve_tag_lookup (mach, tags, "mime", SVT_VOID, NULL))
{
int ismime = 0;
......@@ -218,10 +200,11 @@ sieve_test_header (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
}
}
mu_message_get_header (mach->msg, &clos.header);
if (mu_sieve_vlist_compare (h, v, comp, test, retrieve_header, &clos, &count))
if (mu_sieve_vlist_compare (h, v, comp, test, retrieve_header, &clos,
&count))
return 1;
return do_count (args, tags, count + mcount, 0);
return do_count (mach, args, tags, count + mcount, 0);
}
int
......@@ -261,18 +244,8 @@ sieve_test_envelope (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
int rc;
size_t count;
h = mu_sieve_value_get (args, 0);
if (!h)
{
mu_sieve_arg_error (mach, 1);
mu_sieve_abort (mach);
}
v = mu_sieve_value_get (args, 1);
if (!v)
{
mu_sieve_arg_error (mach, 2);
mu_sieve_abort (mach);
}
h = mu_sieve_value_get_untyped (mach, args, 0);
v = mu_sieve_value_get_untyped (mach, args, 1);
mu_message_get_envelope (mu_sieve_get_message (mach),
(mu_envelope_t*)&clos.data);
......@@ -281,7 +254,7 @@ sieve_test_envelope (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
rc = mu_sieve_vlist_compare (h, v, comp, test, retrieve_envelope, &clos,
&count);
mu_address_destroy (&clos.addr);
return do_count (args, tags, count, rc);
return do_count (mach, args, tags, count, rc);
}
int
......@@ -290,22 +263,17 @@ sieve_test_size (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
int rc = 1;
mu_sieve_runtime_tag_t *tag = NULL;
size_t size;
size_t arg;
mu_sieve_value_t *val = mu_sieve_value_get (args, 0);
if (!val)
{
mu_sieve_arg_error (mach, 1);
mu_sieve_abort (mach);
}
mu_sieve_value_get (mach, args, 0, SVT_NUMBER, &arg);
mu_message_size (mu_sieve_get_message (mach), &size);
mu_list_get (tags, 0, (void **)&tag);
if (!tag)
rc = size == val->v.number;
rc = size == arg;
else if (strcmp (tag->tag, "over") == 0)
rc = size > val->v.number;
rc = size > arg;
else if (strcmp (tag->tag, "under") == 0)
rc = size < val->v.number;
rc = size < arg;
return rc;
}
......@@ -326,13 +294,7 @@ sieve_test_exists (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
mu_sieve_value_t *val;
mu_message_get_header (mu_sieve_get_message (mach), &header);
val = mu_sieve_value_get (args, 0);
if (!val)
{
mu_sieve_arg_error (mach, 1);
mu_sieve_abort (mach);
}
val = mu_sieve_value_get_untyped (mach, args, 0);
return mu_sieve_vlist_do (val, _test_exists, header) == 0;
}
......
......@@ -156,7 +156,6 @@ mu_sieve_value_create (mu_sieve_data_type type, void *data)
val->v.string = data;
break;
case SVT_VALUE_LIST:
case SVT_STRING_LIST:
val->v.list = data;
break;
......@@ -178,13 +177,57 @@ mu_sieve_value_create (mu_sieve_data_type type, void *data)
}
mu_sieve_value_t *
mu_sieve_value_get (mu_list_t vlist, size_t index)
mu_sieve_value_get_untyped (mu_sieve_machine_t mach, mu_list_t vlist,
size_t index)
{
mu_sieve_value_t *val = NULL;
mu_list_get (vlist, index, (void **)&val);
int rc = mu_list_get (vlist, index, (void **)&val);
if (rc)
{
mu_sieve_error (mach, _("can't get argument %zu: %s"),
index, mu_strerror (rc));
mu_sieve_abort (mach);
}
return val;
}
mu_sieve_value_t *
mu_sieve_value_get_optional (mu_sieve_machine_t mach, mu_list_t vlist,
size_t index)
{
mu_sieve_value_t *val = NULL;
int rc = mu_list_get (vlist, index, (void **)&val);
if (rc == MU_ERR_NOENT)
return NULL;
else if (rc)
{
mu_sieve_error (mach, _("can't get argument %zu: %s"),
index, mu_strerror (rc));
mu_sieve_abort (mach);
}
return val;
}
int
mu_sieve_value_get (mu_sieve_machine_t mach, mu_list_t vlist,
size_t index,
mu_sieve_data_type type, void *ret)
{
mu_sieve_value_t *val = mu_sieve_value_get_untyped (mach, vlist, index);
if (val->type != type)
{
mu_sieve_error (mach,
_("bad type for argument %zu: %s, instead of expected %s"),
index,
mu_sieve_type_str (val->type),
mu_sieve_type_str (type));
mu_sieve_abort (mach);
}
*(union mu_sieve_value_storage *)ret = val->v;
return 0;
}
void
mu_sieve_error (mu_sieve_machine_t mach, const char *fmt, ...)
{
......@@ -204,12 +247,6 @@ mu_sieve_error (mu_sieve_machine_t mach, const char *fmt, ...)
mu_stream_write (mach->errstream, "\n", 1, NULL);
va_end (ap);
}
void
mu_sieve_arg_error (mu_sieve_machine_t mach, int n)
{
mu_sieve_error (mach, _("cannot retrieve argument %d"), n);
}
const char *
mu_sieve_type_str (mu_sieve_data_type type)
......@@ -234,9 +271,6 @@ mu_sieve_type_str (mu_sieve_data_type type)
case SVT_IDENT:
return "ident";
case SVT_VALUE_LIST:
return "value-list";
case SVT_POINTER:
return "pointer";
}
......@@ -367,26 +401,54 @@ tag_finder (void *item, void *data)
}
int
mu_sieve_tag_lookup (mu_list_t taglist, char *name, mu_sieve_value_t **arg)
mu_sieve_tag_lookup_untyped (mu_sieve_machine_t mach, mu_list_t taglist,
char *name, mu_sieve_value_t **ret)
{
mu_sieve_runtime_tag_t t;
t.tag = name;
if (taglist && mu_list_foreach (taglist, tag_finder, &t))
{
if (arg)
*arg = t.arg;
if (ret)
*ret = t.arg;
return 1;
}
return 0;
}
int
mu_sieve_tag_lookup (mu_sieve_machine_t mach, mu_list_t taglist,
char *name, mu_sieve_data_type type,
void *ret)
{
mu_sieve_value_t *val;
int found = mu_sieve_tag_lookup_untyped (mach, taglist, name, &val);
if (found)
{
if (ret)
{
if (val->type != type)
{
mu_sieve_error (mach,
_("bad type for tag %s: %s, instead of expected %s"),
name,
mu_sieve_type_str (val->type),
mu_sieve_type_str (type));
mu_sieve_abort (mach);
}
*(union mu_sieve_value_storage *)ret = val->v;
}
}
return found;
}
int
mu_sieve_vlist_do (mu_sieve_value_t *val, mu_list_action_t ac, void *data)
{
switch (val->type)
{
case SVT_VALUE_LIST:
case SVT_STRING_LIST:
return mu_list_foreach (val->v.list, ac, data);
case SVT_STRING:
......