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

📄 2002-12-24_rulefile.cpp

📁 JK Proxy Project - Version 0.1 ------------------------------ This was going to be a proxy serve
💻 CPP
字号:
/*
+-----------------------------------------------------------------------------+
|                                                                             |
|   rulefile.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 module loads a rulefile (i.e. a file that contains rules which are   |
|   used to indicate if a message is blocked or may be passed) and creates a  |
|   RULEFILE struct which can then be used by the rule processor.             |
|                                                                             |
+-----------------------------------------------------------------------------+
*/

#include "proxymain.h"
#include "cfgfiles.h"
#include "rulefile.h"

#include "iostream.h"
#include <map>

// prototypes
RULE_COMMAND StrToCommand(CHARPTR command);
UINT AddRule(CHARPTR* parameters, RULESETPTR ruleset);
UINT AddList(CHARPTR* parameters, LISTMAPPTR listmap);
void SetFunctPointer(RULE* rule, RULE_TYPE type, bool insensitive);
int strstrcaps (const char* x, const char* y);
int stristrcaps (const char* x, const char* y);
RULE_TYPE StrToRuletype(CHARPTR command);
char* stristr(const char *szSrc,const char *szFind );

CHARPTR curfile;		// Filename of current file
UINT curline;			// Current line
LISTMAPPTR vlistmap;	// Listmap must be globally accessible

RULEFILE* LoadRules(CHARPTR file) // exported
// loads a set of rules from a file and returns a pointer to the set
{
	COMMAND cur;
	RULE_COMMAND cur_cmd;

	// create map of lists
	vlistmap = new LISTMAP;
	// create new ruleset
	RULESETPTR vruleset = new RULESET;
	// ruleset and map of lists are combined in the RULEFILE struct
	RULEFILE* vreturn = new RULEFILE;

	UINT retval;
	

	// first of all open the file
	OpenConfigFile(file);

	// now iterate through all lines
	cur = GetNextFullCommand();

	curfile = file;

	while (cur.command != 0)
	{

		// find out which command this is (convert the string to an integer)
		cur_cmd = StrToCommand(cur.command);

		// save current line
		curline = cur.line;

		// whic command is it?
		switch (cur_cmd)
		{
		case C_RULE:
			// it is a rule, call AddRule()
			retval = AddRule(cur.paras,vruleset);
			if (retval != 0)
			{
				// if return value of AddRule != -> something went wrong
				// return 0 to indicate error
				return 0;
			}
			break;

		case C_LIST:
			// A list to be loaded, call AddList()
			AddList(cur.paras,vlistmap);
			break;

		default:
			// invalid command
			cout << "Error in " << curfile << "(" << curline << ")"
				 << ": Unknown command '" << cur.command << "'" << endl;
			// return zero to indicate error
			return 0;
		}
		
 
		// release memory allocated for this command
		ReleaseCommand(&cur);
		// get next command
		cur = GetNextFullCommand();
	}
	


	// release file (= deallocate memory)
	ReleaseConfigFile();

	// set return value
	vreturn->rules = vruleset;
	vreturn->list  = vlistmap;


	return vreturn;
}

void ReleaseRuleFile(RULEFILE* rulefile)
// dellocates all memory that has been allocated for a RULEFILE struct
{
	UINT i,n;
	LIST* curlist;
	RULE* currule;

	// first of all delete lists

	// declare iterator
	std::map<std::string, LIST*>::const_iterator iter;
	// iterate throug map
	for (iter = rulefile->list->begin(); iter != rulefile->list->end(); iter++)
	{
		// get current list
		curlist = iter->second;

		// iterate through list and delete each item
		for (i=0;i<curlist->count;i++)
			delete curlist->items[i];

		// now delete array pointer of list
		delete curlist->items;

		// delete list pointer itsself
		delete curlist;
	}
	// delete list-map
	delete rulefile->list;


	// delete rule structs
	n = rulefile->rules->size();

	for( i=0; i<n ; i++ )
	{
		// get rule from vector
		currule = (*(rulefile->rules))[i];

		// only 'fieldname' is a pointer that has to be deleted
		delete currule->fieldname;

		// now delete rule struct itself
		delete currule;

	}

	// delete vector
	delete rulefile->rules;


	// finished... delete RULEFILE struct
	delete rulefile;

	// done
}

