
#include "local_scan.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <fcntl.h>
#include <sys/types.h>
#include <syslog.h>
#include <sys/stat.h>
#include <errno.h>
#include "spamtest.h"
#include "msgstore.h"

//#define SPAMTEST_USE_SYSLOG

/* Default values for configuration options */
#define KAS_CONNECT_TIMEOUT             60000
#define KAS_DEFAULT_DOMAIN              ""
#define KAS_LOG_LEVEL                   0
#define KAS_ON_ERROR                    "tempfail"
#define KAS_DATA_TIMEOUT                60000
#define KAS_CONNECT_TO                  "tcp:127.0.0.1:2277"
#define KAS_FILTERING_SIZE_LIMIT        512

/* Result variables for configuration options */
static uschar *result_default_domain;
static uschar *result_connect_to;
static uschar *result_on_error_str;
static int result_on_error;

/* Configuration options */
//old
static int st_connect_timeout = 0;
static int debug_level = 0;
static int st_rw_timeout = 0;
static int filtering_size_limit=0;
static uschar *st_mail_domain;
static uschar *st_on_error;
static uschar *st_address;
//new
static int kas_connect_timeout = 0;
static int kas_log_level = 0;
static int kas_data_timeout = 0;
static int kas_filtering_size_limit = 0;
static uschar *kas_default_domain;
static uschar *kas_on_error;
static uschar *kas_connect_to;

optionlist local_scan_options[] = 
{/* The entries must appear in alphabetical order */
    { "connect_timeout", opt_int, &st_connect_timeout },
    { "kas_connect_timeout", opt_int, &kas_connect_timeout },
    { "kas_connect_to", opt_stringptr, &kas_connect_to },
    { "kas_data_timeout", opt_int, &kas_data_timeout },
    { "kas_default_domain", opt_stringptr, &kas_default_domain },
    { "kas_filtering_size_limit", opt_int, &kas_filtering_size_limit },
    { "kas_log_level",opt_int,&kas_log_level},
    { "kas_on_error",opt_stringptr,&kas_on_error},
    { "local_mail_domain", opt_stringptr, &st_mail_domain },
    { "log_level",opt_int,&debug_level},
    { "on_spamtest_error",opt_stringptr,&st_on_error},
    { "rw_timeout", opt_int, &st_rw_timeout },
    { "spamtest_address", opt_stringptr, &st_address },
    { "spamtest_filtering_size_limit", opt_int, &filtering_size_limit },
};

int local_scan_options_count = sizeof(local_scan_options)/sizeof(optionlist);


int check_results(spamtest_session_t *s,spamtest_status_t *status,int *res,int fd,uschar **return_text);
int proceed_accept(spamtest_status_t *status,int fd);
void logger(const int log_level,const char *fmt,...);
void prepare_config_parameters();
void free_conf();


