<?php
/*
	DevSaver Web Framework
	Copyright (c) 2013-2016 DevSaver. 
	All rights reserved.
		web:  www.devsaver.com
		mail: support@devsaver.com		
*/

// dependencies

/**
* description
*
* @library	
* @author	
* @since	
*/
class CAntiSpam extends CPlugin{

	/**
	* description
	*
	* @var type
	*
	* @access type
	*/
	var $charset = array(
	
		"ar"	=> array('أ','ب','ت','ث','ج','ح','خ','د','ذ','ر','ز','س','ش','ص','ض','ط','ظ','ع','غ','ف','ق','ك','ل','م','ن','ﮬ','و','ي'),

		"default" => array(			
			"upper"		=> array("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"),
			"lower"		=> array("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"),
			"digits"	=> array(/*"1",*/"2","3","4","5","6","7","8","9")
		)
	);
	
	
	var $tplvars; 
	/**
	* description
	*
	* @var type
	*
	* @access type
	*/
	var $iscale = 5;
	var $perturbation = 0.85;
	

	function __constructor() {
		//$this->CPlugin($db, $tables , $templates);
		$this->name = "antispam";
	}

	function DoEvents(){
		global $base, $_CONF, $_TSM , $_VARS , $_USER , $_BASE , $_SESS;	
		
		parent::DoEvents();

		if ($_GET["mod"] == "antispam") {

			$this->__init();

			switch ($_GET["sub"]) {
				case "image.captcha":
					return $this->CaptchaImage();
				break;

			}
		}
		
	}

	function __init() {
		global $_CONF;

		if ($this->__inited) {
			return "";
		}

		$this->__inited = true;
		
		$path = $this->tpl_path;

		$templates = array(
			"classic"			=> "classic.htm",
			"recaptcha"			=> "recaptcha.htm",
		);

		foreach ($templates as $key => $val) {
			$this->private->templates[$key] = new CTemplateDynamic(
				$path . $val
			);
		}

		$this->tpl_module = $this->plugins["modules"]->LoadDefaultModule($this->name);


		//add recaptcha header
		if ($this->private->vars->data["set_captcha_type"] == "2") {
			$this->plugins["seo"]->AppedToHead($this->private->templates["recaptcha"]->blockReplace("Header"));
		}
		

	} 


	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function GetCaptchaField($default = 0 , $field = "" , $template = null , $block = "Field") {
		global $_SESS;

		$this->__init();

		if (!$this->tpl_module["settings"]["set_captcha"]) {
			return "";
		}
		
		

		if ($template) {		
			$tpl = $template;			
		} else {
			switch ($this->private->vars->data["set_captcha_type"]) {
				default: 
					$tpl = &$this->private->templates["classic"];
					$block = "Field";
				break;

				case "2":
					$tpl = &$this->private->templates["recaptcha"];
					$block = "Field";
				break;

			}
		}


		switch ($default) {
			case "0":
				//never show capcha
				return "";
			break;

			case "1":
				if (!$_SESS["client"]) {					
					return $tpl->blockReplace(
						$block , 
						$this->tpl_module["settings"],
						array(
							"code"	=> md5($field)
						)
					);
				}
				
			break;

			case "2":				
				return $tpl->blockReplace(
					$block , 
					$this->tpl_module["settings"],
					array(
						"code"	=> md5($field)
					)
				);
			break;
		}

		return "";

	}

	
	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function ValidateCaptcha($default = 0 , $field) {
		global $_SESS;

		$this->__init();

		if (!$this->tpl_module["settings"]["set_captcha"]) {
			return true;
		}


		switch ($default) {
			default:
				//never show capcha
				$validate = false;
			break;

			case "1":
				if (!$_SESS["client"]) {					
					$validate = true;
				}
				
			break;

			case "2":
				$validate = true;
			break;
		}


		$field = md5($field);

		if ($validate) {


			switch ($this->private->vars->data["set_captcha_type"]) {
				case "1":

					if (!$this->private->vars->data["set_capcha_cs"]) {
					   $_POST["image_code"] = strtoupper($_POST["image_code"]);

					   if ($_SESS["XML_verify_key" . $field]) {
						   $_SESS["XML_verify_key" . $field] = strtoupper($_SESS["XML_verify_key" . $field]);
					   }					   
					} 
					
					if ((!$_POST["image_code"]) || ($_POST["image_code"] != $_SESS["XML_verify_key" . $field])) {

						//invalidate this captcha
						$_SESS["XML_verify_key" . $field] = "invalidate";
						return false;
					}
				break;

				case "2":
					$data = CHTTP::NewInstance()
					->Get(
						"https://www.google.com/recaptcha/api/siteverify",
						array(
							"secret"	=> $this->private->vars->data["set_recaptcha_secret"],
							"response"	=> $_POST["g-recaptcha-response"],
							"remoteip"	=> $_SERVER["REMOTE_ADDR"],
						)
					)
					->Json();

					if (!$data["success"]) {
						return false;
					}
					
					return false;
					//validate
				break;
			}
		}

		//foce one use 
		if (isset($_SESS["XML_verify_key" . $field])) {
			unset($_SESS["XML_verify_key" . $field]);
		}	

		return true;
		
	}

	

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function CaptchaImage() {
		global $_SESS;
		
		//Select Font
		$set = "default";

		//Select random background image
		$bgurl = rand(1, 1);

		if ($this->vars->data["set_captcha_bg"] && file_exists("upload/antispam/captcha.png")) {
			$file = "upload/antispam/captcha.png";
		} elseif (file_exists("assets/antispam/bg".$bgurl.".png")) {
			$file = "assets/antispam/bg".$bgurl.".png";
		} else {
			$file = $this->path . "assets/bg".$bgurl.".png";
		}
		
		$this->image = ImageCreateFromPNG($file);
		//Generate the random string

		
		switch ($this->vars->data["set_captcha_style"]) {
			//alpha numberic
			default:
				if ($this->vars->data["set_capcha_cs"]) {
					$chars = array_merge(
						$this->charset[$set]["upper"],
						$this->charset[$set]["lower"],
						$this->charset[$set]["digits"]
					);
				} else {
					$chars = array_merge(
						$this->charset[$set]["upper"],
						$this->charset[$set]["digits"]					
					);
				}				
			break;

			//alpha
			case "1":
				if ($this->vars->data["set_capcha_cs"]) {
					$chars = $this->charset[$set]["upper"];				
				} else {
					$chars = array_merge(
						$this->charset[$set]["upper"],
						$this->charset[$set]["lower"]
					);
				}	
			break;

			//case numeric
			case "2":
				$chars = $this->charset[$set]["digits"];				
			break;

		}
		
		$length = max(1,$this->private->vars->data["set_captcha_width"]);
		$textstr = "";

		for ($i=0; $i<$length; $i++) {
		   $textstr .= ($chars[rand(0, count($chars)-1)]);		
		}

		//debug($textstr,1);

		$_SESS["XML_verify_key" . $_GET["code"]] = $textstr;

		$this->drawCaptcha(
			$textstr ,	//text
			$this->vars->data["set_captcha_text_size"] ? $this->vars->data["set_captcha_text_size"] : 15,
			$this->path . "assets/default.ttf",	//font
			$this->vars->data["set_captcha_color_text"] ? $this->vars->data["set_captcha_color_text"] : '#f3f3f3',	//text color
			$this->vars->data["set_captcha_color_bg"] ? $this->vars->data["set_captcha_color_bg"] : '#4e4e4e',	//background-color
			90,														//width
			45,														//height
			$this->vars->data["set_captcha_noice_lines"],			//noice lines
			$this->vars->data["set_captcha_noice_dots"],			//noice dots
			$this->vars->data["set_captcha_color_noice"] ? $this->vars->data["set_captcha_color_noice"] : '#f3f3f3'	//noice color
		);
		

		//Output PNG Image
		header("Content-Type: image/png");
		ImagePNG($this->image);

		//Destroy the image to free memory
		imagedestroy($this->image);

		die();

	}

	
	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function ValidateClient($module) {
		$this->__init();

		if (!$this->tpl_module["settings"]["set_domains"]) {
			return true;
		}


		$ip = explode("." , $_SERVER["REMOTE_ADDR"]);

		$ban_ip = $this->db->QFetchRowArray("
			SELECT * 
			FROM 
				{$this->tables['core:antispam_banned_domains']}
			WHERE
				( 
					domain_name LIKE '{$ip[0]}.0.0.0' OR 
					domain_name LIKE '{$ip[0]}.{$ip[1]}.0.0' OR 
					domain_name LIKE '{$ip[0]}.{$ip[1]}.{$ip[2]}.0' OR 
					domain_name LIKE '{$ip[0]}.{$ip[1]}.{$ip[2]}.{$ip[3]}' 
				) AND
				
				domain_type = 1 AND 
				domain_burner = 0 AND
				( domain_block_type = 0 OR ( domain_block_type = 1 AND find_in_set({$module[module_id]} , domain_modules) ) )
			"
		);


		if (is_array($ban_ip)) {
			foreach ($ban_ip as $key => $val) {
				//increase the ban set
				$this->db->QueryUpdateById(
					$this->tables['core:antispam_banned_domains'],
					array(
						"domain_blocks"	=> $val["domain_blocks"] + 1
					),
					$val["domain_id"]
				);
			}			
		}

		//in some cases the remote host wont be resolved by web server
		$host = $_SERVER["REMOTE_HOST"] ? $_SERVER["REMOTE_HOST"] : gethostbyaddr($_SERVER['REMOTE_ADDR']);

		if ($host) {

			$parts = array_reverse(explode("." , $host));

			$cond = array();

			foreach ($parts as $key => $val) {
				$cur[] = $val;

				$cur_dom = array_reverse($cur);
				$cond[] = " domain_name LIKE '" . implode("." , $cur_dom) . "' ";
			}
			
			$ban_domain = $this->db->QFetchRowArray("
				SELECT * 
				FROM 
					{$this->tables['core:antispam_banned_domains']} 
				WHERE
					'%s' LIKE concat('%%' , domain_name , '%%') AND
					domain_type = 0 AND 
					domain_burner = 0 AND
					( domain_block_type = 0 OR ( domain_block_type = 1 AND find_in_set({$module[module_id]} , domain_modules) ) )
			" , array($host));

			if (is_array($ban_domain)) {
				foreach ($ban_domain as $key => $val) {
					//increase the ban set
					$this->db->QueryUpdateById(
						$this->tables['core:antispam_banned_domains'],
						array(
							"domain_blocks"	=> $val["domain_blocks"] + 1
						),
						$val["domain_id"]
					);
				}				
			}
			
		}
		
		return !(is_array($ban_ip) || is_array($ban_domain));

	}

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function ValidateEmail($module , $email) {
		$this->__init();

		if (!$this->tpl_module["settings"]["set_burners"]) {
			return true;
		}


		if (!$email) {
			return true;
		}

		$parts = explode("@" , $email);

		$ban_domain = $this->db->QFetchRowArray("
			SELECT * 
			FROM 
				{$this->tables['core:antispam_banned_domains']} 
			WHERE
				'%s' LIKE concat('%%' , domain_name , '%%') AND
				domain_burner = 1 AND
				( domain_block_type = 0 OR ( domain_block_type = 1 AND find_in_set({$module[module_id]} , domain_modules) ) )
			",
			array(
				$parts[1]
			)
		);

		if (is_array($ban_domain)) {
			foreach ($ban_domain as $key => $val) {
				//increase the ban set
				$this->db->QueryUpdateById(
					$this->tables['core:antispam_banned_domains'],
					array(
						"domain_blocks"	=> $val["domain_blocks"] + 1
					),
					$val["domain_id"]
				);
			}				

			return false;
		}
		

		return true;
	}

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function CaptchaError() {
		return $this->tpl_module["settings"]["lang_capcha"];
	}

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function ClientError() {
		return $this->tpl_module["settings"]["lang_domain"];
	}

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function EmailError() {
		return $this->tpl_module["settings"]["lang_email"];
	}

	/* credits http://www.w3schools.in/php-script/captcha/ */
	function drawCaptcha($text , $fontSize , $font , $textColor,$backgroundColor,$imgWidth,$imgHeight,$noiceLines=0,$noiceDots=0,$noiceColor ) {	

		$textColor=$this->hexToRGB($textColor);	
		
		$im = imagecreatetruecolor($imgWidth, $imgHeight);	
		$textColor = imagecolorallocate($im, $textColor['r'],$textColor['g'],$textColor['b']);			
		
		$backgroundColor = $this->hexToRGB($backgroundColor);
		$backgroundColor = imagecolorallocate($im, $backgroundColor['r'],$backgroundColor['g'],$backgroundColor['b']);

		imagefill($im,0,0,$backgroundColor);	

		/* generating lines randomly in background of image */
		if($noiceLines>0){
			$noiceColor=$this->hexToRGB($noiceColor);	
			$noiceColor = imagecolorallocate($im, $noiceColor['r'],$noiceColor['g'],$noiceColor['b']);

			for( $i=0; $i<$noiceLines; $i++ ) {				
				imageline($im, mt_rand(0,$imgWidth), mt_rand(0,$imgHeight),
				mt_rand(0,$imgWidth), mt_rand(0,$imgHeight), $noiceColor);
			}
		}				
				
		if($noiceDots>0){/* generating the dots randomly in background */
			for( $i=0; $i<$noiceDots; $i++ ) {
				imagefilledellipse($im, mt_rand(0,$imgWidth),
				mt_rand(0,$imgHeight), 3, 3, $textColor);
			}
		}		
		
		list($x, $y) = $this->ImageTTFCenter($im, $text, $font, $fontSize);	
		imagettftext($im, $fontSize, 0, $x, $y, $textColor, $font, $text);		

		$this->image = $im;

	}
	
	/*function to convert hex value to rgb array*/
	function hexToRGB($colour) {
        if ( $colour[0] == '#' ) {
			$colour = substr( $colour, 1 );
        }
        if ( strlen( $colour ) == 6 ) {
			list( $r, $g, $b ) = array( $colour[0] . $colour[1], $colour[2] . $colour[3], $colour[4] . $colour[5] );
        } elseif ( strlen( $colour ) == 3 ) {
			list( $r, $g, $b ) = array( $colour[0] . $colour[0], $colour[1] . $colour[1], $colour[2] . $colour[2] );
        } else {
			return false;
        }
        $r = hexdec( $r );
        $g = hexdec( $g );
        $b = hexdec( $b );
        return array( 'r' => $r, 'g' => $g, 'b' => $b );
	}
		
		
	/*function to get center position on image*/
	function ImageTTFCenter($image, $text, $font, $size, $angle = 8) {
		$xi = imagesx($image);
		$yi = imagesy($image);
		$box = imagettfbbox($size, $angle, $font, $text);
		$xr = abs(max($box[2], $box[4]))+5;
		$yr = abs(max($box[5], $box[7]));
		$x = intval(($xi - $xr) / 2);
		$y = intval(($yi + $yr) / 2);
		return array($x, $y);	
	}



	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function isSpam($module , $data) {
		global $_CONF;
		
		//check if akismet is enabled
		if (!$this->tpl_module["settings"]["set_akismet"]) {
			return false;
		}
		
		//check if is enabled for this particular module
		if ($this->vars->data["set_akismet_type"]) {
			$mods = explode("," , $this->vars->data["set_akismet_modules"]);

			if (!in_array($module["module_id"] , $mods)) {
				return false;
			}			
		}
		
		//build the request
		$request = array(
			"blog"			=> $_CONF["url"] ,
			"user_ip"		=> $_SERVER["REMOTE_ADDR"],
			"user_agent"	=> $_SERVER["HTTP_USER_AGENT"],
			"referrer"		=> $_SERVER["HTTP_REFERER"],
		);

		if ($data["type"]) {
			$request["comment_type"] = $data["type"];
		}
		
		if ($data["url"]) {
			$request["permalink"] = $data["url"];
		}

		if ($data["author"]) {
			$request["comment_author"] = $data["author"];
		}
		
		if ($data["email"]) {
			$request["comment_author_email"] = $data["email"];
		}
		

		if ($data["message"]) {
			$request["comment_content"] = $data["message"];
		}

		if ($data["author_url"]) {
			$request["comment_author_url"] = $data["author_url"];
		}

		$host = $http_host = $this->vars->data["set_akismet_api"] .'.rest.akismet.com';
		$params = http_build_query($request);

		$path = '/1.1/comment-check';
		$port = 443;
		$akismet_ua = "DevSaver CMS | Akismet/3.1.7";
		$content_length = strlen( $params );
		$http_request  = "POST $path HTTP/1.0\r\n";
		$http_request .= "Host: $host\r\n";
		$http_request .= "Content-Type: application/x-www-form-urlencoded\r\n";
		$http_request .= "Content-Length: {$content_length}\r\n";
		$http_request .= "User-Agent: {$akismet_ua}\r\n";
		$http_request .= "\r\n";
		$http_request .= $params;
		$response = '';

		try {

			if( false != ( $fs = @fsockopen( 'ssl://' . $http_host, $port, $errno, $errstr, 10 ) ) ) {
				 
				fwrite( $fs, $http_request );
			 
				while ( !feof( $fs ) ) {
					$response .= fgets( $fs, 1160 ); // One TCP-IP packet
				}

				fclose( $fs );
				 
				$response = explode( "\r\n\r\n", $response, 2 );
			}

			 
			if ( 'true' == $response[1] ) {
				return true;
			} else {
				return false;
			}

		} catch (Exception $e) {
			//log somehow the error later
			return false;
		}
	}
	

}

?>