aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/includes/captcha
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB/includes/captcha')
-rwxr-xr-xphpBB/includes/captcha/captcha_factory.php90
-rw-r--r--phpBB/includes/captcha/captcha_non_gd.php6
-rwxr-xr-xphpBB/includes/captcha/captcha_plugin.php97
-rwxr-xr-xphpBB/includes/captcha/plugins/captcha_abstract.php301
-rwxr-xr-xphpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php101
-rwxr-xr-xphpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php58
6 files changed, 650 insertions, 3 deletions
diff --git a/phpBB/includes/captcha/captcha_factory.php b/phpBB/includes/captcha/captcha_factory.php
new file mode 100755
index 0000000000..dfbe605917
--- /dev/null
+++ b/phpBB/includes/captcha/captcha_factory.php
@@ -0,0 +1,90 @@
+<?
+/**
+*
+* @package VC
+* @version $Id: $
+* @copyright (c) 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+if (!interface_exists('phpbb_captcha_plugin'))
+{
+ include(PHPBB_ROOT_PATH . "includes/captcha/captcha_plugin." . PHP_EXT);
+}
+
+/** A small class until we get the autoloader done */
+class phpbb_captcha_factory
+{
+ /**
+ * return an instance of class $name in file $name_plugin.php
+ */
+ public static function get_instance($name)
+ {
+ $name = basename($name);
+ if (!class_exists($name))
+ {
+ include(PHPBB_ROOT_PATH . "includes/captcha/plugins/{$name}_plugin." . PHP_EXT);
+ }
+ return call_user_func(array($name, 'get_instance'));
+ }
+
+ /**
+ * Call the garbage collector
+ */
+ public static function garbage_collect($name)
+ {
+ $name = basename($name);
+ if (!class_exists($name))
+ {
+ include(PHPBB_ROOT_PATH . "includes/captcha/plugins/{$name}_plugin." . PHP_EXT);
+ }
+ call_user_func(array($name, 'garbage_collect'), 0);
+ }
+
+ /**
+ * return a list of all discovered CAPTCHA plugins
+ */
+ public static function get_captcha_types()
+ {
+ $captchas = array();
+ $captchas['available'] = array();
+ $captchas['unavailable'] = array();
+
+ $dp = @opendir(PHPBB_ROOT_PATH . 'includes/captcha/plugins');
+
+ if ($dp)
+ {
+ while (($file = readdir($dp)) !== false)
+ {
+ if ((preg_match('#_plugin\.' . PHP_EXT . '$#', $file)))
+ {
+ $name = preg_replace('#^(.*?)_plugin\.' . PHP_EXT . '$#', '\1', $file);
+ if (!class_exists($name))
+ {
+ include(PHPBB_ROOT_PATH . "includes/captcha/plugins/$file");
+ }
+ if (call_user_func(array($name, 'is_available')))
+ {
+ $captchas['available'][$name] = call_user_func(array($name, 'get_name'));
+ }
+ else
+ {
+ $captchas['unavailable'][$name] = call_user_func(array($name, 'get_name'));
+ }
+ }
+ }
+ closedir($dp);
+ }
+
+ return $captchas;
+ }
+} \ No newline at end of file
diff --git a/phpBB/includes/captcha/captcha_non_gd.php b/phpBB/includes/captcha/captcha_non_gd.php
index 24452aca26..3f9db24f3a 100644
--- a/phpBB/includes/captcha/captcha_non_gd.php
+++ b/phpBB/includes/captcha/captcha_non_gd.php
@@ -85,7 +85,7 @@ class captcha
}
else
{
- for ($j = 0; $j < $this->width; $j++)
+ for ($j = 0; $j < self::width; $j++)
{
$image .= chr(mt_rand(140, 255));
}
@@ -93,7 +93,7 @@ class captcha
}
unset($hold_chars);
- $image = self::create_png($image, $this->width, $this->height);
+ $image = self::create_png($image, self::width, self::height);
// Output image
header('Content-Type: image/png');
@@ -149,7 +149,7 @@ class captcha
* png because it's a fully recognised open standard and supported
* by practically all modern browsers and OSs
*/
- function create_png($raw_image, $width, $height)
+ static function create_png($raw_image, $width, $height)
{
// SIG
$image = pack('C8', 137, 80, 78, 71, 13, 10, 26, 10);
diff --git a/phpBB/includes/captcha/captcha_plugin.php b/phpBB/includes/captcha/captcha_plugin.php
new file mode 100755
index 0000000000..08a149764c
--- /dev/null
+++ b/phpBB/includes/captcha/captcha_plugin.php
@@ -0,0 +1,97 @@
+<?
+
+interface phpbb_captcha_plugin
+{
+ /**
+ * Initiates the CAPTCHA to validate codes.
+ * @param int $type the type as defined in constants.php
+ */
+ function init($type);
+
+
+ /**
+ * Returns true if the captcha will work on the current install
+ */
+ static function is_available();
+
+ /**
+ * Returns the translated pretty name of the captcha.
+ */
+ static function get_name();
+
+ /**
+ * Returns the class name of the captcha.
+ */
+ static function get_class_name();
+
+ /**
+ * Returns an instance; does not have to be the same instance twice.
+ */
+ static function get_instance();
+
+ /**
+ * Returns the HTML needed to embed the captcha in another template
+ */
+ function get_template();
+
+
+ /**
+ * Delivers the image of image based captchas; not required for text/remote etc CAPTCHAs
+ */
+ function execute();
+
+ /**
+ * Returns the HTML needed to display a demo of the captcha
+ */
+ function get_demo_template($id);
+
+
+ /**
+ * Delivers the demo image of image based captchas; not required for text/remote etc CAPTCHAs
+ */
+ function execute_demo();
+
+ /**
+ * Clears leftover entries in the database.
+ */
+ static function garbage_collect($type);
+
+
+ /**
+ * Clears all entries from the database if the CAPTCHA is replaced
+ */
+ function uninstall();
+
+ /**
+ * Sets up the CAPTCHA when it is selected in the ACP.
+ */
+ function install();
+
+
+ /**
+ * Checks the captcha; returns false if the code was correct; a translated error string otherwise
+ */
+ function validate();
+
+ /**
+ * Prepares the captcha to ask a new question; required call on failed answers
+ */
+ function reset();
+
+ /**
+ * Displays the configuration options in the ACP
+ */
+ function acp_page($id, &$module);
+
+ /**
+ * Returns the entries for the hidden field array needed to preserve the current state.
+ */
+ function get_hidden_fields();
+
+
+ /**
+ * Returns the number of solving attempts of the current user
+ */
+ function get_attempt_count();
+
+} \ No newline at end of file
diff --git a/phpBB/includes/captcha/plugins/captcha_abstract.php b/phpBB/includes/captcha/plugins/captcha_abstract.php
new file mode 100755
index 0000000000..a1a56db1e1
--- /dev/null
+++ b/phpBB/includes/captcha/plugins/captcha_abstract.php
@@ -0,0 +1,301 @@
+<?
+/**
+*
+* @package VC
+* @version $Id: $
+* @copyright (c) 2006 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+
+/**
+* This class holds the code shared by the two default 3.0 CAPTCHAs.
+*/
+abstract class phpbb_default_captcha implements phpbb_captcha_plugin
+{
+ protected $confirm_id;
+ protected $confirm_code;
+ protected $code;
+ protected $seed;
+ protected $type;
+ protected $solved = false;
+
+
+ function init($type)
+ {
+ global $config, $db, $user;
+
+ // read input
+ $this->confirm_id = request_var('confirm_id', '');
+ $this->confirm_code = request_var('confirm_code', '');
+ $this->type = (int) $type;
+
+ if (!strlen($this->confirm_id))
+ {
+ // we have no confirm ID, better get ready to display something
+ $this->generate_code();
+ }
+ }
+
+ function execute_demo()
+ {
+ global $user;
+
+ $this->code = gen_rand_string(mt_rand(5, 8));
+ $this->seed = hexdec(substr(unique_id(), 4, 10));
+
+ // compute $seed % 0x7fffffff
+ $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff);
+
+ captcha::execute($this->code, $this->seed);
+ }
+
+
+ function execute()
+ {
+ if (empty($this->code))
+ {
+ if (!$this->load_code())
+ {
+ // invalid request, bail out
+ return false;
+ }
+ }
+ captcha::execute($this->code, $this->seed);
+ }
+
+
+ function get_template()
+ {
+ global $config, $user, $template;
+
+ $template->set_filenames(array(
+ 'captcha' => 'captcha_default.html')
+ );
+
+ $template->assign_vars(array(
+ 'CONFIRM_IMAGE' => append_sid('ucp', 'mode=confirm&amp;confirm_id=' . $this->confirm_id . '&amp;type=' . $this->type),
+ 'CONFIRM_ID' => $this->confirm_id,
+ ));
+
+ return $template->assign_display('captcha');
+ }
+
+ function get_demo_template($id)
+ {
+ global $config, $user, $template;
+
+ $template->set_filenames(array(
+ 'captcha_demo' => 'captcha_default_acp_demo.html')
+ );
+ // acp_captcha has a delivery function; let's use it
+ $template->assign_vars(array(
+ 'CONFIRM_IMAGE' => append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, 'captcha_demo=1&amp;mode=visual&amp;i=' . $id . '&amp;select_captcha=' . $this->get_class_name()),
+ 'CONFIRM_ID' => $this->confirm_id,
+ ));
+
+ return $template->assign_display('captcha_demo');
+ }
+
+ function get_hidden_fields()
+ {
+ $hidden_fields = array();
+
+ // this is required for postig.php - otherwise we would forget about the captcha being already solved
+ if ($this->solved)
+ {
+ $hidden_fields['confirm_code'] = $this->confirm_code;
+ }
+ $hidden_fields['confirm_id'] = $this->confirm_id;
+ return $hidden_fields;
+ }
+
+ static function garbage_collect($type)
+ {
+ global $db, $config;
+
+ $sql = 'SELECT DISTINCT c.session_id
+ FROM ' . CONFIRM_TABLE . ' c
+ LEFT JOIN ' . SESSIONS_TABLE . ' s ON (c.session_id = s.session_id)
+ WHERE s.session_id IS NULL' .
+ ((empty($type)) ? '' : ' AND c.confirm_type = ' . (int) $type);
+ $result = $db->sql_query($sql);
+
+ if ($row = $db->sql_fetchrow($result))
+ {
+ $sql_in = array();
+ do
+ {
+ $sql_in[] = (string) $row['session_id'];
+ }
+ while ($row = $db->sql_fetchrow($result));
+
+ if (sizeof($sql_in))
+ {
+ $sql = 'DELETE FROM ' . CONFIRM_TABLE . '
+ WHERE ' . $db->sql_in_set('session_id', $sql_in);
+ $db->sql_query($sql);
+ }
+ }
+ $db->sql_freeresult($result);
+ }
+
+ function uninstall()
+ {
+ self::garbage_collect(0);
+ }
+
+ function install()
+ {
+ return;
+ }
+
+ function validate()
+ {
+ global $config, $db, $user;
+
+ $this->confirm_code = request_var('confirm_code', '');
+
+ if (!$this->confirm_id)
+ {
+ $error = $user->lang['CONFIRM_CODE_WRONG'];
+ }
+ else
+ {
+ if ($this->check_code())
+ {
+ // $this->delete_code(); commented out to allow posting.php to repeat the question
+ $this->solved = true;
+ }
+ else
+ {
+ $error = $user->lang['CONFIRM_CODE_WRONG'];
+ }
+ }
+
+ if (strlen($error))
+ {
+ // okay, inorect answer. Let's ask a new question
+ $this->reset();
+ return $error;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+
+ /**
+ * The old way to generate code, suitable for GD and non-GD. Resets the internal state.
+ */
+ protected function generate_code()
+ {
+ global $db, $user;
+
+ $this->code = gen_rand_string(mt_rand(5, 8));
+ $this->confirm_id = md5(unique_id($user->ip));
+ $this->seed = hexdec(substr(unique_id(), 4, 10));
+ $this->solved = false;
+ // compute $seed % 0x7fffffff
+ $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff);
+
+ $sql = 'INSERT INTO ' . CONFIRM_TABLE . ' ' . $db->sql_build_array('INSERT', array(
+ 'confirm_id' => (string) $this->confirm_id,
+ 'session_id' => (string) $user->session_id,
+ 'confirm_type' => (int) $this->type,
+ 'code' => (string) $this->code,
+ 'seed' => (int) $this->seed)
+ );
+ $db->sql_query($sql);
+ }
+
+ /**
+ * Look up everything we need for painting&checking.
+ */
+ protected function load_code()
+ {
+ global $db, $user;
+ $sql = 'SELECT code, seed
+ FROM ' . CONFIRM_TABLE . "
+ WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "'
+ AND session_id = '" . $db->sql_escape($user->session_id) . "'
+ AND confirm_type = " . $this->type;
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+ if ($row)
+ {
+ $this->code = $row['code'];
+ $this->seed = $row['seed'];
+ return true;
+ }
+ return false;
+
+ }
+
+ protected function check_code()
+ {
+ global $db;
+
+ if (empty($this->code))
+ {
+ if (!$this->load_code())
+ {
+ return false;
+ }
+ }
+ return (strcasecmp($this->code, $this->confirm_code) === 0);
+ }
+
+ protected function delete_code()
+ {
+ global $db, $user;
+
+ $sql = 'DELETE FROM ' . CONFIRM_TABLE . "
+ WHERE confirm_id = '" . $db->sql_escape($confirm_id) . "'
+ AND session_id = '" . $db->sql_escape($user->session_id) . "'
+ AND confirm_type = " . $this->type;
+ $db->sql_query($sql);
+ }
+
+ function get_attempt_count()
+ {
+ global $db, $user;
+
+ $sql = 'SELECT COUNT(session_id) AS attempts
+ FROM ' . CONFIRM_TABLE . "
+ WHERE session_id = '" . $db->sql_escape($user->session_id) . "'
+ AND confirm_type = " . $this->type;
+ $result = $db->sql_query($sql);
+ $attempts = (int) $db->sql_fetchfield('attempts');
+ $db->sql_freeresult($result);
+
+ return $attempts;
+ }
+
+
+ function reset()
+ {
+ global $db, $user;
+
+ $sql = 'DELETE FROM ' . CONFIRM_TABLE . "
+ WHERE session_id = '" . $db->sql_escape($user->session_id) . "'
+ AND confirm_type = " . (int) $this->type;
+ $db->sql_query($sql);
+
+ // we leave the class usable by generating a new question
+ $this->generate_code();
+ }
+
+}
+
diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php
new file mode 100755
index 0000000000..e4f0bff87e
--- /dev/null
+++ b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php
@@ -0,0 +1,101 @@
+<?
+/**
+*
+* @package VC
+* @version $Id: $
+* @copyright (c) 2006 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Placeholder for autoload
+*/
+include_once(PHPBB_ROOT_PATH . "includes/captcha/plugins/captcha_abstract." . PHP_EXT);
+
+class phpbb_captcha_gd extends phpbb_default_captcha implements phpbb_captcha_plugin
+{
+
+ function __construct()
+ {
+ include_once(PHPBB_ROOT_PATH . "includes/captcha/captcha_gd." . PHP_EXT);
+ }
+
+ public static function get_instance()
+ {
+ return new phpbb_captcha_gd();
+ }
+
+ static function is_available()
+ {
+ return (@extension_loaded('gd') || can_load_dll('gd'));
+ }
+
+ static function get_name()
+ {
+ return 'CAPTCHA_GD';
+ }
+
+ static function get_class_name()
+ {
+ return 'phpbb_captcha_gd';
+ }
+
+ function acp_page($id, &$module)
+ {
+ global $config, $db, $template, $user;
+
+ $captcha_vars = array(
+ 'captcha_gd_x_grid' => 'CAPTCHA_GD_X_GRID',
+ 'captcha_gd_y_grid' => 'CAPTCHA_GD_Y_GRID',
+ 'captcha_gd_foreground_noise' => 'CAPTCHA_GD_FOREGROUND_NOISE',
+ 'captcha_gd' => 'CAPTCHA_GD_PREVIEWED'
+ );
+
+ $module->tpl_name = 'captcha_gd_acp';
+ $module->page_title = 'ACP_VC_SETTINGS';
+ $form_key = 'acp_captcha';
+ add_form_key($form_key);
+
+ $submit = request_var('submit', '');
+
+ if ($submit && check_form_key($form_key))
+ {
+ $captcha_vars = array_keys($captcha_vars);
+ foreach ($captcha_vars as $captcha_var)
+ {
+ $value = request_var($captcha_var, 0);
+ if ($value >= 0)
+ {
+ set_config($captcha_var, $value);
+ }
+ }
+ trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action));
+ }
+ else if ($submit)
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($module->u_action));
+ }
+ else
+ {
+ foreach ($captcha_vars as $captcha_var => $template_var)
+ {
+ $var = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, 0) : $config[$captcha_var];
+ $template->assign_var($template_var, $var);
+ }
+ $template->assign_vars(array(
+ 'CAPTCHA_PREVIEW' => $this->get_demo_template($id),
+ 'CAPTCHA_NAME' => $this->get_class_name(),
+ ));
+
+ }
+ }
+}
+
diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php
new file mode 100755
index 0000000000..a2521a330e
--- /dev/null
+++ b/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php
@@ -0,0 +1,58 @@
+<?
+/**
+*
+* @package VC
+* @version $Id: $
+* @copyright (c) 2006 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+include_once(PHPBB_ROOT_PATH . "includes/captcha/plugins/captcha_abstract." . PHP_EXT);
+
+class phpbb_captcha_nogd extends phpbb_default_captcha implements phpbb_captcha_plugin
+{
+
+ function __construct()
+ {
+ include_once(PHPBB_ROOT_PATH . "includes/captcha/captcha_non_gd." . PHP_EXT);
+ }
+
+ public static function get_instance()
+ {
+ return new phpbb_captcha_nogd();
+ }
+
+ static function is_available()
+ {
+ return true;
+ }
+
+ static function get_name()
+ {
+ global $user;
+
+ return 'CAPTCHA_NO_GD';
+ }
+
+ static function get_class_name()
+ {
+ return 'phpbb_captcha_nogd';
+ }
+
+
+ function acp_page($id, &$module)
+ {
+ global $user;
+
+ trigger_error($user->lang['CAPTCHA_NO_OPTIONS'] . adm_back_link($module->u_action));
+ }
+}
+