/src/pigeonhole/src/lib-sieve/cmp-i-ascii-casemap.c
Line | Count | Source |
1 | | /* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file |
2 | | */ |
3 | | |
4 | | /* Comparator 'i;ascii-casemap': |
5 | | * |
6 | | */ |
7 | | |
8 | | #include "lib.h" |
9 | | |
10 | | #include "sieve-common.h" |
11 | | #include "sieve-comparators.h" |
12 | | |
13 | | #include <string.h> |
14 | | #include <stdio.h> |
15 | | #include <ctype.h> |
16 | | |
17 | | /* |
18 | | * Forward declarations |
19 | | */ |
20 | | |
21 | | static int |
22 | | cmp_i_ascii_casemap_compare(const struct sieve_comparator *cmp, |
23 | | const char *val1, size_t val1_size, |
24 | | const char *val2, size_t val2_size); |
25 | | static bool |
26 | | cmp_i_ascii_casemap_char_match(const struct sieve_comparator *cmp, |
27 | | const char **val1, const char *val1_end, |
28 | | const char **val2, const char *val2_end); |
29 | | |
30 | | /* |
31 | | * Comparator object |
32 | | */ |
33 | | |
34 | | const struct sieve_comparator_def i_ascii_casemap_comparator = { |
35 | | SIEVE_OBJECT("i;ascii-casemap", &comparator_operand, |
36 | | SIEVE_COMPARATOR_I_ASCII_CASEMAP), |
37 | | .flags = |
38 | | SIEVE_COMPARATOR_FLAG_ORDERING | |
39 | | SIEVE_COMPARATOR_FLAG_EQUALITY | |
40 | | SIEVE_COMPARATOR_FLAG_SUBSTRING_MATCH | |
41 | | SIEVE_COMPARATOR_FLAG_PREFIX_MATCH, |
42 | | .compare = cmp_i_ascii_casemap_compare, |
43 | | .char_match = cmp_i_ascii_casemap_char_match, |
44 | | .char_skip = sieve_comparator_octet_skip |
45 | | }; |
46 | | |
47 | | /* |
48 | | * Comparator implementation |
49 | | */ |
50 | | |
51 | | static int |
52 | | cmp_i_ascii_casemap_compare(const struct sieve_comparator *cmp ATTR_UNUSED, |
53 | | const char *val1, size_t val1_size, |
54 | | const char *val2, size_t val2_size) |
55 | 0 | { |
56 | 0 | size_t size = I_MIN(val1_size, val2_size); |
57 | 0 | int ret = strncasecmp(val1, val2, size); |
58 | |
|
59 | 0 | return (ret != 0 ? ret : (int)val1_size - (int)val2_size); |
60 | 0 | } |
61 | | |
62 | | static bool |
63 | | cmp_i_ascii_casemap_char_match(const struct sieve_comparator *cmp ATTR_UNUSED, |
64 | | const char **val, const char *val_end, |
65 | | const char **key, const char *key_end) |
66 | 0 | { |
67 | 0 | const char *val_begin = *val; |
68 | 0 | const char *key_begin = *key; |
69 | |
|
70 | 0 | while (*val < val_end && *key < key_end && |
71 | 0 | i_tolower(**val) == i_tolower(**key)) { |
72 | 0 | (*val)++; |
73 | 0 | (*key)++; |
74 | 0 | } |
75 | |
|
76 | 0 | if (*key < key_end) { |
77 | | /* Reset */ |
78 | 0 | *val = val_begin; |
79 | 0 | *key = key_begin; |
80 | |
|
81 | 0 | return FALSE; |
82 | 0 | } |
83 | 0 | return TRUE; |
84 | 0 | } |