Login   Register  
PHP Classes
elePHPant
Icontem

File: floodassassin.php

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Benjamin Falk  >  Flood Assassin  >  floodassassin.php  >  Download  
File: floodassassin.php
Role: Class source
Content type: text/plain
Description: FloodAssassin class
Class: Flood Assassin
Check whether a message can be spam
Author: By
Last change: Added a new kind of rule.
Now it is possible to add rules which count the occurrences and adds for each time levels
Date: 6 years ago
Size: 10,621 bytes
 

Contents

Class file image Download
<?php
	/**
	 * FloodAssassin - protect your webpage of spam and flood
	 *
	 * requires PHP Version 5
	 *
	 * Copyright (C) 2008 Benjamin Falk
	 *
	 * FloodAssassin 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 3 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, see <http://www.gnu.org/licenses/>.
	 *
	 * @category   Text processing
	 * @package    FloodAssassin - protect your webpage of spam and flood
	 * @author     Benjamin Falk
	 * @copyright  2008 Benjamin Falk
	 * @license    http://www.gnu.org/licenses/gpl.txt GNU GPL Version 3
	 * @version    0.2
	 * @link       http://projects.citrosaft.com/floodassassin
	 */
	
	class FLOODASSASSIN
	{
		/*
		 * Default level-values
		 */
		public $lvContent		= 3;
		public $lvName			= 0.5;
		public $lvMail			= 0.3;
		public $lvIP			= 1;
		
		/*
		 * How much difference has to be between words for readable text
		 * status? 6 = default
		 */
		public $readable		= 6;
		
		/*
		 * The following variables are for the connection to a mysql
		 * database
		 */
		private $sqlHost		= 'localhost';
		private $sqlUsername	= 'root';
		private $sqlPassword	= 'root';
		private $sqlDatabase	= 'floodassassin';
		private $sqlTable		= 'floodrules';
		
		/*
		 * The following variables are for the structure of the
		 * database table
		 */
		private $sqlContent		= 'rule_content';
		private $sqlContentCount= 'rule_contentcount';
		private $sqlName		= 'rule_name';
		private $sqlMail		= 'rule_mail';
		private $sqlIP			= 'rule_ip';
		private $sqlModifier	= 'rule_modifier';
		private $sqlContentLv	= 'rule_contentlevel';
		private $sqlNameLv		= 'rule_namelevel';
		private $sqlMailLv		= 'rule_maillevel';
		private $sqlIPLv		= 'rule_iplevel';
		private $sqlDesc		= 'rule_description';
		
		/*
		 * The current connection
		 */
		private $sqlConnection	= null;
		
		/*
		 * The $rules-variables get automatically filled.
		 */
		private $rulesContent	= array();
		private $rulesContentCount=array();
		private $rulesName		= array();
		private $rulesMail		= array();
		private $rulesIP		= array();
		private $rulesModifier	= array();
		private $rulesContentLv	= array();
		private $rulesNameLv	= array();
		private $rulesMailLv	= array();
		private $rulesIPLv		= array();
		private $rulesDesc		= array();
		
		/*
		 @ readExternalConfFile	- reads an external configuration-file
		 */
		private function readExternalConfFile($file)
		{
			if (!file_exists($file))
				die('External configuration-file ('.$file.') does not exist');
			
			require_once($file);
			$vars = array(	'sqlHost', 'sqlUsername', 'sqlPassword',
							'sqlDatabase', 'sqlTable', 'sqlContent',
							'sqlContentCount', 'sqlName', 'sqlMail', 'sqlIP',
							'sqlModifier', 'sqlContentLv', 'sqlNameLv',
							'sqlMailLv');
			foreach ($vars as $var)
			{	//Check all variables
				if (isset($$var))
					$this->$var = $$var;
			}
			
			return true;
		}
		
		/*
		 @ sqlConnect			- create mysql-connection
		 */
		private function sqlConnect()
		{
			//Create connection
			$this->sqlConnection = mysql_connect($this->sqlHost, $this->sqlUsername, $this->sqlPassword);
			if (!$this->sqlConnection || mysql_error())
				die(mysql_error());
			
			//Select database
			$dbResult = mysql_select_db($this->sqlDatabase);
			if (!$dbResult || mysql_error())
				die(mysql_error());
		}
		
		/*
		 @ fillRules			- get rules
		 */
		private function fillRules()
		{
			if ($this->sqlConnection == null) return false;
			
			$dbSql		= "SELECT `{$this->sqlContent}`, `{$this->sqlContentCount}`, `{$this->sqlName}`, `{$this->sqlMail}`, `{$this->sqlIP}`, `{$this->sqlModifier}`, `{$this->sqlContentLv}`,	`{$this->sqlNameLv}`, `{$this->sqlMailLv}`, `{$this->sqlIPLv}`, `{$this->sqlDesc}` FROM `{$this->sqlTable}`;";
			$dbResult	= mysql_query($dbSql);
			if (mysql_error()) die(mysql_error());
			
			while ($row = mysql_fetch_assoc($dbResult))
			{
				$row[$this->sqlContent]		= $this->replaceVars($row[$this->sqlContent]);
				$row[$this->sqlName]		= $this->replaceVars($row[$this->sqlName]);
				$row[$this->sqlMail]		= $this->replaceVars($row[$this->sqlMail]);
				
				$this->rulesContent[]		= $row[$this->sqlContent];
				$this->rulesContentCount[]	= $row[$this->sqlContentCount];
				$this->rulesName[]			= $row[$this->sqlName];
				$this->rulesMail[]			= $row[$this->sqlMail];
				$this->rulesIP[]			= $row[$this->sqlIP];
				$this->rulesModifier[]		= $row[$this->sqlModifier];
				$this->rulesContentLv[]		= $row[$this->sqlContentLv];
				$this->rulesNameLv[]		= $row[$this->sqlNameLv];
				$this->rulesMailLv[]		= $row[$this->sqlMailLv];
				$this->rulesIPLv[]			= $row[$this->sqlIPLv];
				$this->rulesDesc[]			= $row[$this->sqlDesc];
			}
		}
		
		/*
		 @ replaceVars			- replaces some simple vars into regex
		 @ $str					- contains the regular expression
		 */
		private function replaceVars($str)
		{
			$str = str_replace('%link', '(mailto\:|http(s?)\:\/\/|http(s?)\:\/\/www|www){1}[\w\d\.\-]+(.^[\s])*', $str);
			$str = str_replace('%mail', '[\w\d\-\.]+[\s]*(@|\[at\])[\s]*[\w\d\-]\.[\w\d\-]+', $str);
			preg_match_all('/\%neglook\(\[(.+?)\/([\d]+)\]\)/', $str, $match);
			foreach ($match[0] as $i => $s)
			{
				$part	= '';
				$chars	= $match[1][$i];
				$count	= intval($match[2][$i]);
				if ($count == 1)
					$part = $chars;
				elseif ($count > 1)
				{
					$part = '(?i:';
					for ($ic=1; $ic<$count; $ic++)
					{
						$part .= '('.$chars.')(?!';
						for ($ii=1; $ii<=$ic; $ii++)
							$part .= '\\'.$ii;
						$part .= ')';
					}
					$part .= '('.$chars.'))';
				}
				$str = str_replace($match[0][$i], $part, $str);
			}
			
			return $str;
		}
		
		/*
		 @ __construct			- the main-function for initializing the class
		 @ [$confFile]			- an external file for the sql-configuration
		 @ [$useConnection]		- use existing database-connection
		 */
		public function __construct($confFile=-1, $useConnection=-1)
		{
			if ($confFile != -1) //Read external configuration, if needed
				$this->readExternalConfFile($confFile);
			
			if ($useConnection == -1)	$this->sqlConnect();
			else						$this->sqlConnection = $useConnection;
			
			$this->fillRules();
		}
		
		/*
		 @ checkMessage			- the main-function for checking an incomming
		 @						  message
		 @ $content				- contains the content of the given message
		 @ [$name]				- the author of the message
		 @ [$mail]				- email of author
		 @ [$ip]				- the IP of the author
		 */
		public function checkMessage($content, $name='', $mail='', $ip='')
		{
			$count		= count($this->rulesContent);
			$level		= array();
			$levelDesc	= array();
			
			//If the message is empty, it seems, it is spam
			if ($content == '') $level = $this->lvContent;
			
			for ($i=0; $i<$count; $i++)
			{	//Check message with every rule
				if ($this->rulesContentCount[$i] == 0)
				{	//Check with basic rule
					if ($this->rulesContent[$i] != '' && preg_match('/'.$this->rulesContent[$i].'/'.$this->rulesModifier[$i], $content) == 1)
					{	//Check content
						$levelDesc[] = $this->rulesDesc[$i];
						if ($this->rulesContentLv[$i] != 0)
							$level[] = $this->rulesContentLv[$i];
						else
							$level[] = $this->lvContent;
					}
				}
				else
				{	//Check with a counting rule
					if ($this->rulesContent[$i] != '' && ($resultCount = preg_match_all('/'.$this->rulesContent[$i].'/'.$this->rulesModifier[$i], $content, $match)) > 0)
					{
						$baseLevel		= $this->rulesContentCount;
						$levelDesc[]	= $this->rulesDesc[$i].' ('.$resultCount.')';
						$level[]		= $this->rulesContentCount[$i]*$resultCount;
					}
				}
				
				if ($name != '')
				{	//Check name
					if ($this->rulesName[$i] != '' && preg_match('/'.$this->rulesName[$i].'/'.$this->rulesModifier[$i], $name) == 1)
					{
						$levelDesc[] = $this->rulesDesc[$i];
						if ($this->rulesNameLv[$i] != 0)
							$level[] = $this->rulesNameLv[$i];
						else
							$level[] = $this->lvName;
					}
				}
				
				if ($mail != '')
				{	//Check mail
					if ($this->rulesMail[$i] != '' && preg_match('/'.$this->rulesMail[$i].'/'.$this->rulesModifier[$i], $mail) == 1)
					{
						$levelDesc[] = $this->rulesDesc[$i];
						if ($this->rulesMailLv[$i] != 0)
							$level[] = $this->rulesMailLv[$i];
						else
							$level[] = $this->lvMail;
					}
				}
				
				if ($ip != '')
				{	//Check ip
					if ($this->rulesIP[$i] == $ip)
					{
						$levelDesc[] = $this->rulesDesc[$i];
						if ($this->rulesIPLv[$i] != 0)
							$level[] = $this->rulesIPLv[$i];
						else
							$level[] = $this->lvIP;
					}
				}
			}
			
			//Now check if text is readable
			$wordMin = $wordMax = 0;
			$smile = false;
			$parts = preg_split('/[\s]+/', $content);
			foreach ($parts as $part)
			{
				if (preg_match('/^[\:\$8][\)\w]{1,2}$/', $part) == 1 && $smile == false)
				{	//Smile
					$levelDesc[] = 'HUMAN EMOTION';
					$level[] = -0.2;
					$smile = true;
				}
				else
				{	//Word
					$words = array($part);
					if (strpos($part, '/') !== false)
						$words	= explode('/', $part); //split inner words
					
					foreach($words as $word)
					{
						$word	= trim($part, ',.:');
						$len	= strlen($word);
						if ($wordMin == 0 || $len < $wordMin)
							$wordMin = $len;
						
						if ($len > $wordMax)
							$wordMax = $len;
					}
				}
			}
			$wordDif = $wordMax-$wordMin;
			if ($wordDif >= $this->readable)
			{	//Seems to be readable
				$level[] = -0.5;
				$levelDesc[] = 'READABLE';
			}
			else
			{
				$levelDesc[] = 'NOT READABLE';
				$level[] = 0.5;
			}
			
			$words = count($parts);
			if ($words < 3)
			{
				$levelDesc[] = 'TINY TEXT';
				$level[] = 5;
			}
			elseif ($words < 7)
			{
				$levelDesc[] = 'SMALL TEXT';
				$level[] = 2;
			}
			
			//Check if links and email-addresses are in content
			preg_match_all('/'.$this->replaceVars('%link').'/', $content, $result);
			$count			= count($result[0]);
			$level[]		= $count*0.7;
			$levelDesc[]	= "LINKS ($count)";
			preg_match_all('/'.$this->replaceVars('%mail').'/', $content, $result);
			$count			= count($result[0]);
			$level[]		= $count*0.7;
			$levelDesc[]	= "MAILS ($count)";
			
			
			return array(array_sum($level), $level, $levelDesc);
		}
	}
?>