Commit 1040ed4b 1040ed4bdcd07fdfac57baebca3bf9cb931e2cf1 by uid65697

New sieve extension test.

1 parent 37dbcca2
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003 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 2, 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Implements "list" sieve extension test. See "Syntax:" below for the
description */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <mailutils/libsieve.h>
/* Auxiliary functions */
struct header_closure {
header_t header; /* Message header */
int index; /* Header index */
char *delim; /* List delimiter */
char *value; /* Retrieved header value */
char *save; /* Save pointer for strtok_r */
};
static void
cleanup (struct header_closure *hc)
{
free (hc->value);
hc->value = hc->save = NULL;
}
static int
retrieve_next_header (struct header_closure *hc, char *name, char **pval)
{
char buf[512];
size_t n;
cleanup (hc);
while (!header_get_field_name (hc->header, hc->index, buf, sizeof(buf), &n))
{
int i = hc->index++;
if (strcasecmp (buf, name) == 0)
{
if (header_aget_field_value (hc->header, i, &hc->value))
return 1;
*pval = strtok_r (hc->value, hc->delim, &hc->save);
if (*pval == NULL)
{
cleanup (hc);
return 1;
}
return 0;
}
}
return 1;
}
static int
list_retrieve_header (void *item, void *data, int idx, char **pval)
{
struct header_closure *hc = data;
char *p;
if (idx == 0)
hc->index = 1;
while (1)
{
if (!hc->value)
{
if (retrieve_next_header (hc, (char*) item, &p))
return 1;
}
else
{
p = strtok_r (NULL, hc->delim, &hc->save);
if (!p)
{
cleanup (hc);
continue;
}
}
*pval = strdup (p);
return 0;
}
return 1;
}
static int
waitdebug()
{
static volatile int _st=0;
while (!_st)
_st=_st;
}
/* The test proper */
/* Syntax: list [COMPARATOR] [MATCH-TYPE]
[ :delim <delimiters: string> ]
<headers: string-list> <key-list: string-list>
The "list" test evaluates to true if any of the headers
match any key. Each header is regarded as containing a
list of keywords. By default, comma is assumed as list
separator. This can be overridden by specifying ":delim"
tag, whose value is a string consisting of valid list
delimiter characters.
list :matches :delim " ," [ "X-Spam-Keywords", "X-Spamd-Keywords" ]
[ "HTML_*", "FORGED_*" ]
*/
static int
list_test (sieve_machine_t mach, list_t args, list_t tags)
{
sieve_value_t *h, *v, *arg;
sieve_comparator_t comp = sieve_get_comparator (mach, tags);
struct header_closure clos;
int result;
memset (&clos, 0, sizeof clos);
if (sieve_tag_lookup (tags, "delim", &arg))
clos.delim = arg->v.string;
else
clos.delim = ",";
h = sieve_value_get (args, 0);
if (!h)
{
sieve_error (mach, _("list: can't get argument 1"));
sieve_abort (mach);
}
v = sieve_value_get (args, 1);
if (!v)
{
sieve_error (mach, _("list: can't get argument 2"));
sieve_abort (mach);
}
message_get_header (sieve_get_message (mach), &clos.header);
result = sieve_vlist_compare (h, v, comp, sieve_get_relcmp (mach, tags),
list_retrieve_header,
&clos, NULL) > 0;
cleanup (&clos);
return result;
}
/* Initialization */
/* Required arguments: */
static sieve_data_type list_req_args[] = {
SVT_STRING_LIST,
SVT_STRING_LIST,
SVT_VOID
};
static sieve_tag_def_t match_part_tags[] = {
{ "is", SVT_VOID },
{ "contains", SVT_VOID },
{ "matches", SVT_VOID },
{ "regex", SVT_VOID },
{ "count", SVT_STRING },
{ "value", SVT_STRING },
{ "comparator", SVT_STRING },
{ NULL }
};
static sieve_tag_def_t delim_part_tags[] = {
{ "delim", SVT_STRING },
{ NULL }
};
static sieve_tag_group_t list_tag_groups[] = {
{ match_part_tags, sieve_match_part_checker },
{ delim_part_tags, NULL },
{ NULL }
};
/* Initialization function. */
int
SIEVE_EXPORT(list,init) (sieve_machine_t mach)
{
return sieve_register_test (mach, "list", list_test,
list_req_args, list_tag_groups, 1);
}
/* End of list.c */