UINT AddRule(CHARPTR* parameters, RULESETPTR ruleset)
// adds a single rule to the ruleset 'ruleset'
// return 0 for success
{
	RULE* newrule = new RULE;
	RULE_TYPE ruletype;
	bool issensitive;

	// now check each parameter of this line, if something is wrong
	// return 1 (= non-zero) and output error msg

	// 1. parameter: field (header or body)
	// must be 'header' or 'body'
	if (stricmp(parameters[0],"header") == 0)
		newrule->field = F_HEADER;
	else if (stricmp(parameters[0],"body") == 0)
		newrule->field = F_BODY;
	else
	{
		// wrong parameter, output error
		cout << "Error in " << curfile << "(" << curline << ")"
			 << ": 1. parameter must be 'header' or 'body'"<< endl;
		return 1;
	}

	// 2. parameter: name of header field
	// if field = F_HEADER and 2. para empty -> error
	if ((strlen(parameters[1]) == 0) && (newrule->field == F_HEADER))
	{
		cout << "Error in " << curfile << "(" << curline << ")"
			 << ": 2. parameter may not be empty if field = 'header'"<< endl;

		return 1;
	}
	else
	{
		// copy string
		newrule->fieldname = (CHARPTR)CopyAndPtr(parameters[1],strlen(parameters[1]));
		// lowercase (for string comparison)
		strlwr(newrule->fieldname);
	}
	
	// 3. parameter: rule type (contains, equals ... etc.)

	// convert from string to integer
	ruletype = StrToRuletype(parameters[2]);

	if (ruletype == R_UNKNOWN)
	{
		// unknown type -> error
		cout << "Error in " << curfile << "(" << curline << ")"
			 << ": 3. parameter must be 'equals', 'notequals', 'contains', 'notcontains', 'pattern' or 'notpattern'"<< endl;

		return 1;
	}

	// 4. parameter: case sensitivity
	// C for sensitive, I for insensitive
	if (stricmp(parameters[3],"C") == 0)
		issensitive = true;
	else if (stricmp(parameters[3],"I") == 0)
		issensitive = false;
	else
	{
		// error
		cout << "Error in " << curfile << "(" << curline << ")"
			 << ": 4. parameter must be 'C' (case-sensitive) or 'I' (case-insensitive)"<< endl;
		return 1;
		
	}

	// Now combine parameter 3 and 4 to get the pointer to the
	// comparison function and the negation value 
	// (read comment in SetFunctPointer() for detailled description of "negation" value)
	SetFunctPointer(newrule,ruletype,issensitive);

	// 5. parameter: value
	// if first byte is a @ -> pointer to list
	if (*parameters[4] == '@')
	{
		// is list

		// check if list already defined before
		LIST* check;
		check = (*vlistmap)[&(parameters[4])[1]];
		// if check == 0 then list doesn't exist
		if (check != 0)
		{
			// list exits. set a pointer to it
			newrule->islist = true;
			newrule->value = check;

			LIST* ts = (LIST*) newrule->value;
			ts = ts;
		}
		else
		{
			// list is not defined yet -> error
			cout << "Error in " << curfile << "(" << curline << ")"
				 << ": 5. parameter - list '" << &(parameters[4])[1] << "' does not exist or is not loaded yet" << endl;
			return 1;
			
		}


	}
	// no list, must be a value in quotes ""
	else if	(*parameters[4] == '"')
	{
		// Find closing quote

		// Point to last byte
		CHARPTR search = parameters[4] + strlen(parameters[4]) - 1;

		// Go backwards to find closing quite
		while (*search != '\"') 
			search--;
		search--;

		// Copy
		newrule->islist = false;
		newrule->value = (CHARPTR)CopyAndPtr(&(parameters[4])[1],search-parameters[4]);


	}
	else
	{
			cout << "Error in " << curfile << "(" << curline << ")"
				 << ": 5. parameter must be a list pointer (@listname) or a value in quotes (\"val\")" << endl;
			return 1;

	}

	// 6. parameter: action. sets what will be done if this rule matches
	// must be 'pass' or 'isspam' 
	if (stricmp(parameters[5],"isspam") == 0)
		newrule->action = A_ISSPAM;
	else if (stricmp(parameters[5],"pass") == 0)
		newrule->action = A_PASS;
	else
	{
		cout << "Error in " << curfile << "(" << curline << ")"
			 << ": 6. parameter must be 'isspam' or 'pass'" << endl;
		return 1;
	}


	// if the code ran up to this point, the command is ok
	// add to vector and return 0 (success)
	ruleset->push_back(newrule);

	return 0;

}

void SetFunctPointer(RULE* rule, RULE_TYPE type, bool issensitive)
// Sets the pointer of the comparison function according to the rule type
// and to the case sensitivity.

// About negation: Some comparison functions return zero if both strings match
// (e.g. strcmp), others return a non-zero values (e.g. strstr). The program
// expects a non-zero value for matching strings, so some results have to be negated

