summaryrefslogtreecommitdiffstats
path: root/pigeonhole/src/lib-sieve/mcht-contains.c
blob: a9b3190081557de17a21e8f882f0732b68524f04 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file
 */

/* Match-type ':contains'
 */

#include "lib.h"

#include "sieve-match-types.h"
#include "sieve-comparators.h"
#include "sieve-match.h"

#include <string.h>
#include <stdio.h>

/*
 * Forward declarations
 */

static int mcht_contains_match_key
	(struct sieve_match_context *mctx, const char *val, size_t val_size,
		const char *key, size_t key_size);

/*
 * Match-type object
 */

const struct sieve_match_type_def contains_match_type = {
	SIEVE_OBJECT("contains",
		&match_type_operand, SIEVE_MATCH_TYPE_CONTAINS),
	.validate_context = sieve_match_substring_validate_context,
	.match_key = mcht_contains_match_key
};

/*
 * Match-type implementation
 */

/* FIXME: Naive substring match implementation. Should switch to more
 * efficient algorithm if large values need to be searched (e.g. message body).
 */
static int mcht_contains_match_key
(struct sieve_match_context *mctx, const char *val, size_t val_size,
	const char *key, size_t key_size)
{
	const struct sieve_comparator *cmp = mctx->comparator;
	const char *vend = (const char *) val + val_size;
	const char *kend = (const char *) key + key_size;
	const char *vp = val;
	const char *kp = key;

	if ( val_size == 0 )
		return ( key_size == 0 ? 1 : 0 );

	if ( cmp->def == NULL || cmp->def->char_match == NULL )
		return 0;

	while ( (vp < vend) && (kp < kend) ) {
		if ( !cmp->def->char_match(cmp, &vp, vend, &kp, kend) )
			vp++;
	}

	return ( kp == kend ? 1 : 0 );
}