Exemplo n.º 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;
}
Exemplo n.º 2
0
/* Test the iterator interface */
static void test_iterator(void)
{
    struct address_itr ai;
    const struct address *a;

    address_itr_init(&ai, "");
    a = address_itr_next(&ai);
    CU_ASSERT_PTR_NULL(a);
    address_itr_fini(&ai);

    address_itr_init(&ai, "Fred Bloggs <*****@*****.**>, Sarah Jane Smith <*****@*****.**>");
    a = address_itr_next(&ai);
    CU_ASSERT_PTR_NOT_NULL_FATAL(a);
    CU_ASSERT_STRING_EQUAL(a->name, "Fred Bloggs");
    CU_ASSERT_STRING_EQUAL(a->mailbox, "fbloggs");
    CU_ASSERT_STRING_EQUAL(a->domain, "fastmail.fm");
    a = address_itr_next(&ai);
    CU_ASSERT_PTR_NOT_NULL_FATAL(a);
    CU_ASSERT_STRING_EQUAL(a->name, "Sarah Jane Smith");
    CU_ASSERT_STRING_EQUAL(a->mailbox, "sjsmith");
    CU_ASSERT_STRING_EQUAL(a->domain, "gmail.com");
    CU_ASSERT_PTR_NULL(a->next);
    address_itr_fini(&ai);
}
Exemplo n.º 3
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;
}