Пример #1
0
/* look for myaddr and myaddrs in the body of a header - return the match */
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 ;

    /* loop through each TO header */
    for (l = 0; body[l] != NULL && !found; l++) {
	struct address_itr ai;
	const struct address *a;

	address_itr_init(&ai, body[l]);

	/* loop through each address in the header */
	while (!found && (a = address_itr_next(&ai)) != NULL) {
	    char *addr = address_get_all(a, 0);
	    if (!addr) addr = xstrdup("");

	    if (!strcasecmp(addr, myaddr)) {
		free(addr);
		found = xstrdup(myaddr);
		break;
	    }

	    curra=i;

	    for(x=0; x<numaddresses; x++)
	    {
		char *altaddr;
		const char *str;

		curra = unwrap_string(bc, curra, &str, NULL);
		
		/* is this address one of my addresses? */
		altaddr = address_canonicalise(str);

		if (!strcasecmp(addr,altaddr)) {
		    free(altaddr);
		    found=xstrdup(str);
		    break;
		}
		free(altaddr);
	    }
	    free(addr);
	}
	address_itr_fini(&ai);
    }

    return found;
}
Пример #2
0
static int write_list(int list_len, int i, bytecode_input_t * d)
{
    int x;
    i++;
    for (x=0; x<list_len; x++)
    {
	const char *data;
	int len;
	
	i = unwrap_string(d, i, &data, &len);
	
	printf("{%d}%s\n", len, data);
    }
    return i;
}
Пример #3
0
/* The entrypoint for bytecode evaluation */
int sieve_eval_bc(sieve_execute_t *exe, int is_incl, sieve_interp_t *i,
		  void *sc, void *m,
		  strarray_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;
    
    /* Check that we
     * a) have bytecode
     * b) it is atleast long enough for the magic number, the version
     *    and one opcode */
    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);

    /* this is because there was a time where integers were not network byte
       order.  all the scripts written then would have version 0x01 written
       in host byte order.*/

     if(version == (int)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:/*0*/
	    res=1;
	    break;

	case B_KEEP:/*1*/
	    res = do_keep(actions, imapflags);
	    if (res == SIEVE_RUN_ERROR)
		*errmsg = "Keep can not be used with Reject";
	    ip++;
	    break;

	case B_DISCARD:/*2*/
	    res=do_discard(actions);
	    ip++;
	    break;

	case B_REJECT:/*3*/
	    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:/*19*/
	    copy = ntohl(bc[ip+1].value);
	    ip+=1;

	    /* fall through */
	case B_FILEINTO_ORIG:/*4*/
	{
	    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:/*20*/
	    copy = ntohl(bc[ip+1].value);
	    ip+=1;

	    /* fall through */
	case B_REDIRECT_ORIG:/*5*/
	{
	    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:/*6*/
	{
	    int testend=ntohl(bc[ip+1].value);
	    int result;
	   
	    ip+=2;
	    result=eval_bc_test(i, m, bc, &ip);
	    
	    if (result<0) {
		*errmsg = "Invalid test";
		return SIEVE_FAIL;
	    } else if (result) {
	    	/*skip over jump instruction*/
		testend+=2;
	    }
	    ip=testend;
	    
	    break;
	}

	case B_MARK:/*8*/
	    res = do_mark(actions);
	    ip++;
	    break;

	case B_UNMARK:/*9*/
	    res = do_unmark(actions);
	    ip++;
	    break;

	case B_ADDFLAG:/*10*/ 
	{
	    int x;
	    int list_len=ntohl(bc[ip+1].len);

	    ip+=3; /* skip opcode, list_len, and list data len */

	    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; /* skip opcode, list_len, and list data len */

	    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; /* skip opcode, list_len, and list data len */

	    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++;

	    /* method */
	    ip = unwrap_string(bc, ip, &method, NULL);

	    /* id */
	    ip = unwrap_string(bc, ip, &id, NULL);

	    /*options*/
	    options=bc_makeArray(bc, &ip); 

	    /* priority */
	    pri=ntohl(bc[ip].value);
	    ip++;
	    
	    switch (pri)
	    {
	    case B_LOW:
		priority="low";
		break;
	    case B_NORMAL:
		priority="normal";
		break;
	    case B_HIGH: 
		priority="high";
		break; 
	    case B_ANY:
		priority="any";
		break;
	    default:
		res=SIEVE_RUN_ERROR;
	    }

	    /* message */
	    ip = unwrap_string(bc, ip, &message, NULL);
	  
	    res = do_notify(notify_list, id, method, options,
			    priority, message);

	    break;
	}
	case B_DENOTIFY:
	{
         /*
	  * i really have no idea what the count matchtype should do here.
	  * the sanest thing would be to use 1.
	  * however that would require passing on the match type to do_notify.
	  *  -jsmith2
	  */

	    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";		
		break;
	    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++;/* skip placeholder this has no comparator function */
		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]; /* Basically unused */
		
		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_ORIG:
	case B_VACATION:
	{
	    int respond;
	    char *fromaddr = NULL; /* relative to message we send */
	    char *toaddr = NULL; /* relative to message we send */
	    const char *handle = NULL;
	    const char *message = NULL;
	    int seconds, 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) 
		{
		    /* we have to generate a subject */
		    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 {
			/* s[0] contains the original subject */
			const char *origsubj = s[0];
			snprintf(subject, sizeof(subject), "Auto: %s", origsubj);
		    }
		} else {
		    /* user specified subject */
		    strlcpy(subject, data, sizeof(subject));
		}

		ip = unwrap_string(bc, ip, &message, NULL);

		seconds = ntohl(bc[ip].value);
		if (op == B_VACATION_ORIG) {
		    seconds *= DAY2SEC;
		}
		mime = ntohl(bc[ip+1].value);

		ip+=2;

		if (version >= 0x05) {
		    ip = unwrap_string(bc, ip, &data, NULL);

		    if (data) {
			/* user specified from address */
			free(fromaddr);
			fromaddr = xstrdup(data);
		    }

		    ip = unwrap_string(bc, ip, &data, NULL);

		    if (data) {
			/* user specified handle */
			handle = data;
		    }
		}

		res = do_vacation(actions, toaddr, fromaddr, xstrdup(subject),
				  message, seconds, mime, handle);

		if (res == SIEVE_RUN_ERROR)
		    *errmsg = "Vacation can not be used with Reject or Vacation";
	    } else if (respond == SIEVE_DONE) {
                /* skip subject and message */

		ip = unwrap_string(bc, ip, &data, NULL);
		ip = unwrap_string(bc, ip, &data, NULL);

		ip+=2;/*skip days and mime flag*/

		if (version >= 0x05) {
		    /* skip from and handle */
		    ip = unwrap_string(bc, ip, &data, NULL);
		    ip = unwrap_string(bc, ip, &data, NULL);
		}
	    } else {
		res = SIEVE_RUN_ERROR; /* something is bad */ 
	    }

	    break;
	}
	case B_NULL:/*15*/
	    ip++;
	    break;

	case B_JUMP:/*16*/
	    ip= ntohl(bc[ip+1].jump);
	    break;

	case B_INCLUDE:/*17*/
	{
	    int isglobal = (ntohl(bc[ip+1].value) & 63) == B_GLOBAL;
	    int once = ntohl(bc[ip+1].value) & 64 ? 1 : 0;
	    int isoptional = ntohl(bc[ip+1].value) & 128 ? 1 : 0;
	    char fpath[4096];

	    ip = unwrap_string(bc, ip+2, &data, NULL);

	    res = i->getinclude(sc, data, isglobal, fpath, sizeof(fpath));
	    if (res != SIEVE_OK) {
		if (isoptional == 0)
		    *errmsg = "Include can not find script";
		else
		    res = SIEVE_OK;
	        break;
	    }
	    res = sieve_script_load(fpath, &exe);
	    if (res == SIEVE_SCRIPT_RELOADED) {
		if (once == 1) {
		    res = SIEVE_OK;
		    break;
		}
	    } else if (res != SIEVE_OK) { /* SIEVE_FAIL */
		if (isoptional == 0)
		    *errmsg = "Include can not load script";
		else
		    res = SIEVE_OK;
		break;
	    }

	    res = sieve_eval_bc(exe, 1, i,
				sc, m, imapflags, actions,
				notify_list, errmsg);
	    break;
	}

	case B_RETURN:/*18*/
	    if (is_incl)
		goto done;
	    else
		res=1;
	    break;

	default:
	    if(errmsg) *errmsg = "Invalid sieve bytecode";
	    return SIEVE_FAIL;
	}
      
	if (res) /* we've either encountered an error or a stop */
	    break;
    }

  done:
    bc_cur->is_executing = 0;

    return res;
}
Пример #4
0
/* Evaluate a bytecode test */
static int eval_bc_test(sieve_interp_t *interp, void* m,
			bytecode_input_t * bc, int * ip)
{
    int res=0; 
    int i=*ip;
    int x,y,z;/* loop variable */
    int list_len; /* for allof/anyof/exists */
    int list_end; /* for allof/anyof/exists */
    int address=0;/*to differentiate between address and envelope*/
    comparator_t * comp=NULL;
    void * comprock=NULL;
    int op= ntohl(bc[i].op);
    #define SCOUNT_SIZE 20
    char scount[SCOUNT_SIZE];

    switch(op)
    {
    case BC_FALSE:
	res=0; i++; break;

    case BC_TRUE:
	res=1; i++; break;

    case BC_NOT:/*2*/
	i+=1;
	res = eval_bc_test(interp, m, bc, &i);
	if(res >= 0) res = !res; /* Only invert in non-error case */
	break;

    case BC_EXISTS:/*3*/
    {
	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; /* adjust for short-circuit */
	break;
    }
    case BC_SIZE:/*4*/
    {
	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) {
	    /* over */
	    res= s > x;
	} else {
            /* under */
	    res= s < x;
	}
	i+=3;
	break;
    }
    case BC_ANYOF:/*5*/
	res = 0;
	list_len=ntohl(bc[i+1].len);
	list_end=ntohl(bc[i+2].len)/4;
	i+=3;

	/* need to process all of them, to ensure our instruction pointer stays
	 * in the right place */
	for (x=0; x<list_len && !res; x++) { 
	    int tmp;
	    tmp = eval_bc_test(interp, m, bc, &i);
	    if(tmp < 0) {
		res = tmp;
		break;
	    }
	    res = res || tmp;
	}

	i = list_end; /* handle short-circuting */

	break; 
    case BC_ALLOF:/*6*/ 
        res = 1;     
	list_len=ntohl(bc[i+1].len);
	list_end=ntohl(bc[i+2].len)/4;
	i+=3;

	/* return 1 unless you find one that isn't true, then return 0 */
	for (x=0; x<list_len && res; x++) {
	    int tmp;
	    tmp = eval_bc_test(interp, m, bc, &i);
	    if(tmp < 0) {
		res = tmp;
		break;
	    }
	    res = res && tmp; 
	}

	i = list_end; /* handle short-circuiting */
	
	break;
    case BC_ADDRESS:/*7*/
	address=1;
	/* fall through */
    case BC_ENVELOPE:/*8*/
    {
	const char ** val;
	struct address_itr ai;
	const struct address *a;
	char *addr;

 	int headersi=i+5;/* the i value for the begining of the headers */
	int datai=(ntohl(bc[headersi+1].value)/4);

	int numheaders=ntohl(bc[headersi].len);
	int numdata=ntohl(bc[datai].len);

	int currh, currd; /* current header, current data */

	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;
	int isReg = (match==B_REGEX);
	int ctag = 0;
	regex_t *reg;
	char errbuf[100]; /* Basically unused, as regexps are tested at compile */

	/* set up variables needed for compiling regex */
	if (isReg)
	{
	    if (comparator== B_ASCIICASEMAP)
	    {
		ctag = REG_EXTENDED | REG_NOSUB | REG_ICASE;
	    }
	    else
	    {
		ctag = REG_EXTENDED | REG_NOSUB;
	    }
	}

	/*find the correct comparator fcn*/
	comp = lookup_comp(comparator, match, relation, &comprock);

	if(!comp) {
	    res = SIEVE_RUN_ERROR;
	    break;
	}

	/*loop through all the headers*/
	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);
	    
	    /* Try the next string if we don't have this one */
	    if(address) {
		/* Header */
		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 {
		/* Envelope */
		if(interp->getenvelope(m, this_header, &val) != SIEVE_OK)
		    continue;
	    }
	
	    /*header exists, now to test it*/
	    /*search through all the headers that match*/
	    
	    for (y=0; val[y]!=NULL && !res; y++) {
		
#if VERBOSE
		printf("about to parse %s\n", val[y]);
#endif
		    
		address_itr_init(&ai, val[y]);

		while (!res && (a = address_itr_next(&ai)) != NULL) {
#if VERBOSE
		    printf("working addr %s\n", (addr ? addr : "[nil]"));
#endif
		    /*find the part of the address that we want*/
		    switch(apart)
		    {
		    case B_ALL:
			addr = address_get_all(a, /*canon_domain*/0);
			break;
		    case B_LOCALPART:
			addr = address_get_localpart(a);
			break;
		    case B_DOMAIN:
			addr = address_get_domain(a, /*canon_domain*/0);
			break;
		    case B_USER:
			addr = address_get_user(a);
			break;
		    case B_DETAIL:
			addr = address_get_detail(a);
			break;
		    default:
			/* this shouldn't happen with correct bytecode */
			res = SIEVE_RUN_ERROR;
			goto envelope_err;
		    }

		    if (!addr) addr = xstrdup("");

		    if (match == B_COUNT) {
			count++;
		    } else {
			/*search through all the data*/ 
			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) {
				    /* Oops */
				    free(addr);
				    res=-1;
				    goto alldone;
				}

				res |= comp(addr, strlen(addr),
					    (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);
			    }
			} /* For each data */
		    }
		    free(addr);
		} /* For each address */

		address_itr_fini(&ai);
	    }/* For each message header */
	    
