#ifndef MFILTER_HEADER2
#define MFILTER_HEADER2

#include "pcre.h"

#define MAX_LINE 10000

typedef struct PAIRS {char *var; char *val; struct PAIRS *next;} Pairs;


typedef struct HIDDEN {char *word; char *original; double score; struct HIDDEN *next;} Hidden;


#define MAX_HEAD 3200
typedef struct BOUNCE {double score; char *find; char *show; struct BOUNCE *next;} Bounce;
#define BHASH 5000
#define FWDDATA_RCPT 1
struct fwddata
{
	char *uinfo;
	char *path;
	char *rcpt;
	void *r;
	int lineno;
	int cur;
	struct fwddata *next;
};



#define MAX_HEADERS 200
#define MAX_FLAGS 300

typedef struct _expr_token
{
	int type;
	int flag;
	struct _expr_token *next;
} expr_token;

typedef struct _expr_handle
{
	char *orig_expr;
	int n;
	expr_token *expr;
	struct _expr_handle *next;
} expr_handle;

typedef struct EXP {double score; int fn; int binop; int header; int header2; int isnot; char *p2; char *p3; pcre *pcreg; pcre_extra *hints; int srcline; struct EXP *next; struct MFILTER *m;} Exp;
typedef struct LINE {int action,lineno; int p1; int p2; int cpu; char *reason; char *src; Exp *elist; struct LINE *next;} Linex;

#define MFHASH 1000
typedef struct FAST {
	char *reg;
	double score;
	int used;
	char *reason;
	int xflag;
	pcre *pcreg;
	pcre_extra *hints;
	int len;
	struct FAST *next;
} Fast;
struct rexps
{
	char *id;
	char *value;
	int count;
	struct rexps *next;
};

typedef struct rexps Rexps;

typedef struct fwddata Fwddata; 

typedef struct SPAMLIST {float score; char *reason; struct SPAMLIST *next;} Spamlist;


typedef struct FPROG {Linex *lines; char *headers[MAX_HEADERS]; int nheaders; char *flags[MAX_FLAGS]; int nflags;
	expr_handle *expr_handles;
	Fast *ftable[MFHASH];
	Wordlist *feature;
	struct MFILTER *m; // New pointer to global structures, each fprog has exactly one mfilter structure!!! this doesn't change.  
 } FProg;


typedef struct MFILTER {
	int noisey;
	void (*copy_dst)(char *sstart,char *send); 
	Bounce *bhash[BHASH];
	int fix_len;
	int nbin;
	double poly_score;
	Fwddata *cur_fwd;
	int ishidden;
	int is_rexp_fast;  // here
	char cur_sender[BFSZ];
	char cur_ip[BFSZ];
	char cur_ipname[BFSZ];
	int body_lines,body_words;
	char msgfile[BFSZ];
	char item_paragraph1[BFSZ];
	char item_paragraph2[BFSZ];
	char item_paragraph3[BFSZ];
	char firsturl[BFSZ];
//	FProg *fprog;
	FProg *fp; // new one, used to store the fprog...
	char mfilter_fname[BFSZ];	
	char spamdetect_save[BFSZ];
	char *inmem;
	int inmem_len;
	int true_len;
	int dec_len;
	int max_len;
	char *item;
	char *item_decoded;
	char *item_cleaned;
	char *urls;
	int real_len;
	Fwddata *forward_cc;
	char cur_recipient[BFSZ];
	int lineno,nthis;
	char derr[BFSZ];
	int global_np; 
	char **global_p;
	int skip_filteri,skip_fromi,skip_dupi;
	int nurls;
	char compile_fname[BFSZ];
	FProg *curprog;  // upto here

	char *hdrs[MAX_HEADERS];
	int hdrs_len[MAX_HEADERS];
	int hdrs_fake[MAX_HEADERS];
	int hdrs_changed[MAX_HEADERS];

	char *hdrs_add[100];
	int nadd;
	char item_head[MAX_HEAD];
	int item_head_len;
	int item_size;
	int item_lines;
	char *run_item;
	int run_len;
	int item_isuuencoded;  // upto here
	int item_isbinary;
	int item_ishtml;
	int item_isbase64;
	int item_isimage;
	int item_isclickimage;
	int item_nimage;
	int item_isencodedhtml;
	int item_isencodedtext;
	int item_isencodedurl;
	int item_istext;
	int flags[MAX_FLAGS];
	void (*hdrs_external)(char *hdr);
	double aspam_score;		// upto here
	Wordlist *hdr_add;
	Hidden *hlist;
	Pairs *vlist;
	char bounce_reason[BFSZ];
	Spamlist *splist;			// upto here.
	Spamlist *passed_splist;
	Spamlist *add_splist;
	char mfilter_to[BFSZ];
	char return_path[BFSZ];
	int mfilter_unfriend;
	char mfilter_whitelist[BFSZ];
	char store_folder[BFSZ];

	int mitem_image_size;
	int mitem_isimage;
	int mitem_isjpg;
	int mitem_nimage;
	int mitem_ispdf;
	char attach_name[BFSZ];
	int mitem_pdf_size;
	char *item_string;
	int nact;
	int item_isloggedin;
	int item_islocal;
	int item_isfriend;
	char user_mdir[BFSZ];
	int lastall;
	int df_chan;
	int trace;
	
	int df_add_disabled;
	int show_always;
	int g_pairs;
	int (*fmsg)(const char *format, ... );
	int (*imsg)(const char *format, ... );

} Mfilter;

