📄 ruleprocessor.cpp
字号:
/*
+-----------------------------------------------------------------------------+
| |
| ruleprocessor.cpp |
| Last change: yyyy-mm-dd |
| |
| Author: Jan Krumsiek |
| eMail: proxy@krumsiek.com |
| Web: http://www.krumsiek.com/proxy |
| |
| Copyright 2003 - Jan Krumsiek |
| This source code can freely be modified and redistributed. No liability |
| whatsoever is taken by the author for any use of this software. |
| |
| Description: |
| This file is the rule processor. It applies all rules defined in a |
| RULEFILE struct (loaded via LoadRules() in rulefile.cpp) and returns if |
| this message is spam or if it may pass |
| |
+-----------------------------------------------------------------------------+
*/
#include "proxymain.h"
#include "rulefile.h"
#include "ruleprocessor.h"
void ExtractElement(CHARPTR header, CHARPTR headerlwr, CHARPTR element, CHARPTR* start, CHARPTR* end);
int CheckString(CHARPTR string, RULE* rule);
void ExtractEmail (CHARPTR sourcestart, CHARPTR sourceend, CHARPTR* emailstart, CHARPTR* emailend);
int CheckMsg(CHARPTR msg,
RULEFILE* rulefile) // exported
// checks a message against a set of rules and returns if the message
// is spam or may pass
{
UINT i,n;
RULE* currule;
CHARPTR headerlwr,element, tocheck;
CHARPTR sep;
UINT msglen;
bool sizematch;
// we are 'caching' all entitys that have already been extracted from the
// header so they don't need to be extracted again. this cache is a simple
// map from a string to another string (from entity name to entity contents)
STRCACHEPTR cache = new STRCACHE;
CHARPTR chkstart,chkend;
UINT result;
CHARPTR header,body;
// we need to seperate header and body
// find first occurence of double line break
sep = strstr(msg, "\x0D\x0A\x0D\x0A\0");
if (sep == 0)
// this is not even a real message, it has no header -> block
return false;
// simply put a \0 at this place to indicate end of header
sep[0] = 0;
header = msg;
// body starts 4 bytes later
body = sep + 4;
// change header to lower-case for future comparison
UINT test = strlen(header);
headerlwr = new char[strlen(header)+1];
strcpy(headerlwr,header);
strlwr(headerlwr);
// walk through rules
n = rulefile->rules->size();
for( i=0; i<n ; i++ )
{
// Get rule from vector
currule = (*(rulefile->rules))[i];
// Body, subject or size?
if (currule->field == F_BODY)
{
// Body
// Start = body start, end = body end
tocheck = body;
}
else if (currule->field == F_HEADER)
{
// header or email
// Check if string is already in cache
element = (*cache)[currule->fieldname];
if (element == 0)
{
// Not in cache
// extract from header and save in cache
ExtractElement(header,headerlwr,currule->fieldname,&chkstart,&chkend);
if (chkstart != 0)
{
element = (CHARPTR)CopyAndPtr(chkstart, chkend-chkstart+1);
// Save in cache
(*cache)[currule->fieldname] = element;
}
}
tocheck = element;
}
else if (currule->field == F_SIZE)
{
// checks for message size
// get msg len
msglen = strlen(msg);
// perform test
sizematch = false;
if (currule->negate == true)
{
// 'greater than'
if (msglen > *((UINT*)currule->value))
sizematch = true;
}
else
{
// 'less than'
if (msglen < *((UINT*)currule->value))
sizematch = true;
}
// return true or false, depending on 'action'
if (currule->action == A_ISSPAM)
return !sizematch;
else
return sizematch;
// rest of the loop is not used for size check! skip this part
continue;
}
// Now run check
if (tocheck != 0)
result = CheckString(tocheck,currule);
else
return true;
// restore CR
sep[0] = 13;
// If result = 0 -> nomatch, otherwise -> match
if (result != 0)
{
// return value
if (currule->action == A_ISSPAM)
{
// SPAM
return false;
}
else if (currule->action == A_PASS)
{
// PASS
return true;
}
}
}
// if no rule matched -> PASS
return true;
}
int CheckString(CHARPTR string, RULE* rule)
// this msg checks if a single string matches a rule
{
LIST* list;
UINT i;
int result;
// rule value points to a list or to a value?
if (rule->islist == true)
{
// List !
list = (LIST*)rule->value;
// Iterate through list
for (i=0;i<list->count;i++)
{
// call rule->compare which is the saved comparision function
result = rule->compare(string,list->items[i]);
// Negate?
if (rule->negate == true)
result = (result != 0) ? 0 : 1;
// If now result != 0 then rule does match!
if (result != 0)
{
return 1;
}
}
}
else
{
// No list, simple check
CHARPTR test= (CHARPTR)rule->value;
result = rule->compare(string,(CHARPTR)rule->value);
// Negate?
if (rule->negate == true)
result = (result != 0) ? 0 : 1;
// If now result != 0 then rule does match!
if (result != 0)
{
return 1;
}
}
return 0;
}
void ExtractElement(CHARPTR header, CHARPTR headerlwr, CHARPTR element, CHARPTR* start, CHARPTR* end)
// extracts a single entity from the header and returns the beginning and ending of
// the entity in 'start' and 'end'
{
CHARPTR temp;
CHARPTR search,search2;
UINT ilen1,ilen2;
// now check if 'element' is char [-1] (signed, unsigned would be 255)
// this would indicate that the rule is an 'email' rule. we need to extrat
// the email address from the header's 'From' entity.
if (element[0] == -1)
{
CHARPTR fromstart, fromend;
CHARPTR emailstart, emailend;
// recursively call ExtractElement() to get 'From' entity
ExtractElement(header,headerlwr,"from\0",&fromstart,&fromend);
// now extract email
ExtractEmail(fromstart,fromend,&emailstart,&emailend);
// return email delimiters
*start = emailstart;
*end = emailend;
}
else
// do a header entity normal extraction
{
// Put ':' at the end of element
ilen1 = strlen(element);
temp = (CHARPTR)CopyAndPtr(element,ilen1+1);
temp[ilen1] = ':';
temp[ilen1+1] = 0;
ilen2 = strlen(header);
search = headerlwr;
while (search != 0)
{
// Find occurence of that string in header
search = strstr(search,temp);
// not found?
if (search == 0)
{
*start = 0;
return;
}
// Check if beginning of line
// (last byte = line break of first byte found)
if ((search == headerlwr) || (search[-1] = 10))
{
// Is beginning of line: correct position found
// Now seek end of line
search2 = strchr(search,10);
// If no end-of-line found -> last line!
if (search2 == 0) search2 = headerlwr+ilen2;
break;
}
else
{
// No.. not beginning of a line... find next occurence
search++;
}
}
// Delete memory in temporary variable
delete temp;
// If search == 0 -> element not found
if (search == 0)
*start = 0;
else
{
*start = search + ilen1+1;
*end = search2-1;
}
// Translate positions for real 'header' (currently 'headerlwr')
*start = (*start-headerlwr)+header;
*end = (*end -headerlwr)+header-1;
// Find first char that is no space
while (**start == 32)
(*start)++;
}
}
void ExtractEmail (CHARPTR sourcestart, CHARPTR sourceend, CHARPTR* emailstart, CHARPTR* emailend)
// this function extracts the email from a header "from" entity
// it searches for an '@' and then finds delimiters to the right
// emailstart and emailend contain the delimiting characters of the email address
// after the function is finished
{
CHARPTR find=0;
UINT lensource = sourceend-sourcestart+1;
UINT len=0;
UINT start=0,pos1=0,pos2=0;
// find '@'
find = strchr(sourcestart,'@');
if (find>0 && find<sourceend)
{
// find left-hand delimiter
start = (find-sourcestart);
for(;;)
{
start--;
if (start < 0) return;
if (start == 0xFFFFFFFF)
{
// email is at beginning of string
pos1 = -1;
break;
}
else if ((sourcestart[start]) == '<' || (sourcestart[start] == '>') || (sourcestart[start] == '"') || (sourcestart[start] == ' '))
{
// space , ", < or > found
pos1 = start;
break;
}
}
// find right-hand delimiter
start = (find-sourcestart);
for (;;)
{
start++;
if (start>= lensource)
{
// string is at end of string
pos2 = (lensource-1);
// return pos
len = pos2-pos1;
*emailstart = &sourcestart[pos1+1];
*emailend = &sourcestart[pos1+1+len-1];
/*len = pos2-pos1;
return (CHARPTR)CopyAndPtr(&source[pos1+1],len);*/
return;
}
if ((sourcestart[start]) == '<' || (sourcestart[start] == '>') || (sourcestart[start] == '"') || (sourcestart[start] == ' ') || (sourcestart[start] == 13))
{
pos2 = start;
break;
}
}
// return pos
len = pos2-pos1-1;
*emailstart = &sourcestart[pos1+1];
*emailend = &sourcestart[pos1+1+len-1];
/*len = pos2-pos1;
return (CHARPTR)CopyAndPtr(&source[pos1+1],len);*/
return;
}
else
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -