Location: PHPKode > projects > Shinobu > system/lib/captcha.class.php
<?php

/* ---

	Copyright (C) 2008-2009 Frank Smit
	http://shinobu.61924.nl/

	This file is part of Shinobu.

	Shinobu 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.

	Shinobu 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 Shinobu. If not, see <http://www.gnu.org/licenses/>.

---  */

class captcha
{
	public $xml_array, $total_items, $rand_item_id, $question;

	public function __construct()
	{
		global $sys_config;

		// Load file, make array and count it
		$this->xml_array = self::object2array(simplexml_load_file(SYS_LANG_DIR.$sys_config['language'].'/questions.xml'));
		$this->xml_array = $this->xml_array['item'];
		$this->total_items = count($this->xml_array) - 1;
	}

	private function get_random_item_id()
	{
		$this->rand_item_id = mt_rand(0, $this->total_items);

		set_cookie('captcha_rand_item_id', $this->rand_item_id, time() + 300);
	}

	public function get_question()
	{
		$this->get_random_item_id();

		// Code from encodeEmailAddress() function in PHP Markdown
		$question = $this->xml_array[$this->rand_item_id]['q'];
		$chars = preg_split('/(?<!^)(?!$)/', $question);
		$seed = (int)abs(crc32($question) / strlen($question)); # Deterministic seed.

		foreach ($chars as $key => $char)
		{
			$ord = ord($char);

			# Ignore non-ascii chars.
			if ($ord < 128)
			{
				$r = ($seed * (1 + $key)) % 100; # Pseudo-random function.
				# roughly 10% raw, 45% hex, 45% dec
				# '@' *must* be encoded. I insist.
				if ($r > 90 && $char != '@') /* do nothing */;
				else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';';
				else              $chars[$key] = '&#'.$ord.';';
			}
		}

		return implode($chars);
	}

	public function check_answer($answer)
	{
		return strtolower($answer) == strtolower($this->xml_array[get_cookie('captcha_rand_item_id')]['a']) ? true : false;
	}

	// Source: http://nl.php.net/manual/en/function.simplexml-load-file.php#56691
	static private function object2array($object)
	{
		$return = NULL;

		if(is_array($object))
			foreach($object as $key => $value)
				$return[$key] = self::object2array($value);
		else
		{
			$var = get_object_vars($object);

			if($var)
				foreach($var as $key => $value)
					$return[$key] = ($key && !$value) ? NULL : self::object2array($value);
			else
				return $object;
		}

		return $return;
	}
}

?>
Return current item: Shinobu