#if VERBOSE
	    printf("end of loop, res is %d, x is %d (%d)\n", res, x, numheaders);
#endif	    
	} /* For each script header */
     
	if  (match == B_COUNT)
	{
	    snprintf(scount, SCOUNT_SIZE, "%u", count);
	    /* search through all the data */ 
	    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);
	    }
	}

	/* Update IP */
	i=(ntohl(bc[datai+1].value)/4);
	
envelope_err:
	break;
    }
    case BC_HEADER:/*9*/
    {
	const char** val;

	int headersi=i+4;/*the i value for the begining of hte headers*/
	int datai=(ntohl(bc[headersi+1].value)/4);

	int numheaders=ntohl(bc[headersi].len);
	int numdata=ntohl(bc[datai].len);

	int currh, currd; /*current header, current data*/

	int match=ntohl(bc[i+1].value);
	int relation=ntohl(bc[i+2].value);
	int comparator=ntohl(bc[i+3].value);
	int count=0;	
	int isReg = (match==B_REGEX);
	int ctag = 0;
	regex_t *reg;
	char errbuf[100]; /* Basically unused, regexps tested at compile */ 
	char *decoded_header;

	/* set up variables needed for compiling regex */
	if (isReg)
	{
	    if (comparator== B_ASCIICASEMAP)
	    {
		ctag= REG_EXTENDED | REG_NOSUB | REG_ICASE;
	    }
	    else
	    {
		ctag= REG_EXTENDED | REG_NOSUB;
	    }
     
	}
	
	/*find the correct comparator fcn*/
	comp=lookup_comp(comparator, match, relation, &comprock);

	if(!comp) {
	    res = SIEVE_RUN_ERROR;
	    break;
	}

	/*search through all the flags for the header*/
	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; /*this header does not exist, search the next*/ 
	    }
