1
/* bc_eval.c - evaluate the bytecode
4
/***********************************************************
5
Copyright 2001 by Carnegie Mellon University
9
Permission to use, copy, modify, and distribute this software and its
10
documentation for any purpose and without fee is hereby granted,
11
provided that the above copyright notice appear in all copies and that
12
both that copyright notice and this permission notice appear in
13
supporting documentation, and that the name of Carnegie Mellon
14
University not be used in advertising or publicity pertaining to
15
distribution of the software without specific, written prior
18
CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
19
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
20
FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR
21
ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
23
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
24
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25
******************************************************************/
31
#include "sieve_interface.h"
43
/**************************************************************************/
44
/**************************************************************************/
45
/**************************************************************************/
46
/**************************EXECUTING BYTECODE******************************/
47
/**************************************************************************/
48
/**************************************************************************/
49
/**************************************************************************/
50
/**************************************************************************/
52
/* Given a bytecode_input_t at the beginning of a string (the len block),
53
* return the string, the length, and the bytecode index of the NEXT
55
int unwrap_string(bytecode_input_t *bc, int pos, const char **str, int *len)
57
int local_len = ntohl(bc[pos].value);
62
/* -1 length indicates NULL */
65
/* This cast is ugly, but necessary */
66
*str = (const char *)&bc[pos].str;
68
/* Compute the next index */
69
pos += ((ROUNDUP(local_len+1))/sizeof(bytecode_input_t));
72
if(len) *len = local_len;
78
/* this is used by notify to pass the options list to do_notify
79
* do_notify needs null-terminated (char *)[],
80
* we have a stringlist, the beginning of which is pointed at by pos */
81
static const char ** bc_makeArray(bytecode_input_t *bc, int *pos)
85
int len = ntohl(bc[*pos].value);
87
(*pos)+=2; /* Skip # Values and Total Byte Length */
89
array=(const char **)xmalloc((len+1) * sizeof(char *));
91
for (i=0; i<len; i++) {
92
*pos = unwrap_string(bc, *pos, &(array[i]), NULL);
100
/* Compile a regular expression for use during parsing */
101
static regex_t * bc_compile_regex(const char *s, int ctag,
102
char *errmsg, size_t errsiz)
105
regex_t *reg = (regex_t *) xmalloc(sizeof(regex_t));
107
if ( (ret=regcomp(reg, s, ctag)) != 0)
109
(void) regerror(ret, reg, errmsg, errsiz);
116
/* Determine if addr is a system address */
117
static int sysaddr(const char *addr)
119
if (!strncasecmp(addr, "MAILER-DAEMON", 13))
122
if (!strncasecmp(addr, "LISTSERV", 8))
125
if (!strncasecmp(addr, "majordomo", 9))
128
if (strstr(addr, "-request@"))
131
if (!strncmp(addr, "owner-", 6))
137
/* look for myaddr and myaddrs in the body of a header - return the match */
138
static char* look_for_me(char *myaddr, int numaddresses,
139
bytecode_input_t *bc, int i, const char **body)
145
/* loop through each TO header */
146
for (l = 0; body[l] != NULL && !found; l++) {
147
void *data = NULL, *marker = NULL;
150
parse_address(body[l], &data, &marker);
152
/* loop through each address in the header */
154
((addr = get_address(ADDRESS_ALL,&data, &marker, 1))!= NULL)) {
156
if (!strcasecmp(addr, myaddr)) {
157
found = xstrdup(myaddr);
163
for(x=0; x<numaddresses; x++)
165
void *altdata = NULL, *altmarker = NULL;
169
curra = unwrap_string(bc, curra, &str, NULL);
171
/* is this address one of my addresses? */
172
parse_address(str, &altdata, &altmarker);
174
altaddr = get_address(ADDRESS_ALL, &altdata, &altmarker, 1);
176
if (!strcasecmp(addr,altaddr)) {
181
free_address(&altdata, &altmarker);
185
free_address(&data, &marker);
191
static char *list_fields[] = {
202
/* Determine if we should respond to a vacation message */
203
static int shouldRespond(void * m, sieve_interp_t *interp,
204
int numaddresses, bytecode_input_t* bc,
205
int i, char **from, char **to)
211
void *data = NULL, *marker = NULL;
217
/* Implementations SHOULD NOT respond to any message that contains a
218
"List-Id" [RFC2919], "List-Help", "List-Subscribe", "List-
219
Unsubscribe", "List-Post", "List-Owner" or "List-Archive" [RFC2369]
221
for (j = 0; list_fields[j]; j++) {
222
strcpy(buf, list_fields[j]);
223
if (interp->getheader(m, buf, &body) == SIEVE_OK) {
229
/* Implementations SHOULD NOT respond to any message that has an
230
"Auto-submitted" header field with a value other than "no".
231
This header field is described in [RFC3834]. */
232
strcpy(buf, "auto-submitted");
233
if (interp->getheader(m, buf, &body) == SIEVE_OK) {
234
/* we don't deal with comments, etc. here */
235
/* skip leading white-space */
236
while (*body[0] && isspace((int) *body[0])) body[0]++;
237
if (strcasecmp(body[0], "no")) l = SIEVE_DONE;
240
/* is there a Precedence keyword of "junk | bulk | list"? */
241
/* XXX non-standard header, but worth checking */
242
strcpy(buf, "precedence");
243
if (interp->getheader(m, buf, &body) == SIEVE_OK) {
244
/* we don't deal with comments, etc. here */
245
/* skip leading white-space */
246
while (*body[0] && isspace((int) *body[0])) body[0]++;
247
if (!strcasecmp(body[0], "junk") ||
248
!strcasecmp(body[0], "bulk") ||
249
!strcasecmp(body[0], "list"))
253
/* Note: the domain-part of all addresses are canonicalized */
254
/* grab my address from the envelope */
257
l = interp->getenvelope(m, buf, &body);
260
parse_address(body[0], &data, &marker);
261
tmp = get_address(ADDRESS_ALL, &data, &marker, 1);
262
myaddr = (tmp != NULL) ? xstrdup(tmp) : NULL;
263
free_address(&data, &marker);
269
l = interp->getenvelope(m, buf, &body);
271
if (l == SIEVE_OK && body[0]) {
272
/* we have to parse this address & decide whether we
273
want to respond to it */
274
parse_address(body[0], &data, &marker);
275
tmp = get_address(ADDRESS_ALL, &data, &marker, 1);
276
reply_to = (tmp != NULL) ? xstrdup(tmp) : NULL;
277
free_address(&data, &marker);
279
/* first, is there a reply-to address? */
280
if (reply_to == NULL) {
284
/* first, is it from me? */
285
if (l == SIEVE_OK && !strcmp(myaddr, reply_to)) {
289
/* ok, is it any of the other addresses i've
294
for(x=0; x<numaddresses; x++) {
297
curra = unwrap_string(bc, curra, &address, NULL);
299
if (!strcmp(address, reply_to))
304
/* ok, is it a system address? */
305
if (l == SIEVE_OK && sysaddr(reply_to)) {
310
/* ok, we're willing to respond to the sender.
311
but is this message to me? that is, is my address
312
in the [Resent]-To, [Resent]-Cc or [Resent]-Bcc fields? */
313
if (strcpy(buf, "to"),
314
interp->getheader(m, buf, &body) == SIEVE_OK)
315
found = look_for_me(myaddr, numaddresses ,bc, i, body);
316
if (!found && (strcpy(buf, "cc"),
317
(interp->getheader(m, buf, &body) == SIEVE_OK)))
318
found = look_for_me(myaddr, numaddresses, bc, i, body);
319
if (!found && (strcpy(buf, "bcc"),
320
(interp->getheader(m, buf, &body) == SIEVE_OK)))
321
found = look_for_me(myaddr, numaddresses, bc, i, body);
322
if (!found && (strcpy(buf, "resent-to"),
323
(interp->getheader(m, buf, &body) == SIEVE_OK)))
324
found = look_for_me(myaddr, numaddresses ,bc, i, body);
325
if (!found && (strcpy(buf, "resent-cc"),
326
(interp->getheader(m, buf, &body) == SIEVE_OK)))
327
found = look_for_me(myaddr, numaddresses, bc, i, body);
328
if (!found && (strcpy(buf, "resent-bcc"),
329
(interp->getheader(m, buf, &body) == SIEVE_OK)))
330
found = look_for_me(myaddr, numaddresses, bc, i, body);
334
/* ok, ok, if we got here maybe we should reply */
335
if (myaddr) free(myaddr);
341
/* Evaluate a bytecode test */
342
static int eval_bc_test(sieve_interp_t *interp,
343
struct hash_table *body_cache, void* m,
344
bytecode_input_t * bc, int * ip)
348
int x,y,z;/* loop variable */
349
int list_len; /* for allof/anyof/exists */
350
int list_end; /* for allof/anyof/exists */
351
int address=0;/*to differentiate between address and envelope*/
352
comparator_t * comp=NULL;
353
void * comprock=NULL;
354
int op= ntohl(bc[i].op);
366
res = eval_bc_test(interp, body_cache, m, bc, &i);
367
if(res >= 0) res = !res; /* Only invert in non-error case */
378
list_len=ntohl(bc[headersi].len);
379
list_end=ntohl(bc[headersi+1].value)/4;
383
for(x=0; x<list_len && res; x++)
387
currh = unwrap_string(bc, currh, &str, NULL);
389
if(interp->getheader(m,str, &val) != SIEVE_OK)
393
i=list_end; /* adjust for short-circuit */
399
int sizevar=ntohl(bc[i+1].value);
400
int x=ntohl(bc[i+2].value);
402
if (interp->getsize(m, &s) != SIEVE_OK)
405
if (sizevar ==B_OVER) {
417
list_len=ntohl(bc[i+1].len);
418
list_end=ntohl(bc[i+2].len)/4;
421
/* need to process all of them, to ensure our instruction pointer stays
422
* in the right place */
423
for (x=0; x<list_len && !res; x++) {
425
tmp = eval_bc_test(interp,body_cache,m,bc,&i);
433
i = list_end; /* handle short-circuting */
438
list_len=ntohl(bc[i+1].len);
439
list_end=ntohl(bc[i+2].len)/4;
442
/* return 1 unless you find one that isn't true, then return 0 */
443
for (x=0; x<list_len && res; x++) {
445
tmp = eval_bc_test(interp,body_cache,m,bc,&i);
453
i = list_end; /* handle short-circuiting */
456
case BC_ADDRESS:/*7*/
459
case BC_ENVELOPE:/*8*/
465
int addrpart=ADDRESS_ALL;/* XXX correct default behavior?*/
467
int headersi=i+5;/* the i value for the begining of the headers */
468
int datai=(ntohl(bc[headersi+1].value)/4);
470
int numheaders=ntohl(bc[headersi].len);
471
int numdata=ntohl(bc[datai].len);
473
int currh, currd; /* current header, current data */
475
int match=ntohl(bc[i+1].value);
476
int relation=ntohl(bc[i+2].value);
477
int comparator=ntohl(bc[i+3].value);
478
int apart=ntohl(bc[i+4].value);
481
int isReg = (match==B_REGEX);
484
char errbuf[100]; /* Basically unused, as regexps are tested at compile */
486
/* set up variables needed for compiling regex */
489
if (comparator== B_ASCIICASEMAP)
491
ctag = REG_EXTENDED | REG_NOSUB | REG_ICASE;
495
ctag = REG_EXTENDED | REG_NOSUB;
499
/*find the correct comparator fcn*/
500
comp = lookup_comp(comparator, match, relation, &comprock);
503
res = SIEVE_RUN_ERROR;
507
/*find the part of the address that we want*/
511
addrpart = ADDRESS_ALL; break;
513
addrpart = ADDRESS_LOCALPART; break;
515
addrpart = ADDRESS_DOMAIN; break;
517
addrpart = ADDRESS_USER; break;
519
addrpart = ADDRESS_DETAIL; break;
521
/* this shouldn't happen with correcct bytecode */
522
res = SIEVE_RUN_ERROR;
525
if(res == SIEVE_RUN_ERROR) break;
527
/*loop through all the headers*/
530
printf("about to process %d headers\n", numheaders);
532
for (x=0; x<numheaders && !res; x++)
534
const char *this_header;
536
currh = unwrap_string(bc, currh, &this_header, NULL);
538
/* Try the next string if we don't have this one */
541
if(interp->getheader(m, this_header, &val) != SIEVE_OK)
544
printf(" [%d] header %s is %s\n", x, this_header, val[0]);
548
if(interp->getenvelope(m, this_header, &val) != SIEVE_OK)
552
/*header exists, now to test it*/
553
/*search through all the headers that match*/
555
for (y=0; val[y]!=NULL && !res; y++) {
558
printf("about to parse %s\n", val[y]);
561
if (parse_address(val[y], &data, &marker)!=SIEVE_OK)
565
(addr = get_address(addrpart, &data, &marker, 0))) {
567
printf("working addr %s\n", (addr ? addr : "[nil]"));
570
if (match == B_COUNT) {
573
/*search through all the data*/
575
for (z=0; z<numdata && !res; z++)
577
const char *data_val;
579
currd = unwrap_string(bc, currd, &data_val, NULL);
582
reg = bc_compile_regex(data_val, ctag,
583
errbuf, sizeof(errbuf));
590
res |= comp(val[y], strlen(val[y]),
591
(const char *)reg, comprock);
595
printf("%s compared to %s(from script)\n",
598
res |= comp(addr, strlen(addr),
601
} /* For each data */
603
} /* For each address */
605
free_address(&data, &marker);
606
}/* For each message header */
609
printf("end of loop, res is %d, x is %d (%d)\n", res, x, numheaders);
611
} /* For each script header */
613
if (match == B_COUNT)
615
sprintf(scount, "%u", count);
616
/* search through all the data */
618
for (z=0; z<numdata && !res; z++)
620
const char *data_val;
622
currd = unwrap_string(bc, currd, &data_val, NULL);
624
res |= comp(scount, strlen(scount), data_val, comprock);
629
i=(ntohl(bc[datai+1].value)/4);
637
int headersi=i+4;/*the i value for the begining of hte headers*/
638
int datai=(ntohl(bc[headersi+1].value)/4);
640
int numheaders=ntohl(bc[headersi].len);
641
int numdata=ntohl(bc[datai].len);
643
int currh, currd; /*current header, current data*/
645
int match=ntohl(bc[i+1].value);
646
int relation=ntohl(bc[i+2].value);
647
int comparator=ntohl(bc[i+3].value);
650
int isReg = (match==B_REGEX);
653
char errbuf[100]; /* Basically unused, regexps tested at compile */
655
/* set up variables needed for compiling regex */
658
if (comparator== B_ASCIICASEMAP)
660
ctag= REG_EXTENDED | REG_NOSUB | REG_ICASE;
664
ctag= REG_EXTENDED | REG_NOSUB;
669
/*find the correct comparator fcn*/
670
comp=lookup_comp(comparator, match, relation, &comprock);
673
res = SIEVE_RUN_ERROR;
677
/*search through all the flags for the header*/
679
for(x=0; x<numheaders && !res; x++)
681
const char *this_header;
683
currh = unwrap_string(bc, currh, &this_header, NULL);
685
if(interp->getheader(m, this_header, &val) != SIEVE_OK) {
686
continue; /*this header does not exist, search the next*/
689
printf ("val %s %s %s\n", val[0], val[1], val[2]);
692
/* search through all the headers that match */
694
for (y=0; val[y]!=NULL && !res; y++)
696
if (match == B_COUNT) {
699
/*search through all the data*/
701
for (z=0; z<numdata && !res; z++)
703
const char *data_val;
705
currd = unwrap_string(bc, currd, &data_val, NULL);
708
reg= bc_compile_regex(data_val, ctag, errbuf,
717
res |= comp(val[y], strlen(val[y]),
718
(const char *)reg, comprock);
721
res |= comp(val[y], strlen(val[y]),
729
if (match == B_COUNT )
731
sprintf(scount, "%u", count);
732
/*search through all the data*/
734
for (z=0; z<numdata && !res; z++)
736
const char *data_val;
738
currd = unwrap_string(bc, currd, &data_val, NULL);
740
printf("%d, %s \n", count, data_val);
742
res |= comp(scount, strlen(scount), data_val, comprock);
748
i=(ntohl(bc[datai+1].value)/4);
754
sieve_bodypart_t *val;
755
const char **content_types = NULL;
757
int typesi=i+6;/* the i value for the begining of the content-types */
758
int datai=(ntohl(bc[typesi+1].value)/4);
760
int numdata=ntohl(bc[datai].len);
762
int currd; /* current data */
764
int match=ntohl(bc[i+1].value);
765
int relation=ntohl(bc[i+2].value);
766
int comparator=ntohl(bc[i+3].value);
767
int transform=ntohl(bc[i+4].value);
768
/*int offset=ntohl(bc[i+5].value);*/
771
int isReg = (match==B_REGEX);
774
char errbuf[100]; /* Basically unused, as regexps are tested at compile */
776
/* set up variables needed for compiling regex */
779
if (comparator== B_ASCIICASEMAP)
781
ctag = REG_EXTENDED | REG_NOSUB | REG_ICASE;
785
ctag = REG_EXTENDED | REG_NOSUB;
789
/*find the correct comparator fcn*/
790
comp = lookup_comp(comparator, match, relation, &comprock);
793
res = SIEVE_RUN_ERROR;
797
/*find the part(s) of the body that we want*/
798
content_types = bc_makeArray(bc, &typesi);
799
if(interp->getbody(m, content_types, transform != B_RAW, &val) != SIEVE_OK) {
800
res = SIEVE_RUN_ERROR;
805
/* bodypart(s) exist, now to test them */
807
for (y=0; val[y].content!=NULL && !res; y++) {
809
if (match == B_COUNT) {
812
const char *content = val[y].content;
813
size_t size = val[y].size;
815
/* search through all the data */
817
for (z=0; z<numdata && !res; z++)
819
const char *data_val;
821
currd = unwrap_string(bc, currd, &data_val, NULL);
824
reg = bc_compile_regex(data_val, ctag,
825
errbuf, sizeof(errbuf));
832
res |= comp(content, size, (const char *)reg, comprock);
835
res |= comp(content, size, data_val, comprock);
837
} /* For each data */
840
} /* For each body part */
842
if (match == B_COUNT)
844
sprintf(scount, "%u", count);
845
/* search through all the data */
847
for (z=0; z<numdata && !res; z++)
849
const char *data_val;
851
currd = unwrap_string(bc, currd, &data_val, NULL);
853
res |= comp(scount, strlen(scount), data_val, comprock);
858
i=(ntohl(bc[datai+1].value)/4);
864
printf("WERT, can't evaluate if statement. %d is not a valid command",
867
return SIEVE_RUN_ERROR;
877
/* The entrypoint for bytecode evaluation */
878
int sieve_eval_bc(sieve_execute_t *exe, int is_incl, sieve_interp_t *i,
879
struct hash_table *body_cache, void *sc, void *m,
880
sieve_imapflags_t * imapflags, action_list_t *actions,
881
notify_list_t *notify_list, const char **errmsg)
888
sieve_bytecode_t *bc_cur = exe->bc_cur;
889
bytecode_input_t *bc = (bytecode_input_t *) bc_cur->data;
890
int ip = 0, ip_max = (bc_cur->len/sizeof(bytecode_input_t));
892
if (bc_cur->is_executing) {
893
*errmsg = "Recursive Include";
894
return SIEVE_RUN_ERROR;
896
bc_cur->is_executing = 1;
900
* b) it is atleast long enough for the magic number, the version
902
if(!bc) return SIEVE_FAIL;
903
if(bc_cur->len < (BYTECODE_MAGIC_LEN + 2*sizeof(bytecode_input_t)))
906
if(memcmp(bc, BYTECODE_MAGIC, BYTECODE_MAGIC_LEN)) {
907
*errmsg = "Not a bytecode file";
911
ip = BYTECODE_MAGIC_LEN / sizeof(bytecode_input_t);
913
version= ntohl(bc[ip].op);
915
/* this is because there was a time where integers were not network byte
916
order. all the scripts written then would have version 0x01 written
917
in host byte order.*/
919
if(version == (int)ntohl(1)) {
922
"Incorrect Bytecode Version, please recompile (use sievec)";
928
if((version < BYTECODE_MIN_VERSION) || (version > BYTECODE_VERSION)) {
931
"Incorrect Bytecode Version, please recompile (use sievec)";
937
printf("version number %d\n",version);
940
for(ip++; ip<ip_max; ) {
950
res = do_keep(actions, imapflags);
951
if (res == SIEVE_RUN_ERROR)
952
*errmsg = "Keep can not be used with Reject";
957
res=do_discard(actions);
962
ip = unwrap_string(bc, ip+1, &data, NULL);
964
res = do_reject(actions, data);
966
if (res == SIEVE_RUN_ERROR)
967
*errmsg = "Reject can not be used with any other action";
971
case B_FILEINTO:/*19*/
972
copy = ntohl(bc[ip+1].value);
975
case B_FILEINTO_ORIG:/*4*/
977
ip = unwrap_string(bc, ip+1, &data, NULL);
979
res = do_fileinto(actions, data, !copy, imapflags);
981
if (res == SIEVE_RUN_ERROR)
982
*errmsg = "Fileinto can not be used with Reject";
987
case B_REDIRECT:/*20*/
988
copy = ntohl(bc[ip+1].value);
991
case B_REDIRECT_ORIG:/*5*/
993
ip = unwrap_string(bc, ip+1, &data, NULL);
995
res = do_redirect(actions, data, !copy);
997
if (res == SIEVE_RUN_ERROR)
998
*errmsg = "Redirect can not be used with Reject";
1005
int testend=ntohl(bc[ip+1].value);
1009
result=eval_bc_test(i, body_cache, m, bc, &ip);
1012
*errmsg = "Invalid test";
1014
} else if (result) {
1015
/*skip over jump instruction*/
1024
res = do_mark(actions);
1029
res = do_unmark(actions);
1033
case B_ADDFLAG:/*10*/
1036
int list_len=ntohl(bc[ip+1].len);
1038
ip+=3; /* skip opcode, list_len, and list data len */
1040
for (x=0; x<list_len; x++) {
1041
ip = unwrap_string(bc, ip, &data, NULL);
1043
res = do_addflag(actions, data);
1045
if (res == SIEVE_RUN_ERROR)
1046
*errmsg = "addflag can not be used with Reject";
1054
int list_len=ntohl(bc[ip+1].len);
1056
ip+=3; /* skip opcode, list_len, and list data len */
1058
ip = unwrap_string(bc, ip, &data, NULL);
1060
res = do_setflag(actions, data);
1062
if (res == SIEVE_RUN_ERROR) {
1063
*errmsg = "setflag can not be used with Reject";
1065
for (x=1; x<list_len; x++) {
1066
ip = unwrap_string(bc, ip, &data, NULL);
1068
res = do_addflag(actions, data);
1070
if (res == SIEVE_RUN_ERROR)
1071
*errmsg = "setflag can not be used with Reject";
1081
int list_len=ntohl(bc[ip+1].len);
1083
ip+=3; /* skip opcode, list_len, and list data len */
1085
for (x=0; x<list_len; x++) {
1086
ip = unwrap_string(bc, ip, &data, NULL);
1088
res = do_removeflag(actions, data);
1090
if (res == SIEVE_RUN_ERROR)
1091
*errmsg = "removeflag can not be used with Reject";
1099
const char * method;
1100
const char **options = NULL;
1101
const char *priority = NULL;
1102
const char * message;
1108
ip = unwrap_string(bc, ip, &method, NULL);
1111
ip = unwrap_string(bc, ip, &id, NULL);
1114
options=bc_makeArray(bc, &ip);
1117
pri=ntohl(bc[ip].value);
1134
res=SIEVE_RUN_ERROR;
1138
ip = unwrap_string(bc, ip, &message, NULL);
1140
res = do_notify(notify_list, id, method, options,
1148
* i really have no idea what the count matchtype should do here.
1149
* the sanest thing would be to use 1.
1150
* however that would require passing on the match type to do_notify.
1154
comparator_t *comp = NULL;
1156
const char *pattern;
1159
const char *priority = NULL;
1160
void *comprock = NULL;
1166
pri=ntohl(bc[ip].value);
1183
res=SIEVE_RUN_ERROR;
1186
if(res == SIEVE_RUN_ERROR)
1189
comparator =ntohl( bc[ip].value);
1192
if (comparator == B_ANY)
1194
ip++;/* skip placeholder this has no comparator function */
1197
int x= ntohl(bc[ip].value);
1200
comp=lookup_comp(B_ASCIICASEMAP,comparator,
1204
ip = unwrap_string(bc, ip, &pattern, NULL);
1206
if (comparator == B_REGEX)
1208
char errmsg[1024]; /* Basically unused */
1210
reg=bc_compile_regex(pattern,
1211
REG_EXTENDED | REG_NOSUB | REG_ICASE,
1212
errmsg, sizeof(errmsg));
1214
res = SIEVE_RUN_ERROR;
1216
res = do_denotify(notify_list, comp, reg,
1217
comprock, priority);
1221
res = do_denotify(notify_list, comp, pattern,
1222
comprock, priority);
1230
char *fromaddr = NULL; /* relative to message we send */
1231
char *toaddr = NULL; /* relative to message we send */
1232
const char *handle = NULL;
1233
const char *message = NULL;
1241
x=ntohl( bc[ip].len);
1243
respond=shouldRespond(m, i, x, bc, ip+2,
1244
&fromaddr, &toaddr);
1246
ip=(ntohl(bc[ip+1].value)/4);
1247
if (respond==SIEVE_OK)
1249
ip = unwrap_string(bc, ip, &data, NULL);
1253
/* we have to generate a subject */
1255
strlcpy(buf, "subject", sizeof(buf));
1256
if (i->getheader(m, buf, &s) != SIEVE_OK ||
1258
strlcpy(subject, "Automated reply", sizeof(subject));
1260
/* s[0] contains the original subject */
1261
const char *origsubj = s[0];
1263
snprintf(subject, sizeof(subject), "Auto: %s", origsubj);
1266
/* user specified subject */
1267
strlcpy(subject, data, sizeof(subject));
1270
ip = unwrap_string(bc, ip, &message, NULL);
1272
days = ntohl(bc[ip].value);
1273
mime = ntohl(bc[ip+1].value);
1277
if (version >= 0x05) {
1278
ip = unwrap_string(bc, ip, &data, NULL);
1281
/* user specified from address */
1283
fromaddr = xstrdup(data);
1286
ip = unwrap_string(bc, ip, &data, NULL);
1289
/* user specified handle */
1294
res = do_vacation(actions, toaddr, fromaddr, xstrdup(subject),
1295
message, days, mime, handle);
1297
if (res == SIEVE_RUN_ERROR)
1298
*errmsg = "Vacation can not be used with Reject or Vacation";
1299
} else if (respond == SIEVE_DONE) {
1300
/* skip subject and message */
1302
ip = unwrap_string(bc, ip, &data, NULL);
1303
ip = unwrap_string(bc, ip, &data, NULL);
1305
ip+=2;/*skip days and mime flag*/
1307
if (version >= 0x05) {
1308
/* skip from and handle */
1309
ip = unwrap_string(bc, ip, &data, NULL);
1310
ip = unwrap_string(bc, ip, &data, NULL);
1313
res = SIEVE_RUN_ERROR; /* something is bad */
1323
ip= ntohl(bc[ip+1].jump);
1326
case B_INCLUDE:/*17*/
1328
int isglobal = (ntohl(bc[ip+1].value) == B_GLOBAL);
1331
ip = unwrap_string(bc, ip+2, &data, NULL);
1333
res = i->getinclude(sc, data, isglobal, fpath, sizeof(fpath));
1334
if (res != SIEVE_OK)
1335
*errmsg = "Include can not find script";
1338
res = sieve_script_load(fpath, &exe);
1339
if (res != SIEVE_OK)
1340
*errmsg = "Include can not load script";
1344
res = sieve_eval_bc(exe, 1, i, body_cache,
1345
sc, m, imapflags, actions,
1346
notify_list, errmsg);
1351
case B_RETURN:/*18*/
1359
if(errmsg) *errmsg = "Invalid sieve bytecode";
1363
if (res) /* we've either encountered an error or a stop */
1368
bc_cur->is_executing = 0;