Mfilter *mfilter_new(void);
int mfilter_get_unfriend(Mfilter *m);
FProg *dfilter_compile(Mfilter *m,char *fname) ;
int dfilter_run(Mfilter *m,int chan, FProg *fp, char *item, char *item_decoded, char *item_cleaned, int len, Fwddata **fwdlist, char *tfile, char *reason, Spamlist *startspam);
void dfilter_free(Mfilter *m,FProg *dfilterprog);
int skip_filter(Mfilter *m);
int skip_from(Mfilter *m);
char *mfilter_get_returnpath(Mfilter *m);
int skip_dup(Mfilter *m);
int mfilter_set_extra(Mfilter *m, Wordlist *w);
char *mfilter_get_tohost(Mfilter *m);
char *mfilter_get_whitelist(Mfilter *m);
void dfilter_emsg(Mfilter *m, int (*msgfn)( const char *format,... ));
void dfilter_trace(Mfilter *m,int x);
void dfilter_imsg(Mfilter *m, int (*msgfn)( const char *format, ... ));
int dfilter_setmem(Mfilter *m,char *s, int len);
int dfilter_setmax(Mfilter *m,int len);
int dfilter_silent(Mfilter *m,int x);
int util_rexp(char *exp, char *sample, char *result, int *len);
int df_send_report(Mfilter *m,char *to, char *subj, int lines);

int mfilter_test_rexp(char *exp, char *sample, char *result);
#ifdef SURGEMAIL
int mfilter_test(int (*msgfn)( char *mtext),char *tfile, char *rfile);
#else
int mfilter_test(int chan, char *tfile, char *rfile);
#endif

int df_bounce_fast_add(Mfilter *m, double score, char *find, char *show);
int mfilter_reject(Mfilter *m, int chan, char *fname, struct fwddata **fwdlist, char *reason, char *ip, char *sender, char *ipname);
int mfilter_reload(Mfilter *m, char *fname);
int mfilter_free(Mfilter *m);


int mfilter_reject_prog(FProg *fprogx, int chan, char *fname, struct fwddata **fwdlist
						, char *reason
						, char *ip, char *sender, char *ipname);