#if VERBOSE
	    printf ("val %s %s %s\n", val[0], val[1], val[2]);
#endif
	    
	    /* search through all the headers that match */
	    
	    for (y = 0; val[y] && !res; y++)
	    {
		if  (match == B_COUNT) {
		    count++;
		} else {
		    decoded_header = charset_parse_mimeheader(val[y]);
		    /*search through all the data*/ 
		    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)
			    {
				/* Oops */
				res=-1;
				goto alldone;
			    }
			    
			    res |= comp(decoded_header, strlen(decoded_header),
					(const char *)reg, comprock);
			    free(reg);
			} else {
			    res |= comp(decoded_header, strlen(decoded_header),
					data_val, comprock);
			}
		    }
		    free(decoded_header);
		}
	    }
	}
	
	if  (match == B_COUNT )
	{
	    snprintf(scount, SCOUNT_SIZE, "%u", count);
	    /*search through all the data*/ 
	    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);
	    }
	      
	}

	/* Update IP */
	i=(ntohl(bc[datai+1].value)/4);
	
	break;
    }
    case BC_BODY:/*10*/
    {
	sieve_bodypart_t ** val;
	const char **content_types = NULL;

	int typesi=i+6;/* the i value for the begining of the content-types */
 	int datai=(ntohl(bc[typesi+1].value)/4);

	int numdata=ntohl(bc[datai].len);

	int currd; /* current data */

	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);
	/* ntohl(bc[i+5].value) is the now unused 'offset' */
	int count=0;
	int isReg = (match==B_REGEX);
	int ctag = 0;
	regex_t *reg;
	char errbuf[100]; /* Basically unused, as regexps are tested at compile */

	/* set up variables needed for compiling regex */
	if (isReg)
	{
	    if (comparator== B_ASCIICASEMAP)
	    {
		ctag = REG_EXTENDED | REG_NOSUB | REG_ICASE;
	    }
	    else
	    {
		ctag = REG_EXTENDED | REG_NOSUB;
	    }
	}

	/*find the correct comparator fcn*/
	comp = lookup_comp(comparator, match, relation, &comprock);

	if(!comp) {
	    res = SIEVE_RUN_ERROR;
	    break;
	}
	
	if (transform == B_RAW) {
	    /* XXX - we never handled this properly, it has to search the
 	     * RAW message body, totally un-decoded, as a single string
 	     *
	     * ignore - or just search in the UTF-8.  I think the UTF-8 makes more sense 
             */
             /* break; */
	}

	/*find the part(s) of the body that we want*/
	content_types = bc_makeArray(bc, &typesi);
	if(interp->getbody(m, content_types, &val) != SIEVE_OK) {
	    res = SIEVE_RUN_ERROR;
	    break;
	}
	free(content_types);
	
	/* bodypart(s) exist, now to test them */
	    
	for (y = 0; val && val[y] && !res; y++) {

	    if (match == B_COUNT) {
		count++;
	    } else if (val[y]->decoded_body) {
		const char *content = val[y]->decoded_body;

		/* search through all the data */ 
		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) {
			    /* Oops */
			    res=-1;
			    goto alldone;
			}

			res |= comp(content, strlen(content), (const char *)reg, comprock);
			free(reg);
		    } else {
			res |= comp(content, strlen(content), data_val, comprock);
		    }
		} /* For each data */
	    }

	    /* free the bodypart */
	    free(val[y]);

	} /* For each body part */

	/* free the bodypart array */
	if (val) free(val);

	if  (match == B_COUNT)
	{
	    snprintf(scount, SCOUNT_SIZE, "%u", count);
	    /* search through all the data */ 
	    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);
	    }
	}

	/* Update IP */
	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;
}
Пример #5
0
/* Determine if we should respond to a vacation message */
static 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;
    int curra, x;
    char *found = NULL;
    char *reply_to = NULL;
  
    /* Implementations SHOULD NOT respond to any message that contains a
       "List-Id" [RFC2919], "List-Help", "List-Subscribe", "List-
       Unsubscribe", "List-Post", "List-Owner" or "List-Archive" [RFC2369]
       header field. */
    for (j = 0; list_fields[j]; j++) {
	strcpy(buf, list_fields[j]);
	if (interp->getheader(m, buf, &body) == SIEVE_OK) {
	    l = SIEVE_DONE;
	    break;
	}
    }

    /* Implementations SHOULD NOT respond to any message that has an
       "Auto-submitted" header field with a value other than "no".
       This header field is described in [RFC3834]. */
    strcpy(buf, "auto-submitted");
    if (interp->getheader(m, buf, &body) == SIEVE_OK) {
	/* we don't deal with comments, etc. here */
	/* skip leading white-space */
	while (*body[0] && Uisspace(*body[0])) body[0]++;
	if (strcasecmp(body[0], "no")) l = SIEVE_DONE;
    }

    /* is there a Precedence keyword of "junk | bulk | list"? */
    /* XXX  non-standard header, but worth checking */
    strcpy(buf, "precedence");
    if (interp->getheader(m, buf, &body) == SIEVE_OK) {
	/* we don't deal with comments, etc. here */
	/* skip leading white-space */
	while (*body[0] && Uisspace(*body[0])) body[0]++;
	if (!strcasecmp(body[0], "junk") ||
	    !strcasecmp(body[0], "bulk") ||
	    !strcasecmp(body[0], "list"))
	    l = SIEVE_DONE;
    }

    /* Note: the domain-part of all addresses are canonicalized */
    /* grab my address from the envelope */
    if (l == SIEVE_OK) {
	strcpy(buf, "to");
	l = interp->getenvelope(m, buf, &body);
	
	if (body[0])
	    myaddr = address_canonicalise(body[0]);
    }  
  
    if (l == SIEVE_OK) {
	strcpy(buf, "from");
	l = interp->getenvelope(m, buf, &body);
    }
    if (l == SIEVE_OK && body[0]) {
	/* we have to parse this address & decide whether we
	   want to respond to it */
	reply_to = address_canonicalise(body[0]);

	/* first, is there a reply-to address? */
	if (reply_to == NULL) {
	    l = SIEVE_DONE;
	}
    
	/* first, is it from me? */
	if (l == SIEVE_OK && myaddr && !strcmp(myaddr, reply_to)) {
	    l = SIEVE_DONE;
	}
   
	/* ok, is it any of the other addresses i've
	   specified? */
	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;
	    }
	}
   
	/* ok, is it a system address? */
	if (l == SIEVE_OK && sysaddr(reply_to)) {
	    l = SIEVE_DONE;
	}
    }
    if (l == SIEVE_OK) {
	/* ok, we're willing to respond to the sender.
	   but is this message to me?  that is, is my address
	   in the [Resent]-To, [Resent]-Cc or [Resent]-Bcc fields? */
	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;
    }
    /* ok, ok, if we got here maybe we should reply */
    if (myaddr) free(myaddr);
    *from = found;
    *to = reply_to;
    return l;
}
Пример #6
0
void write(obj_t obj) {
    char c;
    char *str;

    if (obj == imm_empty_list) {
      printf("()");
    } else if (is_pair(obj)) {
      printf("(");
      write_pair(obj);
      printf(")");
    } else if (is_symbol(obj)) {
      printf("%s", unwrap_symbol(obj)->value);
    } else if (is_string(obj)) {
      printf("\"%s\"", unwrap_string(obj)->value);
    } else if (is_boolean(obj)) {
      printf("#%c", obj==imm_false ? 'f' : 't');
    } else if (is_fixnum(obj)) {
      printf("%lld", unwrap_fixnum(obj));
    } else if (is_thunk(obj)) {
      printf("#<thunk>");
    } else if (is_primitive_proc(obj)) { 
      printf("#<primitive fn>");
    } else if (obj == imm_undefined) {
      printf("#<undefined>");
    } else {
      assert(0);
    }
#if 0
        case SYMBOL:
            printf("%s", obj->data.symbol->value);
            break;
        case FIXNUM:
            printf("%ld", obj->data.fixnum);
            break;
        case CHARACTER:
            c = obj->data.character;
            printf("#\\");
            switch (c) {
                case '\n':
                    printf("newline");
                    break;
                case ' ':
                    printf("space");
                    break;
                default:
                    putchar(c);
            }
            break;
        case STRING:
            str = obj->data.string->value;
            putchar('"');
            while (*str != '\0') {
                switch (*str) {
                    case '\n':
                        printf("\\n");
                        break;
                    case '\\':
                        printf("\\\\");
                        break;
                    case '"':
                        printf("\\\"");
                        break;
                    default:
                        putchar(*str);
                }
                str++;
            }
            putchar('"');
            break;
        case PAIR:
            printf("(");
            write_pair(obj);
            printf(")");
            break;
        case PRIMITIVE_PROC:
        case COMPOUND_PROC:
            printf("#<procedure>");
            break;
        default:
            fprintf(stderr, "cannot write unknown type\n");
            exit(1);
    }
