From 160ff7b912243dc14d871b820213ddcd20dd06f4 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Fri, 8 Aug 2014 18:02:03 +0200 Subject: [ticket/11854] Move captcha stuff to phpbb/ and use DI for plugins PHPBB3-11854 --- phpBB/phpbb/captcha/plugins/qa.php | 982 +++++++++++++++++++++++++++++++++++++ 1 file changed, 982 insertions(+) create mode 100644 phpBB/phpbb/captcha/plugins/qa.php (limited to 'phpBB/phpbb/captcha/plugins/qa.php') diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php new file mode 100644 index 0000000000..6dab573c3e --- /dev/null +++ b/phpBB/phpbb/captcha/plugins/qa.php @@ -0,0 +1,982 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\captcha\plugins; + +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 +*/ +class 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(); + } + } + + /** + * See if the captcha has created its tables. + */ + public function is_installed() + { + global $db; + + $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 + */ + public 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 (!$this->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 + */ + static public function get_name() + { + return 'CAPTCHA_QA'; + } + + /** + * API function + */ + function get_service_name() + { + return 'core.captcha.plugins.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; + + $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' => array('INDEX', 'lang_iso'), + ), + ), + CAPTCHA_ANSWERS_TABLE => array ( + 'COLUMNS' => array( + 'question_id' => array('UINT', 0), + 'answer_text' => array('STEXT_UNI', ''), + ), + 'KEYS' => array( + 'qid' => 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->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 + */ + 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 (!self::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 . "&configure=1&select_captcha=" . $this->get_service_name(); + + $template->assign_vars(array( + 'U_ACTION' => $module->u_action, + 'QUESTION_ID' => $question_id , + 'CLASS' => $this->get_service_name(), + )); + + // show the list? + if (!$question_id && $action != 'add') + { + $this->acp_question_list($module); + } + else if ($question_id && $action == 'delete') + { + if ($this->get_service_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_service_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 . "&question_id={$row['question_id']}&configure=1&select_captcha=" . $this->get_service_name() . '&'; + + $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; + } + } +} -- cgit v1.2.1 From 02f3b74e8a7259560f48b6fdf06c3bbd8aa09dbb Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 10 Aug 2014 00:08:52 +0200 Subject: [ticket/11854] Fix coding style PHPBB3-11854 --- phpBB/phpbb/captcha/plugins/qa.php | 64 +++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 35 deletions(-) (limited to 'phpBB/phpbb/captcha/plugins/qa.php') diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php index 6dab573c3e..3d8112e0f0 100644 --- a/phpBB/phpbb/captcha/plugins/qa.php +++ b/phpBB/phpbb/captcha/plugins/qa.php @@ -13,12 +13,6 @@ namespace phpbb\captcha\plugins; -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 @@ -41,7 +35,7 @@ class qa */ function init($type) { - global $config, $db, $user; + global $config, $db, $user, $table_prefix; // load our language file $user->add_lang('captcha_qa'); @@ -56,7 +50,7 @@ class qa // 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 . " + FROM ' . $table_prefix . 'captcha_questions' . " WHERE lang_iso = '" . $db->sql_escape($user->lang_name) . "'"; $result = $db->sql_query($sql, 3600); @@ -72,7 +66,7 @@ class qa $this->question_lang = $config['default_lang']; $sql = 'SELECT question_id - FROM ' . CAPTCHA_QUESTIONS_TABLE . " + FROM ' . $table_prefix . 'captcha_questions' . " WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'"; $result = $db->sql_query($sql, 7200); @@ -96,11 +90,11 @@ class qa */ public function is_installed() { - global $db; + global $db, $table_prefix; $db_tool = new \phpbb\db\tools($db); - return $db_tool->sql_table_exists(CAPTCHA_QUESTIONS_TABLE); + return $db_tool->sql_table_exists($table_prefix . 'captcha_questions'); } /** @@ -108,7 +102,7 @@ class qa */ public function is_available() { - global $config, $db, $phpbb_root_path, $phpEx, $user; + global $config, $db, $phpbb_root_path, $phpEx, $user, $table_prefix; // load language file for pretty display in the ACP dropdown $user->add_lang('captcha_qa'); @@ -119,7 +113,7 @@ class qa } $sql = 'SELECT COUNT(question_id) AS question_count - FROM ' . CAPTCHA_QUESTIONS_TABLE . " + FROM ' . $table_prefix . 'captcha_questions' . " WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'"; $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); @@ -195,12 +189,12 @@ class qa */ function get_demo_template() { - global $config, $db, $template; + global $config, $db, $template, $table_prefix; if ($this->is_available()) { $sql = 'SELECT question_text - FROM ' . CAPTCHA_QUESTIONS_TABLE . " + FROM ' . $table_prefix . 'captcha_questions' . " WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'"; $result = $db->sql_query_limit($sql, 1); if ($row = $db->sql_fetchrow($result)) @@ -279,16 +273,16 @@ class qa */ function install() { - global $db; + global $db, $table_prefix; $db_tool = new \phpbb\db\tools($db); - $tables = array(CAPTCHA_QUESTIONS_TABLE, CAPTCHA_ANSWERS_TABLE, CAPTCHA_QA_CONFIRM_TABLE); + $tables = array($table_prefix . 'captcha_questions', CAPTCHA_ANSWERS_TABLE, CAPTCHA_QA_CONFIRM_TABLE); $schemas = array( - CAPTCHA_QUESTIONS_TABLE => array ( + $table_prefix . 'captcha_questions' => array ( 'COLUMNS' => array( - 'question_id' => array('UINT', Null, 'auto_increment'), + 'question_id' => array('UINT', null, 'auto_increment'), 'strict' => array('BOOL', 0), 'lang_id' => array('UINT', 0), 'lang_iso' => array('VCHAR:30', ''), @@ -480,7 +474,7 @@ class qa */ function load_answer() { - global $db, $user; + global $db, $user, $table_prefix; if (!strlen($this->confirm_id) || !sizeof($this->question_ids)) { @@ -488,7 +482,7 @@ class qa } $sql = 'SELECT con.question_id, attempts, question_text, strict - FROM ' . CAPTCHA_QA_CONFIRM_TABLE . ' con, ' . CAPTCHA_QUESTIONS_TABLE . " qes + FROM ' . CAPTCHA_QA_CONFIRM_TABLE . ' con, ' . $table_prefix . 'captcha_questions' . " 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) . "' @@ -731,10 +725,10 @@ class qa */ function acp_question_list(&$module) { - global $db, $template; + global $db, $template, $table_prefix; $sql = 'SELECT * - FROM ' . CAPTCHA_QUESTIONS_TABLE; + FROM ' . $table_prefix . 'captcha_questions'; $result = $db->sql_query($sql); $template->assign_vars(array( @@ -761,12 +755,12 @@ class qa */ function acp_get_question_data($question_id) { - global $db; + global $db, $table_prefix; if ($question_id) { $sql = 'SELECT * - FROM ' . CAPTCHA_QUESTIONS_TABLE . ' + FROM ' . $table_prefix . 'captcha_questions' . ' WHERE question_id = ' . $question_id; $result = $db->sql_query($sql); $question = $db->sql_fetchrow($result); @@ -816,7 +810,7 @@ class qa */ function acp_update_question($data, $question_id) { - global $db, $cache; + global $db, $cache, $table_prefix; // easier to delete all answers than to figure out which to update $sql = 'DELETE FROM ' . CAPTCHA_ANSWERS_TABLE . " WHERE question_id = $question_id"; @@ -827,14 +821,14 @@ class qa $question_ary['lang_id'] = $langs[$question_ary['lang_iso']]['id']; unset($question_ary['answers']); - $sql = 'UPDATE ' . CAPTCHA_QUESTIONS_TABLE . ' + $sql = 'UPDATE ' . $table_prefix . 'captcha_questions' . ' 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); + $cache->destroy('sql', $table_prefix . 'captcha_questions'); } /** @@ -843,7 +837,7 @@ class qa */ function acp_add_question($data) { - global $db, $cache; + global $db, $cache, $table_prefix; $langs = $this->get_languages(); $question_ary = $data; @@ -851,14 +845,14 @@ class qa $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); + $sql = 'INSERT INTO ' . $table_prefix . 'captcha_questions' . ' ' . $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); + $cache->destroy('sql', $table_prefix . 'captcha_questions'); } /** @@ -888,9 +882,9 @@ class qa */ function acp_delete_question($question_id) { - global $db, $cache; + global $db, $cache, $table_prefix; - $tables = array(CAPTCHA_QUESTIONS_TABLE, CAPTCHA_ANSWERS_TABLE); + $tables = array($table_prefix . 'captcha_questions', CAPTCHA_ANSWERS_TABLE); foreach ($tables as $table) { @@ -960,12 +954,12 @@ class qa */ function acp_is_last($question_id) { - global $config, $db; + global $config, $db, $table_prefix; if ($question_id) { $sql = 'SELECT question_id - FROM ' . CAPTCHA_QUESTIONS_TABLE . " + FROM ' . $table_prefix . 'captcha_questions' . " WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "' AND question_id <> " . (int) $question_id; $result = $db->sql_query_limit($sql, 1); -- cgit v1.2.1 From e889b8f9318ab8e6324f6d5ca4fedc08ce418c8f Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 10 Aug 2014 13:15:07 +0200 Subject: [ticket/11854] Remove constants and use DI for QA tables PHPBB3-11854 --- phpBB/phpbb/captcha/plugins/qa.php | 78 +++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 30 deletions(-) (limited to 'phpBB/phpbb/captcha/plugins/qa.php') diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php index 3d8112e0f0..c0bcf86531 100644 --- a/phpBB/phpbb/captcha/plugins/qa.php +++ b/phpBB/phpbb/captcha/plugins/qa.php @@ -30,6 +30,24 @@ class qa // dirty trick: 0 is false, but can still encode that the captcha is not yet validated var $solved = 0; + protected $table_captcha_questions; + protected $table_captcha_answers; + protected $table_qa_confirm; + + /** + * Constructor + * + * @param string $table_captcha_questions + * @param string $table_captcha_answers + * @param string $table_qa_confirm + */ + function __construct($table_captcha_questions, $table_captcha_answers, $table_qa_confirm) + { + $this->table_captcha_questions = $table_captcha_questions; + $this->table_captcha_answers = $table_captcha_answers; + $this->table_qa_confirm = $table_qa_confirm; + } + /** * @param int $type as per the CAPTCHA API docs, the type */ @@ -50,7 +68,7 @@ class qa // 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 ' . $table_prefix . 'captcha_questions' . " + FROM ' . $this->table_captcha_questions . " WHERE lang_iso = '" . $db->sql_escape($user->lang_name) . "'"; $result = $db->sql_query($sql, 3600); @@ -66,7 +84,7 @@ class qa $this->question_lang = $config['default_lang']; $sql = 'SELECT question_id - FROM ' . $table_prefix . 'captcha_questions' . " + FROM ' . $this->table_captcha_questions . " WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'"; $result = $db->sql_query($sql, 7200); @@ -94,7 +112,7 @@ class qa $db_tool = new \phpbb\db\tools($db); - return $db_tool->sql_table_exists($table_prefix . 'captcha_questions'); + return $db_tool->sql_table_exists($this->table_captcha_questions); } /** @@ -113,7 +131,7 @@ class qa } $sql = 'SELECT COUNT(question_id) AS question_count - FROM ' . $table_prefix . 'captcha_questions' . " + FROM ' . $this->table_captcha_questions . " WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'"; $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); @@ -194,7 +212,7 @@ class qa if ($this->is_available()) { $sql = 'SELECT question_text - FROM ' . $table_prefix . 'captcha_questions' . " + FROM ' . $this->table_captcha_questions . " WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'"; $result = $db->sql_query_limit($sql, 1); if ($row = $db->sql_fetchrow($result)) @@ -233,7 +251,7 @@ class qa global $db, $config; $sql = 'SELECT c.confirm_id - FROM ' . CAPTCHA_QA_CONFIRM_TABLE . ' c + FROM ' . $this->table_qa_confirm . ' c LEFT JOIN ' . SESSIONS_TABLE . ' s ON (c.session_id = s.session_id) WHERE s.session_id IS NULL' . @@ -252,7 +270,7 @@ class qa if (sizeof($sql_in)) { - $sql = 'DELETE FROM ' . CAPTCHA_QA_CONFIRM_TABLE . ' + $sql = 'DELETE FROM ' . $this->table_qa_confirm . ' WHERE ' . $db->sql_in_set('confirm_id', $sql_in); $db->sql_query($sql); } @@ -277,10 +295,10 @@ class qa $db_tool = new \phpbb\db\tools($db); - $tables = array($table_prefix . 'captcha_questions', CAPTCHA_ANSWERS_TABLE, CAPTCHA_QA_CONFIRM_TABLE); + $tables = array($this->table_captcha_questions, $this->table_captcha_answers, $this->table_qa_confirm); $schemas = array( - $table_prefix . 'captcha_questions' => array ( + $this->table_captcha_questions => array ( 'COLUMNS' => array( 'question_id' => array('UINT', null, 'auto_increment'), 'strict' => array('BOOL', 0), @@ -293,7 +311,7 @@ class qa 'lang' => array('INDEX', 'lang_iso'), ), ), - CAPTCHA_ANSWERS_TABLE => array ( + $this->table_captcha_answers => array ( 'COLUMNS' => array( 'question_id' => array('UINT', 0), 'answer_text' => array('STEXT_UNI', ''), @@ -302,7 +320,7 @@ class qa 'qid' => array('INDEX', 'question_id'), ), ), - CAPTCHA_QA_CONFIRM_TABLE => array ( + $this->table_qa_confirm => array ( 'COLUMNS' => array( 'session_id' => array('CHAR:32', ''), 'confirm_id' => array('CHAR:32', ''), @@ -386,7 +404,7 @@ class qa $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( + $sql = 'INSERT INTO ' . $this->table_qa_confirm . ' ' . $db->sql_build_array('INSERT', array( 'confirm_id' => (string) $this->confirm_id, 'session_id' => (string) $user->session_id, 'lang_iso' => (string) $this->question_lang, @@ -413,7 +431,7 @@ class qa $this->question = (int) array_rand($this->question_ids); $this->solved = 0; - $sql = 'UPDATE ' . CAPTCHA_QA_CONFIRM_TABLE . ' + $sql = 'UPDATE ' . $this->table_qa_confirm . ' SET question_id = ' . (int) $this->question . " WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "' AND session_id = '" . $db->sql_escape($user->session_id) . "'"; @@ -433,7 +451,7 @@ class qa $this->question = (int) array_rand($this->question_ids); $this->solved = 0; - $sql = 'UPDATE ' . CAPTCHA_QA_CONFIRM_TABLE . ' + $sql = 'UPDATE ' . $this->table_qa_confirm . ' SET question_id = ' . (int) $this->question . ", attempts = attempts + 1 WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "' @@ -452,7 +470,7 @@ class qa global $db, $user; $sql = 'SELECT confirm_id - FROM ' . CAPTCHA_QA_CONFIRM_TABLE . " + FROM ' . $this->table_qa_confirm . " WHERE session_id = '" . $db->sql_escape($user->session_id) . "' AND lang_iso = '" . $db->sql_escape($this->question_lang) . "' @@ -482,7 +500,7 @@ class qa } $sql = 'SELECT con.question_id, attempts, question_text, strict - FROM ' . CAPTCHA_QA_CONFIRM_TABLE . ' con, ' . $table_prefix . 'captcha_questions' . " qes + FROM ' . $this->table_qa_confirm . ' con, ' . $this->table_captcha_questions . " 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) . "' @@ -516,7 +534,7 @@ class qa $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 . ' + FROM ' . $this->table_captcha_answers . ' WHERE question_id = ' . (int) $this->question; $result = $db->sql_query($sql); @@ -551,7 +569,7 @@ class qa { global $db, $user; - $sql = 'DELETE FROM ' . CAPTCHA_QA_CONFIRM_TABLE . " + $sql = 'DELETE FROM ' . $this->table_qa_confirm . " WHERE session_id = '" . $db->sql_escape($user->session_id) . "' AND confirm_type = " . (int) $this->type; $db->sql_query($sql); @@ -728,7 +746,7 @@ class qa global $db, $template, $table_prefix; $sql = 'SELECT * - FROM ' . $table_prefix . 'captcha_questions'; + FROM ' . $this->table_captcha_questions; $result = $db->sql_query($sql); $template->assign_vars(array( @@ -760,7 +778,7 @@ class qa if ($question_id) { $sql = 'SELECT * - FROM ' . $table_prefix . 'captcha_questions' . ' + FROM ' . $this->table_captcha_questions . ' WHERE question_id = ' . $question_id; $result = $db->sql_query($sql); $question = $db->sql_fetchrow($result); @@ -774,7 +792,7 @@ class qa $question['answers'] = array(); $sql = 'SELECT * - FROM ' . CAPTCHA_ANSWERS_TABLE . ' + FROM ' . $this->table_captcha_answers . ' WHERE question_id = ' . $question_id; $result = $db->sql_query($sql); @@ -813,7 +831,7 @@ class qa global $db, $cache, $table_prefix; // easier to delete all answers than to figure out which to update - $sql = 'DELETE FROM ' . CAPTCHA_ANSWERS_TABLE . " WHERE question_id = $question_id"; + $sql = 'DELETE FROM ' . $this->table_captcha_answers . " WHERE question_id = $question_id"; $db->sql_query($sql); $langs = $this->get_languages(); @@ -821,14 +839,14 @@ class qa $question_ary['lang_id'] = $langs[$question_ary['lang_iso']]['id']; unset($question_ary['answers']); - $sql = 'UPDATE ' . $table_prefix . 'captcha_questions' . ' + $sql = 'UPDATE ' . $this->table_captcha_questions . ' 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', $table_prefix . 'captcha_questions'); + $cache->destroy('sql', $this->table_captcha_questions); } /** @@ -845,14 +863,14 @@ class qa $question_ary['lang_id'] = $langs[$data['lang_iso']]['id']; unset($question_ary['answers']); - $sql = 'INSERT INTO ' . $table_prefix . 'captcha_questions' . ' ' . $db->sql_build_array('INSERT', $question_ary); + $sql = 'INSERT INTO ' . $this->table_captcha_questions . ' ' . $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', $table_prefix . 'captcha_questions'); + $cache->destroy('sql', $this->table_captcha_questions); } /** @@ -870,11 +888,11 @@ class qa 'answer_text' => $answer, ); - $sql = 'INSERT INTO ' . CAPTCHA_ANSWERS_TABLE . ' ' . $db->sql_build_array('INSERT', $answer_ary); + $sql = 'INSERT INTO ' . $this->table_captcha_answers . ' ' . $db->sql_build_array('INSERT', $answer_ary); $db->sql_query($sql); } - $cache->destroy('sql', CAPTCHA_ANSWERS_TABLE); + $cache->destroy('sql', $this->table_captcha_answers); } /** @@ -884,7 +902,7 @@ class qa { global $db, $cache, $table_prefix; - $tables = array($table_prefix . 'captcha_questions', CAPTCHA_ANSWERS_TABLE); + $tables = array($this->table_captcha_questions, $this->table_captcha_answers); foreach ($tables as $table) { @@ -959,7 +977,7 @@ class qa if ($question_id) { $sql = 'SELECT question_id - FROM ' . $table_prefix . 'captcha_questions' . " + FROM ' . $this->table_captcha_questions . " WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "' AND question_id <> " . (int) $question_id; $result = $db->sql_query_limit($sql, 1); -- cgit v1.2.1 From 036a61a904ce1a3023bb137fbfaf546b473c528d Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 10 Aug 2014 14:53:15 +0200 Subject: [ticket/11854] Remove unused globals PHPBB3-11854 --- phpBB/phpbb/captcha/plugins/qa.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'phpBB/phpbb/captcha/plugins/qa.php') diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php index c0bcf86531..96cd99826d 100644 --- a/phpBB/phpbb/captcha/plugins/qa.php +++ b/phpBB/phpbb/captcha/plugins/qa.php @@ -53,7 +53,7 @@ class qa */ function init($type) { - global $config, $db, $user, $table_prefix; + global $config, $db, $user; // load our language file $user->add_lang('captcha_qa'); @@ -108,7 +108,7 @@ class qa */ public function is_installed() { - global $db, $table_prefix; + global $db; $db_tool = new \phpbb\db\tools($db); @@ -120,7 +120,7 @@ class qa */ public function is_available() { - global $config, $db, $phpbb_root_path, $phpEx, $user, $table_prefix; + global $config, $db, $phpbb_root_path, $phpEx, $user; // load language file for pretty display in the ACP dropdown $user->add_lang('captcha_qa'); @@ -207,7 +207,7 @@ class qa */ function get_demo_template() { - global $config, $db, $template, $table_prefix; + global $config, $db, $template; if ($this->is_available()) { @@ -291,7 +291,7 @@ class qa */ function install() { - global $db, $table_prefix; + global $db; $db_tool = new \phpbb\db\tools($db); @@ -492,7 +492,7 @@ class qa */ function load_answer() { - global $db, $user, $table_prefix; + global $db, $user; if (!strlen($this->confirm_id) || !sizeof($this->question_ids)) { @@ -743,7 +743,7 @@ class qa */ function acp_question_list(&$module) { - global $db, $template, $table_prefix; + global $db, $template; $sql = 'SELECT * FROM ' . $this->table_captcha_questions; @@ -773,7 +773,7 @@ class qa */ function acp_get_question_data($question_id) { - global $db, $table_prefix; + global $db; if ($question_id) { @@ -828,7 +828,7 @@ class qa */ function acp_update_question($data, $question_id) { - global $db, $cache, $table_prefix; + global $db, $cache; // easier to delete all answers than to figure out which to update $sql = 'DELETE FROM ' . $this->table_captcha_answers . " WHERE question_id = $question_id"; @@ -855,7 +855,7 @@ class qa */ function acp_add_question($data) { - global $db, $cache, $table_prefix; + global $db, $cache; $langs = $this->get_languages(); $question_ary = $data; @@ -900,7 +900,7 @@ class qa */ function acp_delete_question($question_id) { - global $db, $cache, $table_prefix; + global $db, $cache; $tables = array($this->table_captcha_questions, $this->table_captcha_answers); @@ -972,7 +972,7 @@ class qa */ function acp_is_last($question_id) { - global $config, $db, $table_prefix; + global $config, $db; if ($question_id) { -- cgit v1.2.1 From fa2ac1f27126292a24aa33136b2d3a7f1832ea47 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 10 Aug 2014 15:10:14 +0200 Subject: [ticket/11854] Use a set_name method instead of overriding get_service_name PHPBB3-11854 --- phpBB/phpbb/captcha/plugins/qa.php | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'phpBB/phpbb/captcha/plugins/qa.php') diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php index 96cd99826d..a7ba994cc3 100644 --- a/phpBB/phpbb/captcha/plugins/qa.php +++ b/phpBB/phpbb/captcha/plugins/qa.php @@ -34,6 +34,11 @@ class qa protected $table_captcha_answers; protected $table_qa_confirm; + /** + * @var string name of the service. + */ + protected $service_name; + /** * Constructor * @@ -157,11 +162,21 @@ class qa } /** - * API function + * @return string the name of the service corresponding to the plugin */ function get_service_name() { - return 'core.captcha.plugins.qa'; + return $this->service_name; + } + + /** + * Set the name of the plugin + * + * @param string $name + */ + public function set_name($name) + { + $this->service_name = $name; } /** -- cgit v1.2.1 From 9a03b3aab6033b52492296730c30849f96f430bf Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 24 Jan 2015 12:49:58 +0100 Subject: [ticket/13522] Remove empty answers from possible answers in Q&A PHPBB3-13522 --- phpBB/phpbb/captcha/plugins/qa.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'phpBB/phpbb/captcha/plugins/qa.php') diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php index a7ba994cc3..13ff3d7f91 100644 --- a/phpBB/phpbb/captcha/plugins/qa.php +++ b/phpBB/phpbb/captcha/plugins/qa.php @@ -827,13 +827,22 @@ class qa function acp_get_question_input() { $answers = utf8_normalize_nfc(request_var('answers', '', true)); + + // Convert answers into array and filter if answers are set + if (strlen($answers)) + { + $answers = array_filter(explode("\n", $answers), function ($value) { + return trim($value) !== ''; + }); + } + + $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) : '', + 'answers' => $answers, ); - return $question; } -- cgit v1.2.1 From 874f3584e2713cd332215b159b740e53330a900c Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 24 Jan 2015 13:40:42 +0100 Subject: [ticket/13522] Remove unused variables and unexpected returns PHPBB3-13522 --- phpBB/phpbb/captcha/plugins/qa.php | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'phpBB/phpbb/captcha/plugins/qa.php') diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php index 13ff3d7f91..12da64c750 100644 --- a/phpBB/phpbb/captcha/plugins/qa.php +++ b/phpBB/phpbb/captcha/plugins/qa.php @@ -125,7 +125,7 @@ class qa */ public function is_available() { - global $config, $db, $phpbb_root_path, $phpEx, $user; + global $config, $db, $user; // load language file for pretty display in the ACP dropdown $user->add_lang('captcha_qa'); @@ -263,7 +263,7 @@ class qa */ function garbage_collect($type = 0) { - global $db, $config; + global $db; $sql = 'SELECT c.confirm_id FROM ' . $this->table_qa_confirm . ' c @@ -310,8 +310,6 @@ class qa $db_tool = new \phpbb\db\tools($db); - $tables = array($this->table_captcha_questions, $this->table_captcha_answers, $this->table_qa_confirm); - $schemas = array( $this->table_captcha_questions => array ( 'COLUMNS' => array( @@ -366,7 +364,7 @@ class qa */ function validate() { - global $config, $db, $user; + global $user; $error = ''; @@ -414,7 +412,7 @@ class qa if (!sizeof($this->question_ids)) { - return false; + return; } $this->confirm_id = md5(unique_id($user->ip)); $this->question = (int) array_rand($this->question_ids); @@ -440,7 +438,7 @@ class qa if (!sizeof($this->question_ids)) { - return false; + return; } $this->question = (int) array_rand($this->question_ids); @@ -611,8 +609,8 @@ class qa */ function acp_page($id, &$module) { - global $db, $user, $auth, $template; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $user, $template; + global $config; $user->add_lang('acp/board'); $user->add_lang('captcha_qa'); @@ -674,7 +672,6 @@ class qa 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); @@ -819,6 +816,8 @@ class qa return $question; } + + return false; } /** -- cgit v1.2.1 From 12fe882741db91a155620d5870c6127798125720 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 24 Jan 2015 13:53:22 +0100 Subject: [ticket/13522] Trim array elements before processing further PHPBB3-13522 --- phpBB/phpbb/captcha/plugins/qa.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'phpBB/phpbb/captcha/plugins/qa.php') diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php index 12da64c750..824e6db3b0 100644 --- a/phpBB/phpbb/captcha/plugins/qa.php +++ b/phpBB/phpbb/captcha/plugins/qa.php @@ -830,12 +830,11 @@ class qa // Convert answers into array and filter if answers are set if (strlen($answers)) { - $answers = array_filter(explode("\n", $answers), function ($value) { - return trim($value) !== ''; + $answers = array_filter(array_map('trim', explode("\n", $answers)), function ($value) { + return $value !== ''; }); } - $question = array( 'question_text' => request_var('question_text', '', true), 'strict' => request_var('strict', false), -- cgit v1.2.1 From d15e5372caf1d0811e1f2bc87d5deddba171cb09 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 25 Jan 2015 22:52:40 +0100 Subject: [ticket/13522] Use acp_get_question_input() for retrieving input data PHPBB3-13522 --- phpBB/phpbb/captcha/plugins/qa.php | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'phpBB/phpbb/captcha/plugins/qa.php') diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php index 824e6db3b0..3a2652d02c 100644 --- a/phpBB/phpbb/captcha/plugins/qa.php +++ b/phpBB/phpbb/captcha/plugins/qa.php @@ -672,10 +672,7 @@ class qa else { // okay, show the editor - $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); + $question_input = $this->acp_get_question_input(); $langs = $this->get_languages(); foreach ($langs as $lang => $entry) @@ -694,12 +691,12 @@ class qa { if ($question = $this->acp_get_question_data($question_id)) { - $answers = (isset($input_answers[$lang])) ? $input_answers[$lang] : implode("\n", $question['answers']); + $answers = (isset($question_input['answers'][$lang])) ? $question_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'], + 'QUESTION_TEXT' => ($question_input['question_text']) ? $question_input['question_text'] : $question['question_text'], + 'LANG_ISO' => ($question_input['lang_iso']) ? $question_input['lang_iso'] : $question['lang_iso'], + 'STRICT' => (isset($_REQUEST['strict'])) ? $question_input['strict'] : $question['strict'], 'ANSWERS' => $answers, )); } @@ -711,10 +708,10 @@ class qa else { $template->assign_vars(array( - 'QUESTION_TEXT' => $input_question, - 'LANG_ISO' => $input_lang, - 'STRICT' => $input_strict, - 'ANSWERS' => $input_answers, + 'QUESTION_TEXT' => $question_input['question_text'], + 'LANG_ISO' => $question_input['lang_iso'], + 'STRICT' => $question_input['strict'], + 'ANSWERS' => $question_input['answers'], )); } -- cgit v1.2.1 From 8e737e483e2fbd20712bbcd1b3bb96d623ac0f24 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 31 Jan 2015 12:39:58 +0100 Subject: [ticket/13522] Remove unneeded variables and correctly output input on error PHPBB3-13522 --- phpBB/phpbb/captcha/plugins/qa.php | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'phpBB/phpbb/captcha/plugins/qa.php') diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php index 3a2652d02c..04052b3406 100644 --- a/phpBB/phpbb/captcha/plugins/qa.php +++ b/phpBB/phpbb/captcha/plugins/qa.php @@ -691,13 +691,11 @@ class qa { if ($question = $this->acp_get_question_data($question_id)) { - $answers = (isset($question_input['answers'][$lang])) ? $question_input['answers'][$lang] : implode("\n", $question['answers']); - $template->assign_vars(array( 'QUESTION_TEXT' => ($question_input['question_text']) ? $question_input['question_text'] : $question['question_text'], 'LANG_ISO' => ($question_input['lang_iso']) ? $question_input['lang_iso'] : $question['lang_iso'], 'STRICT' => (isset($_REQUEST['strict'])) ? $question_input['strict'] : $question['strict'], - 'ANSWERS' => $answers, + 'ANSWERS' => implode("\n", $question['answers']), )); } else @@ -711,15 +709,13 @@ class qa 'QUESTION_TEXT' => $question_input['question_text'], 'LANG_ISO' => $question_input['lang_iso'], 'STRICT' => $question_input['strict'], - 'ANSWERS' => $question_input['answers'], + 'ANSWERS' => (is_array($question_input['answers'])) ? implode("\n", $question_input['answers']) : '', )); } if ($submit && check_form_key($form_key)) { - $data = $this->acp_get_question_input(); - - if (!$this->validate_input($data)) + if (!$this->validate_input($question_input)) { $template->assign_vars(array( 'S_ERROR' => true, @@ -729,11 +725,11 @@ class qa { if ($question_id) { - $this->acp_update_question($data, $question_id); + $this->acp_update_question($question_input, $question_id); } else { - $this->acp_add_question($data); + $this->acp_add_question($question_input); } add_log('admin', 'LOG_CONFIG_VISUAL'); -- cgit v1.2.1 From 9203bf3141851812bbef9cff3a2634d9849d8f44 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 7 Jun 2015 22:53:41 +0200 Subject: [ticket/13930] Add missing spaces to code PHPBB3-13930 --- phpBB/phpbb/captcha/plugins/qa.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'phpBB/phpbb/captcha/plugins/qa.php') diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php index 04052b3406..2771369e57 100644 --- a/phpBB/phpbb/captcha/plugins/qa.php +++ b/phpBB/phpbb/captcha/plugins/qa.php @@ -350,7 +350,7 @@ class qa ), ); - foreach($schemas as $table => $schema) + foreach ($schemas as $table => $schema) { if (!$db_tool->sql_table_exists($table)) { -- cgit v1.2.1 From 4c5c289f75c267e1f3e789c0304054ed4e3e2564 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 11 Mar 2016 10:51:07 +0100 Subject: [ticket/14241] Prevent empty q&a as a result of improper settings Improper setup of the q&a captcha in combination with the admin choosing a default language that does not have any questions and answers set might result in the user being presented empty questions and answers. This change will try to fall back to any question in case the admin incorrectly set the default language and has no questions & answers set. If that does not work, the captcha will not allow passing it and suggest to contact the board admin to resolve this issue. PHPBB3-14241 --- phpBB/phpbb/captcha/plugins/qa.php | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'phpBB/phpbb/captcha/plugins/qa.php') diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php index 2771369e57..e6059b968f 100644 --- a/phpBB/phpbb/captcha/plugins/qa.php +++ b/phpBB/phpbb/captcha/plugins/qa.php @@ -100,6 +100,28 @@ class qa $db->sql_freeresult($result); } + // final fallback to any language + if (!sizeof($this->question_ids)) + { + $this->question_lang = ''; + + $sql = 'SELECT q.question_id, q.lang_iso + FROM ' . $this->table_captcha_questions . ' q, ' . $this->table_captcha_answers . ' a + WHERE q.question_id = a.question_id + GROUP BY lang_iso'; + $result = $db->sql_query($sql, 7200); + + while ($row = $db->sql_fetchrow($result)) + { + if (empty($this->question_lang)) + { + $this->question_lang = $row['lang_iso']; + } + $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())) { @@ -200,7 +222,7 @@ class qa { global $template; - if ($this->is_solved()) + if ($this->is_solved() || !count($this->question_ids)) { return false; } @@ -370,7 +392,7 @@ class qa if (!sizeof($this->question_ids)) { - return false; + return $user->lang['CONFIRM_QUESTION_MISSING']; } if (!$this->confirm_id) -- cgit v1.2.1 From 215fad420f20ba48cda00c7ceedfa31e035ee76f Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 12 Mar 2016 10:24:07 +0100 Subject: [ticket/14241] Log fatal captcha error to error log PHPBB3-14241 --- phpBB/phpbb/captcha/plugins/qa.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'phpBB/phpbb/captcha/plugins/qa.php') diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php index e6059b968f..8f2da838c5 100644 --- a/phpBB/phpbb/captcha/plugins/qa.php +++ b/phpBB/phpbb/captcha/plugins/qa.php @@ -220,10 +220,12 @@ class qa */ function get_template() { - global $template; + global $phpbb_log, $template, $user; - if ($this->is_solved() || !count($this->question_ids)) + if ($this->is_solved() || empty($this->question_text) || !count($this->question_ids)) { + /** @var \phpbb\log\log_interface $phpbb_log */ + $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_ERROR_CAPTCHA', time(), array($user->lang('CONFIRM_QUESTION_MISSING'))); return false; } else @@ -386,13 +388,15 @@ class qa */ function validate() { - global $user; + global $phpbb_log, $user; $error = ''; if (!sizeof($this->question_ids)) { - return $user->lang['CONFIRM_QUESTION_MISSING']; + /** @var \phpbb\log\log_interface $phpbb_log */ + $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_ERROR_CAPTCHA', time(), array($user->lang('CONFIRM_QUESTION_MISSING'))); + return $user->lang('CONFIRM_QUESTION_MISSING'); } if (!$this->confirm_id) -- cgit v1.2.1 From 3572f4c92ef554860262dbd953953cafb3af2ebc Mon Sep 17 00:00:00 2001 From: Richard McGirr Date: Sun, 8 May 2016 08:50:06 -0400 Subject: [ticket/14610] Don't log an error if the Q&A captcha has been solved https://tracker.phpbb.com/browse/PHPBB3-14610 PHPBB3-14610 --- phpBB/phpbb/captcha/plugins/qa.php | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'phpBB/phpbb/captcha/plugins/qa.php') diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php index 8f2da838c5..5b63cf53b8 100644 --- a/phpBB/phpbb/captcha/plugins/qa.php +++ b/phpBB/phpbb/captcha/plugins/qa.php @@ -224,6 +224,11 @@ class qa if ($this->is_solved() || empty($this->question_text) || !count($this->question_ids)) { + // don't log an error if the captcha has been solved + if ($this->is_solved()) + { + return; + } /** @var \phpbb\log\log_interface $phpbb_log */ $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_ERROR_CAPTCHA', time(), array($user->lang('CONFIRM_QUESTION_MISSING'))); return false; -- cgit v1.2.1 From f57f09f814f7faadf232625e2185a12fe0e503c6 Mon Sep 17 00:00:00 2001 From: Richard McGirr Date: Sun, 8 May 2016 09:24:11 -0400 Subject: [ticket/14610] Remove whitespace PHPBB3-14610 --- phpBB/phpbb/captcha/plugins/qa.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'phpBB/phpbb/captcha/plugins/qa.php') diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php index 5b63cf53b8..7dc3ef796f 100644 --- a/phpBB/phpbb/captcha/plugins/qa.php +++ b/phpBB/phpbb/captcha/plugins/qa.php @@ -228,7 +228,7 @@ class qa if ($this->is_solved()) { return; - } + } /** @var \phpbb\log\log_interface $phpbb_log */ $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_ERROR_CAPTCHA', time(), array($user->lang('CONFIRM_QUESTION_MISSING'))); return false; -- cgit v1.2.1 From 03348087d8bf8794da257f6e7ac4e318dd562fc0 Mon Sep 17 00:00:00 2001 From: Richard McGirr Date: Mon, 9 May 2016 17:00:16 -0400 Subject: [ticket/14610] Implement lavigor method PHPBB3-14610 --- phpBB/phpbb/captcha/plugins/qa.php | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'phpBB/phpbb/captcha/plugins/qa.php') diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php index 7dc3ef796f..a9d133d8f2 100644 --- a/phpBB/phpbb/captcha/plugins/qa.php +++ b/phpBB/phpbb/captcha/plugins/qa.php @@ -222,13 +222,12 @@ class qa { global $phpbb_log, $template, $user; - if ($this->is_solved() || empty($this->question_text) || !count($this->question_ids)) + if ($this->is_solved()) + { + return false; + } + else if (empty($this->question_text) || !count($this->question_ids)) { - // don't log an error if the captcha has been solved - if ($this->is_solved()) - { - return; - } /** @var \phpbb\log\log_interface $phpbb_log */ $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_ERROR_CAPTCHA', time(), array($user->lang('CONFIRM_QUESTION_MISSING'))); return false; @@ -236,10 +235,10 @@ class qa 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, + 'QA_CONFIRM_QUESTION' => $this->question_text, + 'QA_CONFIRM_ID' => $this->confirm_id, + 'S_CONFIRM_CODE' => true, + 'S_TYPE' => $this->type, )); return 'captcha_qa.html'; -- cgit v1.2.1