Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

add captcha, fix de mail text, fix footer link text for legacy version

  • Loading branch information...
commit 1df987430fc6bae3bdd95dc634ead111de022481 1 parent 9e8d482
slam authored
View
8 languages/de/email/pm_report_closed.txt
@@ -0,0 +1,8 @@
+Subject: Meldung geschlossen — „{PM_SUBJECT}“
+
+Hallo {USERNAME},
+
+du erhältst diese Nachricht, weil deine Meldung zur Privaten Nachricht „{PM_SUBJECT}“ auf „{SITENAME}“ von einem Moderator oder Administrator bearbeitet wurde. Die Meldung wurde anschließend geschlossen. Wenn du weitere Fragen dazu hast, kannst du {CLOSER_NAME} mit einer Privaten Nachricht kontaktieren.
+
+
+{EMAIL_SIG}
View
8 languages/de/email/pm_report_deleted.txt
@@ -0,0 +1,8 @@
+Subject: Meldung gelöscht — „{PM_SUBJECT}“
+
+Hallo {USERNAME},
+
+du erhältst diese Nachricht, weil deine Meldung zur Privaten Nachricht „{PM_SUBJECT}“ auf „{SITENAME}“ von einem Moderator oder Administrator gelöscht wurde.
+
+
+{EMAIL_SIG}
View
380 zafenio/includes/captcha/plugins/captcha_abstract.php
@@ -0,0 +1,380 @@
+<?php
+/**
+*
+* @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.x CAPTCHAs.
+*
+* @package VC
+*/
+class phpbb_default_captcha
+{
+ var $confirm_id;
+ var $confirm_code;
+ var $code;
+ var $seed;
+ var $attempts = 0;
+ var $type;
+ var $solved = 0;
+ var $captcha_vars = false;
+
+ function init($type)
+ {
+ global $config, $db, $user;
+
+ // read input
+ $this->confirm_id = request_var('confirm_id', '');
+ $this->confirm_code = request_var('confirm_code', '');
+ $refresh = request_var('refresh_vc', false) && $config['confirm_refresh'];
+
+ $this->type = (int) $type;
+
+ if (!strlen($this->confirm_id) || !$this->load_code())
+ {
+ // we have no confirm ID, better get ready to display something
+ $this->generate_code();
+ }
+ else if ($refresh)
+ {
+ $this->regenerate_code();
+ }
+ }
+
+ function execute_demo()
+ {
+ global $user;
+
+ $this->code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
+ $this->seed = hexdec(substr(unique_id(), 4, 10));
+
+ // compute $seed % 0x7fffffff
+ $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff);
+
+ $captcha = new captcha();
+ define('IMAGE_OUTPUT', 1);
+ $captcha->execute($this->code, $this->seed);
+ }
+
+ function execute()
+ {
+ if (empty($this->code))
+ {
+ if (!$this->load_code())
+ {
+ // invalid request, bail out
+ return false;
+ }
+ }
+ $captcha = new captcha();
+ define('IMAGE_OUTPUT', 1);
+ $captcha->execute($this->code, $this->seed);
+ }
+
+ function get_template()
+ {
+ global $config, $user, $template, $phpEx, $phpbb_root_path;
+
+ if ($this->is_solved())
+ {
+ return false;
+ }
+ else
+ {
+ $link = append_sid($phpbb_root_path . 'ucp.' . $phpEx, 'mode=confirm&amp;confirm_id=' . $this->confirm_id . '&amp;type=' . $this->type);
+ $explain = $user->lang(($this->type != CONFIRM_POST) ? 'CONFIRM_EXPLAIN' : 'POST_CONFIRM_EXPLAIN', '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>');
+
+ $template->assign_vars(array(
+ 'CONFIRM_IMAGE_LINK' => $link,
+ 'CONFIRM_IMAGE' => '<img src="' . $link . '" />',
+ 'CONFIRM_IMG' => '<img src="' . $link . '" />',
+ 'CONFIRM_ID' => $this->confirm_id,
+ 'S_CONFIRM_CODE' => true,
+ 'S_TYPE' => $this->type,
+ 'S_CONFIRM_REFRESH' => ($config['enable_confirm'] && $config['confirm_refresh'] && $this->type == CONFIRM_REG) ? true : false,
+ 'L_CONFIRM_EXPLAIN' => $explain,
+ ));
+
+ return 'captcha_default.html';
+ }
+ }
+
+ function get_demo_template($id)
+ {
+ global $config, $user, $template, $phpbb_admin_path, $phpEx;
+
+ $variables = '';
+
+ if (is_array($this->captcha_vars))
+ {
+ foreach ($this->captcha_vars as $captcha_var => $template_var)
+ {
+ $variables .= '&amp;' . rawurlencode($captcha_var) . '=' . request_var($captcha_var, (int) $config[$captcha_var]);
+ }
+ }
+
+ // acp_captcha has a delivery function; let's use it
+ $template->assign_vars(array(
+ 'CONFIRM_IMAGE' => append_sid($phpbb_admin_path . 'index.' . $phpEx, 'captcha_demo=1&amp;mode=visual&amp;i=' . $id . '&amp;select_captcha=' . $this->get_class_name()) . $variables,
+ 'CONFIRM_ID' => $this->confirm_id,
+ ));
+
+ return 'captcha_default_acp_demo.html';
+ }
+
+ function get_hidden_fields()
+ {
+ $hidden_fields = array();
+
+ // this is required for posting.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;
+ }
+
+ 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()
+ {
+ $this->garbage_collect(0);
+ }
+
+ function install()
+ {
+ return;
+ }
+
+ function validate()
+ {
+ global $config, $db, $user;
+
+ if (empty($user->lang))
+ {
+ $user->setup();
+ }
+
+ $error = '';
+ 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, incorrect answer. Let's ask a new question.
+ $this->new_attempt();
+ return $error;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * The old way to generate code, suitable for GD and non-GD. Resets the internal state.
+ */
+ function generate_code()
+ {
+ global $db, $user;
+
+ $this->code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
+ $this->confirm_id = md5(unique_id($user->ip));
+ $this->seed = hexdec(substr(unique_id(), 4, 10));
+ $this->solved = 0;
+ // 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);
+ }
+
+ /**
+ * New Question, if desired.
+ */
+ function regenerate_code()
+ {
+ global $db, $user;
+
+ $this->code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
+ $this->seed = hexdec(substr(unique_id(), 4, 10));
+ $this->solved = 0;
+ // compute $seed % 0x7fffffff
+ $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff);
+
+ $sql = 'UPDATE ' . CONFIRM_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array(
+ 'code' => (string) $this->code,
+ 'seed' => (int) $this->seed)) . '
+ WHERE
+ confirm_id = \'' . $db->sql_escape($this->confirm_id) . '\'
+ AND session_id = \'' . $db->sql_escape($user->session_id) . '\'';
+ $db->sql_query($sql);
+ }
+
+ /**
+ * New Question, if desired.
+ */
+ function new_attempt()
+ {
+ global $db, $user;
+
+ $this->code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
+ $this->seed = hexdec(substr(unique_id(), 4, 10));
+ $this->solved = 0;
+ // compute $seed % 0x7fffffff
+ $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff);
+
+ $sql = 'UPDATE ' . CONFIRM_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array(
+ 'code' => (string) $this->code,
+ 'seed' => (int) $this->seed)) . '
+ , attempts = attempts + 1
+ WHERE
+ confirm_id = \'' . $db->sql_escape($this->confirm_id) . '\'
+ AND session_id = \'' . $db->sql_escape($user->session_id) . '\'';
+ $db->sql_query($sql);
+ }
+
+ /**
+ * Look up everything we need for painting&checking.
+ */
+ function load_code()
+ {
+ global $db, $user;
+
+ $sql = 'SELECT code, seed, attempts
+ 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'];
+ $this->attempts = $row['attempts'];
+ return true;
+ }
+
+ return false;
+ }
+
+ function check_code()
+ {
+ return (strcasecmp($this->code, $this->confirm_code) === 0);
+ }
+
+ 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()
+ {
+ return $this->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();
+ }
+
+ function is_solved()
+ {
+ if (request_var('confirm_code', false) && $this->solved === 0)
+ {
+ $this->validate();
+ }
+ return (bool) $this->solved;
+ }
+
+ /**
+ * API function
+ */
+ function has_config()
+ {
+ return false;
+ }
+
+}
+
+?>
View
165 zafenio/includes/captcha/plugins/phpbb_captcha_gd_plugin.php
@@ -0,0 +1,165 @@
+<?php
+/**
+*
+* @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
+*/
+if (!class_exists('phpbb_default_captcha'))
+{
+ include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx);
+}
+
+/**
+* @package VC
+*/
+class phpbb_captcha_gd extends phpbb_default_captcha
+{
+
+ var $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',
+ 'captcha_gd_wave' => 'CAPTCHA_GD_WAVE',
+ 'captcha_gd_3d_noise' => 'CAPTCHA_GD_3D_NOISE',
+ 'captcha_gd_fonts' => 'CAPTCHA_GD_FONTS',
+ );
+
+ function phpbb_captcha_gd()
+ {
+ global $phpbb_root_path, $phpEx;
+
+ if (!class_exists('captcha'))
+ {
+ include($phpbb_root_path . 'includes/captcha/captcha_gd.' . $phpEx);
+ }
+ }
+
+ function &get_instance()
+ {
+ $instance =& new phpbb_captcha_gd();
+ return $instance;
+ }
+
+ function is_available()
+ {
+ global $phpbb_root_path, $phpEx;
+
+ if (@extension_loaded('gd'))
+ {
+ return true;
+ }
+
+ if (!function_exists('can_load_dll'))
+ {
+ include($phpbb_root_path . 'includes/functions_install.' . $phpEx);
+ }
+
+ return can_load_dll('gd');
+ }
+
+ /**
+ * API function
+ */
+ function has_config()
+ {
+ return true;
+ }
+
+ function get_name()
+ {
+ return 'CAPTCHA_GD';
+ }
+
+ function get_class_name()
+ {
+ return 'phpbb_captcha_gd';
+ }
+
+ function acp_page($id, &$module)
+ {
+ global $db, $user, $auth, $template;
+ global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
+
+ $user->add_lang('acp/board');
+
+ $config_vars = array(
+ 'enable_confirm' => 'REG_ENABLE',
+ 'enable_post_confirm' => 'POST_ENABLE',
+ 'confirm_refresh' => 'CONFIRM_REFRESH',
+ 'captcha_gd' => 'CAPTCHA_GD',
+ );
+
+ $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($this->captcha_vars);
+ foreach ($captcha_vars as $captcha_var)
+ {
+ $value = request_var($captcha_var, 0);
+ if ($value >= 0)
+ {
+ set_config($captcha_var, $value);
+ }
+ }
+
+ add_log('admin', 'LOG_CONFIG_VISUAL');
+ 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 ($this->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(),
+ 'U_ACTION' => $module->u_action,
+ ));
+ }
+ }
+
+ function execute_demo()
+ {
+ global $config;
+
+ $config_old = $config;
+ foreach ($this->captcha_vars as $captcha_var => $template_var)
+ {
+ $config[$captcha_var] = request_var($captcha_var, (int) $config[$captcha_var]);
+ }
+ parent::execute_demo();
+ $config = $config_old;
+ }
+
+}
+
+?>
View
83 zafenio/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php
@@ -0,0 +1,83 @@
+<?php
+/**
+*
+* @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
+*/
+if (!class_exists('phpbb_default_captcha'))
+{
+ include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx);
+}
+
+/**
+* @package VC
+*/
+class phpbb_captcha_gd_wave extends phpbb_default_captcha
+{
+
+ function phpbb_captcha_gd_wave()
+ {
+ global $phpbb_root_path, $phpEx;
+
+ if (!class_exists('captcha'))
+ {
+ include_once($phpbb_root_path . 'includes/captcha/captcha_gd_wave.' . $phpEx);
+ }
+ }
+
+ function get_instance()
+ {
+ return new phpbb_captcha_gd_wave();
+ }
+
+ function is_available()
+ {
+ global $phpbb_root_path, $phpEx;
+
+ if (@extension_loaded('gd'))
+ {
+ return true;
+ }
+
+ if (!function_exists('can_load_dll'))
+ {
+ include($phpbb_root_path . 'includes/functions_install.' . $phpEx);
+ }
+
+ return can_load_dll('gd');
+ }
+
+ function get_name()
+ {
+ return 'CAPTCHA_GD_3D';
+ }
+
+ function get_class_name()
+ {
+ return 'phpbb_captcha_gd_wave';
+ }
+
+ function acp_page($id, &$module)
+ {
+ global $config, $db, $template, $user;
+
+ trigger_error($user->lang['CAPTCHA_NO_OPTIONS'] . adm_back_link($module->u_action));
+ }
+}
+
+?>
View
72 zafenio/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php
@@ -0,0 +1,72 @@
+<?php
+/**
+*
+* @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
+*/
+if (!class_exists('phpbb_default_captcha'))
+{
+ include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx);
+}
+
+/**
+* @package VC
+*/
+class phpbb_captcha_nogd extends phpbb_default_captcha
+{
+
+ function phpbb_captcha_nogd()
+ {
+ global $phpbb_root_path, $phpEx;
+
+ if (!class_exists('captcha'))
+ {
+ include_once($phpbb_root_path . 'includes/captcha/captcha_non_gd.' . $phpEx);
+ }
+ }
+
+ function &get_instance()
+ {
+ $instance =& new phpbb_captcha_nogd();
+ return $instance;
+ }
+
+ function is_available()
+ {
+ return true;
+ }
+
+ function get_name()
+ {
+ return 'CAPTCHA_NO_GD';
+ }
+
+ 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));
+ }
+}
+
+?>
View
1,022 zafenio/includes/captcha/plugins/phpbb_captcha_qa_plugin.php
@@ -0,0 +1,1022 @@
+<?php
+/**
+*
+* @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;
+}
+
+global $table_prefix;
+
+define('CAPTCHA_QUESTIONS_TABLE', $table_prefix . 'captcha_questions');
+define('CAPTCHA_ANSWERS_TABLE', $table_prefix . 'captcha_answers');
+define('CAPTCHA_QA_CONFIRM_TABLE', $table_prefix . 'qa_confirm');
+
+/**
+* And now to something completely different. Let's make a captcha without extending the abstract class.
+* QA CAPTCHA sample implementation
+*
+* @package VC
+*/
+class phpbb_captcha_qa
+{
+ var $confirm_id;
+ var $answer;
+ var $question_ids;
+ var $question_text;
+ var $question_lang;
+ var $question_strict;
+ var $attempts = 0;
+ var $type;
+ // dirty trick: 0 is false, but can still encode that the captcha is not yet validated
+ var $solved = 0;
+
+ /**
+ * @param int $type as per the CAPTCHA API docs, the type
+ */
+ function init($type)
+ {
+ global $config, $db, $user;
+
+ // load our language file
+ $user->add_lang('captcha_qa');
+
+ // read input
+ $this->confirm_id = request_var('qa_confirm_id', '');
+ $this->answer = utf8_normalize_nfc(request_var('qa_answer', '', true));
+
+ $this->type = (int) $type;
+ $this->question_lang = $user->lang_name;
+
+ // we need all defined questions - shouldn't be too many, so we can just grab them
+ // try the user's lang first
+ $sql = 'SELECT question_id
+ FROM ' . CAPTCHA_QUESTIONS_TABLE . "
+ WHERE lang_iso = '" . $db->sql_escape($user->lang_name) . "'";
+ $result = $db->sql_query($sql, 3600);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $this->question_ids[$row['question_id']] = $row['question_id'];
+ }
+ $db->sql_freeresult($result);
+
+ // fallback to the board default lang
+ if (!sizeof($this->question_ids))
+ {
+ $this->question_lang = $config['default_lang'];
+
+ $sql = 'SELECT question_id
+ FROM ' . CAPTCHA_QUESTIONS_TABLE . "
+ WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'";
+ $result = $db->sql_query($sql, 7200);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $this->question_ids[$row['question_id']] = $row['question_id'];
+ }
+ $db->sql_freeresult($result);
+ }
+
+ // okay, if there is a confirm_id, we try to load that confirm's state. If not, we try to find one
+ if (!$this->load_answer() && (!$this->load_confirm_id() || !$this->load_answer()))
+ {
+ // we have no valid confirm ID, better get ready to ask something
+ $this->select_question();
+ }
+ }
+
+ /**
+ * API function
+ */
+ function &get_instance()
+ {
+ $instance =& new phpbb_captcha_qa();
+
+ return $instance;
+ }
+
+ /**
+ * See if the captcha has created its tables.
+ */
+ function is_installed()
+ {
+ global $db, $phpbb_root_path, $phpEx;
+
+ if (!class_exists('phpbb_db_tools'))
+ {
+ include("$phpbb_root_path/includes/db/db_tools.$phpEx");
+ }
+ $db_tool = new phpbb_db_tools($db);
+
+ return $db_tool->sql_table_exists(CAPTCHA_QUESTIONS_TABLE);
+ }
+
+ /**
+ * API function - for the captcha to be available, it must have installed itself and there has to be at least one question in the board's default lang
+ */
+ function is_available()
+ {
+ global $config, $db, $phpbb_root_path, $phpEx, $user;
+
+ // load language file for pretty display in the ACP dropdown
+ $user->add_lang('captcha_qa');
+
+ if (!phpbb_captcha_qa::is_installed())
+ {
+ return false;
+ }
+
+ $sql = 'SELECT COUNT(question_id) AS question_count
+ FROM ' . CAPTCHA_QUESTIONS_TABLE . "
+ WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'";
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ return ((bool) $row['question_count']);
+ }
+
+ /**
+ * API function
+ */
+ function has_config()
+ {
+ return true;
+ }
+
+ /**
+ * API function
+ */
+ function get_name()
+ {
+ return 'CAPTCHA_QA';
+ }
+
+ /**
+ * API function
+ */
+ function get_class_name()
+ {
+ return 'phpbb_captcha_qa';
+ }
+
+ /**
+ * API function - not needed as we don't display an image
+ */
+ function execute_demo()
+ {
+ }
+
+ /**
+ * API function - not needed as we don't display an image
+ */
+ function execute()
+ {
+ }
+
+ /**
+ * API function - send the question to the template
+ */
+ function get_template()
+ {
+ global $template;
+
+ if ($this->is_solved())
+ {
+ return false;
+ }
+ else
+ {
+ $template->assign_vars(array(
+ 'QA_CONFIRM_QUESTION' => $this->question_text,
+ 'QA_CONFIRM_ID' => $this->confirm_id,
+ 'S_CONFIRM_CODE' => true,
+ 'S_TYPE' => $this->type,
+ ));
+
+ return 'captcha_qa.html';
+ }
+ }
+
+ /**
+ * API function - we just display a mockup so that the captcha doesn't need to be installed
+ */
+ function get_demo_template()
+ {
+ global $config, $db, $template;
+
+ if ($this->is_available())
+ {
+ $sql = 'SELECT question_text
+ FROM ' . CAPTCHA_QUESTIONS_TABLE . "
+ WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'";
+ $result = $db->sql_query_limit($sql, 1);
+ if ($row = $db->sql_fetchrow($result))
+ {
+ $template->assign_vars(array(
+ 'QA_CONFIRM_QUESTION' => $row['question_text'],
+ ));
+ }
+ $db->sql_freeresult($result);
+ }
+ return 'captcha_qa_acp_demo.html';
+ }
+
+ /**
+ * API function
+ */
+ function get_hidden_fields()
+ {
+ $hidden_fields = array();
+
+ // this is required - otherwise we would forget about the captcha being already solved
+ if ($this->solved)
+ {
+ $hidden_fields['qa_answer'] = $this->answer;
+ }
+ $hidden_fields['qa_confirm_id'] = $this->confirm_id;
+
+ return $hidden_fields;
+ }
+
+ /**
+ * API function
+ */
+ function garbage_collect($type = 0)
+ {
+ global $db, $config;
+
+ $sql = 'SELECT c.confirm_id
+ FROM ' . CAPTCHA_QA_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['confirm_id'];
+ }
+ while ($row = $db->sql_fetchrow($result));
+
+ if (sizeof($sql_in))
+ {
+ $sql = 'DELETE FROM ' . CAPTCHA_QA_CONFIRM_TABLE . '
+ WHERE ' . $db->sql_in_set('confirm_id', $sql_in);
+ $db->sql_query($sql);
+ }
+ }
+ $db->sql_freeresult($result);
+ }
+
+ /**
+ * API function - we don't drop the tables here, as that would cause the loss of all entered questions.
+ */
+ function uninstall()
+ {
+ $this->garbage_collect(0);
+ }
+
+ /**
+ * API function - set up shop
+ */
+ function install()
+ {
+ global $db, $phpbb_root_path, $phpEx;
+
+ if (!class_exists('phpbb_db_tools'))
+ {
+ include("$phpbb_root_path/includes/db/db_tools.$phpEx");
+ }
+ $db_tool = new phpbb_db_tools($db);
+
+ $tables = array(CAPTCHA_QUESTIONS_TABLE, CAPTCHA_ANSWERS_TABLE, CAPTCHA_QA_CONFIRM_TABLE);
+
+ $schemas = array(
+ CAPTCHA_QUESTIONS_TABLE => array (
+ 'COLUMNS' => array(
+ 'question_id' => array('UINT', Null, 'auto_increment'),
+ 'strict' => array('BOOL', 0),
+ 'lang_id' => array('UINT', 0),
+ 'lang_iso' => array('VCHAR:30', ''),
+ 'question_text' => array('TEXT_UNI', ''),
+ ),
+ 'PRIMARY_KEY' => 'question_id',
+ 'KEYS' => array(
+ 'lang_iso' => array('INDEX', 'lang_iso'),
+ ),
+ ),
+ CAPTCHA_ANSWERS_TABLE => array (
+ 'COLUMNS' => array(
+ 'question_id' => array('UINT', 0),
+ 'answer_text' => array('STEXT_UNI', ''),
+ ),
+ 'KEYS' => array(
+ 'question_id' => array('INDEX', 'question_id'),
+ ),
+ ),
+ CAPTCHA_QA_CONFIRM_TABLE => array (
+ 'COLUMNS' => array(
+ 'session_id' => array('CHAR:32', ''),
+ 'confirm_id' => array('CHAR:32', ''),
+ 'lang_iso' => array('VCHAR:30', ''),
+ 'question_id' => array('UINT', 0),
+ 'attempts' => array('UINT', 0),
+ 'confirm_type' => array('USINT', 0),
+ ),
+ 'KEYS' => array(
+ 'session_id' => array('INDEX', 'session_id'),
+ 'lookup' => array('INDEX', array('confirm_id', 'session_id', 'lang_iso')),
+ ),
+ 'PRIMARY_KEY' => 'confirm_id',
+ ),
+ );
+
+ foreach($schemas as $table => $schema)
+ {
+ if (!$db_tool->sql_table_exists($table))
+ {
+ $db_tool->sql_create_table($table, $schema);
+ }
+ }
+ }
+
+ /**
+ * API function - see what has to be done to validate
+ */
+ function validate()
+ {
+ global $config, $db, $user;
+
+ $error = '';
+
+ if (!sizeof($this->question_ids))
+ {
+ return false;
+ }
+
+ if (!$this->confirm_id)
+ {
+ $error = $user->lang['CONFIRM_QUESTION_WRONG'];
+ }
+ else
+ {
+ if ($this->check_answer())
+ {
+ // $this->delete_code(); commented out to allow posting.php to repeat the question
+ $this->solved = true;
+ }
+ else
+ {
+ $error = $user->lang['CONFIRM_QUESTION_WRONG'];
+ }
+ }
+
+ if (strlen($error))
+ {
+ // okay, incorrect answer. Let's ask a new question.
+ $this->new_attempt();
+ $this->solved = false;
+
+ return $error;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Select a question
+ */
+ function select_question()
+ {
+ global $db, $user;
+
+ if (!sizeof($this->question_ids))
+ {
+ return false;
+ }
+ $this->confirm_id = md5(unique_id($user->ip));
+ $this->question = (int) array_rand($this->question_ids);
+
+ $sql = 'INSERT INTO ' . CAPTCHA_QA_CONFIRM_TABLE . ' ' . $db->sql_build_array('INSERT', array(
+ 'confirm_id' => (string) $this->confirm_id,
+ 'session_id' => (string) $user->session_id,
+ 'lang_iso' => (string) $this->question_lang,
+ 'confirm_type' => (int) $this->type,
+ 'question_id' => (int) $this->question,
+ ));
+ $db->sql_query($sql);
+
+ $this->load_answer();
+ }
+
+ /**
+ * New Question, if desired.
+ */
+ function reselect_question()
+ {
+ global $db, $user;
+
+ if (!sizeof($this->question_ids))
+ {
+ return false;
+ }
+
+ $this->question = (int) array_rand($this->question_ids);
+ $this->solved = 0;
+
+ $sql = 'UPDATE ' . CAPTCHA_QA_CONFIRM_TABLE . '
+ SET question_id = ' . (int) $this->question . "
+ WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "'
+ AND session_id = '" . $db->sql_escape($user->session_id) . "'";
+ $db->sql_query($sql);
+
+ $this->load_answer();
+ }
+
+ /**
+ * Wrong answer, so we increase the attempts and use a different question.
+ */
+ function new_attempt()
+ {
+ global $db, $user;
+
+ // yah, I would prefer a stronger rand, but this should work
+ $this->question = (int) array_rand($this->question_ids);
+ $this->solved = 0;
+
+ $sql = 'UPDATE ' . CAPTCHA_QA_CONFIRM_TABLE . '
+ SET question_id = ' . (int) $this->question . ",
+ attempts = attempts + 1
+ WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "'
+ AND session_id = '" . $db->sql_escape($user->session_id) . "'";
+ $db->sql_query($sql);
+
+ $this->load_answer();
+ }
+
+
+ /**
+ * See if there is already an entry for the current session.
+ */
+ function load_confirm_id()
+ {
+ global $db, $user;
+
+ $sql = 'SELECT confirm_id
+ FROM ' . CAPTCHA_QA_CONFIRM_TABLE . "
+ WHERE
+ session_id = '" . $db->sql_escape($user->session_id) . "'
+ AND lang_iso = '" . $db->sql_escape($this->question_lang) . "'
+ AND confirm_type = " . $this->type;
+ $result = $db->sql_query_limit($sql, 1);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ if ($row)
+ {
+ $this->confirm_id = $row['confirm_id'];
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Look up everything we need and populate the instance variables.
+ */
+ function load_answer()
+ {
+ global $db, $user;
+
+ if (!strlen($this->confirm_id) || !sizeof($this->question_ids))
+ {
+ return false;
+ }
+
+ $sql = 'SELECT con.question_id, attempts, question_text, strict
+ FROM ' . CAPTCHA_QA_CONFIRM_TABLE . ' con, ' . CAPTCHA_QUESTIONS_TABLE . " qes
+ WHERE con.question_id = qes.question_id
+ AND confirm_id = '" . $db->sql_escape($this->confirm_id) . "'
+ AND session_id = '" . $db->sql_escape($user->session_id) . "'
+ AND qes.lang_iso = '" . $db->sql_escape($this->question_lang) . "'
+ AND confirm_type = " . $this->type;
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ if ($row)
+ {
+ $this->question = $row['question_id'];
+
+ $this->attempts = $row['attempts'];
+ $this->question_strict = $row['strict'];
+ $this->question_text = $row['question_text'];
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * The actual validation
+ */
+ function check_answer()
+ {
+ global $db;
+
+ $answer = ($this->question_strict) ? utf8_normalize_nfc(request_var('qa_answer', '', true)) : utf8_clean_string(utf8_normalize_nfc(request_var('qa_answer', '', true)));
+
+ $sql = 'SELECT answer_text
+ FROM ' . CAPTCHA_ANSWERS_TABLE . '
+ WHERE question_id = ' . (int) $this->question;
+ $result = $db->sql_query($sql);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $solution = ($this->question_strict) ? $row['answer_text'] : utf8_clean_string($row['answer_text']);
+
+ if ($solution === $answer)
+ {
+ $this->solved = true;
+
+ break;
+ }
+ }
+ $db->sql_freeresult($result);
+
+ return $this->solved;
+ }
+
+ /**
+ * API function - clean the entry
+ */
+ function delete_code()
+ {
+ global $db, $user;
+
+ $sql = 'DELETE FROM ' . CAPTCHA_QA_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);
+ }
+
+ /**
+ * API function
+ */
+ function get_attempt_count()
+ {
+ return $this->attempts;
+ }
+
+ /**
+ * API function
+ */
+ function reset()
+ {
+ global $db, $user;
+
+ $sql = 'DELETE FROM ' . CAPTCHA_QA_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->select_question();
+ }
+
+ /**
+ * API function
+ */
+ function is_solved()
+ {
+ if (request_var('qa_answer', false) && $this->solved === 0)
+ {
+ $this->validate();
+ }
+
+ return (bool) $this->solved;
+ }
+
+ /**
+ * API function - The ACP backend, this marks the end of the easy methods
+ */
+ function acp_page($id, &$module)
+ {
+ global $db, $user, $auth, $template;
+ global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
+
+ $user->add_lang('acp/board');
+ $user->add_lang('captcha_qa');
+
+ if (!$this->is_installed())
+ {
+ $this->install();
+ }
+
+ $module->tpl_name = 'captcha_qa_acp';
+ $module->page_title = 'ACP_VC_SETTINGS';
+ $form_key = 'acp_captcha';
+ add_form_key($form_key);
+
+ $submit = request_var('submit', false);
+ $question_id = request_var('question_id', 0);
+ $action = request_var('action', '');
+
+ // we have two pages, so users might want to navigate from one to the other
+ $list_url = $module->u_action . "&amp;configure=1&amp;select_captcha=" . $this->get_class_name();
+
+ $template->assign_vars(array(
+ 'U_ACTION' => $module->u_action,
+ 'QUESTION_ID' => $question_id ,
+ 'CLASS' => $this->get_class_name(),
+ ));
+
+ // show the list?
+ if (!$question_id && $action != 'add')
+ {
+ $this->acp_question_list($module);
+ }
+ else if ($question_id && $action == 'delete')
+ {
+ if ($this->get_class_name() !== $config['captcha_plugin'] || !$this->acp_is_last($question_id))
+ {
+ if (confirm_box(true))
+ {
+ $this->acp_delete_question($question_id);
+
+ trigger_error($user->lang['QUESTION_DELETED'] . adm_back_link($list_url));
+ }
+ else
+ {
+ confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
+ 'question_id' => $question_id,
+ 'action' => $action,
+ 'configure' => 1,
+ 'select_captcha' => $this->get_class_name(),
+ ))
+ );
+ }
+ }
+ else
+ {
+ trigger_error($user->lang['QA_LAST_QUESTION'] . adm_back_link($list_url), E_USER_WARNING);
+ }
+ }
+ else
+ {
+ // okay, show the editor
+ $error = false;
+ $input_question = request_var('question_text', '', true);
+ $input_answers = request_var('answers', '', true);
+ $input_lang = request_var('lang_iso', '', true);
+ $input_strict = request_var('strict', false);
+ $langs = $this->get_languages();
+
+ foreach ($langs as $lang => $entry)
+ {
+ $template->assign_block_vars('langs', array(
+ 'ISO' => $lang,
+ 'NAME' => $entry['name'],
+ ));
+ }
+
+ $template->assign_vars(array(
+ 'U_LIST' => $list_url,
+ ));
+
+ if ($question_id)
+ {
+ if ($question = $this->acp_get_question_data($question_id))
+ {
+ $answers = (isset($input_answers[$lang])) ? $input_answers[$lang] : implode("\n", $question['answers']);
+
+ $template->assign_vars(array(
+ 'QUESTION_TEXT' => ($input_question) ? $input_question : $question['question_text'],
+ 'LANG_ISO' => ($input_lang) ? $input_lang : $question['lang_iso'],
+ 'STRICT' => (isset($_REQUEST['strict'])) ? $input_strict : $question['strict'],
+ 'ANSWERS' => $answers,
+ ));
+ }
+ else
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($list_url));
+ }
+ }
+ else
+ {
+ $template->assign_vars(array(
+ 'QUESTION_TEXT' => $input_question,
+ 'LANG_ISO' => $input_lang,
+ 'STRICT' => $input_strict,
+ 'ANSWERS' => $input_answers,
+ ));
+ }
+
+ if ($submit && check_form_key($form_key))
+ {
+ $data = $this->acp_get_question_input();
+
+ if (!$this->validate_input($data))
+ {
+ $template->assign_vars(array(
+ 'S_ERROR' => true,
+ ));
+ }
+ else
+ {
+ if ($question_id)
+ {
+ $this->acp_update_question($data, $question_id);
+ }
+ else
+ {
+ $this->acp_add_question($data);
+ }
+
+ add_log('admin', 'LOG_CONFIG_VISUAL');
+ trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($list_url));
+ }
+ }
+ else if ($submit)
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($list_url), E_USER_WARNING);
+ }
+ }
+ }
+
+ /**
+ * This handles the list overview
+ */
+ function acp_question_list(&$module)
+ {
+ global $db, $template;
+
+ $sql = 'SELECT *
+ FROM ' . CAPTCHA_QUESTIONS_TABLE;
+ $result = $db->sql_query($sql);
+
+ $template->assign_vars(array(
+ 'S_LIST' => true,
+ ));
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $url = $module->u_action . "&amp;question_id={$row['question_id']}&amp;configure=1&amp;select_captcha=" . $this->get_class_name() . '&amp;';
+
+ $template->assign_block_vars('questions', array(
+ 'QUESTION_TEXT' => $row['question_text'],
+ 'QUESTION_ID' => $row['question_id'],
+ 'QUESTION_LANG' => $row['lang_iso'],
+ 'U_DELETE' => "{$url}action=delete",
+ 'U_EDIT' => "{$url}action=edit",
+ ));
+ }
+ $db->sql_freeresult($result);
+ }
+
+ /**
+ * Grab a question and bring it into a format the editor understands
+ */
+ function acp_get_question_data($question_id)
+ {
+ global $db;
+
+ if ($question_id)
+ {
+ $sql = 'SELECT *
+ FROM ' . CAPTCHA_QUESTIONS_TABLE . '
+ WHERE question_id = ' . $question_id;
+ $result = $db->sql_query($sql);
+ $question = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ if (!$question)
+ {
+ return false;
+ }
+
+ $question['answers'] = array();
+
+ $sql = 'SELECT *
+ FROM ' . CAPTCHA_ANSWERS_TABLE . '
+ WHERE question_id = ' . $question_id;
+ $result = $db->sql_query($sql);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $question['answers'][] = $row['answer_text'];
+ }
+ $db->sql_freeresult($result);
+
+ return $question;
+ }
+ }
+
+ /**
+ * Grab a question from input and bring it into a format the editor understands
+ */
+ function acp_get_question_input()
+ {
+ $answers = utf8_normalize_nfc(request_var('answers', '', true));
+ $question = array(
+ 'question_text' => request_var('question_text', '', true),
+ 'strict' => request_var('strict', false),
+ 'lang_iso' => request_var('lang_iso', ''),
+ 'answers' => (strlen($answers)) ? explode("\n", $answers) : '',
+ );
+
+ return $question;
+ }
+
+ /**
+ * Update a question.
+ * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data
+ */
+ function acp_update_question($data, $question_id)
+ {
+ global $db, $cache;
+
+ // easier to delete all answers than to figure out which to update
+ $sql = 'DELETE FROM ' . CAPTCHA_ANSWERS_TABLE . " WHERE question_id = $question_id";
+ $db->sql_query($sql);
+
+ $langs = $this->get_languages();
+ $question_ary = $data;
+ $question_ary['lang_id'] = $langs[$question_ary['lang_iso']]['id'];
+ unset($question_ary['answers']);
+
+ $sql = 'UPDATE ' . CAPTCHA_QUESTIONS_TABLE . '
+ SET ' . $db->sql_build_array('UPDATE', $question_ary) . "
+ WHERE question_id = $question_id";
+ $db->sql_query($sql);
+
+ $this->acp_insert_answers($data, $question_id);
+
+ $cache->destroy('sql', CAPTCHA_QUESTIONS_TABLE);
+ }
+
+ /**
+ * Insert a question.
+ * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data
+ */
+ function acp_add_question($data)
+ {
+ global $db, $cache;
+
+ $langs = $this->get_languages();
+ $question_ary = $data;
+
+ $question_ary['lang_id'] = $langs[$data['lang_iso']]['id'];
+ unset($question_ary['answers']);
+
+ $sql = 'INSERT INTO ' . CAPTCHA_QUESTIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $question_ary);
+ $db->sql_query($sql);
+
+ $question_id = $db->sql_nextid();
+
+ $this->acp_insert_answers($data, $question_id);
+
+ $cache->destroy('sql', CAPTCHA_QUESTIONS_TABLE);
+ }
+
+ /**
+ * Insert the answers.
+ * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data
+ */
+ function acp_insert_answers($data, $question_id)
+ {
+ global $db, $cache;
+
+ foreach ($data['answers'] as $answer)
+ {
+ $answer_ary = array(
+ 'question_id' => $question_id,
+ 'answer_text' => $answer,
+ );
+
+ $sql = 'INSERT INTO ' . CAPTCHA_ANSWERS_TABLE . ' ' . $db->sql_build_array('INSERT', $answer_ary);
+ $db->sql_query($sql);
+ }
+
+ $cache->destroy('sql', CAPTCHA_ANSWERS_TABLE);
+ }
+
+ /**
+ * Delete a question.
+ */
+ function acp_delete_question($question_id)
+ {
+ global $db, $cache;
+
+ $tables = array(CAPTCHA_QUESTIONS_TABLE, CAPTCHA_ANSWERS_TABLE);
+
+ foreach ($tables as $table)
+ {
+ $sql = "DELETE FROM $table
+ WHERE question_id = $question_id";
+ $db->sql_query($sql);
+ }
+
+ $cache->destroy('sql', $tables);
+ }
+
+ /**
+ * Check if the entered data can be inserted/used
+ * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data
+ */
+ function validate_input($question_data)
+ {
+ $langs = $this->get_languages();
+
+ if (!isset($question_data['lang_iso']) ||
+ !isset($question_data['question_text']) ||
+ !isset($question_data['strict']) ||
+ !isset($question_data['answers']))
+ {
+ return false;
+ }
+
+ if (!isset($langs[$question_data['lang_iso']]) ||
+ !strlen($question_data['question_text']) ||
+ !sizeof($question_data['answers']) ||
+ !is_array($question_data['answers']))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * List the installed language packs
+ */
+ function get_languages()
+ {
+ global $db;
+
+ $sql = 'SELECT *
+ FROM ' . LANG_TABLE;
+ $result = $db->sql_query($sql);
+
+ $langs = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $langs[$row['lang_iso']] = array(
+ 'name' => $row['lang_local_name'],
+ 'id' => (int) $row['lang_id'],
+ );
+ }
+ $db->sql_freeresult($result);
+
+ return $langs;
+ }
+
+
+
+ /**
+ * See if there is a question other than the one we have
+ */
+ function acp_is_last($question_id)
+ {
+ global $config, $db;
+
+ if ($question_id)
+ {
+ $sql = 'SELECT question_id
+ FROM ' . CAPTCHA_QUESTIONS_TABLE . "
+ WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'
+ AND question_id <> " . (int) $question_id;
+ $result = $db->sql_query_limit($sql, 1);
+ $question = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ if (!$question)
+ {
+ return true;
+ }
+ return false;
+ }
+ }
+}
+
+?>
View
343 zafenio/includes/captcha/plugins/phpbb_recaptcha_plugin.php
@@ -0,0 +1,343 @@
+<?php
+/**
+*
+* @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;
+}
+
+if (!class_exists('phpbb_default_captcha'))
+{
+ // we need the classic captcha code for tracking solutions and attempts
+ include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx);
+}
+
+/**
+* @package VC
+*/
+class phpbb_recaptcha extends phpbb_default_captcha
+{
+ var $recaptcha_server = 'http://api.recaptcha.net';
+ var $recaptcha_server_secure = 'https://api-secure.recaptcha.net'; // class constants :(
+ var $recaptcha_verify_server = 'api-verify.recaptcha.net';
+ var $challenge;
+ var $response;
+
+ // PHP4 Constructor
+ function phpbb_recaptcha()
+ {
+ $this->recaptcha_server = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? $this->recaptcha_server_secure : $this->recaptcha_server;
+ }
+
+ function init($type)
+ {
+ global $config, $db, $user;
+
+ $user->add_lang('captcha_recaptcha');
+ parent::init($type);
+ $this->challenge = request_var('recaptcha_challenge_field', '');
+ $this->response = request_var('recaptcha_response_field', '');
+ }
+
+ function &get_instance()
+ {
+ $instance =& new phpbb_recaptcha();
+ return $instance;
+ }
+
+ function is_available()
+ {
+ global $config, $user;
+ $user->add_lang('captcha_recaptcha');
+ return (isset($config['recaptcha_pubkey']) && !empty($config['recaptcha_pubkey']));
+ }
+
+ /**
+ * API function
+ */
+ function has_config()
+ {
+ return true;
+ }
+
+ function get_name()
+ {
+ return 'CAPTCHA_RECAPTCHA';
+ }
+
+ function get_class_name()
+ {
+ return 'phpbb_recaptcha';
+ }
+
+ function acp_page($id, &$module)
+ {
+ global $config, $db, $template, $user;
+
+ $captcha_vars = array(
+ 'recaptcha_pubkey' => 'RECAPTCHA_PUBKEY',
+ 'recaptcha_privkey' => 'RECAPTCHA_PRIVKEY',
+ );
+
+ $module->tpl_name = 'captcha_recaptcha_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, '');
+ if ($value)
+ {
+ set_config($captcha_var, $value);
+ }
+ }
+
+ add_log('admin', 'LOG_CONFIG_VISUAL');
+ 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, '') : ((isset($config[$captcha_var])) ? $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(),
+ 'U_ACTION' => $module->u_action,
+ ));
+
+ }
+ }
+
+ // not needed
+ function execute_demo()
+ {
+ }
+
+ // not needed
+ function execute()
+ {
+ }
+
+ function get_template()
+ {
+ global $config, $user, $template;
+
+ if ($this->is_solved())
+ {
+ return false;
+ }
+ else
+ {
+ $explain = $user->lang(($this->type != CONFIRM_POST) ? 'CONFIRM_EXPLAIN' : 'POST_CONFIRM_EXPLAIN', '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>');
+
+ $template->assign_vars(array(
+ 'RECAPTCHA_SERVER' => $this->recaptcha_server,
+ 'RECAPTCHA_PUBKEY' => isset($config['recaptcha_pubkey']) ? $config['recaptcha_pubkey'] : '',
+ 'RECAPTCHA_ERRORGET' => '',
+ 'S_RECAPTCHA_AVAILABLE' => $this->is_available(),
+ 'S_CONFIRM_CODE' => true,
+ 'S_TYPE' => $this->type,
+ 'L_CONFIRM_EXPLAIN' => $explain,
+ ));
+
+ return 'captcha_recaptcha.html';
+ }
+ }
+
+ function get_demo_template($id)
+ {
+ return $this->get_template();
+ }
+
+ function get_hidden_fields()
+ {
+ $hidden_fields = array();
+
+ // this is required for posting.php - otherwise we would forget about the captcha being already solved
+ if ($this->solved)
+ {
+ $hidden_fields['confirm_code'] = $this->code;
+ }
+ $hidden_fields['confirm_id'] = $this->confirm_id;
+ return $hidden_fields;
+ }
+
+ function uninstall()
+ {
+ $this->garbage_collect(0);
+ }
+
+ function install()
+ {
+ return;
+ }
+
+ function validate()
+ {
+ if (!parent::validate())
+ {
+ return false;
+ }
+ else
+ {
+ return $this->recaptcha_check_answer();
+ }
+ }
+
+// Code from here on is based on recaptchalib.php
+/*
+ * This is a PHP library that handles calling reCAPTCHA.
+ * - Documentation and latest version
+ * http://recaptcha.net/plugins/php/
+ * - Get a reCAPTCHA API Key
+ * http://recaptcha.net/api/getkey
+ * - Discussion group
+ * http://groups.google.com/group/recaptcha
+ *
+ * Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
+ * AUTHORS:
+ * Mike Crawford
+ * Ben Maurer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+ /**
+ * Submits an HTTP POST to a reCAPTCHA server
+ * @param string $host
+ * @param string $path
+ * @param array $data
+ * @param int port
+ * @return array response
+ */
+ function _recaptcha_http_post($host, $path, $data, $port = 80)
+ {
+ $req = $this->_recaptcha_qsencode ($data);
+
+ $http_request = "POST $path HTTP/1.0\r\n";
+ $http_request .= "Host: $host\r\n";
+ $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
+ $http_request .= "Content-Length: " . strlen($req) . "\r\n";
+ $http_request .= "User-Agent: reCAPTCHA/PHP/phpBB\r\n";
+ $http_request .= "\r\n";
+ $http_request .= $req;
+
+ $response = '';
+ if (false == ($fs = @fsockopen($host, $port, $errno, $errstr, 10)))
+ {
+ trigger_error('Could not open socket', E_USER_ERROR);
+ }
+
+ fwrite($fs, $http_request);
+
+ while (!feof($fs))
+ {
+ // One TCP-IP packet
+ $response .= fgets($fs, 1160);
+ }
+ fclose($fs);
+ $response = explode("\r\n\r\n", $response, 2);
+
+ return $response;
+ }
+
+ /**
+ * Calls an HTTP POST function to verify if the user's guess was correct
+ * @param array $extra_params an array of extra variables to post to the server
+ * @return ReCaptchaResponse
+ */
+ function recaptcha_check_answer($extra_params = array())
+ {
+ global $config, $user;
+
+ //discard spam submissions
+ if ($this->challenge == null || strlen($this->challenge) == 0 || $this->response == null || strlen($this->response) == 0)
+ {
+ return $user->lang['RECAPTCHA_INCORRECT'];
+ }
+
+ $response = $this->_recaptcha_http_post($this->recaptcha_verify_server, '/verify',
+ array(
+ 'privatekey' => $config['recaptcha_privkey'],
+ 'remoteip' => $user->ip,
+ 'challenge' => $this->challenge,
+ 'response' => $this->response
+ ) + $extra_params
+ );
+
+ $answers = explode("\n", $response[1]);
+
+ if (trim($answers[0]) === 'true')
+ {
+ $this->solved = true;
+ return false;
+ }
+ else
+ {
+ if ($answers[1] === 'incorrect-captcha-sol')
+ {
+ return $user->lang['RECAPTCHA_INCORRECT'];
+ }
+ }
+ }
+
+ /**
+ * Encodes the given data into a query string format
+ * @param $data - array of string elements to be encoded
+ * @return string - encoded request
+ */
+ function _recaptcha_qsencode($data)
+ {
+ $req = '';
+ foreach ($data as $key => $value)
+ {
+ $req .= $key . '=' . urlencode(stripslashes($value)) . '&';
+ }
+
+ // Cut the last '&'
+ $req = substr($req, 0, strlen($req) - 1);
+ return $req;
+ }
+}
+
+?>
View
512 zafenio/includes/questionnaire/questionnaire.php
@@ -0,0 +1,512 @@
+<?php
+/**
+*
+* @package phpBB3
+* @version $Id$
+* @copyright (c) 2005 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* This class collects data which is used to create some usage statistics.
+*
+* The collected data is - after authorization of the administrator - submitted
+* to a central server. For privacy reasons we try to collect only data which aren't private
+* or don't give any information which might help to identify the user.
+*
+* @author Johannes Schlueter <johannes@php.net>
+* @copyright (c) 2007-2008 Johannes Schlueter
+*/
+class phpbb_questionnaire_data_collector
+{
+ var $providers;
+ var $data = null;
+ var $install_id = '';
+
+ /**
+ * Constructor.
+ *
+ * @param string
+ */
+ function phpbb_questionnaire_data_collector($install_id)
+ {
+ $this->install_id = $install_id;
+ $this->providers = array();
+ }
+
+ function add_data_provider(&$provider)
+ {
+ $this->providers[] = &$provider;
+ }
+
+ /**
+ * Get data as an array.
+ *
+ * @return array All Data
+ */
+ function get_data_raw()
+ {
+ if (!$this->data)
+ {
+ $this->collect();
+ }
+
+ return $this->data;
+ }
+
+ function get_data_for_form()
+ {
+ return base64_encode(serialize($this->get_data_raw()));
+ }
+
+ /**
+ * Collect info into the data property.
+ *
+ * @return void
+ */
+ function collect()
+ {
+ foreach (array_keys($this->providers) as $key)
+ {
+ $provider = &$this->providers[$key];
+ $this->data[$provider->get_identifier()] = $provider->get_data();
+ }
+ $this->data['install_id'] = $this->install_id;
+ }
+}
+
+/** interface: get_indentifier(), get_data() */
+
+/**
+* Questionnaire PHP data provider
+* @package phpBB3
+*/
+class phpbb_questionnaire_php_data_provider
+{
+ function get_identifier()
+ {
+ return 'PHP';
+ }
+
+ /**
+ * Get data about the PHP runtime setup.
+ *
+ * @return array
+ */
+ function get_data()
+ {
+ return array(
+ 'version' => PHP_VERSION,
+ 'sapi' => PHP_SAPI,
+ 'int_size' => defined('PHP_INT_SIZE') ? PHP_INT_SIZE : '',
+ 'safe_mode' => (int) @ini_get('safe_mode'),
+ 'open_basedir' => (int) @ini_get('open_basedir'),
+ 'memory_limit' => @ini_get('memory_limit'),
+ 'allow_url_fopen' => (int) @ini_get('allow_url_fopen'),
+ 'allow_url_include' => (int) @ini_get('allow_url_include'),
+ 'file_uploads' => (int) @ini_get('file_uploads'),
+ 'upload_max_filesize' => @ini_get('upload_max_filesize'),
+ 'post_max_size' => @ini_get('post_max_size'),
+ 'disable_functions' => @ini_get('disable_functions'),
+ 'disable_classes' => @ini_get('disable_classes'),
+ 'enable_dl' => (int) @ini_get('enable_dl'),
+ 'magic_quotes_gpc' => (int) @ini_get('magic_quotes_gpc'),
+ 'register_globals' => (int) @ini_get('register_globals'),
+ 'filter.default' => @ini_get('filter.default'),
+ 'zend.ze1_compatibility_mode' => (int) @ini_get('zend.ze1_compatibility_mode'),
+ 'unicode.semantics' => (int) @ini_get('unicode.semantics'),
+ 'zend_thread_safty' => (int) function_exists('zend_thread_id'),