Commit 15f6dbf6 15f6dbf66eed6bed5c084d97077e7cc5f8e192a7 by Sergey Poznyakoff

sieve: change string allocation and argument passing convention

Strings are allocated in a per-machine string space.  String and
argument lists form contiguous arrays of structures.  Regular ex-
pressions are compiled when they are needed. Compiled expressions
are cached for eventual reuse.
1 parent ed04bc83
...@@ -95,7 +95,7 @@ numaddr_test (mu_sieve_machine_t mach) ...@@ -95,7 +95,7 @@ numaddr_test (mu_sieve_machine_t mach)
95 vc.count = 0; 95 vc.count = 0;
96 96
97 /* Count the addresses */ 97 /* Count the addresses */
98 rc = mu_sieve_vlist_do (h, _count_items, &vc); 98 rc = mu_sieve_vlist_do (mach, h, _count_items, &vc);
99 99
100 /* Here rc >= 1 iff the counted number of addresses is greater or equal 100 /* Here rc >= 1 iff the counted number of addresses is greater or equal
101 to vc.limit. If `:under' tag was given we reverse the return value */ 101 to vc.limit. If `:under' tag was given we reverse the return value */
......
...@@ -33,6 +33,13 @@ extern "C" { ...@@ -33,6 +33,13 @@ extern "C" {
33 33
34 typedef struct mu_sieve_machine *mu_sieve_machine_t; 34 typedef struct mu_sieve_machine *mu_sieve_machine_t;
35 35
36 typedef struct mu_sieve_string
37 {
38 char *orig;
39 char *exp;
40 void *rx;
41 } mu_sieve_string_t;
42
36 typedef int (*mu_sieve_handler_t) (mu_sieve_machine_t mach); 43 typedef int (*mu_sieve_handler_t) (mu_sieve_machine_t mach);
37 typedef void (*mu_sieve_action_log_t) (mu_sieve_machine_t mach, 44 typedef void (*mu_sieve_action_log_t) (mu_sieve_machine_t mach,
38 const char *action, 45 const char *action,
...@@ -40,13 +47,12 @@ typedef void (*mu_sieve_action_log_t) (mu_sieve_machine_t mach, ...@@ -40,13 +47,12 @@ typedef void (*mu_sieve_action_log_t) (mu_sieve_machine_t mach,
40 47
41 typedef int (*mu_sieve_relcmp_t) (int, int); 48 typedef int (*mu_sieve_relcmp_t) (int, int);
42 typedef int (*mu_sieve_relcmpn_t) (size_t, size_t); 49 typedef int (*mu_sieve_relcmpn_t) (size_t, size_t);
43 typedef int (*mu_sieve_comparator_t) (const char *, const char *); 50 typedef int (*mu_sieve_comparator_t) (mu_sieve_machine_t mach,
51 mu_sieve_string_t *, const char *);
44 typedef int (*mu_sieve_retrieve_t) (void *item, void *data, int idx, 52 typedef int (*mu_sieve_retrieve_t) (void *item, void *data, int idx,
45 char **pval); 53 char **pval);
46 typedef void (*mu_sieve_destructor_t) (void *data); 54 typedef void (*mu_sieve_destructor_t) (void *data);
47 typedef int (*mu_sieve_tag_checker_t) (mu_sieve_machine_t mach, 55 typedef int (*mu_sieve_tag_checker_t) (mu_sieve_machine_t mach);
48 const char *name,
49 mu_list_t tags, mu_list_t args);
50 56
51 typedef enum 57 typedef enum
52 { 58 {
...@@ -55,24 +61,29 @@ typedef enum ...@@ -55,24 +61,29 @@ typedef enum
55 SVT_STRING, 61 SVT_STRING,
56 SVT_STRING_LIST, 62 SVT_STRING_LIST,
57 SVT_TAG, 63 SVT_TAG,
58 SVT_IDENT, 64 SVT_IDENT
59 SVT_POINTER
60 } 65 }
61 mu_sieve_data_type; 66 mu_sieve_data_type;
62 67
63 typedef struct mu_sieve_runtime_tag mu_sieve_runtime_tag_t; 68 struct mu_sieve_slice
69 {
70 size_t first;
71 size_t count;
72 };
73
74 typedef struct mu_sieve_slice *mu_sieve_slice_t;
64 75
65 union mu_sieve_value_storage 76 union mu_sieve_value_storage
66 { 77 {
67 char *string; 78 char *string;
68 size_t number; 79 size_t number;
69 mu_list_t list; 80 struct mu_sieve_slice list;
70 void *ptr;
71 }; 81 };
72 82
73 typedef struct 83 typedef struct
74 { 84 {
75 mu_sieve_data_type type; 85 mu_sieve_data_type type;
86 char *tag;
76 union mu_sieve_value_storage v; 87 union mu_sieve_value_storage v;
77 } mu_sieve_value_t; 88 } mu_sieve_value_t;
78 89
...@@ -88,12 +99,6 @@ typedef struct ...@@ -88,12 +99,6 @@ typedef struct
88 mu_sieve_tag_checker_t checker; 99 mu_sieve_tag_checker_t checker;
89 } mu_sieve_tag_group_t; 100 } mu_sieve_tag_group_t;
90 101
91 struct mu_sieve_runtime_tag
92 {
93 char *tag;
94 mu_sieve_value_t *arg;
95 };
96
97 typedef struct 102 typedef struct
98 { 103 {
99 const char *name; 104 const char *name;
...@@ -135,11 +140,9 @@ void *mu_sieve_realloc (mu_sieve_machine_t mach, void *ptr, size_t size); ...@@ -135,11 +140,9 @@ void *mu_sieve_realloc (mu_sieve_machine_t mach, void *ptr, size_t size);
135 void mu_sieve_reclaim_default (void *p); 140 void mu_sieve_reclaim_default (void *p);
136 void mu_sieve_reclaim_list (void *p); 141 void mu_sieve_reclaim_list (void *p);
137 void mu_sieve_reclaim_value (void *p); 142 void mu_sieve_reclaim_value (void *p);
138 void mu_sieve_reclaim_tag (void *p);
139 143
140 mu_sieve_value_t *mu_sieve_value_create (mu_sieve_machine_t mach, 144 size_t mu_sieve_value_create (mu_sieve_machine_t mach,
141 mu_sieve_data_type type, void *data); 145 mu_sieve_data_type type, void *data);
142 void mu_sieve_slist_destroy (mu_list_t *plist);
143 146
144 /* Symbol space functions */ 147 /* Symbol space functions */
145 mu_sieve_register_t *mu_sieve_test_lookup (mu_sieve_machine_t mach, 148 mu_sieve_register_t *mu_sieve_test_lookup (mu_sieve_machine_t mach,
...@@ -185,30 +188,41 @@ int mu_sieve_str_to_relcmp (const char *str, mu_sieve_relcmp_t *test, ...@@ -185,30 +188,41 @@ int mu_sieve_str_to_relcmp (const char *str, mu_sieve_relcmp_t *test,
185 mu_sieve_relcmpn_t *stest); 188 mu_sieve_relcmpn_t *stest);
186 mu_sieve_relcmp_t mu_sieve_get_relcmp (mu_sieve_machine_t mach); 189 mu_sieve_relcmp_t mu_sieve_get_relcmp (mu_sieve_machine_t mach);
187 190
188 void mu_sieve_require (mu_sieve_machine_t mach, mu_list_t slist); 191 void mu_sieve_require (mu_sieve_machine_t mach, mu_sieve_slice_t list);
189 192
193 void mu_sieve_value_get (mu_sieve_machine_t mach, mu_sieve_value_t *val,
194 mu_sieve_data_type type, void *ret);
195
190 int mu_sieve_get_tag (mu_sieve_machine_t mach, char *name, 196 int mu_sieve_get_tag (mu_sieve_machine_t mach, char *name,
191 mu_sieve_data_type type, void *ret); 197 mu_sieve_data_type type, void *ret);
192 int mu_sieve_get_tag_untyped (mu_sieve_machine_t mach, 198 mu_sieve_value_t *mu_sieve_get_tag_untyped (mu_sieve_machine_t mach,
193 char *name, mu_sieve_value_t **ret); 199 char const *name);
200 mu_sieve_value_t *mu_sieve_get_tag_n (mu_sieve_machine_t mach, size_t n);
194 201
195 int mu_sieve_load_ext (mu_sieve_machine_t mach, const char *name); 202 int mu_sieve_load_ext (mu_sieve_machine_t mach, const char *name);
196 int mu_sieve_match_part_checker (mu_sieve_machine_t mach, 203 int mu_sieve_match_part_checker (mu_sieve_machine_t mach);
197 const char *name, mu_list_t tags, 204
198 mu_list_t args);
199 int mu_sieve_match_part_checker (mu_sieve_machine_t mach,
200 const char *name, mu_list_t tags,
201 mu_list_t args);
202 /* Operations on value lists */ 205 /* Operations on value lists */
203 mu_sieve_value_t *mu_sieve_get_arg_optional (mu_sieve_machine_t mach, 206 mu_sieve_value_t *mu_sieve_get_arg_optional (mu_sieve_machine_t mach,
204 size_t index); 207 size_t index);
205 mu_sieve_value_t *mu_sieve_get_arg_untyped (mu_sieve_machine_t mach, 208 mu_sieve_value_t *mu_sieve_get_arg_untyped (mu_sieve_machine_t mach,
206 size_t index); 209 size_t index);
207 int mu_sieve_get_arg (mu_sieve_machine_t mach, size_t index, 210 void mu_sieve_get_arg (mu_sieve_machine_t mach, size_t index,
208 mu_sieve_data_type type, void *ret); 211 mu_sieve_data_type type, void *ret);
209 int mu_sieve_vlist_do (mu_sieve_value_t *val, mu_list_action_t ac, 212
213 char *mu_sieve_string (mu_sieve_machine_t mach,
214 mu_sieve_slice_t slice,
215 size_t i);
216 struct mu_sieve_string *mu_sieve_string_raw (mu_sieve_machine_t mach,
217 mu_sieve_slice_t slice,
218 size_t i);
219
220
221 int mu_sieve_vlist_do (mu_sieve_machine_t mach,
222 mu_sieve_value_t *val, mu_list_action_t ac,
210 void *data); 223 void *data);
211 int mu_sieve_vlist_compare (mu_sieve_value_t *a, mu_sieve_value_t *b, 224 int mu_sieve_vlist_compare (mu_sieve_machine_t mach,
225 mu_sieve_value_t *a, mu_sieve_value_t *b,
212 mu_sieve_comparator_t comp, 226 mu_sieve_comparator_t comp,
213 mu_sieve_relcmp_t test, mu_sieve_retrieve_t ac, 227 mu_sieve_relcmp_t test, mu_sieve_retrieve_t ac,
214 void *data, size_t *count); 228 void *data, size_t *count);
......
...@@ -42,6 +42,7 @@ libmu_sieve_la_SOURCES = \ ...@@ -42,6 +42,7 @@ libmu_sieve_la_SOURCES = \
42 sieve-gram.h\ 42 sieve-gram.h\
43 sieve-lex.c\ 43 sieve-lex.c\
44 strexp.c\ 44 strexp.c\
45 string.c\
45 tests.c\ 46 tests.c\
46 util.c 47 util.c
47 libmu_sieve_la_LIBADD = ${MU_LIB_MAILUTILS} @LTDL_LIB@ 48 libmu_sieve_la_LIBADD = ${MU_LIB_MAILUTILS} @LTDL_LIB@
......
...@@ -511,24 +511,22 @@ mu_sieve_data_type fileinto_args[] = { ...@@ -511,24 +511,22 @@ mu_sieve_data_type fileinto_args[] = {
511 }; 511 };
512 512
513 static int 513 static int
514 perms_tag_checker (mu_sieve_machine_t mach, 514 perms_tag_checker (mu_sieve_machine_t mach)
515 const char *name, mu_list_t tags, mu_list_t args)
516 { 515 {
517 mu_iterator_t itr; 516 size_t i;
518 int err = 0; 517 int err = 0;
519 518
520 if (!tags || mu_list_get_iterator (tags, &itr)) 519 if (mach->tagcount == 0)
521 return 0; 520 return 0;
522 for (mu_iterator_first (itr); !err && !mu_iterator_is_done (itr); 521 for (i = 0; i < mach->tagcount; i++)
523 mu_iterator_next (itr))
524 { 522 {
525 int flag; 523 int flag;
526 const char *p; 524 const char *p;
527 mu_sieve_runtime_tag_t *t; 525 mu_sieve_value_t *t = mu_sieve_get_tag_n (mach, i);
528 mu_iterator_current (itr, (void **)&t); 526
529 if (strcmp (t->tag, "permissions") == 0) 527 if (strcmp (t->tag, "permissions") == 0)
530 { 528 {
531 if (mu_parse_stream_perm_string (&flag, t->arg->v.string, &p)) 529 if (mu_parse_stream_perm_string (&flag, t->v.string, &p))
532 { 530 {
533 mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, 531 mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
534 _("invalid permissions (near %s)"), p); 532 _("invalid permissions (near %s)"), p);
...@@ -537,7 +535,6 @@ perms_tag_checker (mu_sieve_machine_t mach, ...@@ -537,7 +535,6 @@ perms_tag_checker (mu_sieve_machine_t mach,
537 } 535 }
538 } 536 }
539 } 537 }
540 mu_iterator_destroy (&itr);
541 return err; 538 return err;
542 } 539 }
543 540
......
...@@ -81,7 +81,6 @@ sieve_deleteheader (mu_sieve_machine_t mach) ...@@ -81,7 +81,6 @@ sieve_deleteheader (mu_sieve_machine_t mach)
81 { 81 {
82 mu_sieve_value_t *val; 82 mu_sieve_value_t *val;
83 const char *field_name; 83 const char *field_name;
84 const char *field_pattern;
85 mu_message_t msg; 84 mu_message_t msg;
86 mu_header_t hdr; 85 mu_header_t hdr;
87 int rc; 86 int rc;
...@@ -91,41 +90,9 @@ sieve_deleteheader (mu_sieve_machine_t mach) ...@@ -91,41 +90,9 @@ sieve_deleteheader (mu_sieve_machine_t mach)
91 90
92 mu_sieve_get_arg (mach, 0, SVT_STRING, &field_name); 91 mu_sieve_get_arg (mach, 0, SVT_STRING, &field_name);
93 val = mu_sieve_get_arg_optional (mach, 1); 92 val = mu_sieve_get_arg_optional (mach, 1);
94 if (!val) 93
95 { 94 mu_sieve_log_action (mach, "DELETEHEADER", "%s%s", field_name,
96 field_pattern = NULL; 95 val ? " (values)" : "" );
97 mu_sieve_log_action (mach, "DELETEHEADER", "%s", field_name);
98 }
99 else
100 {
101 switch (val->type)
102 {
103 case SVT_STRING_LIST:
104 if (mu_list_get (val->v.list, 0, (void**)&field_pattern))
105 {
106 mu_sieve_error (mach, "%lu: %s",
107 (unsigned long) mu_sieve_get_message_num (mach),
108 _("cannot get list item"));
109 mu_sieve_abort (mach);
110 }
111 mu_sieve_log_action (mach, "DELETEHEADER", "%s: (regexp)",
112 field_name);
113 break;
114
115 case SVT_STRING:
116 field_pattern = val->v.string;
117 mu_sieve_log_action (mach, "DELETEHEADER", "%s: %s", field_name,
118 field_pattern);
119 break;
120
121 default:
122 mu_sieve_error (mach, "%lu: %s: %d",
123 (unsigned long) mu_sieve_get_message_num (mach),
124 _("unexpected value type"), val->type);
125 mu_sieve_abort (mach);
126
127 }
128 }
129 96
130 if (mu_sieve_is_dry_run (mach)) 97 if (mu_sieve_is_dry_run (mach))
131 return 0; 98 return 0;
...@@ -141,7 +108,14 @@ sieve_deleteheader (mu_sieve_machine_t mach) ...@@ -141,7 +108,14 @@ sieve_deleteheader (mu_sieve_machine_t mach)
141 mu_sieve_abort (mach); 108 mu_sieve_abort (mach);
142 } 109 }
143 110
144 mu_header_get_iterator (hdr, &itr); 111 rc = mu_header_get_iterator (hdr, &itr);
112 if (rc)
113 {
114 mu_sieve_error (mach, "mu_header_get_iterator: %s",
115 mu_strerror (rc));
116 mu_sieve_abort (mach);
117 }
118
145 if (mu_sieve_get_tag (mach, "last", SVT_VOID, NULL)) 119 if (mu_sieve_get_tag (mach, "last", SVT_VOID, NULL))
146 { 120 {
147 int backwards = 1; 121 int backwards = 1;
...@@ -162,10 +136,18 @@ sieve_deleteheader (mu_sieve_machine_t mach) ...@@ -162,10 +136,18 @@ sieve_deleteheader (mu_sieve_machine_t mach)
162 if (idx && ++i < idx) 136 if (idx && ++i < idx)
163 continue; 137 continue;
164 138
165 if (field_pattern) 139 if (val)
166 { 140 {
167 if (comp (field_pattern, fv)) 141 for (i = 0; i < val->v.list.count; i++)
168 mu_iterator_ctl (itr, mu_itrctl_delete, NULL); 142 {
143 mu_sieve_string_t *s = mu_sieve_string_raw (mach,
144 &val->v.list, i);
145 if (comp (mach, s, fv))
146 {
147 mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
148 break;
149 }
150 }
169 } 151 }
170 else 152 else
171 mu_iterator_ctl (itr, mu_itrctl_delete, NULL); 153 mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
......
...@@ -159,7 +159,7 @@ list_test (mu_sieve_machine_t mach) ...@@ -159,7 +159,7 @@ list_test (mu_sieve_machine_t mach)
159 h = mu_sieve_get_arg_untyped (mach, 0); 159 h = mu_sieve_get_arg_untyped (mach, 0);
160 v = mu_sieve_get_arg_untyped (mach, 1); 160 v = mu_sieve_get_arg_untyped (mach, 1);
161 mu_message_get_header (mu_sieve_get_message (mach), &clos.header); 161 mu_message_get_header (mu_sieve_get_message (mach), &clos.header);
162 result = mu_sieve_vlist_compare (h, v, comp, 162 result = mu_sieve_vlist_compare (mach, h, v, comp,
163 mu_sieve_get_relcmp (mach), 163 mu_sieve_get_relcmp (mach),
164 list_retrieve_header, 164 list_retrieve_header,
165 &clos, NULL) > 0; 165 &clos, NULL) > 0;
......
...@@ -161,8 +161,8 @@ _compare (void *item, void *data) ...@@ -161,8 +161,8 @@ _compare (void *item, void *data)
161 of the originating mail. Return non-zero if so and store a pointer 161 of the originating mail. Return non-zero if so and store a pointer
162 to the matching address in *MY_ADDRESS. */ 162 to the matching address in *MY_ADDRESS. */
163 static int 163 static int
164 match_addresses (mu_header_t hdr, char *email, mu_sieve_value_t *addresses, 164 match_addresses (mu_sieve_machine_t mach, mu_header_t hdr, char *email,
165 char const **my_address) 165 mu_sieve_value_t *addresses, char const **my_address)
166 { 166 {
167 int match = 0; 167 int match = 0;
168 const char *str; 168 const char *str;
...@@ -176,7 +176,7 @@ match_addresses (mu_header_t hdr, char *email, mu_sieve_value_t *addresses, ...@@ -176,7 +176,7 @@ match_addresses (mu_header_t hdr, char *email, mu_sieve_value_t *addresses,
176 if (_compare (email, &ad)) 176 if (_compare (email, &ad))
177 match = 1; 177 match = 1;
178 else if (addresses) 178 else if (addresses)
179 match += mu_sieve_vlist_do (addresses, _compare, &ad); 179 match += mu_sieve_vlist_do (mach, addresses, _compare, &ad);
180 mu_address_destroy (&ad.addr); 180 mu_address_destroy (&ad.addr);
181 } 181 }
182 } 182 }
...@@ -188,7 +188,7 @@ match_addresses (mu_header_t hdr, char *email, mu_sieve_value_t *addresses, ...@@ -188,7 +188,7 @@ match_addresses (mu_header_t hdr, char *email, mu_sieve_value_t *addresses,
188 if (_compare (email, &ad)) 188 if (_compare (email, &ad))
189 match = 1; 189 match = 1;
190 else if (addresses) 190 else if (addresses)
191 match += mu_sieve_vlist_do (addresses, _compare, &ad); 191 match += mu_sieve_vlist_do (mach, addresses, _compare, &ad);
192 mu_address_destroy (&ad.addr); 192 mu_address_destroy (&ad.addr);
193 } 193 }
194 } 194 }
...@@ -249,8 +249,8 @@ noreply_address_p (mu_sieve_machine_t mach, char *email) ...@@ -249,8 +249,8 @@ noreply_address_p (mu_sieve_machine_t mach, char *email)
249 for (i = 0; rc == 0 && noreply_sender[i]; i++) 249 for (i = 0; rc == 0 && noreply_sender[i]; i++)
250 rc = regex_comparator (noreply_sender[i], &rd); 250 rc = regex_comparator (noreply_sender[i], &rd);
251 251
252 if (!rc && mu_sieve_get_tag_untyped (mach, "noreply", &arg)) 252 if (!rc && (arg = mu_sieve_get_tag_untyped (mach, "noreply")) != NULL)
253 rc = mu_sieve_vlist_do (arg, regex_comparator, &rd); 253 rc = mu_sieve_vlist_do (mach, arg, regex_comparator, &rd);
254 254
255 return rc; 255 return rc;
256 } 256 }
...@@ -716,12 +716,13 @@ vacation_reply (mu_sieve_machine_t mach, mu_message_t msg, ...@@ -716,12 +716,13 @@ vacation_reply (mu_sieve_machine_t mach, mu_message_t msg,
716 { 716 {
717 mu_header_set_value (newhdr, MU_HEADER_TO, to, 0); 717 mu_header_set_value (newhdr, MU_HEADER_TO, to, 0);
718 718
719 if (mu_sieve_get_tag_untyped (mach, "header", &val)) 719 val = mu_sieve_get_tag_untyped (mach, "header");
720 if (val)
720 { 721 {
721 struct header_closure hc; 722 struct header_closure hc;
722 hc.mach = mach; 723 hc.mach = mach;
723 hc.hdr = newhdr; 724 hc.hdr = newhdr;
724 mu_sieve_vlist_do (val, add_header, &hc); 725 mu_sieve_vlist_do (mach, val, add_header, &hc);
725 } 726 }
726 727
727 vacation_subject (mach, msg, newhdr); 728 vacation_subject (mach, msg, newhdr);
...@@ -807,9 +808,8 @@ sieve_action_vacation (mu_sieve_machine_t mach) ...@@ -807,9 +808,8 @@ sieve_action_vacation (mu_sieve_machine_t mach)
807 return_address = my_address; 808 return_address = my_address;
808 else 809 else
809 { 810 {
810 mu_sieve_value_t *val = NULL; 811 mu_sieve_value_t *val = mu_sieve_get_tag_untyped (mach, "aliases");
811 mu_sieve_get_tag_untyped (mach, "aliases", &val); 812 if (match_addresses (mach, hdr, my_address, val, &return_address) == 0)
812 if (match_addresses (hdr, my_address, val, &return_address) == 0)
813 { 813 {
814 free (my_address); 814 free (my_address);
815 return 0; 815 return 0;
......
...@@ -196,11 +196,42 @@ mu_sieve_reclaim_value (void *p) ...@@ -196,11 +196,42 @@ mu_sieve_reclaim_value (void *p)
196 /* For now, the same as _default. Will change in the future */ 196 /* For now, the same as _default. Will change in the future */
197 free (p); 197 free (p);
198 } 198 }
199 199
200 /* Based on gnulib's x2nrealloc */
200 void 201 void
201 mu_sieve_reclaim_tag (void *p) 202 mu_i_sv_2nrealloc (mu_sieve_machine_t mach, void **pptr, size_t *pnmemb,
203 size_t size)
202 { 204 {
203 mu_sieve_runtime_tag_t *tag = p; 205 void *ptr = *pptr;
204 mu_sieve_reclaim_value (tag->arg); 206 size_t nmemb = *pnmemb;
205 } 207
208 if (!ptr)
209 {
210 if (!nmemb)
211 {
212 /* Initial allocation size */
213 nmemb = 16;
214 }
215 }
216 else
217 {
218 /* Set NMEMB = floor (1.5 * NMEMB) + 1 so that progress is made even
219 if NMEMB == 0.
220 Check for overflow, so that NMEMB * SIZE stays in size_t range.
221 The check may be slightly conservative, but an exact check isn't
222 worth the trouble. */
223 if ((size_t) -1 / 3 * 2 / size <= nmemb)
224 {
225 mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
226 _("requested too much memory %zu * %zu"),
227 nmemb, size);
228 mu_sieve_abort (mach);
229 }
230 nmemb += nmemb / 2 + 1;
231 }
206 232
233 ptr = mu_sieve_realloc (mach, ptr, nmemb * size);
234
235 *pptr = ptr;
236 *pnmemb = nmemb;
237 }
......
...@@ -38,7 +38,8 @@ DCL(ge,>=) ...@@ -38,7 +38,8 @@ DCL(ge,>=)
38 DCL(lt,<) 38 DCL(lt,<)
39 DCL(le,<=) 39 DCL(le,<=)
40 40
41 static struct reltest_tab { 41 static struct reltest_tab
42 {
42 char *name; 43 char *name;
43 mu_sieve_relcmp_t test; 44 mu_sieve_relcmp_t test;
44 mu_sieve_relcmpn_t stest; 45 mu_sieve_relcmpn_t stest;
...@@ -66,7 +67,7 @@ _relcmp_lookup (const char *str) ...@@ -66,7 +67,7 @@ _relcmp_lookup (const char *str)
66 67
67 int 68 int
68 mu_sieve_str_to_relcmp (const char *str, 69 mu_sieve_str_to_relcmp (const char *str,
69 mu_sieve_relcmp_t *test, mu_sieve_relcmpn_t *stest) 70 mu_sieve_relcmp_t *test, mu_sieve_relcmpn_t *stest)
70 { 71 {
71 struct reltest_tab *t = _relcmp_lookup (str); 72 struct reltest_tab *t = _relcmp_lookup (str);
72 if (t) 73 if (t)
......
...@@ -27,30 +27,17 @@ ...@@ -27,30 +27,17 @@
27 #include <sieve-priv.h> 27 #include <sieve-priv.h>
28 28
29 void 29 void
30 mu_sieve_require (mu_sieve_machine_t mach, mu_list_t slist) 30 mu_sieve_require (mu_sieve_machine_t mach, mu_sieve_slice_t list)
31 { 31 {
32 int status; 32 size_t i;
33 mu_iterator_t itr;
34 33
35 status = mu_list_get_iterator (slist, &itr); 34 for (i = 0; i < list->count; i++)
36 if (status)
37 { 35 {
38 mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, 36 struct mu_sieve_string *str = mu_sieve_string_raw (mach, list, i);
39 _("cannot create iterator: %s"), 37 char *name = str->orig;
40 mu_strerror (status));
41 mu_i_sv_error (mach);
42 return;
43 }
44
45 for (mu_iterator_first (itr);
46 !mu_iterator_is_done (itr); mu_iterator_next (itr))
47 {
48 char *name;
49 int (*reqfn) (mu_sieve_machine_t mach, const char *name) = NULL; 38 int (*reqfn) (mu_sieve_machine_t mach, const char *name) = NULL;
50 const char *text = NULL; 39 const char *text = NULL;
51 40
52 mu_iterator_current (itr, (void **)&name);
53
54 if (strncmp (name, "comparator-", 11) == 0) 41 if (strncmp (name, "comparator-", 11) == 0)
55 { 42 {
56 name += 11; 43 name += 11;
...@@ -87,6 +74,5 @@ mu_sieve_require (mu_sieve_machine_t mach, mu_list_t slist) ...@@ -87,6 +74,5 @@ mu_sieve_require (mu_sieve_machine_t mach, mu_list_t slist)
87 mu_i_sv_error (mach); 74 mu_i_sv_error (mach);
88 } 75 }
89 } 76 }
90 mu_iterator_destroy (&itr);
91 } 77 }
92 78
......
...@@ -24,8 +24,8 @@ ...@@ -24,8 +24,8 @@
24 #include <assert.h> 24 #include <assert.h>
25 #include <sieve-priv.h> 25 #include <sieve-priv.h>
26 26
27 #define SIEVE_ARG(m,n,t) ((m)->prog[(m)->pc+(n)].t) 27 #define SIEVE_RT_ARG(m,n,t) ((m)->prog[(m)->pc+(n)].t)
28 #define SIEVE_ADJUST(m,n) (m)->pc+=(n) 28 #define SIEVE_RT_ADJUST(m,n) (m)->pc+=(n)
29 29
30 #define INSTR_DISASS(m) ((m)->state == mu_sieve_state_disass) 30 #define INSTR_DISASS(m) ((m)->state == mu_sieve_state_disass)
31 #define INSTR_DEBUG(m) \ 31 #define INSTR_DEBUG(m) \
...@@ -34,49 +34,53 @@ ...@@ -34,49 +34,53 @@
34 void 34 void
35 _mu_i_sv_instr_source (mu_sieve_machine_t mach) 35 _mu_i_sv_instr_source (mu_sieve_machine_t mach)
36 { 36 {
37 mach->locus.mu_file = (char*) SIEVE_ARG (mach, 0, string); 37 mach->locus.mu_file = (char*) SIEVE_RT_ARG (mach, 0, string);
38 mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM, 38 mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM,
39 MU_IOCTL_LOGSTREAM_SET_LOCUS, 39 MU_IOCTL_LOGSTREAM_SET_LOCUS,
40 &mach->locus); 40 &mach->locus);
41 if (INSTR_DEBUG (mach)) 41 if (INSTR_DEBUG (mach))
42 mu_i_sv_debug (mach, mach->pc - 1, "SOURCE %s", mach->locus.mu_file); 42 mu_i_sv_debug (mach, mach->pc - 1, "SOURCE %s", mach->locus.mu_file);
43 SIEVE_ADJUST (mach, 1); 43 SIEVE_RT_ADJUST (mach, 1);
44 } 44 }
45 45
46 void 46 void
47 _mu_i_sv_instr_line (mu_sieve_machine_t mach) 47 _mu_i_sv_instr_line (mu_sieve_machine_t mach)
48 { 48 {
49 mach->locus.mu_line = SIEVE_ARG (mach, 0, line); 49 mach->locus.mu_line = SIEVE_RT_ARG (mach, 0, line);
50 mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM, 50 mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM,
51 MU_IOCTL_LOGSTREAM_SET_LOCUS, 51 MU_IOCTL_LOGSTREAM_SET_LOCUS,
52 &mach->locus); 52 &mach->locus);
53 if (INSTR_DEBUG (mach)) 53 if (INSTR_DEBUG (mach))
54 mu_i_sv_debug (mach, mach->pc - 1, "LINE %u", 54 mu_i_sv_debug (mach, mach->pc - 1, "LINE %u",
55 mach->locus.mu_line); 55 mach->locus.mu_line);
56 SIEVE_ADJUST (mach, 1); 56 SIEVE_RT_ADJUST (mach, 1);
57 } 57 }
58 58
59 static int 59 static int
60 instr_run (mu_sieve_machine_t mach, char const *what) 60 instr_run (mu_sieve_machine_t mach, char const *what)
61 { 61 {
62 int rc = 0; 62 int rc = 0;
63 mu_sieve_handler_t han = SIEVE_ARG (mach, 0, handler); 63 mu_sieve_handler_t han = SIEVE_RT_ARG (mach, 0, handler);
64 mach->arg_list = SIEVE_ARG (mach, 1, list); 64 mach->argstart = SIEVE_RT_ARG (mach, 1, pc);
65 mach->tag_list = SIEVE_ARG (mach, 2, list); 65 mach->argcount = SIEVE_RT_ARG (mach, 2, pc);
66 mach->identifier = SIEVE_ARG (mach, 3, string); 66 mach->tagcount = SIEVE_RT_ARG (mach, 3, pc);
67 67 mach->identifier = SIEVE_RT_ARG (mach, 4, string);
68 SIEVE_ADJUST (mach, 4); 68 mach->comparator = SIEVE_RT_ARG (mach, 5, comp);
69
70 SIEVE_RT_ADJUST (mach, 6);
69 71
70 if (INSTR_DEBUG (mach)) 72 if (INSTR_DEBUG (mach))
71 mu_i_sv_debug_command (mach, mach->pc - 1, what); 73 mu_i_sv_debug_command (mach, mach->pc - 7, what);
72 else 74 else
73 mu_i_sv_trace (mach, what); 75 mu_i_sv_trace (mach, what);
74 76
75 if (!INSTR_DISASS (mach)) 77 if (!INSTR_DISASS (mach))
76 rc = han (mach); 78 rc = han (mach);
77 mach->arg_list = NULL; 79 mach->argstart = 0;
78 mach->tag_list = NULL; 80 mach->argcount = 0;
81 mach->tagcount = 0;
79 mach->identifier = NULL; 82 mach->identifier = NULL;
83 mach->comparator = NULL;
80 return rc; 84 return rc;
81 } 85 }
82 86
...@@ -138,9 +142,9 @@ _mu_i_sv_instr_not (mu_sieve_machine_t mach) ...@@ -138,9 +142,9 @@ _mu_i_sv_instr_not (mu_sieve_machine_t mach)
138 void 142 void
139 _mu_i_sv_instr_branch (mu_sieve_machine_t mach) 143 _mu_i_sv_instr_branch (mu_sieve_machine_t mach)
140 { 144 {
141 long num = SIEVE_ARG (mach, 0, number); 145 long num = SIEVE_RT_ARG (mach, 0, number);
142 146
143 SIEVE_ADJUST (mach, 1); 147 SIEVE_RT_ADJUST (mach, 1);
144 if (INSTR_DEBUG (mach)) 148 if (INSTR_DEBUG (mach))
145 mu_i_sv_debug (mach, mach->pc - 2, "BRANCH %lu", 149 mu_i_sv_debug (mach, mach->pc - 2, "BRANCH %lu",
146 (unsigned long)(mach->pc + num)); 150 (unsigned long)(mach->pc + num));
...@@ -153,8 +157,8 @@ _mu_i_sv_instr_branch (mu_sieve_machine_t mach) ...@@ -153,8 +157,8 @@ _mu_i_sv_instr_branch (mu_sieve_machine_t mach)
153 void 157 void
154 _mu_i_sv_instr_brz (mu_sieve_machine_t mach) 158 _mu_i_sv_instr_brz (mu_sieve_machine_t mach)
155 { 159 {
156 long num = SIEVE_ARG (mach, 0, number); 160 long num = SIEVE_RT_ARG (mach, 0, number);
157 SIEVE_ADJUST (mach, 1); 161 SIEVE_RT_ADJUST (mach, 1);
158 162
159 if (INSTR_DEBUG (mach)) 163 if (INSTR_DEBUG (mach))
160 mu_i_sv_debug (mach, mach->pc - 2, "BRZ %lu", 164 mu_i_sv_debug (mach, mach->pc - 2, "BRZ %lu",
...@@ -169,8 +173,8 @@ _mu_i_sv_instr_brz (mu_sieve_machine_t mach) ...@@ -169,8 +173,8 @@ _mu_i_sv_instr_brz (mu_sieve_machine_t mach)
169 void 173 void
170 _mu_i_sv_instr_brnz (mu_sieve_machine_t mach) 174 _mu_i_sv_instr_brnz (mu_sieve_machine_t mach)
171 { 175 {
172 long num = SIEVE_ARG (mach, 0, number); 176 long num = SIEVE_RT_ARG (mach, 0, number);
173 SIEVE_ADJUST (mach, 1); 177 SIEVE_RT_ADJUST (mach, 1);
174 178
175 if (INSTR_DEBUG (mach)) 179 if (INSTR_DEBUG (mach))
176 mu_i_sv_debug (mach, mach->pc - 2, "BRNZ %lu", 180 mu_i_sv_debug (mach, mach->pc - 2, "BRNZ %lu",
......
...@@ -19,8 +19,7 @@ ...@@ -19,8 +19,7 @@
19 #include <mailutils/sieve.h> 19 #include <mailutils/sieve.h>
20 #include <setjmp.h> 20 #include <setjmp.h>
21 #include <string.h> 21 #include <string.h>
22 22 #include <regex.h>
23 #define SIEVE_CODE_INCR 128
24 23
25 typedef void (*sieve_instr_t) (mu_sieve_machine_t mach); 24 typedef void (*sieve_instr_t) (mu_sieve_machine_t mach);
26 25
...@@ -29,6 +28,7 @@ typedef union ...@@ -29,6 +28,7 @@ typedef union
29 sieve_instr_t instr; 28 sieve_instr_t instr;
30 mu_sieve_handler_t handler; 29 mu_sieve_handler_t handler;
31 mu_sieve_value_t *val; 30 mu_sieve_value_t *val;
31 mu_sieve_comparator_t comp;
32 mu_list_t list; 32 mu_list_t list;
33 long number; 33 long number;
34 size_t pc; 34 size_t pc;
...@@ -37,7 +37,7 @@ typedef union ...@@ -37,7 +37,7 @@ typedef union
37 char *string; 37 char *string;
38 unsigned unum; 38 unsigned unum;
39 } sieve_op_t; 39 } sieve_op_t;
40 40
41 struct mu_locus_range 41 struct mu_locus_range
42 { 42 {
43 struct mu_locus beg; 43 struct mu_locus beg;
...@@ -73,6 +73,14 @@ struct mu_sieve_machine ...@@ -73,6 +73,14 @@ struct mu_sieve_machine
73 mu_list_t action_list; /* Actions */ 73 mu_list_t action_list; /* Actions */
74 mu_list_t comp_list; /* Comparators */ 74 mu_list_t comp_list; /* Comparators */
75 mu_list_t source_list; /* Source names (for diagnostics) */ 75 mu_list_t source_list; /* Source names (for diagnostics) */
76
77 mu_sieve_string_t *stringspace;
78 size_t stringcount;
79 size_t stringmax;
80
81 mu_sieve_value_t *valspace;
82 size_t valcount;
83 size_t valmax;
76 84
77 size_t progsize; /* Number of allocated program cells */ 85 size_t progsize; /* Number of allocated program cells */
78 sieve_op_t *prog; /* Compiled program */ 86 sieve_op_t *prog; /* Compiled program */
...@@ -85,8 +93,10 @@ struct mu_sieve_machine ...@@ -85,8 +93,10 @@ struct mu_sieve_machine
85 93
86 /* Call environment */ 94 /* Call environment */
87 const char *identifier; /* Name of action or test being executed */ 95 const char *identifier; /* Name of action or test being executed */
88 mu_list_t arg_list; /* Positional arguments */ 96 size_t argstart; /* Index of the first argument in valspace */
89 mu_list_t tag_list; /* Tagged arguments */ 97 size_t argcount; /* Number of positional arguments */
98 size_t tagcount; /* Number of tagged arguments */
99 mu_sieve_comparator_t comparator; /* Comparator (for tests) */
90 100
91 int dry_run; /* Dry-run mode */ 101 int dry_run; /* Dry-run mode */
92 jmp_buf errbuf; /* Target location for non-local exits */ 102 jmp_buf errbuf; /* Target location for non-local exits */
...@@ -146,7 +156,10 @@ struct mu_sieve_node ...@@ -146,7 +156,10 @@ struct mu_sieve_node
146 struct 156 struct
147 { 157 {
148 mu_sieve_register_t *reg; 158 mu_sieve_register_t *reg;
149 mu_list_t arg; 159 size_t argstart;
160 size_t argcount;
161 size_t tagcount;
162 mu_sieve_comparator_t comparator; /* Comparator (for tests) */
150 } command; 163 } command;
151 } v; 164 } v;
152 }; 165 };
...@@ -161,18 +174,16 @@ void mu_i_sv_lex_finish (struct mu_sieve_machine *mach); ...@@ -161,18 +174,16 @@ void mu_i_sv_lex_finish (struct mu_sieve_machine *mach);
161 174
162 extern mu_sieve_machine_t mu_sieve_machine; 175 extern mu_sieve_machine_t mu_sieve_machine;
163 176
164 #define TAG_COMPFUN "__compfun__" 177 void mu_i_sv_code (struct mu_sieve_machine *mach, sieve_op_t op);
165
166 int mu_i_sv_code (struct mu_sieve_machine *mach, sieve_op_t op);
167 178
168 void mu_i_sv_compile_error (struct mu_sieve_machine *mach, 179 void mu_i_sv_compile_error (struct mu_sieve_machine *mach,
169 const char *fmt, ...) MU_PRINTFLIKE(2,3); 180 const char *fmt, ...) MU_PRINTFLIKE(2,3);
170 181
171 int mu_i_sv_locus (struct mu_sieve_machine *mach, struct mu_locus_range *lr); 182 int mu_i_sv_locus (struct mu_sieve_machine *mach, struct mu_locus_range *lr);
172 int mu_i_sv_code_action (struct mu_sieve_machine *mach, 183 void mu_i_sv_code_action (struct mu_sieve_machine *mach,
173 mu_sieve_register_t *reg, mu_list_t arglist); 184 struct mu_sieve_node *node);
174 int mu_i_sv_code_test (struct mu_sieve_machine *mach, 185 void mu_i_sv_code_test (struct mu_sieve_machine *mach,
175 mu_sieve_register_t *reg, mu_list_t arglist); 186 struct mu_sieve_node *node);
176 187
177 /* Opcodes */ 188 /* Opcodes */
178 void _mu_i_sv_instr_action (mu_sieve_machine_t mach); 189 void _mu_i_sv_instr_action (mu_sieve_machine_t mach);
...@@ -203,8 +214,7 @@ void mu_i_sv_debug_command (mu_sieve_machine_t mach, size_t pc, ...@@ -203,8 +214,7 @@ void mu_i_sv_debug_command (mu_sieve_machine_t mach, size_t pc,
203 char const *what); 214 char const *what);
204 void mu_i_sv_trace (mu_sieve_machine_t mach, const char *what); 215 void mu_i_sv_trace (mu_sieve_machine_t mach, const char *what);
205 216
206 void mu_i_sv_argf (mu_stream_t str, mu_list_t list); 217 void mu_i_sv_valf (mu_sieve_machine_t mach, mu_stream_t str, mu_sieve_value_t *val);
207 void mu_i_sv_valf (mu_stream_t str, mu_sieve_value_t *val);
208 218
209 typedef int (*mu_i_sv_interp_t) (char const *, size_t, char **, void *); 219 typedef int (*mu_i_sv_interp_t) (char const *, size_t, char **, void *);
210 220
...@@ -216,4 +226,15 @@ int mu_i_sv_expand_encoded_char (char const *input, size_t len, char **exp, void ...@@ -216,4 +226,15 @@ int mu_i_sv_expand_encoded_char (char const *input, size_t len, char **exp, void
216 int mu_sieve_require_encoded_character (mu_sieve_machine_t mach, 226 int mu_sieve_require_encoded_character (mu_sieve_machine_t mach,
217 const char *name); 227 const char *name);
218 228
229 void mu_i_sv_2nrealloc (mu_sieve_machine_t mach,
230 void **pptr, size_t *pnmemb, size_t size);
231
232
233 mu_sieve_value_t *mu_i_sv_mach_arg (mu_sieve_machine_t mach, size_t n);
234 mu_sieve_value_t *mu_i_sv_mach_tagn (mu_sieve_machine_t mach, size_t n);
235 void mu_i_sv_lint_command (struct mu_sieve_machine *mach,
236 struct mu_sieve_node *node);
237
238
239 size_t mu_i_sv_string_create (mu_sieve_machine_t mach, char *str);
219 240
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999-2002, 2005-2008, 2010-2012, 2014-2016 Free
3 Software Foundation, Inc.
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 3 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General
16 Public License along with this library. If not, see
17 <http://www.gnu.org/licenses/>. */
18
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #include <stdlib.h>
24 #include <sieve-priv.h>
25
26 size_t
27 mu_i_sv_string_create (mu_sieve_machine_t mach, char *str)
28 {
29 size_t n;
30 mu_sieve_string_t *s;
31
32 if (mach->stringcount == mach->stringmax)
33 {
34 mu_i_sv_2nrealloc (mach, (void**) &mach->stringspace,
35 &mach->stringmax,
36 sizeof mach->stringspace[0]);
37 }
38
39 n = mach->stringcount++;
40 s = &mach->stringspace[n];
41 memset (s, 0, sizeof *s);
42 s->orig = str;
43
44 return n;
45 }
46
47 struct mu_sieve_string *
48 mu_sieve_string_raw (mu_sieve_machine_t mach, mu_sieve_slice_t slice,
49 size_t i)
50 {
51 if (i >= slice->count)
52 abort ();
53 return mach->stringspace + slice->first + i;
54 }
55
56 char *
57 mu_sieve_string (mu_sieve_machine_t mach, mu_sieve_slice_t slice,
58 size_t i)
59 {
60 return mu_sieve_string_raw (mach, slice, i)->orig;
61 }
...@@ -27,32 +27,24 @@ ...@@ -27,32 +27,24 @@
27 27
28 typedef int (*address_aget_t) (mu_address_t addr, size_t no, char **buf); 28 typedef int (*address_aget_t) (mu_address_t addr, size_t no, char **buf);
29 29
30 static int
31 _get_address_part (void *item, void *data)
32 {
33 mu_sieve_runtime_tag_t *t = item;
34 address_aget_t ret = NULL;
35
36 if (strcmp (t->tag, "all") == 0)
37 ret = mu_address_aget_email;
38 else if (strcmp (t->tag, "domain") == 0)
39 ret = mu_address_aget_domain;
40 else if (strcmp (t->tag, "localpart") == 0)
41 ret = mu_address_aget_local_part;
42 if (ret)
43 {
44 *(address_aget_t*)data = ret;
45 return 1; /* break the loop */
46 }
47 return 0; /* continue */
48 }
49
50 address_aget_t 30 address_aget_t
51 sieve_get_address_part (mu_list_t tags) 31 sieve_get_address_part (mu_sieve_machine_t mach)
52 { 32 {
53 address_aget_t ret = mu_address_aget_email; 33 size_t i;
54 mu_list_foreach (tags, _get_address_part, &ret); 34
55 return ret; 35 for (i = 0; i < mach->tagcount; i++)
36 {
37 mu_sieve_value_t *t = mu_sieve_get_tag_n (mach, i);
38 if (strcmp (t->tag, "all") == 0)
39 return mu_address_aget_email;
40 else if (strcmp (t->tag, "domain") == 0)
41 return mu_address_aget_domain;
42 else if (strcmp (t->tag, "localpart") == 0)
43 return mu_address_aget_local_part;
44 }
45 /* RFC 3028, 2.7.4. Comparisons Against Addresses:
46 If an optional address-part is omitted, the default is ":all". */
47 return mu_address_aget_email;
56 } 48 }
57 49
58 /* Structure shared between address and envelope tests */ 50 /* Structure shared between address and envelope tests */
...@@ -72,11 +64,11 @@ do_count (mu_sieve_machine_t mach, size_t count, int retval) ...@@ -72,11 +64,11 @@ do_count (mu_sieve_machine_t mach, size_t count, int retval)
72 { 64 {
73 size_t limit; 65 size_t limit;
74 char *str; 66 char *str;
75 mu_list_t list; 67 struct mu_sieve_slice slice;
76 mu_sieve_relcmpn_t stest; 68 mu_sieve_relcmpn_t stest;
77 69
78 mu_sieve_get_arg (mach, 1, SVT_STRING_LIST, &list); 70 mu_sieve_get_arg (mach, 1, SVT_STRING_LIST, &slice);
79 mu_list_get (list, 0, (void **) &str); 71 str = mu_sieve_string (mach, &slice, 0);
80 limit = strtoul (str, &str, 10); 72 limit = strtoul (str, &str, 10);
81 73
82 mu_sieve_str_to_relcmp (relcmp, NULL, &stest); 74 mu_sieve_str_to_relcmp (relcmp, NULL, &stest);
...@@ -117,16 +109,16 @@ sieve_test_address (mu_sieve_machine_t mach) ...@@ -117,16 +109,16 @@ sieve_test_address (mu_sieve_machine_t mach)
117 mu_sieve_relcmp_t test = mu_sieve_get_relcmp (mach); 109 mu_sieve_relcmp_t test = mu_sieve_get_relcmp (mach);
118 struct address_closure clos; 110 struct address_closure clos;
119 int rc; 111 int rc;
120 size_t count; 112 size_t count = 0;
121 113
122 h = mu_sieve_get_arg_untyped (mach, 0); 114 h = mu_sieve_get_arg_untyped (mach, 0);
123 v = mu_sieve_get_arg_untyped (mach, 1); 115 v = mu_sieve_get_arg_untyped (mach, 1);
124 116
125 mu_message_get_header (mu_sieve_get_message (mach), &header); 117 mu_message_get_header (mu_sieve_get_message (mach), &header);
126 clos.data = header; 118 clos.data = header;
127 clos.aget = sieve_get_address_part (mach->tag_list); 119 clos.aget = sieve_get_address_part (mach);
128 clos.addr = NULL; 120 clos.addr = NULL;
129 rc = mu_sieve_vlist_compare (h, v, comp, test, retrieve_address, &clos, 121 rc = mu_sieve_vlist_compare (mach, h, v, comp, test, retrieve_address, &clos,
130 &count); 122 &count);
131 mu_address_destroy (&clos.addr); 123 mu_address_destroy (&clos.addr);
132 124
...@@ -169,7 +161,7 @@ sieve_test_header (mu_sieve_machine_t mach) ...@@ -169,7 +161,7 @@ sieve_test_header (mu_sieve_machine_t mach)
169 mu_sieve_value_t *h, *v; 161 mu_sieve_value_t *h, *v;
170 mu_sieve_comparator_t comp = mu_sieve_get_comparator (mach); 162 mu_sieve_comparator_t comp = mu_sieve_get_comparator (mach);
171 mu_sieve_relcmp_t test = mu_sieve_get_relcmp (mach); 163 mu_sieve_relcmp_t test = mu_sieve_get_relcmp (mach);
172 size_t count, mcount = 0; 164 size_t count = 0, mcount = 0;
173 struct header_closure clos; 165 struct header_closure clos;
174 166
175 h = mu_sieve_get_arg_untyped (mach, 0); 167 h = mu_sieve_get_arg_untyped (mach, 0);
...@@ -192,7 +184,7 @@ sieve_test_header (mu_sieve_machine_t mach) ...@@ -192,7 +184,7 @@ sieve_test_header (mu_sieve_machine_t mach)
192 if (mu_message_get_part (mach->msg, i, &message) == 0) 184 if (mu_message_get_part (mach->msg, i, &message) == 0)
193 { 185 {
194 mu_message_get_header (message, &clos.header); 186 mu_message_get_header (message, &clos.header);
195 if (mu_sieve_vlist_compare (h, v, comp, test, 187 if (mu_sieve_vlist_compare (mach, h, v, comp, test,
196 retrieve_header, &clos, &mcount)) 188 retrieve_header, &clos, &mcount))
197 return 1; 189 return 1;
198 } 190 }
...@@ -200,7 +192,7 @@ sieve_test_header (mu_sieve_machine_t mach) ...@@ -200,7 +192,7 @@ sieve_test_header (mu_sieve_machine_t mach)
200 } 192 }
201 } 193 }
202 mu_message_get_header (mach->msg, &clos.header); 194 mu_message_get_header (mach->msg, &clos.header);
203 if (mu_sieve_vlist_compare (h, v, comp, test, retrieve_header, &clos, 195 if (mu_sieve_vlist_compare (mach, h, v, comp, test, retrieve_header, &clos,
204 &count)) 196 &count))
205 return 1; 197 return 1;
206 198
...@@ -242,16 +234,16 @@ sieve_test_envelope (mu_sieve_machine_t mach) ...@@ -242,16 +234,16 @@ sieve_test_envelope (mu_sieve_machine_t mach)
242 mu_sieve_relcmp_t test = mu_sieve_get_relcmp (mach); 234 mu_sieve_relcmp_t test = mu_sieve_get_relcmp (mach);
243 struct address_closure clos; 235 struct address_closure clos;
244 int rc; 236 int rc;
245 size_t count; 237 size_t count = 0;
246 238
247 h = mu_sieve_get_arg_untyped (mach, 0); 239 h = mu_sieve_get_arg_untyped (mach, 0);
248 v = mu_sieve_get_arg_untyped (mach, 1); 240 v = mu_sieve_get_arg_untyped (mach, 1);
249 241
250 mu_message_get_envelope (mu_sieve_get_message (mach), 242 mu_message_get_envelope (mu_sieve_get_message (mach),
251 (mu_envelope_t*)&clos.data); 243 (mu_envelope_t*)&clos.data);
252 clos.aget = sieve_get_address_part (mach->tag_list); 244 clos.aget = sieve_get_address_part (mach);
253 clos.addr = NULL; 245 clos.addr = NULL;
254 rc = mu_sieve_vlist_compare (h, v, comp, test, retrieve_envelope, &clos, 246 rc = mu_sieve_vlist_compare (mach, h, v, comp, test, retrieve_envelope, &clos,
255 &count); 247 &count);
256 mu_address_destroy (&clos.addr); 248 mu_address_destroy (&clos.addr);
257 return do_count (mach, count, rc); 249 return do_count (mach, count, rc);
...@@ -261,19 +253,23 @@ int ...@@ -261,19 +253,23 @@ int
261 sieve_test_size (mu_sieve_machine_t mach) 253 sieve_test_size (mu_sieve_machine_t mach)
262 { 254 {
263 int rc = 1; 255 int rc = 1;
264 mu_sieve_runtime_tag_t *tag = NULL;
265 size_t size; 256 size_t size;
266 size_t arg; 257 size_t arg;
267 258
268 mu_sieve_get_arg (mach, 0, SVT_NUMBER, &arg); 259 mu_sieve_get_arg (mach, 0, SVT_NUMBER, &arg);
269 mu_message_size (mu_sieve_get_message (mach), &size); 260 mu_message_size (mu_sieve_get_message (mach), &size);
270 mu_list_get (mach->tag_list, 0, (void **)&tag); 261 if (mach->tagcount)
271 if (!tag) 262 {
263 mu_sieve_value_t *tag = mu_sieve_get_tag_n (mach, 0);
264 if (strcmp (tag->tag, "over") == 0)
265 rc = size > arg;
266 else if (strcmp (tag->tag, "under") == 0)
267 rc = size < arg;
268 else
269 abort ();
270 }
271 else
272 rc = size == arg; 272 rc = size == arg;
273 else if (strcmp (tag->tag, "over") == 0)
274 rc = size > arg;
275 else if (strcmp (tag->tag, "under") == 0)
276 rc = size < arg;
277 273
278 return rc; 274 return rc;
279 } 275 }
...@@ -295,7 +291,7 @@ sieve_test_exists (mu_sieve_machine_t mach) ...@@ -295,7 +291,7 @@ sieve_test_exists (mu_sieve_machine_t mach)
295 291
296 mu_message_get_header (mu_sieve_get_message (mach), &header); 292 mu_message_get_header (mu_sieve_get_message (mach), &header);
297 val = mu_sieve_get_arg_untyped (mach, 0); 293 val = mu_sieve_get_arg_untyped (mach, 0);
298 return mu_sieve_vlist_do (val, _test_exists, header) == 0; 294 return mu_sieve_vlist_do (mach, val, _test_exists, header) == 0;
299 } 295 }
300 296
301 static mu_sieve_tag_def_t address_part_tags[] = { 297 static mu_sieve_tag_def_t address_part_tags[] = {
......
...@@ -125,7 +125,7 @@ Subject: Ping ...@@ -125,7 +125,7 @@ Subject: Ping
125 Test message, please discard. 125 Test message, please discard.
126 126
127 ], 127 ],
128 [DELETEHEADER on msg uid 1: X-Agent: (regexp) 128 [DELETEHEADER on msg uid 1: X-Agent (values)
129 ]) 129 ])
130 130
131 m4_popdef([MUT_SIEVE_EXT_NAME]) 131 m4_popdef([MUT_SIEVE_EXT_NAME])
......
...@@ -19,7 +19,6 @@ AT_KEYWORDS([encoded-character enc-char]) ...@@ -19,7 +19,6 @@ AT_KEYWORDS([encoded-character enc-char])
19 19
20 AT_CHECK([ 20 AT_CHECK([
21 AT_DATA([prog],[[require ["reject", "encoded-character"]; 21 AT_DATA([prog],[[require ["reject", "encoded-character"];
22
23 reject "$${hex:40}"; 22 reject "$${hex:40}";
24 reject "${hex: 40 }"; 23 reject "${hex: 40 }";
25 reject "${HEX: 40}"; 24 reject "${HEX: 40}";
...@@ -38,25 +37,25 @@ reject "Nested ${hex: 73 65 71 ${hex: 75 65 6E}}ce"; ...@@ -38,25 +37,25 @@ reject "Nested ${hex: 73 65 71 ${hex: 75 65 6E}}ce";
38 reject "Invalid ${hex: 73 RE}"; 37 reject "Invalid ${hex: 73 RE}";
39 ]]) 38 ]])
40 39
41 sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -D prog | grep ACTION 40 sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -D prog | sed -n 's/.*ACTION: //p'
42 ], 41 ],
43 [0], 42 [0],
44 [ 9: ACTION: reject "$@" 43 [reject "$@"
45 16: ACTION: reject "@" 44 reject "@"
46 23: ACTION: reject "@" 45 reject "@"
47 30: ACTION: reject "${hex:40" 46 reject "${hex:40"
48 37: ACTION: reject "${hex:400}" 47 reject "${hex:400}"
49 44: ACTION: reject "${hex:40}" 48 reject "${hex:40}"
50 51: ACTION: reject "@" 49 reject "@"
51 58: ACTION: reject "${ unicode:40}" 50 reject "${ unicode:40}"
52 65: ACTION: reject "@" 51 reject "@"
53 72: ACTION: reject "@" 52 reject "@"
54 79: ACTION: reject "@" 53 reject "@"
55 86: ACTION: reject "${Unicode:Cool}" 54 reject "${Unicode:Cool}"
56 93: ACTION: reject "Now is the time" 55 reject "Now is the time"
57 100: ACTION: reject "Unbalanced ${hex: 73 65 71 uence" 56 reject "Unbalanced ${hex: 73 65 71 uence"
58 107: ACTION: reject "Nested ${hex: 73 65 71 uen}ce" 57 reject "Nested ${hex: 73 65 71 uen}ce"
59 114: ACTION: reject "Invalid ${hex: 73 RE}" 58 reject "Invalid ${hex: 73 RE}"
60 ]) 59 ])
61 60
62 AT_CLEANUP 61 AT_CLEANUP
......