int local_scan(int fd, uschar **return_text)
{
    int myfd;
    char buf[4096];
    int cnt = 0;
    int totalcnt = 0;
    int i;
    header_line * tmp;
    spamtest_session_t s;
    int errorcode = STS_ERR_NO_ERR;
    spamtest_status_t *status = NULL;
    int rcpt_sent = 0;
    int res = 0;
    int rest = 0;
    char *ctmp;

    /* Initialize spamtest session */
    
    prepare_config_parameters();

    if(filtering_size_limit > 0)
	{
	    struct stat sb;
	    fstat(fd,&sb);
	    if(sb.st_size > filtering_size_limit * 1024)
		{
		    logger(LOG_DEBUG," Message larger than filtering_size_limit, accepting");
                    free_conf();
		    return LOCAL_SCAN_ACCEPT;
		}
	}
    
    bzero(&s,sizeof(s));
    s.access_address = result_connect_to;
    s.rw_timeout = st_rw_timeout;
    s.connect_timeout = st_connect_timeout;
    s.mail_domain = result_default_domain;

    if ( s.access_address == NULL || s.access_address[0] == '\0' )
    {
	logger(LOG_ERR," Spamtest access address not defined, cannot process mail by spam filtering");
        free_conf();
	return LOCAL_SCAN_ACCEPT;
    }
    
    logger(LOG_DEBUG," Spam test session: %s %s %d %d",s.access_address,s.mail_domain,s.connect_timeout,s.rw_timeout);

    if ( (errorcode = sts_init(&s)) < 0 )
    {
	logger(LOG_ERR," Unable to connect to %s (%s)",s.access_address,sts_strerror(errorcode));
        free_conf();
	return result_on_error;
    };
    
    if ( ! s.should_store_message )
    {
	/* SMTP mode, blackholing message because filter will send message */
	logger(LOG_ERR," Filter in SMTP mode, Incorrect situation.");
	//recipients_count = 0;
	sts_close(&s);
        free_conf();
	return result_on_error;
    }

    if ( sender_address != NULL && sender_address[0] != '\0' )
    {
	if ( (errorcode = sts_set_sender(&s,sender_address)) != STS_ERR_NO_ERR )
	{
	    logger(LOG_ERR," Unable to pass sender address %s(%d)",sender_address,errorcode);
            free_conf();
	    return result_on_error;
	}
    }
    
    if ( sender_host_address != NULL && sender_host_address[0] != '\0' )
    {
	if ( ( errorcode = sts_set_relay(&s,sender_host_address) ) != STS_ERR_NO_ERR )
	{
	    logger(LOG_ERR," Unable to pass relay IP");
	    if(errorcode == STS_ERR_OUT_OF_MEMORY){
                free_conf();
		return result_on_error;
            }
	}
    }

    rcpt_sent = 0;
    for ( i = 0;i<recipients_count;i++)
    {
	if ( recipients_list[i].address != NULL && recipients_list[i].address[0] != '\0' )
	{
	    if ( ( errorcode = sts_add_recipient(&s,recipients_list[i].address) ) != STS_ERR_NO_ERR )
	    {
		logger(LOG_ERR," Unable to pass recipient '%s' to filter",recipients_list[i].address);
	    }
	    else
	    {
		rcpt_sent++;
	    }
	}
    }
    if ( rcpt_sent == 0 )
    {
	logger(LOG_DEBUG," Recipients not sent to filter. Continue.");
    }

    tmp = header_list;
    while ( tmp != NULL )
    {
	if(tmp->type != '*')
	    {
		logger(LOG_DEBUG,"Iterating a , %c %d %s|%d",tmp->type,tmp->slen,tmp->text,tmp->text[tmp->slen-1]);
		if ( ( status = sts_send_body(&s,tmp->text,tmp->slen,STS_REINIT_TIMEOUT) ) == NULL )
		    {
			/* failure. finish proceed */
			logger(LOG_ERR," NULL status after sending header %s",tmp->text);
			sts_close(&s);
		    }
		else
		    { /* check status and finish if need */
			logger(LOG_DEBUG," header %s sent to filter",tmp->text);
			if ( check_results(&s,status,&res,fd,return_text) > 0 ){
                            free_conf();
			    return res;
                        }
		    }
	    }
	if(tmp==header_last)
	    break;
	tmp = tmp->next;
    }

    logger(LOG_DEBUG," Headers sent");

    if ( ( status = sts_send_body(&s,"\n",1,STS_REINIT_TIMEOUT) ) == NULL )
    {
        /* failure. finish proceed */
        logger(LOG_ERR," NULL status after sending empty string(end of headers)");
        sts_close(&s);
    }
    else
    { /* check status and finish if need */
        logger(LOG_DEBUG," empty string (end of headers) sent to filter");
	if ( check_results(&s,status,&res,fd,return_text) > 0 ){
            free_conf();
	    return res;
        }
    }

    logger(LOG_DEBUG," Enter sent");

    i = 0;
    ctmp = buf;
    while ( (cnt = read(fd,ctmp,buf + sizeof(buf) - ctmp)) > 0 )
    {
	logger(LOG_DEBUG,"sending %d bytes to filter",cnt);
	status = sts_send_body(&s,buf,cnt,STS_REINIT_TIMEOUT);
	logger(LOG_DEBUG,"send");
	if ( status == NULL )
	{
	    // failure. finish proceed 
	    logger(LOG_ERR," NULL status after sending part of body");
	    sts_close(&s);
	}
	else
	{ // check status and finish if need 
	    logger(LOG_DEBUG," part of body sent to filter");
	    if ( check_results(&s,status,&res,fd,return_text) > 0 ){
                free_conf();
		return res;
            }
	}
    };

    logger(LOG_DEBUG," Total sent %d bytes of message",totalcnt);

    status = sts_body_end(&s,STS_FLUSH_DATA);
    logger(LOG_DEBUG," Body sent");


    if ( check_results(&s,status,&res,fd,return_text) > 0 ){
        free_conf();
	return res;
    }
    else
	sts_close(&s);

    logger(LOG_DEBUG," EOF");

    free_conf();
    return LOCAL_SCAN_ACCEPT;
    
}