int mfilter_set_aspam(Mfilter *m, double score);
int dfilter_show_stats(Mfilter *m,FProg *fp, char *fname);
#ifdef DFILTER_MAIN
/* Private stuff here */
int df_group_match(Mfilter *m, char *wild, char *grp2);
int df_group_match_list(Mfilter *m, char *wild, char *grps);
int count_lines(char  *item, int *xbody_lines, int *xbody_words);
int df_flag_findadd(Mfilter *m, char *header);
int df_flag_get(Mfilter *m, int x);
int df_comp_assign(Mfilter *m, char *p[], int np, int qq[]);
void df_var_set(Mfilter *m, char *var, char *val);
//int dfilter_crash(void);
char *gp(Mfilter *m, int n);
char *df_var_get(Mfilter *m,char *var);
void df_var_free(Mfilter *m);
int df_var_replace(Mfilter *m, char *p[], int np, int qq[]);
Linex *df_comp_if (FProg *fp,char *p[], int np, int qq[]);
Linex *df_comp_call (FProg *fp,char *p[], int np, int qq[]);
Exp *df_comp_exp(FProg *fp,char *p[], int np, int *upto);
int df_token(char *line, char *p[], int maxp, int qq[], char *bfline);
int df_find_action(Mfilter *m, Linex **eline,char *p[],int np,int *upto);
int df_header_findadd(Mfilter *m,char *arg1);
char *df_hdrs_get(Mfilter *m,int x);
int df_hdrs_free(Mfilter *m);
int df_hdrs_exists(Mfilter *m, int x);
void df_forward(Fwddata *fwd, char *to, int lineno);
int dfilter_do(int chan, FProg *fp, char *fname, Fwddata **fwdlist, char *reason);

int score_one(char *item, char *s);
int score_all(char *item);


