sieve-comparators.c [plain text]
#include "lib.h"
#include "str-sanitize.h"
#include "hash.h"
#include "array.h"
#include "sieve-extensions.h"
#include "sieve-code.h"
#include "sieve-commands.h"
#include "sieve-binary.h"
#include "sieve-validator.h"
#include "sieve-generator.h"
#include "sieve-interpreter.h"
#include "sieve-dump.h"
#include "sieve-comparators.h"
#include <string.h>
#include <stdio.h>
const struct sieve_comparator_def *sieve_core_comparators[] = {
&i_octet_comparator, &i_ascii_casemap_comparator
};
const unsigned int sieve_core_comparators_count =
N_ELEMENTS(sieve_core_comparators);
static bool cmp_validator_load
(const struct sieve_extension *ext, struct sieve_validator *valdtr);
const struct sieve_extension_def comparator_extension = {
"@comparators",
NULL, NULL,
cmp_validator_load,
NULL, NULL, NULL, NULL, NULL,
SIEVE_EXT_DEFINE_NO_OPERATIONS,
SIEVE_EXT_DEFINE_NO_OPERANDS
};
static struct sieve_validator_object_registry *_get_object_registry
(struct sieve_validator *valdtr)
{
struct sieve_instance *svinst;
const struct sieve_extension *mcht_ext;
svinst = sieve_validator_svinst(valdtr);
mcht_ext = sieve_get_comparator_extension(svinst);
return sieve_validator_object_registry_get(valdtr, mcht_ext);
}
void sieve_comparator_register
(struct sieve_validator *valdtr, const struct sieve_extension *ext,
const struct sieve_comparator_def *cmp)
{
struct sieve_validator_object_registry *regs = _get_object_registry(valdtr);
sieve_validator_object_registry_add(regs, ext, &cmp->obj_def);
}
static struct sieve_comparator *sieve_comparator_create
(struct sieve_validator *valdtr, struct sieve_command *cmd,
const char *identifier)
{
struct sieve_validator_object_registry *regs = _get_object_registry(valdtr);
struct sieve_object object;
struct sieve_comparator *cmp;
if ( !sieve_validator_object_registry_find(regs, identifier, &object) )
return NULL;
cmp = p_new(sieve_command_pool(cmd), struct sieve_comparator, 1);
cmp->object = object;
cmp->def = (const struct sieve_comparator_def *) object.def;
return cmp;
}
bool cmp_validator_load
(const struct sieve_extension *ext, struct sieve_validator *valdtr)
{
struct sieve_validator_object_registry *regs =
sieve_validator_object_registry_init(valdtr, ext);
unsigned int i;
for ( i = 0; i < sieve_core_comparators_count; i++ ) {
sieve_validator_object_registry_add
(regs, NULL, &(sieve_core_comparators[i]->obj_def));
}
return TRUE;
}
static bool tag_comparator_validate
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
struct sieve_command *cmd);
static bool tag_comparator_generate
(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg,
struct sieve_command *cmd);
const struct sieve_argument_def comparator_tag = {
"comparator",
NULL,
tag_comparator_validate,
NULL, NULL,
tag_comparator_generate
};
static bool tag_comparator_validate
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
struct sieve_command *cmd)
{
struct sieve_ast_argument *tag = *arg;
const struct sieve_comparator *cmp;
*arg = sieve_ast_argument_next(*arg);
if ( (*arg)->type != SAAT_STRING ) {
sieve_argument_validate_error(valdtr, *arg,
":comparator tag requires one string argument, but %s was found",
sieve_ast_argument_name(*arg) );
return FALSE;
}
if ( !sieve_validator_argument_activate(valdtr, cmd, *arg, FALSE) )
return FALSE;
if ( !sieve_argument_is_string_literal(*arg) ) {
sieve_argument_validate_error(valdtr, *arg,
"this Sieve implementation currently only supports "
"a literal string argument for the :comparator tag");
return FALSE;
}
cmp = sieve_comparator_create(valdtr, cmd, sieve_ast_argument_strc(*arg));
if ( cmp == NULL ) {
sieve_argument_validate_error(valdtr, *arg,
"unknown comparator '%s'",
str_sanitize(sieve_ast_argument_strc(*arg),80));
return FALSE;
}
*arg = sieve_ast_arguments_detach(*arg, 1);
tag->argument->data = (void *) cmp;
return TRUE;
}
static bool tag_comparator_generate
(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg,
struct sieve_command *cmd ATTR_UNUSED)
{
const struct sieve_comparator *cmp =
(const struct sieve_comparator *) arg->argument->data;
sieve_opr_comparator_emit(cgenv->sblock, cmp);
return TRUE;
}
void sieve_comparators_link_tag
(struct sieve_validator *valdtr, struct sieve_command_registration *cmd_reg,
int id_code)
{
struct sieve_instance *svinst;
const struct sieve_extension *mcht_ext;
svinst = sieve_validator_svinst(valdtr);
mcht_ext = sieve_get_comparator_extension(svinst);
sieve_validator_register_tag
(valdtr, cmd_reg, mcht_ext, &comparator_tag, id_code);
}
bool sieve_comparator_tag_is
(struct sieve_ast_argument *tag, const struct sieve_comparator_def *cmp_def)
{
const struct sieve_comparator *cmp;
if ( !sieve_argument_is(tag, comparator_tag) )
return FALSE;
cmp = (const struct sieve_comparator *) tag->argument->data;
return ( cmp->def == cmp_def );
}
const struct sieve_comparator *sieve_comparator_tag_get
(struct sieve_ast_argument *tag)
{
if ( !sieve_argument_is(tag, comparator_tag) )
return NULL;
return (const struct sieve_comparator *) tag->argument->data;
}
const struct sieve_operand_class sieve_comparator_operand_class =
{ "comparator" };
static const struct sieve_extension_objects core_comparators =
SIEVE_EXT_DEFINE_COMPARATORS(sieve_core_comparators);
const struct sieve_operand_def comparator_operand = {
"comparator",
NULL,
SIEVE_OPERAND_COMPARATOR,
&sieve_comparator_operand_class,
&core_comparators
};
bool sieve_comparator_octet_skip
(const struct sieve_comparator *cmp ATTR_UNUSED,
const char **val, const char *val_end)
{
if ( *val < val_end ) {
(*val)++;
return TRUE;
}
return FALSE;
}