// Additionally, if we have negative rule type ("notequals", "notcontains") then
// we also have to negate the value (again)
{
	// now we need to go through all possible combinations of rule types and 
	// case sensitivity values

	switch (type)
	{
	case R_EQUALS:
		// check if value is equal
		if (issensitive == true)
			rule->compare = strcmp;		// case-sensitive equality check
		else
			rule->compare = stricmp;	// case-insensitive equality check

		rule->negate=false;				// no negative funct
		rule->negate=!rule->negate;		// because strcmp returns 0 for matching strings
		break;

	case R_NOTEQUALS:
		// same as R_EQUALS but negated
		if (issensitive == true)
			rule->compare = strcmp;		
		else
			rule->compare = stricmp;


		rule->negate=true;				// negative funct !
		rule->negate=!rule->negate;		// because strcmp returns 0 for matching strings
		break;

	case R_CONTAINS:
		// use function that return a non-zero value if a string
		// is contained in another string
		if (issensitive == true)
			rule->compare = strstrcaps;
		else
			rule->compare = stristrcaps;

		rule->negate = false;		// No negative funct
		break;

	case R_NOTCONTAINS:
		// same as R_CONTAINS but negated
		if (issensitive == true)
			rule->compare = strstrcaps;
		else
			rule->compare = stristrcaps;

		rule->negate = true;		// Negative funct!
		break;


	// [DBG] TODO: insert function for pattern matching

	}

}

int strstrcaps (const char* x, const char* y)
// This function encapsulates strstr as strstr itself does not
// fit to our string comparision function signature CHECKFUNC
// (because it returns char* and we need int)
{
	return (strstr(x,y) == 0) ? 0 : 1;
}

int stristrcaps (const char* x, const char* y)
// This function encapsulates stristr as stristr itself does not
// fit to our string comparision function signature CHECKFUNC
// (because it returns char* and we need int)
{
	return (stristr(x,y) == 0) ? 0 : 1;
}



UINT AddList(CHARPTR* parameters, LISTMAPPTR listmap)
// opens a list file and uses each line as one lsit item
// the list is added to 'listmap'
{

	CHARPTR filecont=0, fileend=0;
	UINT filelen;
	CHARPTR search=0,search2=0;
	UINT linecount=0, cur=0;
	LIST* newlist = new LIST;

	// read file contents
	GetFileCont(parameters[1],&filecont,&filelen);

	// if filecont == 0 then failed opening file
	if (filecont == 0)
	{
		cout << "Error in " << curfile << "(" << curline << ")"
			 << ": failed opening file '" << parameters[1] << "'" << endl; 
		return 1;
	}

	fileend = filecont + filelen - 2;

	// now count number of lines
	search = filecont;
	while ((search != 0) && (search < fileend))
	{
		linecount++;
		search++;
		search = strchr(search,10);
	}

	// reserve array of ptrs large enough for all lines
	newlist->count = linecount;
	newlist->items = new CHARPTR[linecount];
	
	// walk through all lines and save them to array
	search = filecont;
	cur = 0;
	while (search < fileend)
	{
		// find end of line
		search2 = strchr(search,10);
		if (search2 == 0) 
		{
			// last line
			newlist->items[cur] = (CHARPTR)CopyAndPtr(search,fileend-search);
			break;
		}
		search2--;

		// copy string
		newlist->items[cur] = (CHARPTR)CopyAndPtr(search,search2-search+1);
		cur++;


		// go to beginning of next line
		search = search2 + 2;
	}

	// save this list in listmap

	(*listmap)[parameters[0]] = newlist;


	return 0;
	
}

RULE_TYPE StrToRuletype(CHARPTR command)
// determines which rule type from enum RULE_TYPE belongs to
// the string command in 'command'
{
	if (stricmp(command,"contains") == 0)
		return R_CONTAINS;

	if (stricmp(command,"notcontains") == 0)
		return R_NOTCONTAINS;

	if (stricmp(command,"equals") == 0)
		return R_EQUALS;

	if (stricmp(command,"notequals") == 0)
		return R_NOTEQUALS;

	if (stricmp(command,"pattern") == 0)
		return R_PATTERN;

	if (stricmp(command,"notpattern") == 0)
		return R_NOTPATTERN;

	// if code up to this point 'command' does not contain a valid command
	return R_UNKNOWN;
}


RULE_COMMAND StrToCommand(CHARPTR command)
// determines which rule number from enum RULE_COMMAND belongs to
// the command in 'command'
{
	if (stricmp(command,"rule") == 0)
		return C_RULE;

	if (stricmp(command,"loadlist") == 0)
		return C_LIST;

	return C_UNKNOWN;
}

CHARPTR stristr(const char *szsrc,const char *szfind )
// this function performs a case insensitive string search
{
  int i, k, nfind, nsrc;

  // if one of the strings is a zero-pointer or begins with a zero-byte -> no match
  if( !szsrc || !szsrc[0] || !szfind || !szfind[0] )  
	  return(0); 

  // determine lengths of strings
  nsrc= strlen(szsrc);
  nfind= strlen(szfind);

  // now iterate through both strings and check byte for byte for
  // matching strings. all characters are converted to lowercase before comparison
  for( i=k=0 ; k<nfind && i<nsrc ; i++, k++ ) {
    if( toupper(szsrc[i]) != toupper(szfind[k]) ) {
         i -= k;
         k = -1;
    }
  }

  // k contains the max number of matching chars here
  // if this value is equal to the length of the search string -> match!
  if( k==nfind ) 
	return(char*)(szsrc + i-nfind);

  // if the code runs up to this point nothing the search string is not contained
  return(0);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -