Location: PHPKode > projects > Simple Way to Usenet > libs/core/auth/chals/captcha.class.php
<?php
/**
 * 
 * @author  Benjamin Gillissen <hide@address.com>
 * 
 *	**************************************************************

	Copyright (C) 2009  Benjamin Gillissen
	
	This program 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 2
	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 at:
	http://www.gnu.org/copyleft/gpl.html

 *	**************************************************************
 */
class captcha {
	
	private $acceptedChars = 'ABCDEFGHIJKLMNPQRSTUVWXYZ123456789';
	private $stringlength = 4;
	private $contrast = 60;		// A value between 0 and 100 describing how much color overlap
								// there is between text and other objects.  Lower is more
								// secure against bots, but also harder to read.
	private $num_polygons = 3; 	// Number of triangles to draw.  0 = none
	private $num_ellipses = 2;  	// Number of ellipses to draw.  0 = none
	private $num_lines = 2;  		// Number of lines to draw.  0 = none
	private $num_dots = 3;  		// Number of dots to draw.  0 = none

	private $min_thickness = 2;  	// Minimum thickness in pixels of lines
	private $max_thickness = 8;  	// Maximum thickness in pixles of lines
	private $min_radius = 5;  		// Minimum radius in pixels of ellipses
	private $max_radius = 15;  	// Maximum radius in pixels of ellipses

	private $object_alpha = 80;	// How opaque should the obscuring objects be. 0 is opaque, 127 is transparent.
	private $o_contrast;
	private $width;
	private $height;

	
	private $img;
	
	public function __construct(){
		//TODO check needed functions, drop fatal if missing
	}
	
	public function sendimage($key){
		$this->buildimage($key);
		header('Content-type: image/png');
		imagepng($this->img);
	}
		
	public function genkey(){
		$max = strlen($this->acceptedChars)-1;
		$o = '';
		for($i=0; $i < $this->stringlength; $i++) {
			$o .= $this->acceptedChars{mt_rand(0, $max)};
		}
		return $o;
	}
	
	private function buildimage($pass){
		if ( empty($pass) ){ $pass = '  ?  '; }
		// Keep #'s reasonable.
		$this->min_thickness = max(1,$this->min_thickness);
		$this->max_thickness = min(20,$this->max_thickness);
		// Make radii into height/width
		$this->min_radius *= 2;
		$this->max_radius *= 2;
		// Renormalize contrast
		$this->contrast = 255 * ($this->contrast / 100.0);
		$this->o_contrast = 1.3 * $this->contrast;
		$this->width = 15 * imagefontwidth ($this->stringlength+1);
		$this->height = 2.2 * imagefontheight ($this->stringlength+1);
		$this->img = imagecreatetruecolor ($this->width, $this->height);
		imagealphablending($this->img, true);
		imagecolorallocatealpha($this->img,0,0,0,0);
		
		$this->addstring($pass);
		$this->addpoly();
		$this->addcircles();
		$this->addlines();
		$this->adddots();
	}
	
	private function addstring($pass){
		$c=$this->stringlength;
		for($i=0; $i < $this->stringlength; $i++) {
			$chars[$i] = substr($pass, ($this->stringlength-$c), 1 );
			$c--;
		}
		// Add string to image
		$rotated = imagecreatetruecolor (70, 70);
		$x=0;
		for ($i = 0; $i < $this->stringlength; $i++) {
			$buffer = imagecreatetruecolor (20, 20);
			$buffer2 = imagecreatetruecolor (40, 40);
	
			// Get a random color
			$red = mt_rand(0,255);
			$green = mt_rand(0,255);
			$blue = 255 - sqrt($red * $red + $green * $green);
			$color = imagecolorallocate ($buffer, $red, $green, $blue);

			// Create character
			imagestring($buffer, 5, 0, 0, $chars[$i], $color);

			// Resize character
			imagecopyresized ($buffer2, $buffer, 0, 0, 0, 0, 25 + mt_rand(0,12), 25 + mt_rand(0,12), 20, 20);

			// Rotate characters a little
			$rotated = imagerotate($buffer2, mt_rand(-25, 25),imagecolorallocatealpha($buffer2,0,0,0,0)); 
			imagecolortransparent ($rotated, imagecolorallocatealpha($rotated,0,0,0,0));

			// Move characters around a little
			$y = mt_rand(1, 3);
			$x += mt_rand(2, 6); 
			imagecopymerge ($this->img, $rotated, $x, $y, 0, 0, 40, 40, 100);
			$x += 22;

			imagedestroy ($buffer); 
			imagedestroy ($buffer2); 
		}
	}
	
	private function addpoly(){
		// Draw polygons
		if ($this->num_polygons > 0) for ($i = 0; $i < $this->num_polygons; $i++) {
			$vertices = array (
			mt_rand(-0.25*$this->width,$this->width*1.25),mt_rand(-0.25*$this->width,$this->width*1.25),
			mt_rand(-0.25*$this->width,$this->width*1.25),mt_rand(-0.25*$this->width,$this->width*1.25),
			mt_rand(-0.25*$this->width,$this->width*1.25),mt_rand(-0.25*$this->width,$this->width*1.25)
			);
			$color = imagecolorallocatealpha (	$this->img, 
												mt_rand(0,$this->o_contrast),
												mt_rand(0,$this->o_contrast),
												mt_rand(0,$this->o_contrast),
												$this->object_alpha
											);
			imagefilledpolygon($this->img, $vertices, 3, $color);  
		}
	}
	
	private function addcircles(){
		// Draw random circles
		if ($this->num_ellipses > 0) for ($i = 0; $i < $this->num_ellipses; $i++) {
			$x1 = mt_rand(0,$this->width);
			$y1 = mt_rand(0,$this->height);
			$color = imagecolorallocatealpha (	$this->img,
												mt_rand(0,$this->o_contrast), 
												mt_rand(0,$this->o_contrast), 
												mt_rand(0,$this->o_contrast), 
												$this->object_alpha
											);
			imagefilledellipse(	$this->img, 
								$x1, 
								$y1, 
								mt_rand($this->min_radius,$this->max_radius), 
								mt_rand($this->min_radius,$this->max_radius), 
								$color
							);  
		}
	}
	
	private function addlines(){
		// Draw random lines
		if ($this->num_lines > 0) for ($i = 0; $i < $this->num_lines; $i++) {
			$x1 = mt_rand(-$this->width*0.25,$this->width*1.25);
			$y1 = mt_rand(-$this->height*0.25,$this->height*1.25);
			$x2 = mt_rand(-$this->width*0.25,$this->width*1.25);
			$y2 = mt_rand(-$this->height*0.25,$this->height*1.25);
			$color = imagecolorallocatealpha ( $this->img, 
												mt_rand(0,$this->o_contrast), 
												mt_rand(0,$this->o_contrast), 
												mt_rand(0,$this->o_contrast), 
												$this->object_alpha
											);
			imagesetthickness ($this->img, mt_rand($this->min_thickness,$this->max_thickness));
			imageline($this->img, $x1, $y1, $x2, $y2 , $color);  
		}
	}
	
	private function adddots(){
		// Draw random dots
		if ($this->num_dots > 0) for ($i = 0; $i < $this->num_dots; $i++) {
			$x1 = mt_rand(0,$this->width);
			$y1 = mt_rand(0,$this->height);
			$color = imagecolorallocatealpha (	$this->img, 
												mt_rand(0,$this->o_contrast), 
												mt_rand(0,$this->o_contrast),
												mt_rand(0,$this->o_contrast),
												$this->object_alpha
											);
			imagesetpixel($this->img, $x1, $y1, $color);
		}
	}
}
Return current item: Simple Way to Usenet