int check_results(spamtest_session_t *s,spamtest_status_t *status,int *res,int fd,uschar **return_text)
{
    logger(LOG_DEBUG," Check results started.");
    switch ( status->status )
    {
    case STS_SMTP_ACCEPT:
    case STS_BLACKHOLE:
	logger(LOG_DEBUG," SMTP_ACCEPT or BLACK_HOLE.");
        recipients_count = 0;
        sts_close(s);
	*res = LOCAL_SCAN_ACCEPT;
	return 1;
    case STS_REJECT:
	logger(LOG_DEBUG," REJECT");
        *return_text=(uschar *)status->reason;
        sts_close(s);
        *res = LOCAL_SCAN_REJECT;
	return 1;
    case STS_FILTER_ERROR:
	logger(LOG_DEBUG," FILTER_ERROR");
        sts_close(s);
        *res =  result_on_error;
	return 1;
    case STS_ACCEPT:
	logger(LOG_DEBUG," ACCEPT");
	if ( proceed_accept(status,fd) != 0 )
    	    *res = result_on_error;
	else
    	    *res = LOCAL_SCAN_ACCEPT;
    	sts_close(s);
	return 1;
    case STS_CONTINUE:
	logger(LOG_DEBUG," CONTINUE");
	return 0;
    }

}

