/* kbs - Simple, easily fooled, POP3 spam filter Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.co.uk) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------------- Rules database */ static const char id[]="$Id$"; #include #include #include #include #include #include "global.h" #include "dbase.h" #include "dstring.h" #include "config.h" #include "util.h" /* ---------------------------------------- TYPES */ struct Domain { RE_Expression name; int def_block; int no_user; int no_block; int no_allow; char **user; RE_Expression *block; RE_Expression *allow; Domain *next; Domain *prev; }; /* ---------------------------------------- GLOBALS */ static Domain *head; static Domain *tail; static int no_trusted_users=0; static int no_trusted_domains=0; static char **trusted_user=NULL; static char **trusted_domain=NULL; static const char *reason; /* ---------------------------------------- PRVIVATE FUNCTIONS */ static int IsTrustedUser(const char *username) { int f; for(f=0;fname,domain)) return dom; dom=dom->next; } return NULL; } static void DeJunk(DString ds, const char *p) { int last_ws=FALSE; while(*p) { if (isspace(*p)) { if (!last_ws) DSAddChar(ds,' '); last_ws=TRUE; } else last_ws=FALSE; if (isalnum(*p)) { DSAddChar(ds,*p); } p++; } } /* ---------------------------------------- INTERFACES */ Domain *DBNewDomain(RE_Expression name) { Domain *dom; dom=Malloc(sizeof *dom); dom->name=name; dom->def_block=FALSE; dom->no_user=0; dom->no_block=0; dom->no_allow=0; dom->user=NULL; dom->block=NULL; dom->allow=NULL; if (tail) tail->next=dom; else head=tail=dom; dom->prev=tail; dom->next=NULL; return dom; } void DBDefault(Domain *domain, int block) { domain->def_block=block; } void DBBlockUser(Domain *domain, const char *username) { domain->no_user++; domain->user=Realloc(domain->user,sizeof(char *)*domain->no_user); domain->user[domain->no_user-1]=CopyStr(username); } void DBAllowSubject(Domain *domain, RE_Expression re) { domain->no_allow++; domain->allow=Realloc(domain->allow,sizeof(RE_Expression)*domain->no_allow); domain->allow[domain->no_allow-1]=re; } void DBBlockSubject(Domain *domain, RE_Expression re) { domain->no_block++; domain->block=Realloc(domain->block,sizeof(RE_Expression)*domain->no_block); domain->block[domain->no_block-1]=re; } void DBTrustedUser(const char *username) { no_trusted_users++; trusted_user=Realloc(trusted_user,sizeof(char *)*no_trusted_users); trusted_user[no_trusted_users-1]=CopyStr(username); } void DBTrustedDomain(const char *domain) { no_trusted_domains++; trusted_domain=Realloc(trusted_domain,sizeof(char *)*no_trusted_domains); trusted_domain[no_trusted_domains-1]=CopyStr(domain); } int DBBlockMessage(const POP3Message *msg) { static const char *html="text/html"; DString ds; const Domain *dom; int f; reason="None"; if (IsTrustedDomain(msg->from_domain)) return FALSE; if (IsTrustedUser(msg->from_uname)) return FALSE; if (ConfigInt(CONFIG_BLOCKHTML) && (strncmp(msg->content_type,html,strlen(html))==0 || strcmp(msg->content_type,"UNKNOWN")==0)) { reason="HTML message"; return TRUE; } if (!(dom=GetDomain(msg->from_domain))) return FALSE; ds=DSInit(); if (ConfigInt(CONFIG_DEJUNK)) DeJunk(ds,msg->subject); else DSAddCP(ds,msg->subject); for(f=0;fno_allow;f++) { if (RESearch(dom->allow[f],ds->text)) { DSFree(ds); return FALSE; } } for(f=0;fno_user;f++) { int res; if (ConfigInt(CONFIG_CASESENSE)) res=strcmp(dom->user[f],msg->from_uname); else res=strcasecmp(dom->user[f],msg->from_uname); if (res==0) { DSFree(ds); reason="disallowed name"; return TRUE; } } for(f=0;fno_block;f++) { if (RESearch(dom->block[f],ds->text)) { reason="disallowed subject"; DSFree(ds); return TRUE; } } reason="default"; DSFree(ds); return dom->def_block; } const char *DBBlockReason(void) { return reason; } void DBClose(void) { Domain *d; int f; for(f=0;fnext; for(f=0;fno_user;f++) free(t->user[f]); free(t->user); for(f=0;fno_block;f++) REFree(t->block[f]); free(t->block); for(f=0;fno_allow;f++) free(t->allow[f]); free(t->allow); free(t); } no_trusted_users=0; no_trusted_domains=0; head=tail=NULL; trusted_user=NULL; trusted_domain=NULL; } /* END OF FILE */