#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "sieve_interface.h"
#include "interp.h"
#include "message.h"
#include "script.h"
#include "bytecode.h"
#include "charset.h"
#include "hash.h"
#include "xmalloc.h"
#include "xstrlcpy.h"
#include "xstrlcat.h"
#include <string.h>
#include <ctype.h>
int unwrap_string(bytecode_input_t *bc, int pos, const char **str, int *len)
{
int local_len = ntohl(bc[pos].value);
pos++;
if(local_len == -1) {
*str = NULL;
} else {
*str = (const char *)&bc[pos].str;
pos += ((ROUNDUP(local_len+1))/sizeof(bytecode_input_t));
}
if(len) *len = local_len;
return pos;
}
const char ** bc_makeArray(bytecode_input_t *bc, int *pos)
{
int i;
const char** array;
int len = ntohl(bc[*pos].value);
(*pos)+=2;
array=(const char **)xmalloc((len+1) * sizeof(char *));
for (i=0; i<len; i++) {
*pos = unwrap_string(bc, *pos, &(array[i]), NULL);
}
array[i] = NULL;
return array;
}
regex_t * bc_compile_regex(const char *s, int ctag,
char *errmsg, size_t errsiz)
{
int ret;
regex_t *reg = (regex_t *) xmalloc(sizeof(regex_t));
if ( (ret=regcomp(reg, s, ctag)) != 0)
{
(void) regerror(ret, reg, errmsg, errsiz);
free(reg);
return NULL;
}
return reg;
}
static int sysaddr(const char *addr)
{
if (!strncasecmp(addr, "MAILER-DAEMON", 13))
return 1;
if (!strncasecmp(addr, "LISTSERV", 8))
return 1;
if (!strncasecmp(addr, "majordomo", 9))
return 1;
if (strstr(addr, "-request@"))
return 1;
if (!strncmp(addr, "owner-", 6))
return 1;
return 0;
}
static char* look_for_me(char *myaddr, int numaddresses,
bytecode_input_t *bc, int i, const char **body)
{
char *found = NULL;
int l;
int curra,x ;
for (l = 0; body[l] != NULL && !found; l++) {
void *data = NULL, *marker = NULL;
char *addr;
parse_address(body[l], &data, &marker);
while (!found &&
((addr = get_address(ADDRESS_ALL,&data, &marker, 1))!= NULL)) {
if (!strcasecmp(addr, myaddr)) {
found = xstrdup(myaddr);
break;
}
curra=i;
for(x=0; x<numaddresses; x++)
{
void *altdata = NULL, *altmarker = NULL;
char *altaddr;
const char *str;
curra = unwrap_string(bc, curra, &str, NULL);
parse_address(str, &altdata, &altmarker);
altaddr = get_address(ADDRESS_ALL, &altdata, &altmarker, 1);
if (!strcasecmp(addr,altaddr)) {
found=xstrdup(str);
break;
}
free_address(&altdata, &altmarker);
}
}
free_address(&data, &marker);
}
return found;
}
static char *list_fields[] = {
"list-id",
"list-help",
"list-subscribe",
"list-unsubscribe",
"list-post",
"list-owner",
"list-archive",
NULL
};
int shouldRespond(void * m, sieve_interp_t *interp,
int numaddresses, bytecode_input_t* bc,
int i, char **from, char **to)
{
const char **body;
char buf[128];
char *myaddr = NULL;
int l = SIEVE_OK, j;
void *data = NULL, *marker = NULL;
char *tmp;
int curra, x;
char *found=NULL;
char *reply_to=NULL;
for (j = 0; list_fields[j]; j++) {
strcpy(buf, list_fields[j]);
if (interp->getheader(m, buf, &body) == SIEVE_OK) {
l = SIEVE_DONE;
break;
}
}
strcpy(buf, "auto-submitted");
if (interp->getheader(m, buf, &body) == SIEVE_OK) {
while (*body[0] && isspace((int) *body[0])) body[0]++;
if (strcasecmp(body[0], "no")) l = SIEVE_DONE;
}
strcpy(buf, "precedence");
if (interp->getheader(m, buf, &body) == SIEVE_OK) {
while (*body[0] && isspace((int) *body[0])) body[0]++;
if (!strcasecmp(body[0], "junk") ||
!strcasecmp(body[0], "bulk") ||
!strcasecmp(body[0], "list"))
l = SIEVE_DONE;
}
if (l == SIEVE_OK) {
strcpy(buf, "to");
l = interp->getenvelope(m, buf, &body);
if (body[0]) {
parse_address(body[0], &data, &marker);
tmp = get_address(ADDRESS_ALL, &data, &marker, 1);
myaddr = (tmp != NULL) ? xstrdup(tmp) : NULL;
free_address(&data, &marker);
}
}
if (l == SIEVE_OK) {
strcpy(buf, "from");
l = interp->getenvelope(m, buf, &body);
}
if (l == SIEVE_OK && body[0]) {
parse_address(body[0], &data, &marker);
tmp = get_address(ADDRESS_ALL, &data, &marker, 1);
reply_to = (tmp != NULL) ? xstrdup(tmp) : NULL;
free_address(&data, &marker);
if (reply_to == NULL) {
l = SIEVE_DONE;
}
if (l == SIEVE_OK && !strcmp(myaddr, reply_to)) {
l = SIEVE_DONE;
}
if (l == SIEVE_OK)
{
curra=i;
for(x=0; x<numaddresses; x++) {
const char *address;
curra = unwrap_string(bc, curra, &address, NULL);
if (!strcmp(address, reply_to))
l=SIEVE_DONE;
}
}
if (l == SIEVE_OK && sysaddr(reply_to)) {
l = SIEVE_DONE;
}
}
if (l == SIEVE_OK) {
if (strcpy(buf, "to"),
interp->getheader(m, buf, &body) == SIEVE_OK)
found = look_for_me(myaddr, numaddresses ,bc, i, body);
if (!found && (strcpy(buf, "cc"),
(interp->getheader(m, buf, &body) == SIEVE_OK)))
found = look_for_me(myaddr, numaddresses, bc, i, body);
if (!found && (strcpy(buf, "bcc"),
(interp->getheader(m, buf, &body) == SIEVE_OK)))
found = look_for_me(myaddr, numaddresses, bc, i, body);
if (!found && strcpy(buf, "resent-to"),
interp->getheader(m, buf, &body) == SIEVE_OK)
found = look_for_me(myaddr, numaddresses ,bc, i, body);
if (!found && (strcpy(buf, "resent-cc"),
(interp->getheader(m, buf, &body) == SIEVE_OK)))
found = look_for_me(myaddr, numaddresses, bc, i, body);
if (!found && (strcpy(buf, "resent-bcc"),
(interp->getheader(m, buf, &body) == SIEVE_OK)))
found = look_for_me(myaddr, numaddresses, bc, i, body);
if (!found)
l = SIEVE_DONE;
}
if (myaddr) free(myaddr);
*from=found;
*to=reply_to;
return l;
}
int eval_bc_test(sieve_interp_t *interp,
struct hash_table *body_cache, void* m,
bytecode_input_t * bc, int * ip)
{
int res=0;
int i=*ip;
int x,y,z;
int list_len;
int list_end;
int address=0;
comparator_t * comp=NULL;
void * comprock=NULL;
int op= ntohl(bc[i].op);
switch(op)
{
case BC_FALSE:
res=0; i++; break;
case BC_TRUE:
res=1; i++; break;
case BC_NOT:
i+=1;
res = eval_bc_test(interp, body_cache, m, bc, &i);
if(res >= 0) res = !res;
break;
case BC_EXISTS:
{
int headersi=i+1;
const char** val;
int currh;
res=1;
list_len=ntohl(bc[headersi].len);
list_end=ntohl(bc[headersi+1].value)/4;
currh=headersi+2;
for(x=0; x<list_len && res; x++)
{
const char *str;
currh = unwrap_string(bc, currh, &str, NULL);
if(interp->getheader(m,str, &val) != SIEVE_OK)
res = 0;
}
i=list_end;
break;
}
case BC_SIZE:
{
int s;
int sizevar=ntohl(bc[i+1].value);
int x=ntohl(bc[i+2].value);
if (interp->getsize(m, &s) != SIEVE_OK)
break;
if (sizevar ==B_OVER) {
res= s > x;
} else {
res= s < x;
}
i+=3;
break;
}
case BC_ANYOF:
res = 0;
list_len=ntohl(bc[i+1].len);
list_end=ntohl(bc[i+2].len)/4;
i+=3;
for (x=0; x<list_len && !res; x++) {
int tmp;
tmp = eval_bc_test(interp,body_cache,m,bc,&i);
if(tmp < 0) {
res = tmp;
break;
}
res = res || tmp;
}
i = list_end;
break;
case BC_ALLOF:
res = 1;
list_len=ntohl(bc[i+1].len);
list_end=ntohl(bc[i+2].len)/4;
i+=3;
for (x=0; x<list_len && res; x++) {
int tmp;
tmp = eval_bc_test(interp,body_cache,m,bc,&i);
if(tmp < 0) {
res = tmp;
break;
}
res = res && tmp;
}
i = list_end;
break;
case BC_ADDRESS:
address=1;
case BC_ENVELOPE:
{
const char ** val;
void * data=NULL;
void * marker=NULL;
char * addr;
int addrpart=ADDRESS_ALL;
int headersi=i+5;
int datai=(ntohl(bc[headersi+1].value)/4);
int numheaders=ntohl(bc[headersi].len);
int numdata=ntohl(bc[datai].len);
int currh, currd;
int match=ntohl(bc[i+1].value);
int relation=ntohl(bc[i+2].value);
int comparator=ntohl(bc[i+3].value);
int apart=ntohl(bc[i+4].value);
int count=0;
char scount[3];
int isReg = (match==B_REGEX);
int ctag = 0;
regex_t *reg;
char errbuf[100];
if (isReg)
{
if (comparator== B_ASCIICASEMAP)
{
ctag = REG_EXTENDED | REG_NOSUB | REG_ICASE;
}
else
{
ctag = REG_EXTENDED | REG_NOSUB;
}
}
comp = lookup_comp(comparator, match, relation, &comprock);
if(!comp) {
res = SIEVE_RUN_ERROR;
break;
}
switch(apart)
{
case B_ALL:
addrpart = ADDRESS_ALL; break;
case B_LOCALPART:
addrpart = ADDRESS_LOCALPART; break;
case B_DOMAIN:
addrpart = ADDRESS_DOMAIN; break;
case B_USER:
addrpart = ADDRESS_USER; break;
case B_DETAIL:
addrpart = ADDRESS_DETAIL; break;
default:
res = SIEVE_RUN_ERROR;
}
if(res == SIEVE_RUN_ERROR) break;
currh=headersi+2;
#if VERBOSE
printf("about to process %d headers\n", numheaders);
#endif
for (x=0; x<numheaders && !res; x++)
{
const char *this_header;
currh = unwrap_string(bc, currh, &this_header, NULL);
if(address) {
if(interp->getheader(m, this_header, &val) != SIEVE_OK)
continue;
#if VERBOSE
printf(" [%d] header %s is %s\n", x, this_header, val[0]);
#endif
} else {
if(interp->getenvelope(m, this_header, &val) != SIEVE_OK)
continue;
}
for (y=0; val[y]!=NULL && !res; y++) {
#if VERBOSE
printf("about to parse %s\n", val[y]);
#endif
if (parse_address(val[y], &data, &marker)!=SIEVE_OK)
return 0;
while (!res &&
(addr = get_address(addrpart, &data, &marker, 0))) {
#if VERBOSE
printf("working addr %s\n", (addr ? addr : "[nil]"));
#endif
if (match == B_COUNT) {
count++;
} else {
currd=datai+2;
for (z=0; z<numdata && !res; z++)
{
const char *data_val;
currd = unwrap_string(bc, currd, &data_val, NULL);
if (isReg) {
reg = bc_compile_regex(data_val, ctag,
errbuf, sizeof(errbuf));
if (!reg) {
res=-1;
goto alldone;
}
res |= comp(val[y], strlen(val[y]),
(const char *)reg, comprock);
free(reg);
} else {
#if VERBOSE
printf("%s compared to %s(from script)\n",
addr, data_val);
#endif
res |= comp(addr, strlen(addr),
data_val, comprock);
}
}
}
}
free_address(&data, &marker);
}
#if VERBOSE
printf("end of loop, res is %d, x is %d (%d)\n", res, x, numheaders);
#endif
}
if (match == B_COUNT)
{
sprintf(scount, "%u", count);
currd=datai+2;
for (z=0; z<numdata && !res; z++)
{
const char *data_val;
currd = unwrap_string(bc, currd, &data_val, NULL);
res |= comp(scount, strlen(scount), data_val, comprock);
}
}
i=(ntohl(bc[datai+1].value)/4);
break;
}
case BC_HEADER:
{
const char** val;
int headersi=i+4;
int datai=(ntohl(bc[headersi+1].value)/4);
int numheaders=ntohl(bc[headersi].len);
int numdata=ntohl(bc[datai].len);
int currh, currd;
int match=ntohl(bc[i+1].value);
int relation=ntohl(bc[i+2].value);
int comparator=ntohl(bc[i+3].value);
int count=0;
char scount[3];
int isReg = (match==B_REGEX);
int ctag = 0;
regex_t *reg;
char errbuf[100];
if (isReg)
{
if (comparator== B_ASCIICASEMAP)
{
ctag= REG_EXTENDED | REG_NOSUB | REG_ICASE;
}
else
{
ctag= REG_EXTENDED | REG_NOSUB;
}
}
comp=lookup_comp(comparator, match, relation, &comprock);
if(!comp) {
res = SIEVE_RUN_ERROR;
break;
}
currh=headersi+2;
for(x=0; x<numheaders && !res; x++)
{
const char *this_header;
currh = unwrap_string(bc, currh, &this_header, NULL);
if(interp->getheader(m, this_header, &val) != SIEVE_OK) {
continue;
}
#if VERBOSE
printf ("val %s %s %s\n", val[0], val[1], val[2]);
#endif
for (y=0; val[y]!=NULL && !res; y++)
{
if (match == B_COUNT) {
count++;
} else {
currd=datai+2;
for (z=0; z<numdata && !res; z++)
{
const char *data_val;
currd = unwrap_string(bc, currd, &data_val, NULL);
if (isReg) {
reg= bc_compile_regex(data_val, ctag, errbuf,
sizeof(errbuf));
if (!reg)
{
res=-1;
goto alldone;
}
res |= comp(val[y], strlen(val[y]),
(const char *)reg, comprock);
free(reg);
} else {
res |= comp(val[y], strlen(val[y]),
data_val, comprock);
}
}
}
}
}
if (match == B_COUNT )
{
sprintf(scount, "%u", count);
currd=datai+2;
for (z=0; z<numdata && !res; z++)
{
const char *data_val;
currd = unwrap_string(bc, currd, &data_val, NULL);
#if VERBOSE
printf("%d, %s \n", count, data_val);
#endif
res |= comp(scount, strlen(scount), data_val, comprock);
}
}
i=(ntohl(bc[datai+1].value)/4);
break;
}
case BC_BODY:
{
sieve_bodypart_t ** val;
const char **content_types = NULL;
int typesi=i+6;
int datai=(ntohl(bc[typesi+1].value)/4);
int numdata=ntohl(bc[datai].len);
int currd;
int match=ntohl(bc[i+1].value);
int relation=ntohl(bc[i+2].value);
int comparator=ntohl(bc[i+3].value);
int transform=ntohl(bc[i+4].value);
int offset=ntohl(bc[i+5].value);
int count=0;
char scount[3];
int isReg = (match==B_REGEX);
int ctag = 0;
regex_t *reg;
char errbuf[100];
if (isReg)
{
if (comparator== B_ASCIICASEMAP)
{
ctag = REG_EXTENDED | REG_NOSUB | REG_ICASE;
}
else
{
ctag = REG_EXTENDED | REG_NOSUB;
}
}
comp = lookup_comp(comparator, match, relation, &comprock);
if(!comp) {
res = SIEVE_RUN_ERROR;
break;
}
content_types = bc_makeArray(bc, &typesi);
if(interp->getbody(m, content_types, &val) != SIEVE_OK) {
res = SIEVE_RUN_ERROR;
break;
}
free(content_types);
for (y=0; val && val[y]!=NULL && !res; y++) {
if (match == B_COUNT) {
count++;
} else {
const char *content = val[y]->content;
int size = val[y]->size;
if (transform != B_RAW) {
int encoding;
if (!val[y]->encoding)
encoding = ENCODING_NONE;
else if (!strcmp(val[y]->encoding, "BASE64"))
encoding = ENCODING_BASE64;
else if (!strcmp(val[y]->encoding, "QUOTED-PRINTABLE"))
encoding = ENCODING_QP;
else
encoding = ENCODING_NONE;
if (encoding != ENCODING_NONE) {
content = hash_lookup(val[y]->section, body_cache);
if (content) {
size = strlen(content);
}
else {
char *decbuf = NULL;
content = charset_decode_mimebody(val[y]->content,
val[y]->size,
encoding, &decbuf,
0, &size);
hash_insert(val[y]->section, (void *) content,
body_cache);
}
}
}
currd=datai+2;
for (z=0; z<numdata && !res; z++)
{
const char *data_val;
currd = unwrap_string(bc, currd, &data_val, NULL);
if (isReg) {
reg = bc_compile_regex(data_val, ctag,
errbuf, sizeof(errbuf));
if (!reg) {
res=-1;
goto alldone;
}
res |= comp(content, size, (const char *)reg, comprock);
free(reg);
} else {
res |= comp(content, size, data_val, comprock);
}
}
}
free(val[y]);
}
if (val) free(val);
if (match == B_COUNT)
{
sprintf(scount, "%u", count);
currd=datai+2;
for (z=0; z<numdata && !res; z++)
{
const char *data_val;
currd = unwrap_string(bc, currd, &data_val, NULL);
res |= comp(scount, strlen(scount), data_val, comprock);
}
}
i=(ntohl(bc[datai+1].value)/4);
break;
}
default:
#if VERBOSE
printf("WERT, can't evaluate if statement. %d is not a valid command",
op);
#endif
return SIEVE_RUN_ERROR;
}
alldone:
*ip=i;
return res;
}
int sieve_eval_bc(sieve_execute_t *exe, int is_incl, sieve_interp_t *i,
struct hash_table *body_cache, void *sc, void *m,
sieve_imapflags_t * imapflags, action_list_t *actions,
notify_list_t *notify_list, const char **errmsg)
{
const char *data;
int res=0;
int op;
int version;
sieve_bytecode_t *bc_cur = exe->bc_cur;
bytecode_input_t *bc = (bytecode_input_t *) bc_cur->data;
int ip = 0, ip_max = (bc_cur->len/sizeof(bytecode_input_t));
if (bc_cur->is_executing) {
*errmsg = "Recursive Include";
return SIEVE_RUN_ERROR;
}
bc_cur->is_executing = 1;
if(!bc) return SIEVE_FAIL;
if(bc_cur->len < (BYTECODE_MAGIC_LEN + 2*sizeof(bytecode_input_t)))
return SIEVE_FAIL;
if(memcmp(bc, BYTECODE_MAGIC, BYTECODE_MAGIC_LEN)) {
*errmsg = "Not a bytecode file";
return SIEVE_FAIL;
}
ip = BYTECODE_MAGIC_LEN / sizeof(bytecode_input_t);
version= ntohl(bc[ip].op);
if(version == ntohl(1)) {
if(errmsg) {
*errmsg =
"Incorrect Bytecode Version, please recompile (use sievec)";
}
return SIEVE_FAIL;
}
if((version < BYTECODE_MIN_VERSION) || (version > BYTECODE_VERSION)) {
if(errmsg) {
*errmsg =
"Incorrect Bytecode Version, please recompile (use sievec)";
}
return SIEVE_FAIL;
}
#if VERBOSE
printf("version number %d\n",version);
#endif
for(ip++; ip<ip_max; ) {
int copy = 0;
op=ntohl(bc[ip].op);
switch(op) {
case B_STOP:
res=1;
break;
case B_KEEP:
res = do_keep(actions, imapflags);
if (res == SIEVE_RUN_ERROR)
*errmsg = "Keep can not be used with Reject";
ip++;
break;
case B_DISCARD:
res=do_discard(actions);
ip++;
break;
case B_REJECT:
ip = unwrap_string(bc, ip+1, &data, NULL);
res = do_reject(actions, data);
if (res == SIEVE_RUN_ERROR)
*errmsg = "Reject can not be used with any other action";
break;
case B_FILEINTO:
copy = ntohl(bc[ip+1].value);
ip+=1;
case B_FILEINTO_ORIG:
{
ip = unwrap_string(bc, ip+1, &data, NULL);
res = do_fileinto(actions, data, !copy, imapflags);
if (res == SIEVE_RUN_ERROR)
*errmsg = "Fileinto can not be used with Reject";
break;
}
case B_REDIRECT:
copy = ntohl(bc[ip+1].value);
ip+=1;
case B_REDIRECT_ORIG:
{
ip = unwrap_string(bc, ip+1, &data, NULL);
res = do_redirect(actions, data, !copy);
if (res == SIEVE_RUN_ERROR)
*errmsg = "Redirect can not be used with Reject";
break;
}
case B_IF:
{
int testend=ntohl(bc[ip+1].value);
int result;
ip+=2;
result=eval_bc_test(i, body_cache, m, bc, &ip);
if (result<0) {
*errmsg = "Invalid test";
return SIEVE_FAIL;
} else if (result) {
testend+=2;
}
ip=testend;
break;
}
case B_MARK:
res = do_mark(actions);
ip++;
break;
case B_UNMARK:
res = do_unmark(actions);
ip++;
break;
case B_ADDFLAG:
{
int x;
int list_len=ntohl(bc[ip+1].len);
ip+=3;
for (x=0; x<list_len; x++) {
ip = unwrap_string(bc, ip, &data, NULL);
res = do_addflag(actions, data);
if (res == SIEVE_RUN_ERROR)
*errmsg = "addflag can not be used with Reject";
}
break;
}
case B_SETFLAG:
{
int x;
int list_len=ntohl(bc[ip+1].len);
ip+=3;
ip = unwrap_string(bc, ip, &data, NULL);
res = do_setflag(actions, data);
if (res == SIEVE_RUN_ERROR) {
*errmsg = "setflag can not be used with Reject";
} else {
for (x=1; x<list_len; x++) {
ip = unwrap_string(bc, ip, &data, NULL);
res = do_addflag(actions, data);
if (res == SIEVE_RUN_ERROR)
*errmsg = "setflag can not be used with Reject";
}
}
break;
}
case B_REMOVEFLAG:
{
int x;
int list_len=ntohl(bc[ip+1].len);
ip+=3;
for (x=0; x<list_len; x++) {
ip = unwrap_string(bc, ip, &data, NULL);
res = do_removeflag(actions, data);
if (res == SIEVE_RUN_ERROR)
*errmsg = "removeflag can not be used with Reject";
}
break;
}
case B_NOTIFY:
{
const char * id;
const char * method;
const char **options = NULL;
const char *priority = NULL;
const char * message;
int pri;
ip++;
ip = unwrap_string(bc, ip, &method, NULL);
ip = unwrap_string(bc, ip, &id, NULL);
options=bc_makeArray(bc, &ip);
pri=ntohl(bc[ip].value);
ip++;
switch (pri)
{
case B_LOW:
priority="low";
case B_NORMAL:
priority="normal";
break;
case B_HIGH:
priority="high";
break;
case B_ANY:
priority="any";
break;
default:
res=SIEVE_RUN_ERROR;
}
ip = unwrap_string(bc, ip, &message, NULL);
res = do_notify(notify_list, id, method, options,
priority, message);
break;
}
case B_DENOTIFY:
{
comparator_t *comp = NULL;
const char *pattern;
regex_t *reg;
const char *priority = NULL;
void *comprock = NULL;
int comparator;
int pri;
ip++;
pri=ntohl(bc[ip].value);
ip++;
switch (pri)
{
case B_LOW:
priority="low";
case B_NORMAL:
priority="normal";
break;
case B_HIGH:
priority="high";
break;
case B_ANY:
priority="any";
break;
default:
res=SIEVE_RUN_ERROR;
}
if(res == SIEVE_RUN_ERROR)
break;
comparator =ntohl( bc[ip].value);
ip++;
if (comparator == B_ANY)
{
ip++;
comp=NULL;
} else {
int x= ntohl(bc[ip].value);
ip++;
comp=lookup_comp(B_ASCIICASEMAP,comparator,
x, &comprock);
}
ip = unwrap_string(bc, ip, &pattern, NULL);
if (comparator == B_REGEX)
{
char errmsg[1024];
reg=bc_compile_regex(pattern,
REG_EXTENDED | REG_NOSUB | REG_ICASE,
errmsg, sizeof(errmsg));
if (!reg) {
res = SIEVE_RUN_ERROR;
} else {
res = do_denotify(notify_list, comp, reg,
comprock, priority);
free(reg);
}
} else {
res = do_denotify(notify_list, comp, pattern,
comprock, priority);
}
break;
}
case B_VACATION:
{
int respond;
char *fromaddr = NULL;
char *toaddr = NULL;
char *handle = NULL;
const char *message = NULL;
int days, mime;
char buf[128];
char subject[1024];
int x;
ip++;
x=ntohl( bc[ip].len);
respond=shouldRespond(m, i, x, bc, ip+2,
&fromaddr, &toaddr);
ip=(ntohl(bc[ip+1].value)/4);
if (respond==SIEVE_OK)
{
ip = unwrap_string(bc, ip, &data, NULL);
if (!data)
{
const char **s;
strlcpy(buf, "subject", sizeof(buf));
if (i->getheader(m, buf, &s) != SIEVE_OK ||
s[0] == NULL) {
strlcpy(subject, "Automated reply", sizeof(subject));
} else {
const char *origsubj = s[0];
snprintf(subject, sizeof(subject), "Auto: %s", origsubj);
}
} else {
strlcpy(subject, data, sizeof(subject));
}
ip = unwrap_string(bc, ip, &message, NULL);
days = ntohl(bc[ip].value);
mime = ntohl(bc[ip+1].value);
ip+=2;
if (version >= 0x05) {
ip = unwrap_string(bc, ip, &data, NULL);
if (data) {
free(fromaddr);
fromaddr = xstrdup(data);
}
ip = unwrap_string(bc, ip, &data, NULL);
if (data) {
handle = (char *) data;
}
}
res = do_vacation(actions, toaddr, fromaddr, xstrdup(subject),
message, days, mime, handle);
if (res == SIEVE_RUN_ERROR)
*errmsg = "Vacation can not be used with Reject or Vacation";
} else if (respond == SIEVE_DONE) {
ip = unwrap_string(bc, ip, &data, NULL);
ip = unwrap_string(bc, ip, &data, NULL);
ip+=2;
if (version >= 0x05) {
ip = unwrap_string(bc, ip, &data, NULL);
ip = unwrap_string(bc, ip, &data, NULL);
}
} else {
res = SIEVE_RUN_ERROR;
}
break;
}
case B_NULL:
ip++;
break;
case B_JUMP:
ip= ntohl(bc[ip+1].jump);
break;
case B_INCLUDE:
{
int isglobal = (ntohl(bc[ip+1].value) == B_GLOBAL);
char fpath[4096];
ip = unwrap_string(bc, ip+2, &data, NULL);
res = i->getinclude(sc, data, isglobal, fpath, sizeof(fpath));
if (res != SIEVE_OK)
*errmsg = "Include can not find script";
if (!res) {
res = sieve_script_load(fpath, &exe);
if (res != SIEVE_OK)
*errmsg = "Include can not load script";
}
if (!res)
res = sieve_eval_bc(exe, 1, i, body_cache,
sc, m, imapflags, actions,
notify_list, errmsg);
break;
}
case B_RETURN:
if (is_incl)
goto done;
else
res=1;
break;
default:
if(errmsg) *errmsg = "Invalid sieve bytecode";
return SIEVE_FAIL;
}
if (res)
break;
}
done:
bc_cur->is_executing = 0;
return res;
}