Modules

Captcha_Math
extends Captcha

Math captcha class.

package
Captcha
subpackage
Captcha_Math
author
Michael Lavers
Kohana Team
copyright
© 2008-2010 Kohana Team
license
http://kohanaphp.com/license.html

Class declared in MODPATH/captcha/classes/captcha/math.php on line 12.

Properties

public static array $config

Default config values

array(8) (
    "style" => string(5) "basic"
    "width" => integer 150
    "height" => integer 50
    "complexity" => integer 4
    "background" => string(0) ""
    "fontpath" => string(0) ""
    "fonts" => array(0) 
    "promote" => bool FALSE
)

public static object $instance

Captcha singleton

NULL

protected string $driver

Style-dependent Captcha driver

protected string $image

Image resource identifier

protected string $image_type

Image type ("png", "gif" or "jpeg")

protected string $response

The correct Captcha challenge answer

private string $math_exercise

Captcha math exercise

Methods

public generate_challenge( ) (defined in Captcha_Math)

Generates a new Captcha challenge.

Return Values

  • string - The challenge answer

Source Code

public function generate_challenge()
{
	// Easy
	if (Captcha::$config['complexity'] < 4)
	{
		$numbers[] = mt_rand(1, 5);
		$numbers[] = mt_rand(1, 4);
	}
	// Normal
	elseif (Captcha::$config['complexity'] < 7)
	{
		$numbers[] = mt_rand(10, 20);
		$numbers[] = mt_rand(1, 10);
	}
	// Difficult, well, not really ;)
	else
	{
		$numbers[] = mt_rand(100, 200);
		$numbers[] = mt_rand(10, 20);
		$numbers[] = mt_rand(1, 10);
	}

	// Store the question for output
	$this->math_exercise = implode(' + ', $numbers).' = ';

	// Return the answer
	return array_sum($numbers);
}

public render( [ boolean $html = bool TRUE ] ) (defined in Captcha_Math)

Outputs the Captcha riddle.

Parameters

  • boolean $html = bool TRUE - HTML output

Return Values

  • mixed

Source Code

public function render($html = TRUE)
{
	return $this->math_exercise;
}

public __construct( [ string $group = NULL ] ) (defined in Captcha)

Constructs a new Captcha object.

Parameters

  • string $group = NULL - Config group name

Tags

Return Values

  • void

Source Code

public function __construct($group = NULL)
{
	// Create a singleton instance once
	empty(Captcha::$instance) and Captcha::$instance = $this;

	// No config group name given
	if ( ! is_string($group))
	{
		$group = 'default';
	}

	// Load and validate config group
	if ( ! is_array($config = Kohana::$config->load('captcha')->get($group)))
		throw new Kohana_Exception('Captcha group not defined in :group configuration',
				array(':group' => $group));

	// All captcha config groups inherit default config group
	if ($group !== 'default')
	{
		// Load and validate default config group
		if ( ! is_array($default = Kohana::$config->load('captcha')->get('default')))
			throw new Kohana_Exception('Captcha group not defined in :group configuration',
				array(':group' => 'default'));

		// Merge config group with default config group
		$config += $default;
	}

	// Assign config values to the object
	foreach ($config as $key => $value)
	{
		if (array_key_exists($key, Captcha::$config))
		{
			Captcha::$config[$key] = $value;
		}
	}

	// Store the config group name as well, so the drivers can access it
	Captcha::$config['group'] = $group;

	// If using a background image, check if it exists
	if ( ! empty($config['background']))
	{
		Captcha::$config['background'] = str_replace('\\', '/', realpath($config['background']));

		if ( ! is_file(Captcha::$config['background']))
			throw new Kohana_Exception('The specified file, :file, was not found.',
				array(':file' => Captcha::$config['background']));
	}

	// If using any fonts, check if they exist
	if ( ! empty($config['fonts']))
	{
		Captcha::$config['fontpath'] = str_replace('\\', '/', realpath($config['fontpath'])).'/';

		foreach ($config['fonts'] as $font)
		{
			if ( ! is_file(Captcha::$config['fontpath'].$font))
				throw new Kohana_Exception('The specified file, :file, was not found.',
					array(':file' => Captcha::$config['fontpath'].$font));
		}
	}

	// Generate a new challenge
	$this->response = $this->generate_challenge();

	Kohana::$log->add(Log::DEBUG, 'Captcha Library initialized');
}

public __toString( ) (defined in Captcha)

Magically outputs the Captcha challenge.

Return Values

  • mixed

Source Code

public function __toString()
{
	return $this->render(TRUE);
}

public image_create( [ string $background = NULL ] ) (defined in Captcha)

Creates an image resource with the dimensions specified in config. If a background image is supplied, the image dimensions are used.

Parameters

  • string $background = NULL - Path to the background image file

Tags

Return Values

  • void

Source Code

public function image_create($background = NULL)
{
	// Check for GD2 support
	if ( ! function_exists('imagegd2'))
		throw new Kohana_Exception('captcha.requires_GD2');

	// Create a new image (black)
	$this->image = imagecreatetruecolor(Captcha::$config['width'], Captcha::$config['height']);

	// Use a background image
	if ( ! empty($background))
	{
		// Create the image using the right function for the filetype
		$function = 'imagecreatefrom'.$this->image_type($background);
		$this->background_image = $function($background);

		// Resize the image if needed
		if (imagesx($this->background_image) !== Captcha::$config['width']
		    or imagesy($this->background_image) !== Captcha::$config['height'])
		{
			imagecopyresampled
			(
				$this->image, $this->background_image, 0, 0, 0, 0,
				Captcha::$config['width'], Captcha::$config['height'],
				imagesx($this->background_image), imagesy($this->background_image)
			);
		}

		// Free up resources
		imagedestroy($this->background_image);
	}
}

public image_gradient( resource $color1 , resource $color2 [, string $direction = NULL ] ) (defined in Captcha)

Fills the background with a gradient.

Parameters

  • resource $color1 required - GD image color identifier for start color
  • resource $color2 required - GD image color identifier for end color
  • string $direction = NULL - Direction: 'horizontal' or 'vertical', 'random' by default

Return Values

  • void

Source Code

public function image_gradient($color1, $color2, $direction = NULL)
{
	$directions = array('horizontal', 'vertical');

	// Pick a random direction if needed
	if ( ! in_array($direction, $directions))
	{
		$direction = $directions[array_rand($directions)];

		// Switch colors
		if (mt_rand(0, 1) === 1)
		{
			$temp = $color1;
			$color1 = $color2;
			$color2 = $temp;
		}
	}

	// Extract RGB values
	$color1 = imagecolorsforindex($this->image, $color1);
	$color2 = imagecolorsforindex($this->image, $color2);

	// Preparations for the gradient loop
	$steps = ($direction === 'horizontal') ? Captcha::$config['width'] : Captcha::$config['height'];

	$r1 = ($color1['red'] - $color2['red']) / $steps;
	$g1 = ($color1['green'] - $color2['green']) / $steps;
	$b1 = ($color1['blue'] - $color2['blue']) / $steps;

	if ($direction === 'horizontal')
	{
		$x1 =& $i;
		$y1 = 0;
		$x2 =& $i;
		$y2 = Captcha::$config['height'];
	}
	else
	{
		$x1 = 0;
		$y1 =& $i;
		$x2 = Captcha::$config['width'];
		$y2 =& $i;
	}

	// Execute the gradient loop
	for ($i = 0; $i <= $steps; $i++)
	{
		$r2 = $color1['red'] - floor($i * $r1);
		$g2 = $color1['green'] - floor($i * $g1);
		$b2 = $color1['blue'] - floor($i * $b1);
		$color = imagecolorallocate($this->image, $r2, $g2, $b2);

		imageline($this->image, $x1, $y1, $x2, $y2, $color);
	}
}

public image_render( boolean $html ) (defined in Captcha)

Returns the img html element or outputs the image to the browser.

Parameters

  • boolean $html required - Output as HTML

Return Values

  • mixed - HTML, string or void

Source Code

public function image_render($html)
{
	// Output html element
	if ($html === TRUE)
		return '<img src="'.URL::site('captcha/'.Captcha::$config['group']).'" width="'.Captcha::$config['width'].'" height="'.Captcha::$config['height'].'" alt="Captcha" class="captcha" />';

	// Send the correct HTTP header
	Request::current()->response()
		->headers('Content-Type', 'image/'.$this->image_type)
		->headers('Cache-Control', 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0')
		->headers('Pragma', 'no-cache')
		->headers('Connection', 'close');

	// Pick the correct output function
	$function = 'image'.$this->image_type;
	$function($this->image);

	// Free up resources
	imagedestroy($this->image);
}

public image_type( string $filename ) (defined in Captcha)

Returns the image type.

Parameters

  • string $filename required - Filename

Return Values

  • string|boolean - Image type ("png", "gif" or "jpeg")

Source Code

public function image_type($filename)
{
	switch (strtolower(substr(strrchr($filename, '.'), 1)))
	{
		case 'png':
			return 'png';

		case 'gif':
			return 'gif';

		case 'jpg':
		case 'jpeg':
			// Return "jpeg" and not "jpg" because of the GD2 function names
			return 'jpeg';

		default:
			return FALSE;
	}
}

public static instance( [ string $group = string(7) "default" ] ) (defined in Captcha)

Singleton instance of Captcha.

Parameters

  • string $group = string(7) "default" - Config group name

Return Values

  • object

Source Code

public static function instance($group = 'default')
{
	if ( ! isset(Captcha::$instance))
	{
		// Load the configuration for this group
		$config = Kohana::$config->load('captcha.'.$group);

		// Set the captcha driver class name
		$class = 'Captcha_'.ucfirst($config['style']);

		// Create a new captcha instance
		Captcha::$instance = $captcha = new $class($group);

		// Save captcha response at shutdown
		//register_shutdown_function(array($captcha, 'update_response_session'));
	}

	return Captcha::$instance;
}

public invalid_count( [ integer $new_count = NULL ] ) (defined in Captcha)

Gets or sets the number of invalid Captcha responses for this session.

Parameters

  • integer $new_count = NULL - New counter value

Return Values

  • integer - Counter value

Source Code

public function invalid_count($new_count = NULL)
{
	return $this->valid_count($new_count, TRUE);
}

Checks whether user has been promoted after having given enough valid responses.

Parameters

  • integer $threshold = NULL - Valid response count threshold

Return Values

  • boolean

Source Code

public function promoted($threshold = NULL)
{
	// Promotion has been disabled
	if (Captcha::$config['promote'] === FALSE)
		return FALSE;

	// Use the config threshold
	if ($threshold === NULL)
	{
		$threshold = Captcha::$config['promote'];
	}

	// Compare the valid response count to the threshold
	return ($this->valid_count() >= $threshold);
}

public reset_count( ) (defined in Captcha)

Resets the Captcha response counters and removes the count sessions.

Return Values

  • void

Source Code

public function reset_count()
{
	$this->valid_count(0);
	$this->valid_count(0, TRUE);
}

public update_response_session( ) (defined in Captcha)

Update captcha response session variable.

Return Values

  • void

Source Code

public function update_response_session()
{
	// Store the correct Captcha response in a session
	Session::instance()->set('captcha_response', sha1(strtoupper($this->response)));
}

public static valid( string $response ) (defined in Captcha)

Validates user's Captcha response and updates response counter.

Parameters

  • string $response required - User's captcha response

Tags

  • Staticvar - integer $counted Captcha attempts counter

Return Values

  • boolean

Source Code

public static function valid($response)
{
	// Maximum one count per page load
	static $counted;

	// User has been promoted, always TRUE and don't count anymore
	if (Captcha::instance()->promoted())
		return TRUE;

	// Challenge result
	$result = (bool) (sha1(strtoupper($response)) === Session::instance()->get('captcha_response'));

	// Increment response counter
	if ($counted !== TRUE)
	{
		$counted = TRUE;

		// Valid response
		if ($result === TRUE)
		{
			Captcha::instance()->valid_count(Session::instance()->get('captcha_valid_count') + 1);
		}
		// Invalid response
		else
		{
			Captcha::instance()->invalid_count(Session::instance()->get('captcha_invalid_count') + 1);
		}
	}

	return $result;
}

public valid_count( [ integer $new_count = NULL , boolean $invalid = bool FALSE ] ) (defined in Captcha)

Gets or sets the number of valid Captcha responses for this session.

Parameters

  • integer $new_count = NULL - New counter value
  • boolean $invalid = bool FALSE - Trigger invalid counter (for internal use only)

Return Values

  • integer - Counter value

Source Code

public function valid_count($new_count = NULL, $invalid = FALSE)
{
	// Pick the right session to use
	$session = ($invalid === TRUE) ? 'captcha_invalid_count' : 'captcha_valid_count';

	// Update counter
	if ($new_count !== NULL)
	{
		$new_count = (int) $new_count;

		// Reset counter = delete session
		if ($new_count < 1)
		{
			Session::instance()->delete($session);
		}
		// Set counter to new value
		else
		{
			Session::instance()->set($session, (int) $new_count);
		}

		// Return new count
		return (int) $new_count;
	}

	// Return current count
	return (int) Session::instance()->get($session);
}
Documentation comments powered by Disqus