int comp_report(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_forward_cc(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_attached(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_replace(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_ishidden(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_ismixedcase(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_match(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_inpath(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_rexp(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_rexp_case(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_equals(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_constant(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_size(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_folder_exists(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_isin(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_ifflag(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_crash(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_exists(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_matchall(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_unfriend(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_matchone(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_allmod(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
Linex *df_comp_else(char *p[], int np);
Linex *df_comp_end(char *p[], int np);
int comp_isbinaryn(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_get(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_head_len(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_spamdetect(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_feature_header(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_feature_headerm(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_tomanual(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_feature_add(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_feature_manual(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_spawn(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int run_wrongdomain(Exp *exp);
int run_wronguser(Exp *exp);
int run_forged(Exp *exp);
int run_fromtwo(Exp *exp);
int comp_issimilar(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_wrongdomain(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_wronguser(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_forged(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_fromtwo(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_rexpstore(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_rexp_fast(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_rexp_fast_flag(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_evalflags(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_invalidpairs(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_add_aspam(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_add_poly(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_add_header(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);

int run_tomanual(Exp *exp);
int run_add_poly(Exp *exp);
int run_folder_exists(Exp *exp);
int run_add_aspam(Exp *exp);
int run_forward_cc(Exp *exp);
int run_attached(Exp *exp);
int run_isbinaryn(Exp *exp);
int run_ishidden(Exp *exp);
int run_ismixedcase(Exp *exp);
int run_replace(Exp *exp);
int run_report(Exp *exp);
int run_constant(Exp *exp);
int run_match(Exp *exp);
int run_inpath(Exp *exp);
int run_ifflag(Exp *exp);
int run_crash(Exp *exp);
int run_exists(Exp *exp);
int run_rexp(Exp *exp);
int run_equals(Exp *exp);
int run_size(Exp *exp);
int run_isin(Exp *exp);
int run_istwo(Exp *exp);
int run_matchall(Exp *exp);
int run_matchone(Exp *exp);
int run_lines(Exp *exp);
int run_body_lines(Exp *exp);
int run_body_words(Exp *exp);
int run_isuuencoded(Exp *exp);
int run_isbinary(Exp *exp);
int run_ishtml(Exp *exp);
int run_isbase64(Exp *exp);
int run_clickimage(Exp *exp);
int run_isimage(Exp *exp);
int run_allmod(Exp *exp);
int run_isencodedtext(Exp *exp);
int run_isencodedhtml(Exp *exp);
int run_isencodedurl(Exp *exp);
int run_get(Exp *exp);
int run_unfriend(Exp *exp);
int run_head_len(Exp *exp);
int run_spamdetect(Exp *exp);
int run_feature_header(Exp *exp);
int run_feature_headerm(Exp *exp);
int run_feature_add(Exp *exp);
int run_feature_manual(Exp *exp);
int run_spawn(Exp *exp);
int run_isinc(Exp *exp);
int run_islocal(Exp *exp);
int run_isfriend(Exp *exp);
int run_issimilar(Exp *exp);
int run_rexpstore(Exp *exp);
int run_rexp_fast(Exp *exp);
int run_evalflags(Exp *exp);

int run_add_header(Exp *exp);
int run_invalidpairs(Exp *exp);
int comp_hidden_word(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int run_hidden_word(Exp *exp);
int run_nimage(Exp *exp);

void mfilter_set_hdrs_add(Mfilter *m, void (*hdrs_add)(char *s));

int df_getline(char *item, int *upto, char *bf, int bfsz);
int df_match_mod(char *groups);
int df_ismod(char *group);
int df_spamdetect(Mfilter *m, float score, char *reason);
float df_spamdetect_do(Mfilter *m);
void df_hdrs_add(Mfilter *m, char *s);


int mf_fast_add(FProg *fp,double score, char *reg, char *reason, char *flag);
int mf_fast_clear(FProg *fp);
int mf_fast_free(FProg *fp);
int mf_fast_scan(FProg *fp, char *msg, int len);

int df_expr_findadd(Mfilter *m,char *expr);
int df_expr_eval(Mfilter *m, int expr);

#endif

void mfilter_exit(Mfilter *m);
int df_bounce_fast_clear(Mfilter *m);
int df_spamdetect_free(Mfilter *m);
int df_hdrs_free(Mfilter *m);
void df_expr_exit();
int mfilter_get_spamdetect(Mfilter *m,char *s, int sz);
void mfilter_set_hdrs_add(Mfilter *m, void (*hdrs_add)(char *s));
char *cleanstr(char *s,char *s2);

int mfilter_exists(void);
int mfilter_set_local(Mfilter *m,int x);
int mfilter_set_loggedin(Mfilter *m,int x);
int mfilter_clear(Mfilter *m);
int mfilter_do_not_add(Mfilter *m,int x);
char *df_decode_words(Mfilter *m,char *bf);
int mfilter_set_poly(Mfilter *m,double score);
int mfilter_pairs(Mfilter *m);
int mfilter_add_detect(Mfilter *m,char *s, double v);
int mfilter_free_add(Mfilter *m);

int mf_set_always(Mfilter *m,int x);
int mfilter_setipname(Mfilter *m,char *ipname);

int mfilter_set_mdir(Mfilter *m,char *path);
int mfilter_set_real_len(Mfilter *m,int len);
char *mfilter_get_store_folder(Mfilter *m);
int mfilter_set_friend(Mfilter *m,int x);




#define mfisnum(c) (c>='0' && c<='9')
#define mfisalpha(c) ((c>='a' && c<='z')||((c>='A' && c<='Z')))



int run_pdf_size(Exp *exp);
int run_ispdf(Exp *exp);
void add_fwd(Fwddata **flist, int  chan, char *path);
//#define clock clock_disabled
int clock_disabled(void);
Fwddata *makeup_fwd(Mfilter *m,char *item);
int df_spamdetect_free(Mfilter *m);
int df_add_fwd(Fwddata **flist, char *email);

int mf_hidden_free(Mfilter *m);
int mf_hidden_scan(Mfilter *m,char *msg, int len);
int mf_normalize(char *msg, char *out, int outsz, int inlen);
int df_bounce_fast_clear(Mfilter *m);
int df_bounce_fast_find(Mfilter *m,char *body, int len, char *show);
int comp_date_offset(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int run_isloggedin(Exp *exp);
int run_isbounce(Exp *exp);
int run_date_offset(Exp *exp);
int comp_set_tohost(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_set_returnpath(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int run_set_tohost(Exp *exp);
int run_set_returnpath(Exp *exp);
int comp_set_whitelist(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int run_set_whitelist(Exp *exp);
int run_nurls(Exp *exp);
int run_store_folder(Exp *exp);
int run_isjpg(Exp *exp);
int run_image_size(Exp *exp);
int run_ispdf(Exp *exp);
int run_pdf_size(Exp *exp);
int comp_store_folder(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int run_report_full(Exp *exp);
int run_report_brief(Exp *exp);
int comp_is_dayofweek(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int comp_time_hour(FProg *fp,Exp *exp, char *arg1, char *arg2, char *arg3[]);
int run_is_dayofweek(Exp *exp);
int run_time_hour(Exp *exp);
int lstat_lib_msec(void);




#endif
