Location: PHPKode > projects > MicroMVC PHP Framework > modules/core/classes/captcha.php
<?php defined('SYSTEM_PATH') or die('No direct access');
/**
 * Captcha Class
 *
 * Creates Captcha images and math problems for forms
 *
 * @package		MicroMVC
 * @author		David Pennington
 * @copyright	(c) 2010 MicroMVC Framework
 * @license		http://micromvc.com/license
 ********************************** 80 Columns *********************************
 */

/**
 *
 * Sometimes you need to verify that the client posting
 * or registering in your site is actually a human. By
 * asking him/her to type in the word s/he sees, you ensure
 * that the client is human, and not a bot/spider which
 * is probably trying to harm your system.
 * Play around with the values when constructing this
 * object, but also feel free to experiment with the
 * maths inside the image manipulating loops.
 * Note that this class is writing a png file on disk,
 * so you might need to have a png with the same name
 * already present in that location with write
 * permissions set.
 *
 * Note: you must have the GDImage lib installed!
 */

class captcha {

	/**
	 * Create
	 *
	 * Create a captcha PNG image
	 *
	 * @param	string	the text for the captcha
	 * @param	string	the file name
	 * @param	array	params to pass to the model constructor
	 * @return	void
	 */

	public function create($text=null, $file=null, $size=null) {

		//IF no text for the captcha image was set
		if(!$text) {
			$text = random_charaters(6, TRUE);
		}

		//IF no size is set = defualt to "3"
		if(!$size) {$size=3;}

		$font = 4;
		$cosrate = rand(10,19);
		$sinrate = rand(10,18);


		$charwidth = @imagefontwidth($font);
		$charheight = @imagefontheight($font);
		$width=(strlen($text)+2)*$charwidth;
		$height=1.5*$charheight;

		$im = @imagecreatetruecolor($width, $height)
		or trigger_error('Cannot Initialize new GD image stream! (is GD installed?)');
		$im2 = imagecreatetruecolor($width*$size, $height*$size);

		//Here we make the background and text alternate between light and dark
		$bcol = imagecolorallocate($im, rand(80,100), rand(80,100), rand(80,100));
		$fcol = imagecolorallocate($im, rand(150,200), rand(150,200), rand(150,200));


		imagefill($im, 0, 0, $bcol);
		imagefill($im2, 0, 0, $bcol);

		$dotcol = imagecolorallocate($im, (abs($this->rbg_red($fcol)-$this->rbg_red($bcol)))/4,
		(abs($this->rbg_green($fcol)-$this->rbg_green($bcol)))/4,
		(abs($this->rbg_blue($fcol)-$this->rbg_blue($bcol)))/4);

		$dotcol2 = imagecolorallocate($im, (abs($this->rbg_red($fcol)-$this->rbg_red($bcol)))/2,
		(abs($this->rbg_green($fcol)-$this->rbg_green($bcol)))/2,
		(abs($this->rbg_blue($fcol)-$this->rbg_blue($bcol)))/2);

		$linecol = imagecolorallocate($im, (abs($this->rbg_red($fcol)-$this->rbg_red($bcol)))/2,
		(abs($this->rbg_green($fcol)-$this->rbg_green($bcol)))/2,
		(abs($this->rbg_blue($fcol)-$this->rbg_blue($bcol)))/2);


		//Groups and warps Pixels
		for($i=0; $i<$width; $i=$i+rand(0,2)) {
			for($j=0; $j<$height; $j=$j+rand(0,2)) {
				imagesetpixel($im, $i, $j, $dotcol);
			}
		}

		//Adds Text
		imagestring($im, $font, $charwidth, $charheight/3, $text, $fcol);

		/*
		 //Adds Horizontal lines
		 for($j=0; $j<$height*$size; $j=$j+rand(2,6)) {
		 imageline($im2, 0, $j, $width*$size, $j, $linecol);
		 }
		 */

		/*
		 //Adds Vertical lines
		 for($i=0; $i<$width*$size; $i=$i+rand(1,19)) {
		 imageline($im2, $i, 0, $i, $height*$size, $linecol);
		 }
		 */

		//Adds horizontal dots
		for($i=0; $i<$width*$size; $i++) {
			for($j=0; $j<$height*$size; $j++) {
				$x = abs(((cos($i/$cosrate)*5+sin($j/$sinrate*2)*2+$i)/$size))%$width;
				$y = abs(((sin($j/$sinrate)*5+cos($i/$cosrate*2)*2+$j)/$size))%$height;
				$col = imagecolorat($im, $x, $y);
				if ($col!=$bcol) imagesetpixel($im2, $i, $j, $col);
			}
		}

		//Adds more horizontal dots
		for($j=0; $j<$height*$size; $j=$j+rand(2,5)) {
			for($i=0; $i<$width*$size; $i=$i+rand(2,5)) {
				imagesetpixel($im2, $i, $j, $dotcol2);
			}
		}

		/*
		//Adds the same number of vertical lines as chars (2px thick each)
		$start = rand(0, 10);
		for($a = 1; $a <= strlen($text); $a++) {
			$x = $start+$a*30;
			$color = imagecolorallocate($im2, rand(90,120), rand(90,120), rand(90,120));
			imageline($im2, $x, 0, $x, $height*$size, $color);
			imageline($im2, $x + 1, 0, $x + 1, $height*$size, $color);
		}
		*/


		//Adds three polygons to radom places
		for($a = 1; $a < 4; $a++) {
			$points = array(
				rand(0, $width*$size),
				rand(0, $height*$size),
				rand(0, $width*$size),
				rand(0, $height*$size),
				rand(0, $width*$size),
				rand(0, $height*$size),
				rand(0, $width*$size),
				rand(0, $height*$size)
			);

			imagepolygon($im2, $points, 4, imagecolorallocate($im2, rand(60, 120),rand(60, 120),rand(60, 120)));
		};


		//If we are just sending this to the browser
		if(empty($file)) {
			header('Content-type: image/png');
		}

		//Create final png file
		imagepng($im2, $file);

		//Destroy the copies
		imagedestroy($im);
		imagedestroy($im2);

		return $text;
	}


	//functions to extract RGB values from combined 24bit color value
	public function rbg_red($col) {return (($col >> 8) >> 8) % 256;}
	public function rbg_green($col) {return ($col >> 8) % 256;}
	public function rbg_blue($col) {return $col % 256;}


	/**
	 * Create a text based math captcha. Returns
	 * and array of the numeric answer and textual
	 * question.
	 *
	 * @param	int	$min
	 * @param	int	$max
	 * @param	bool $textual
	 * @return	array
	 */
	function math_captcha($min = 0, $max = 10, $textual = TRUE) {

		//textual numbers zero to tweenty
		$numbers = array(
			'zero', 'one', 'two', 'three', 'four', 'five', 'six',
			'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve',
			'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen',
			'eighteen', 'nineteen', 'twenty'
		);

		$first = rand($min, $max);
		$second = rand($min, $max);
		$operator = rand(0, 1);

		//Force the first number to be larger than the second
		if( ! $operator && $first < $second) {

			while( $first < $second ) {
				$first = rand($min, $max);
				$second = rand($min, $max);
			}
		}

		//Solve answer
		$answer = $operator ? $first + $second : $first - $second;

		//Question in textual form?
		if( $textual ) {
			$string = $numbers[$first] . ($operator ? ' plus ' : ' minus '). $numbers[$second];

		} else {
			$string = $first. ($operator ? ' + ' : ' - '). $second;
		}

		//Return the math question and answer
		return array('answer' => $answer, 'question' => $string);

	}
}

Return current item: MicroMVC PHP Framework