⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ruleprocessor.cpp

📁 JK Proxy Project - Version 0.1 ------------------------------ This was going to be a proxy serve
💻 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 + -