extern int recipients_list_max;
int proceed_accept(spamtest_status_t *status,int fd)
{
    spamtest_status_t *st;
    message_status_t *mst;
    int i;
    int rcptn;
    int good_rcpt_cnt = 0,k;
    int found = 0;

    logger(LOG_DEBUG," accept_message started.");

    st = glue_actions(status);

    if (st==NULL) {
      logger(LOG_ERR," glue_actions return NULL" );
      return -1;    
    }

    mst = &st->ms_array[0] ;

    rcptn = rcptlist_count(mst->rcpts);
    for( k=0; k<rcptn; k++)
	if(strlen(rcptlist_getn(mst->rcpts, k))>0)
	    good_rcpt_cnt++;
    if(good_rcpt_cnt <1)
	{
	    logger(LOG_INFO," Empty recipient list");
	    recipients_count = 0;
	    return 0;
	}

    if ( (mst != NULL) && (mst->action == STS_ACTION_CHANGE) ) 
      {
	logger(LOG_DEBUG," spamtest status returned STS_ACTION_CHANGE for message.");
	
	// cleanup old rcpts list
	recipients_count = 0;
	recipients_list = NULL;
	recipients_list_max = 0;
	for (i = 0; i<rcptlist_count(mst->rcpts);i++) 
	  {
	    char *rcpt = rcptlist_getn(mst->rcpts,i);
	    if(rcpt)
	      {
		logger(LOG_DEBUG,"Adding recipient: %s",rcpt);
		receive_add_recipient(string_copy(US rcpt),-1);
	      }
	  }
	
	logger(LOG_DEBUG," new recipients_count=%d",recipients_count);

	if ( sender_address[0] != '\0' )
	{
	    if (strcasecmp(mst->mailfrom,sender_address) != 0 )
	    { /* changing sender address */
		logger(LOG_DEBUG," senders different");
		sender_address = string_copy( US mst->mailfrom );
	    }
	    else
	    {
		logger(LOG_DEBUG," senders equivalented");
	    }
	}
	logger(LOG_DEBUG," Actions count = %d",mst->action_count);
	for (i=0;i<mst->action_count;i++)
	{
	    header_line * tmp;
	    header_line * matched;
	    header_line * last;
	    int deleted_count = 0;
	    int matched_count = 0;
	    int hdrlen = strlen(mst->act_array[i].header);

	    switch ( mst->act_array[i].type )
	    {
		case STS_HEADER_DEL:
		    logger(LOG_DEBUG," Delete header %s",mst->act_array[i].header);
		    tmp = header_list;
		    while ( tmp != NULL )
		    {
			if ( (tmp->type != '*') &&
			     (tmp->slen > 0) && 
			     (strncasecmp(tmp->text,
				mst->act_array[i].header,
				hdrlen < tmp->slen ? hdrlen:tmp->slen) == 0 ) 
			    )
			{
			    deleted_count++;
			    tmp->type = '*';
			}
			tmp = tmp->next;
		    }
		    logger(LOG_DEBUG," deleted %d headers",deleted_count);
		    break;
		case STS_HEADER_ADD:
		    logger(LOG_DEBUG," Add value to header %s %s",mst->act_array[i].header,mst->act_array[i].value);
		    tmp = header_list;
		    matched = NULL;
		    while ( tmp != NULL )
		    {
			logger(LOG_DEBUG,"Iterating, %c %d %s",tmp->type,tmp->slen,tmp->text);
			if ( (tmp->slen > 0) && 
			     (strncasecmp(tmp->text,
				mst->act_array[i].header,
				hdrlen < tmp->slen ? hdrlen:tmp->slen) == 0 ) 
			    )
			{
			    if ( matched != NULL )
			    {
				if ( (tmp->type != '*') || ( matched->type == '*' ) )
				    matched = tmp;
			    }
			    else
			    {
				matched = tmp;
			    }
			}
			tmp = tmp->next;
			if(matched)
			    break;
		    }
		    if ( matched != NULL )
		    { /* adding value to exits header */
			logger(LOG_DEBUG,"Found matched header, %c %d %s",matched->type,matched->slen,matched->text);
			if ( matched->type == '*' )
			{
			    matched->text = string_sprintf("%s: %s\n",mst->act_array[i].header,mst->act_array[i].value);
			    matched->slen = strlen(matched->text);
			    matched->type = ' ';
			    matched->type = header_checkname(matched,0);
			}
			else
			{
			    logger(LOG_DEBUG,"Appending value to existing header value");
			    matched->text = string_sprintf("%s %s\n",matched->text,mst->act_array[i].value);
			    matched->slen += (strlen(mst->act_array[i].value) + 2);
			}
		    }
		    else
		    { /* add new header in case when this header not found */
			logger(LOG_DEBUG," We must add value to header %s but this header not found.",mst->act_array[i].header);
			header_add(' ',"%s: %s\n",mst->act_array[i].header,mst->act_array[i].value);
		    }
		    logger(LOG_DEBUG," Add header %s %s",mst->act_array[i].header,mst->act_array[i].value);
		    break;


		case STS_HEADER_PREPEND:
		    logger(LOG_DEBUG," Prepend value to header %s %s",mst->act_array[i].header,mst->act_array[i].value);
		    tmp = header_list;
		    matched = NULL;
		    while ( tmp != NULL )
		    {
			logger(LOG_DEBUG,"Iterating, %c %d %s",tmp->type,tmp->slen,tmp->text);
			if ( (tmp->slen > 0) && 
			     (strncasecmp(tmp->text,
				mst->act_array[i].header,
				hdrlen < tmp->slen ? hdrlen:tmp->slen) == 0 ) 
			    )
			{
			    if ( matched != NULL )
			    {
				if ( (tmp->type != '*') || ( matched->type == '*' ) )
				    matched = tmp;
			    }
			    else
			    {
				matched = tmp;
			    }
			}
			tmp = tmp->next;
			if(matched)
			    break;
		    }
		    if ( matched != NULL )
		    { /* adding value to exits header */
			logger(LOG_DEBUG,"Found matched header, %c %d %s",matched->type,matched->slen,matched->text);
			if ( matched->type == '*' )
			{
			    matched->text = string_sprintf("%s: %s\n",mst->act_array[i].header,mst->act_array[i].value);
			    matched->slen = strlen(matched->text);
			    matched->type = ' ';
			    matched->type = header_checkname(matched,0);
			}
			else
			{
			    int l = strlen(mst->act_array[i].header);
			    char *p = matched->text+l+2;
			    matched->text[l]=0;
			    matched->text = string_sprintf("%s: %s %s",matched->text,
							   mst->act_array[i].value,p);
			    matched->slen += (strlen(mst->act_array[i].value) + 1);
			    logger(LOG_DEBUG,"Prepending value %s to existing header value %s|",
				   mst->act_array[i].value, matched->text);
			    
			}
		    }
		    else
		    { /* add new header in case when this header not found */
			logger(LOG_DEBUG," We must add value to header %s but this header not found.",mst->act_array[i].header);
			header_add(' ',"%s: %s\n",mst->act_array[i].header,mst->act_array[i].value);
		    }
		    logger(LOG_DEBUG," Prepend header %s %s",mst->act_array[i].header,mst->act_array[i].value);
		    break;

		case STS_HEADER_CHG:
		    logger(LOG_DEBUG," Change header %s %s",mst->act_array[i].header,mst->act_array[i].value);
		    tmp = header_list;
		    matched = NULL;
		    matched_count = 0;
		    while ( tmp != NULL )
		    {
			int hdrlen = strlen(mst->act_array[i].header);
			if ( (tmp->type != '*') &&
			     (tmp->slen > 0) && 
			     (strncasecmp(tmp->text,
				mst->act_array[i].header,
				hdrlen < tmp->slen ? hdrlen:tmp->slen) == 0 ) 
			    )
			{
			    matched = tmp;
			    matched_count++;
			}
			tmp = tmp->next;
		    }
		    if ( matched != NULL )
		    {
			matched->text = string_sprintf("%s: %s\n",mst->act_array[i].header,mst->act_array[i].value);
			matched->slen += (strlen(mst->act_array[i].value) + strlen(mst->act_array[i].header) + 3);
			if ( matched_count > 1 )
			{
			    tmp = header_list;
			    while ( (tmp != NULL) && matched_count > 1 )
			    {
				if ( (tmp->type != '*') &&
			    	     (tmp->slen > 0) && 
			    	     (strncasecmp(tmp->text,
					mst->act_array[i].header,
					hdrlen < tmp->slen ? hdrlen:tmp->slen) == 0 ) &&
				     (tmp != matched)
				   )
				{
				    tmp->type = '*';
				    matched_count--;
				}
				tmp = tmp->next;
			    }
			}
			
		    }
		    else
		    {
			logger(LOG_DEBUG," We must change value for header %s but this header not found.Adding new",mst->act_array[i].header);
			header_add(' ',"%s: %s\n",mst->act_array[i].header,mst->act_array[i].value);
		    }
		    break;
		case STS_HEADER_NEW:
		    logger(LOG_DEBUG," New header %s: %s",mst->act_array[i].header,mst->act_array[i].value);

		    tmp = header_list;
		    matched = NULL;
		    while ( tmp != NULL )
		    {
			if ( (tmp->type != '*') &&
			     (tmp->slen > 0) && 
			     (strncasecmp(tmp->text,
				mst->act_array[i].header,
				hdrlen < tmp->slen ? hdrlen:tmp->slen) == 0 ) 
			    )
			{
			    matched = tmp;
			}
			tmp = tmp->next;
		    }
		    if ( matched != NULL &&  matched != header_last )
			{
			if(matched == header_last)
			    {
				logger(LOG_DEBUG,"Header %s is last in message, adding below",
				       mst->act_array[i].header);
				header_add(' ',"%s: %s\n",mst->act_array[i].header,mst->act_array[i].value);
			    }
			else
			    { /* adding value after last header with this name */
				logger(LOG_DEBUG,"Some headers %s found",mst->act_array[i].header);
				tmp = header_last;
				header_add(' ',"%s: %s\n",mst->act_array[i].header,mst->act_array[i].value);
				tmp->next->next = matched->next;
				matched->next = tmp->next;
				tmp->next = NULL;
				header_last = tmp;
			    }
			}
		    else
		    { /* add new header at the end of headers list */
			logger(LOG_DEBUG,"Headers %s not found",mst->act_array[i].header);
			header_add(' ',"%s: %s\n",mst->act_array[i].header,mst->act_array[i].value);
		    }
		    
		    break;
		default:
		    logger(LOG_INFO," Invalid action type %d",mst->act_array[i].type);
	    }
	}
    }
    else if ( (mst != NULL) && (mst->action == STS_ACTION_BOUNCE) ) 
    { /* bounce message */
	header_line *tmp;
	message_t *bounced_mess;
	
	logger(LOG_DEBUG," bouncing message.");

	/* preparing bounced message */
	bounced_mess = message_init();
	if ( bounced_mess == NULL )
	{
	    logger(LOG_ERR," Unable to allocate memory for bounced message");
	    return -1;
	}
	logger(LOG_DEBUG," new message allocated.");

	/* copying data from filter to prepared message (for automatically creating headers list ) */
	for (i=0;i<msgtext_count_chunks(mst->bouncemsg);i++ )
	{
	    if ( message_put_body(bounced_mess,msgtext_get_chunk(mst->bouncemsg,i),msgtext_chunk_len(mst->bouncemsg,i)) == -1 )
	    {
		logger(LOG_ERR," unable to copy data from filter to bounced message");
		message_free(bounced_mess);
		return -1;
	    }
	    else
	    {
		logger(LOG_DEBUG," message_put_body - ok.");
	    }
	}

	/* deleting exim old headers */
	tmp = header_list;
	while ( tmp != NULL )
	{
	    tmp->type = '*';
	    tmp = tmp->next;
	};
	logger(LOG_DEBUG," headers deleted.");

	/* adding new headers */
	for ( i = 0;i < bounced_mess->headers->used; i++ )
	{
	    header_add(' ',"%s: %s",bounced_mess->headers->array[i].header.hptr,bounced_mess->headers->array[i].value.hptr);
	    logger(LOG_DEBUG," added header: %s: %s",bounced_mess->headers->array[i].header.hptr,bounced_mess->headers->array[i].value.hptr);
	}
	
	/* replacing rcpts */
	recipients_count = 0;
	recipients_list = NULL;
	recipients_list_max = 0;

	if ( rcptlist_count(bounced_mess->recipients) > 0 )
	  {
	    for (i = 0; i<rcptlist_count(bounced_mess->recipients);i++) 
	    {
		char *rcpt = rcptlist_getn(bounced_mess->recipients,i);
		if ( rcpt == NULL )
		{
		    logger(LOG_ERR," unable to get recipient %d",i);
		    message_free(bounced_mess);
		    return -1;
		}
		logger(LOG_DEBUG," rcpt = %s",rcpt);
		receive_add_recipient(string_copy(US rcpt),-1);
	    }
	}
	else
	{
	    if ( sender_address[0] != '\0' )
	      receive_add_recipient(string_copy(US sender_address),-1);
	    else
	    {
		logger(LOG_ERR," Unable to get sender address to bounce, failed");
		return -1;
	    }
	}
	/* cleaning sender ( must be empty string ) */
	logger(LOG_DEBUG," sender address emptied");
	sender_address = "";
	
	/* writing new message body */
	lseek(fd,SPOOL_DATA_START_OFFSET,SEEK_SET);

	if ( get_message_bodychunks_count(bounced_mess) > 0 )
	{
	    for (i=0;i<get_message_bodychunks_count(bounced_mess);i++ )
	    {
		if ( write(fd,get_message_bodychunk_ptr(bounced_mess,i),get_message_bodychunk_len(bounced_mess,i)) == -1 )
		{
		    logger(LOG_ERR," unable to write bounced message body.");
		    message_free(bounced_mess);
		    return -1;
		}
		else
		{
		    logger(LOG_DEBUG," written part of body to file");
		}
	    }
	}
	else
	{
		char *autogenmsg = "Autogenerated message for bouncing\n\n\n";
		if ( write(fd,autogenmsg,strlen(autogenmsg)) == -1 )
		{
		    logger(LOG_ERR," unable to write bounced message body.");
		    message_free(bounced_mess);
		    return -1;
		}
		else
		{
		    logger(LOG_DEBUG," written autogenerated message to file");
		}
	}
	
	message_free(bounced_mess);
	logger(LOG_DEBUG," bouncing finished");
	

    }
    else
    {
	if ( mst != NULL )
	    logger(LOG_ERR," Invalid action %d",mst->action);
	else
	    logger(LOG_ERR," mst is NULL");
    }

    logger(LOG_DEBUG," Message accepted.");
    return 0;

}


void logger(const int log_level,const char *fmt,...)
{
    va_list params;
    char buf[512];
    /* LOG_ERR == 3 is minimum level for us */
    if (log_level <= (debug_level+3))
    {
	va_start(params,fmt);
	vsnprintf(buf,(size_t)512,fmt,params);
	debug_printf("-ls- %s\n",buf);
#ifdef SPAMTEST_USE_SYSLOG
	va_start(params,fmt);
	vsyslog(log_level>LOG_DEBUG?LOG_DEBUG:log_level,fmt,params);
#else
	log_write(0,LOG_MAIN,"spamtest: %s",buf);
#endif
	va_end(params);
    }
}

void prepare_config_parameters()
{
    int len;
        /*
         * Firstly we are looking for new parameter,
         * then - for old parameter, else - we use
         * default value.
         */
    if (kas_log_level != 0)
            debug_level = kas_log_level;
    if (debug_level == 0)
            debug_level = KAS_LOG_LEVEL;

    if (kas_connect_timeout != 0)
            st_connect_timeout = kas_connect_timeout*1000;
    if (st_connect_timeout == 0)
            st_connect_timeout = KAS_CONNECT_TIMEOUT;

    if (kas_data_timeout != 0)
            st_rw_timeout = kas_data_timeout*1000;
    if (st_rw_timeout == 0)
            st_rw_timeout = KAS_DATA_TIMEOUT;
    
    if (kas_filtering_size_limit != 0)
            filtering_size_limit = kas_filtering_size_limit;
    if (filtering_size_limit == 0)
            filtering_size_limit = KAS_FILTERING_SIZE_LIMIT;
    
    
    if (kas_default_domain != NULL){
            len = strlen(kas_default_domain);
            result_default_domain = malloc(len+1);
            strncpy(result_default_domain,kas_default_domain,len);
            result_default_domain[len]='\0';
    }
    else if (st_mail_domain != NULL){
            len = strlen(st_mail_domain);
            result_default_domain = malloc(len+1);
            strncpy(result_default_domain,st_mail_domain,len);
            result_default_domain[len]='\0';
    }
    else{
            len = strlen(KAS_DEFAULT_DOMAIN);
            result_default_domain = malloc(len+1);
            strncpy(result_default_domain,KAS_DEFAULT_DOMAIN,len);
            result_default_domain[len]='\0';
    }

    if (kas_connect_to != NULL){
            len = strlen(kas_connect_to);
            result_connect_to = malloc(len+1);
            strncpy(result_connect_to,kas_connect_to,len);
            result_connect_to[len]='\0';
    }
    else if (st_address != NULL){
            len = strlen(st_address);
            result_connect_to = malloc(len+1);
            strncpy(result_connect_to,st_address,len);
            result_connect_to[len]='\0';
    }/* one parameter have no default,
      * because else we can't disable kas-exim in config file*/

    if (kas_on_error != NULL){
            len = strlen(kas_on_error);
            result_on_error_str = malloc(len+1);
            strncpy(result_on_error_str,kas_on_error,len);
            result_on_error_str[len]='\0';
    }
    else if (st_on_error != NULL){
            len = strlen(st_on_error);
            result_on_error_str = malloc(len+1);
            strncpy(result_on_error_str,st_on_error,len);
            result_on_error_str[len]='\0';
    }
    else{
            len = strlen(KAS_ON_ERROR);
            result_on_error_str = malloc(len+1);
            strncpy(result_on_error_str,KAS_ON_ERROR,len);
            result_on_error_str[len]='\0';
    }

    if ( strcasecmp(result_on_error_str,"accept") == 0 ){
	result_on_error = LOCAL_SCAN_ACCEPT;
    }
    else if ( strcasecmp(result_on_error_str,"reject") == 0 ){
	result_on_error = LOCAL_SCAN_REJECT;
    }
    else if ( strcasecmp(result_on_error_str,"tempfail") == 0 ){
	result_on_error = LOCAL_SCAN_TEMPREJECT;
    }
    else{
	logger(LOG_ERR,"Invalid value for parameter on_spamtest_error. Will use 'accept'");
	result_on_error = LOCAL_SCAN_ACCEPT;
    }
}

void free_conf(){
        free(result_default_domain);
        free(result_connect_to);
        free(result_on_error_str);
}