Пример #7
0
static void dump2(bytecode_input_t *d, int bc_len)
{
    int i;
    int version;
    const char *data;
    int len;

    if (!d) return;
    
    if (memcmp(d, BYTECODE_MAGIC, BYTECODE_MAGIC_LEN)) {
	printf("not a bytecode file [magic number test failed]\n");
	return;
    }

    i = BYTECODE_MAGIC_LEN / sizeof(bytecode_input_t);

    version = ntohl(d[i].op);
    printf("Sievecode version %d\n", version);
    
    for(i++; i<bc_len;) 
    {
	int copy = 0;

	printf("%d: ",i);

	switch(ntohl(d[i++].op)) {
	    
	case B_STOP:/*0*/
	    printf("STOP\n");
	    break;
	    
	case B_KEEP:/*1*/
	    printf("KEEP\n");
	    break;
	    
	case B_DISCARD:/*2*/
	    printf("DISCARD\n");
	    break;
	    
	case B_REJECT:/*3*/
	    i = unwrap_string(d, i, &data, &len);
	    printf("REJECT {%d}%s\n", len, data);
	    break;

	case B_FILEINTO: /*19*/
	    copy = ntohl(d[i++].value);
	    /* fall through */
	case B_FILEINTO_ORIG: /*4*/
	    i = unwrap_string(d, i, &data, &len);
	    printf("FILEINTO COPY(%d) FOLDER({%d}%s)\n",copy,len,data);
	    break;

	case B_REDIRECT: /*20*/
	    copy = ntohl(d[i++].value);
	    /* fall through */
	case B_REDIRECT_ORIG: /*5*/
	    i = unwrap_string(d, i, &data, &len);
	    printf("REDIRECT COPY(%d) ADDRESS({%d}%s)\n",copy,len,data);
	    break;
	     
	case B_IF:/*6*/
	    printf("IF (ends at %d)", ntohl(d[i].value));

            /* there is no short circuiting involved here*/
	    i = dump2_test(d,i+1);
	    printf("\n");

	    break;

	case B_MARK:/*7*/
	    printf("MARK\n");
	    break;

	case B_UNMARK:/*8*/
	    printf("UNMARK\n");
	    break;

	case B_ADDFLAG: /*9*/
	    printf("ADDFLAG  {%d}\n",ntohl(d[i].len));
	    i=write_list(ntohl(d[i].len),i+1,d);
	    break;

	case B_SETFLAG: /*10*/
	    printf("SETFLAG  {%d}\n",ntohl(d[i].len));
	    i=write_list(ntohl(d[i].len),i+1,d);
	    break;
	    
	case B_REMOVEFLAG: /*11*/
	    printf("REMOVEFLAG  {%d}\n",ntohl(d[i].len));
	    i=write_list(ntohl(d[i].len),i+1,d);
	    break;
	    
	case B_DENOTIFY:/*12*/
	    printf("DENOTIFY\n");
	    printf("            PRIORITY(%d) Comparison type %d (relat %d)\n",
		   ntohl(d[i].value), ntohl(d[i+1].value), ntohl(d[i+2].value));
	    i+=3;

	    i = unwrap_string(d, i+1, &data, &len);
	    
	    printf("           ({%d}%s)\n", len, (!data ? "[nil]" : data));
	    break;
	    
	case B_NOTIFY: /*13*/
	    i = unwrap_string(d, i, &data, &len);

	    printf("NOTIFY METHOD({%d}%s)\n",len,data);

	    i = unwrap_string(d, i, &data, &len);

	    printf("            ID({%d}%s) OPTIONS ", len,
		   (!data ? "[nil]" : data));

	    i=write_list(ntohl(d[i].len),i+1,d);
	    
	    printf("            PRIORITY(%d)\n", ntohl(d[i].value));
      	    i++;
		  
	    i = unwrap_string(d, i, &data, &len);

	    printf("            MESSAGE({%d}%s)\n", len, data);

	    break;

	case B_VACATION:/*14*/
	    printf("VACATION\n");
	    /*add address list here!*/
	    i=write_list(ntohl(d[i].len),i+1,d);

	    i = unwrap_string(d, i, &data, &len);
	  
	    printf("%d SUBJ({%d}%s) \n",i, len, (!data ? "[nil]" : data));
	    
	    i = unwrap_string(d, i, &data, &len);

	    printf("%d MESG({%d}%s) \n", i, len, (!data ? "[nil]" : data));

	    printf("DAYS(%d) MIME(%d)\n", ntohl(d[i].value), ntohl(d[i+1].value));
	    i+=2;

	    if (version >= 0x05) {
		i = unwrap_string(d, i, &data, &len);

		printf("%d FROM({%d}%s) \n",i, len, (!data ? "[nil]" : data));

		i = unwrap_string(d, i, &data, &len);

		printf("%d HANDLE({%d}%s) \n",i, len, (!data ? "[nil]" : data));
	    }

	    break;
	case B_NULL:/*15*/
	    printf("NULL\n");
	    break;
	case B_JUMP:/*16*/
	    printf("JUMP %d\n", ntohl(d[i].jump));
	    i+=1;
	    break;

	case B_INCLUDE:/*17*/
	    printf("INCLUDE ");
	    switch (ntohl(d[i].value)) {
	    case B_PERSONAL: printf("Personal"); break;
	    case B_GLOBAL: printf("Global"); break;
	    }
	    i = unwrap_string(d, i+1, &data, &len);
	    printf(" {%d}%s\n", len, data);
	    break;

	case B_RETURN:/*18*/
	    printf("RETURN\n");
	    break;
	    
	default:
	    printf("%d (NOT AN OP)\n",ntohl(d[i-1].op));
	    exit(1);
	}
    }
    printf("full len is: %d\n", bc_len);
}