Verzeichnisstruktur phpBB-3.1.0
- Veröffentlicht
- 27.10.2014
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
qa.php
0001 <?php
0002 /**
0003 *
0004 * This file is part of the phpBB Forum Software package.
0005 *
0006 * @copyright (c) phpBB Limited <https://www.phpbb.com>
0007 * @license GNU General Public License, version 2 (GPL-2.0)
0008 *
0009 * For full copyright and license information, please see
0010 * the docs/CREDITS.txt file.
0011 *
0012 */
0013
0014 namespace phpbb\captcha\plugins;
0015
0016 /**
0017 * And now to something completely different. Let's make a captcha without extending the abstract class.
0018 * QA CAPTCHA sample implementation
0019 */
0020 class qa
0021 {
0022 var $confirm_id;
0023 var $answer;
0024 var $question_ids;
0025 var $question_text;
0026 var $question_lang;
0027 var $question_strict;
0028 var $attempts = 0;
0029 var $type;
0030 // dirty trick: 0 is false, but can still encode that the captcha is not yet validated
0031 var $solved = 0;
0032
0033 protected $table_captcha_questions;
0034 protected $table_captcha_answers;
0035 protected $table_qa_confirm;
0036
0037 /**
0038 * @var string name of the service.
0039 */
0040 protected $service_name;
0041
0042 /**
0043 * Constructor
0044 *
0045 * @param string $table_captcha_questions
0046 * @param string $table_captcha_answers
0047 * @param string $table_qa_confirm
0048 */
0049 function __construct($table_captcha_questions, $table_captcha_answers, $table_qa_confirm)
0050 {
0051 $this->table_captcha_questions = $table_captcha_questions;
0052 $this->table_captcha_answers = $table_captcha_answers;
0053 $this->table_qa_confirm = $table_qa_confirm;
0054 }
0055
0056 /**
0057 * @param int $type as per the CAPTCHA API docs, the type
0058 */
0059 function init($type)
0060 {
0061 global $config, $db, $user;
0062
0063 // load our language file
0064 $user->add_lang('captcha_qa');
0065
0066 // read input
0067 $this->confirm_id = request_var('qa_confirm_id', '');
0068 $this->answer = utf8_normalize_nfc(request_var('qa_answer', '', true));
0069
0070 $this->type = (int) $type;
0071 $this->question_lang = $user->lang_name;
0072
0073 // we need all defined questions - shouldn't be too many, so we can just grab them
0074 // try the user's lang first
0075 $sql = 'SELECT question_id
0076 FROM ' . $this->table_captcha_questions . "
0077 WHERE lang_iso = '" . $db->sql_escape($user->lang_name) . "'";
0078 $result = $db->sql_query($sql, 3600);
0079
0080 while ($row = $db->sql_fetchrow($result))
0081 {
0082 $this->question_ids[$row['question_id']] = $row['question_id'];
0083 }
0084 $db->sql_freeresult($result);
0085
0086 // fallback to the board default lang
0087 if (!sizeof($this->question_ids))
0088 {
0089 $this->question_lang = $config['default_lang'];
0090
0091 $sql = 'SELECT question_id
0092 FROM ' . $this->table_captcha_questions . "
0093 WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'";
0094 $result = $db->sql_query($sql, 7200);
0095
0096 while ($row = $db->sql_fetchrow($result))
0097 {
0098 $this->question_ids[$row['question_id']] = $row['question_id'];
0099 }
0100 $db->sql_freeresult($result);
0101 }
0102
0103 // okay, if there is a confirm_id, we try to load that confirm's state. If not, we try to find one
0104 if (!$this->load_answer() && (!$this->load_confirm_id() || !$this->load_answer()))
0105 {
0106 // we have no valid confirm ID, better get ready to ask something
0107 $this->select_question();
0108 }
0109 }
0110
0111 /**
0112 * See if the captcha has created its tables.
0113 */
0114 public function is_installed()
0115 {
0116 global $db;
0117
0118 $db_tool = new \phpbb\db\tools($db);
0119
0120 return $db_tool->sql_table_exists($this->table_captcha_questions);
0121 }
0122
0123 /**
0124 * 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
0125 */
0126 public function is_available()
0127 {
0128 global $config, $db, $phpbb_root_path, $phpEx, $user;
0129
0130 // load language file for pretty display in the ACP dropdown
0131 $user->add_lang('captcha_qa');
0132
0133 if (!$this->is_installed())
0134 {
0135 return false;
0136 }
0137
0138 $sql = 'SELECT COUNT(question_id) AS question_count
0139 FROM ' . $this->table_captcha_questions . "
0140 WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'";
0141 $result = $db->sql_query($sql);
0142 $row = $db->sql_fetchrow($result);
0143 $db->sql_freeresult($result);
0144
0145 return ((bool) $row['question_count']);
0146 }
0147
0148 /**
0149 * API function
0150 */
0151 function has_config()
0152 {
0153 return true;
0154 }
0155
0156 /**
0157 * API function
0158 */
0159 static public function get_name()
0160 {
0161 return 'CAPTCHA_QA';
0162 }
0163
0164 /**
0165 * @return string the name of the service corresponding to the plugin
0166 */
0167 function get_service_name()
0168 {
0169 return $this->service_name;
0170 }
0171
0172 /**
0173 * Set the name of the plugin
0174 *
0175 * @param string $name
0176 */
0177 public function set_name($name)
0178 {
0179 $this->service_name = $name;
0180 }
0181
0182 /**
0183 * API function - not needed as we don't display an image
0184 */
0185 function execute_demo()
0186 {
0187 }
0188
0189 /**
0190 * API function - not needed as we don't display an image
0191 */
0192 function execute()
0193 {
0194 }
0195
0196 /**
0197 * API function - send the question to the template
0198 */
0199 function get_template()
0200 {
0201 global $template;
0202
0203 if ($this->is_solved())
0204 {
0205 return false;
0206 }
0207 else
0208 {
0209 $template->assign_vars(array(
0210 'QA_CONFIRM_QUESTION' => $this->question_text,
0211 'QA_CONFIRM_ID' => $this->confirm_id,
0212 'S_CONFIRM_CODE' => true,
0213 'S_TYPE' => $this->type,
0214 ));
0215
0216 return 'captcha_qa.html';
0217 }
0218 }
0219
0220 /**
0221 * API function - we just display a mockup so that the captcha doesn't need to be installed
0222 */
0223 function get_demo_template()
0224 {
0225 global $config, $db, $template;
0226
0227 if ($this->is_available())
0228 {
0229 $sql = 'SELECT question_text
0230 FROM ' . $this->table_captcha_questions . "
0231 WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'";
0232 $result = $db->sql_query_limit($sql, 1);
0233 if ($row = $db->sql_fetchrow($result))
0234 {
0235 $template->assign_vars(array(
0236 'QA_CONFIRM_QUESTION' => $row['question_text'],
0237 ));
0238 }
0239 $db->sql_freeresult($result);
0240 }
0241 return 'captcha_qa_acp_demo.html';
0242 }
0243
0244 /**
0245 * API function
0246 */
0247 function get_hidden_fields()
0248 {
0249 $hidden_fields = array();
0250
0251 // this is required - otherwise we would forget about the captcha being already solved
0252 if ($this->solved)
0253 {
0254 $hidden_fields['qa_answer'] = $this->answer;
0255 }
0256 $hidden_fields['qa_confirm_id'] = $this->confirm_id;
0257
0258 return $hidden_fields;
0259 }
0260
0261 /**
0262 * API function
0263 */
0264 function garbage_collect($type = 0)
0265 {
0266 global $db, $config;
0267
0268 $sql = 'SELECT c.confirm_id
0269 FROM ' . $this->table_qa_confirm . ' c
0270 LEFT JOIN ' . SESSIONS_TABLE . ' s
0271 ON (c.session_id = s.session_id)
0272 WHERE s.session_id IS NULL' .
0273 ((empty($type)) ? '' : ' AND c.confirm_type = ' . (int) $type);
0274 $result = $db->sql_query($sql);
0275
0276 if ($row = $db->sql_fetchrow($result))
0277 {
0278 $sql_in = array();
0279
0280 do
0281 {
0282 $sql_in[] = (string) $row['confirm_id'];
0283 }
0284 while ($row = $db->sql_fetchrow($result));
0285
0286 if (sizeof($sql_in))
0287 {
0288 $sql = 'DELETE FROM ' . $this->table_qa_confirm . '
0289 WHERE ' . $db->sql_in_set('confirm_id', $sql_in);
0290 $db->sql_query($sql);
0291 }
0292 }
0293 $db->sql_freeresult($result);
0294 }
0295
0296 /**
0297 * API function - we don't drop the tables here, as that would cause the loss of all entered questions.
0298 */
0299 function uninstall()
0300 {
0301 $this->garbage_collect(0);
0302 }
0303
0304 /**
0305 * API function - set up shop
0306 */
0307 function install()
0308 {
0309 global $db;
0310
0311 $db_tool = new \phpbb\db\tools($db);
0312
0313 $tables = array($this->table_captcha_questions, $this->table_captcha_answers, $this->table_qa_confirm);
0314
0315 $schemas = array(
0316 $this->table_captcha_questions => array (
0317 'COLUMNS' => array(
0318 'question_id' => array('UINT', null, 'auto_increment'),
0319 'strict' => array('BOOL', 0),
0320 'lang_id' => array('UINT', 0),
0321 'lang_iso' => array('VCHAR:30', ''),
0322 'question_text' => array('TEXT_UNI', ''),
0323 ),
0324 'PRIMARY_KEY' => 'question_id',
0325 'KEYS' => array(
0326 'lang' => array('INDEX', 'lang_iso'),
0327 ),
0328 ),
0329 $this->table_captcha_answers => array (
0330 'COLUMNS' => array(
0331 'question_id' => array('UINT', 0),
0332 'answer_text' => array('STEXT_UNI', ''),
0333 ),
0334 'KEYS' => array(
0335 'qid' => array('INDEX', 'question_id'),
0336 ),
0337 ),
0338 $this->table_qa_confirm => array (
0339 'COLUMNS' => array(
0340 'session_id' => array('CHAR:32', ''),
0341 'confirm_id' => array('CHAR:32', ''),
0342 'lang_iso' => array('VCHAR:30', ''),
0343 'question_id' => array('UINT', 0),
0344 'attempts' => array('UINT', 0),
0345 'confirm_type' => array('USINT', 0),
0346 ),
0347 'KEYS' => array(
0348 'session_id' => array('INDEX', 'session_id'),
0349 'lookup' => array('INDEX', array('confirm_id', 'session_id', 'lang_iso')),
0350 ),
0351 'PRIMARY_KEY' => 'confirm_id',
0352 ),
0353 );
0354
0355 foreach($schemas as $table => $schema)
0356 {
0357 if (!$db_tool->sql_table_exists($table))
0358 {
0359 $db_tool->sql_create_table($table, $schema);
0360 }
0361 }
0362 }
0363
0364 /**
0365 * API function - see what has to be done to validate
0366 */
0367 function validate()
0368 {
0369 global $config, $db, $user;
0370
0371 $error = '';
0372
0373 if (!sizeof($this->question_ids))
0374 {
0375 return false;
0376 }
0377
0378 if (!$this->confirm_id)
0379 {
0380 $error = $user->lang['CONFIRM_QUESTION_WRONG'];
0381 }
0382 else
0383 {
0384 if ($this->check_answer())
0385 {
0386 $this->solved = true;
0387 }
0388 else
0389 {
0390 $error = $user->lang['CONFIRM_QUESTION_WRONG'];
0391 }
0392 }
0393
0394 if (strlen($error))
0395 {
0396 // okay, incorrect answer. Let's ask a new question.
0397 $this->new_attempt();
0398 $this->solved = false;
0399
0400 return $error;
0401 }
0402 else
0403 {
0404 return false;
0405 }
0406 }
0407
0408 /**
0409 * Select a question
0410 */
0411 function select_question()
0412 {
0413 global $db, $user;
0414
0415 if (!sizeof($this->question_ids))
0416 {
0417 return false;
0418 }
0419 $this->confirm_id = md5(unique_id($user->ip));
0420 $this->question = (int) array_rand($this->question_ids);
0421
0422 $sql = 'INSERT INTO ' . $this->table_qa_confirm . ' ' . $db->sql_build_array('INSERT', array(
0423 'confirm_id' => (string) $this->confirm_id,
0424 'session_id' => (string) $user->session_id,
0425 'lang_iso' => (string) $this->question_lang,
0426 'confirm_type' => (int) $this->type,
0427 'question_id' => (int) $this->question,
0428 ));
0429 $db->sql_query($sql);
0430
0431 $this->load_answer();
0432 }
0433
0434 /**
0435 * New Question, if desired.
0436 */
0437 function reselect_question()
0438 {
0439 global $db, $user;
0440
0441 if (!sizeof($this->question_ids))
0442 {
0443 return false;
0444 }
0445
0446 $this->question = (int) array_rand($this->question_ids);
0447 $this->solved = 0;
0448
0449 $sql = 'UPDATE ' . $this->table_qa_confirm . '
0450 SET question_id = ' . (int) $this->question . "
0451 WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "'
0452 AND session_id = '" . $db->sql_escape($user->session_id) . "'";
0453 $db->sql_query($sql);
0454
0455 $this->load_answer();
0456 }
0457
0458 /**
0459 * Wrong answer, so we increase the attempts and use a different question.
0460 */
0461 function new_attempt()
0462 {
0463 global $db, $user;
0464
0465 // yah, I would prefer a stronger rand, but this should work
0466 $this->question = (int) array_rand($this->question_ids);
0467 $this->solved = 0;
0468
0469 $sql = 'UPDATE ' . $this->table_qa_confirm . '
0470 SET question_id = ' . (int) $this->question . ",
0471 attempts = attempts + 1
0472 WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "'
0473 AND session_id = '" . $db->sql_escape($user->session_id) . "'";
0474 $db->sql_query($sql);
0475
0476 $this->load_answer();
0477 }
0478
0479
0480 /**
0481 * See if there is already an entry for the current session.
0482 */
0483 function load_confirm_id()
0484 {
0485 global $db, $user;
0486
0487 $sql = 'SELECT confirm_id
0488 FROM ' . $this->table_qa_confirm . "
0489 WHERE
0490 session_id = '" . $db->sql_escape($user->session_id) . "'
0491 AND lang_iso = '" . $db->sql_escape($this->question_lang) . "'
0492 AND confirm_type = " . $this->type;
0493 $result = $db->sql_query_limit($sql, 1);
0494 $row = $db->sql_fetchrow($result);
0495 $db->sql_freeresult($result);
0496
0497 if ($row)
0498 {
0499 $this->confirm_id = $row['confirm_id'];
0500 return true;
0501 }
0502 return false;
0503 }
0504
0505 /**
0506 * Look up everything we need and populate the instance variables.
0507 */
0508 function load_answer()
0509 {
0510 global $db, $user;
0511
0512 if (!strlen($this->confirm_id) || !sizeof($this->question_ids))
0513 {
0514 return false;
0515 }
0516
0517 $sql = 'SELECT con.question_id, attempts, question_text, strict
0518 FROM ' . $this->table_qa_confirm . ' con, ' . $this->table_captcha_questions . " qes
0519 WHERE con.question_id = qes.question_id
0520 AND confirm_id = '" . $db->sql_escape($this->confirm_id) . "'
0521 AND session_id = '" . $db->sql_escape($user->session_id) . "'
0522 AND qes.lang_iso = '" . $db->sql_escape($this->question_lang) . "'
0523 AND confirm_type = " . $this->type;
0524 $result = $db->sql_query($sql);
0525 $row = $db->sql_fetchrow($result);
0526 $db->sql_freeresult($result);
0527
0528 if ($row)
0529 {
0530 $this->question = $row['question_id'];
0531
0532 $this->attempts = $row['attempts'];
0533 $this->question_strict = $row['strict'];
0534 $this->question_text = $row['question_text'];
0535
0536 return true;
0537 }
0538
0539 return false;
0540 }
0541
0542 /**
0543 * The actual validation
0544 */
0545 function check_answer()
0546 {
0547 global $db;
0548
0549 $answer = ($this->question_strict) ? utf8_normalize_nfc(request_var('qa_answer', '', true)) : utf8_clean_string(utf8_normalize_nfc(request_var('qa_answer', '', true)));
0550
0551 $sql = 'SELECT answer_text
0552 FROM ' . $this->table_captcha_answers . '
0553 WHERE question_id = ' . (int) $this->question;
0554 $result = $db->sql_query($sql);
0555
0556 while ($row = $db->sql_fetchrow($result))
0557 {
0558 $solution = ($this->question_strict) ? $row['answer_text'] : utf8_clean_string($row['answer_text']);
0559
0560 if ($solution === $answer)
0561 {
0562 $this->solved = true;
0563
0564 break;
0565 }
0566 }
0567 $db->sql_freeresult($result);
0568
0569 return $this->solved;
0570 }
0571
0572 /**
0573 * API function
0574 */
0575 function get_attempt_count()
0576 {
0577 return $this->attempts;
0578 }
0579
0580 /**
0581 * API function
0582 */
0583 function reset()
0584 {
0585 global $db, $user;
0586
0587 $sql = 'DELETE FROM ' . $this->table_qa_confirm . "
0588 WHERE session_id = '" . $db->sql_escape($user->session_id) . "'
0589 AND confirm_type = " . (int) $this->type;
0590 $db->sql_query($sql);
0591
0592 // we leave the class usable by generating a new question
0593 $this->select_question();
0594 }
0595
0596 /**
0597 * API function
0598 */
0599 function is_solved()
0600 {
0601 if (request_var('qa_answer', false) && $this->solved === 0)
0602 {
0603 $this->validate();
0604 }
0605
0606 return (bool) $this->solved;
0607 }
0608
0609 /**
0610 * API function - The ACP backend, this marks the end of the easy methods
0611 */
0612 function acp_page($id, &$module)
0613 {
0614 global $db, $user, $auth, $template;
0615 global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
0616
0617 $user->add_lang('acp/board');
0618 $user->add_lang('captcha_qa');
0619
0620 if (!self::is_installed())
0621 {
0622 $this->install();
0623 }
0624
0625 $module->tpl_name = 'captcha_qa_acp';
0626 $module->page_title = 'ACP_VC_SETTINGS';
0627 $form_key = 'acp_captcha';
0628 add_form_key($form_key);
0629
0630 $submit = request_var('submit', false);
0631 $question_id = request_var('question_id', 0);
0632 $action = request_var('action', '');
0633
0634 // we have two pages, so users might want to navigate from one to the other
0635 $list_url = $module->u_action . "&configure=1&select_captcha=" . $this->get_service_name();
0636
0637 $template->assign_vars(array(
0638 'U_ACTION' => $module->u_action,
0639 'QUESTION_ID' => $question_id ,
0640 'CLASS' => $this->get_service_name(),
0641 ));
0642
0643 // show the list?
0644 if (!$question_id && $action != 'add')
0645 {
0646 $this->acp_question_list($module);
0647 }
0648 else if ($question_id && $action == 'delete')
0649 {
0650 if ($this->get_service_name() !== $config['captcha_plugin'] || !$this->acp_is_last($question_id))
0651 {
0652 if (confirm_box(true))
0653 {
0654 $this->acp_delete_question($question_id);
0655
0656 trigger_error($user->lang['QUESTION_DELETED'] . adm_back_link($list_url));
0657 }
0658 else
0659 {
0660 confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
0661 'question_id' => $question_id,
0662 'action' => $action,
0663 'configure' => 1,
0664 'select_captcha' => $this->get_service_name(),
0665 ))
0666 );
0667 }
0668 }
0669 else
0670 {
0671 trigger_error($user->lang['QA_LAST_QUESTION'] . adm_back_link($list_url), E_USER_WARNING);
0672 }
0673 }
0674 else
0675 {
0676 // okay, show the editor
0677 $error = false;
0678 $input_question = request_var('question_text', '', true);
0679 $input_answers = request_var('answers', '', true);
0680 $input_lang = request_var('lang_iso', '', true);
0681 $input_strict = request_var('strict', false);
0682 $langs = $this->get_languages();
0683
0684 foreach ($langs as $lang => $entry)
0685 {
0686 $template->assign_block_vars('langs', array(
0687 'ISO' => $lang,
0688 'NAME' => $entry['name'],
0689 ));
0690 }
0691
0692 $template->assign_vars(array(
0693 'U_LIST' => $list_url,
0694 ));
0695
0696 if ($question_id)
0697 {
0698 if ($question = $this->acp_get_question_data($question_id))
0699 {
0700 $answers = (isset($input_answers[$lang])) ? $input_answers[$lang] : implode("\n", $question['answers']);
0701
0702 $template->assign_vars(array(
0703 'QUESTION_TEXT' => ($input_question) ? $input_question : $question['question_text'],
0704 'LANG_ISO' => ($input_lang) ? $input_lang : $question['lang_iso'],
0705 'STRICT' => (isset($_REQUEST['strict'])) ? $input_strict : $question['strict'],
0706 'ANSWERS' => $answers,
0707 ));
0708 }
0709 else
0710 {
0711 trigger_error($user->lang['FORM_INVALID'] . adm_back_link($list_url));
0712 }
0713 }
0714 else
0715 {
0716 $template->assign_vars(array(
0717 'QUESTION_TEXT' => $input_question,
0718 'LANG_ISO' => $input_lang,
0719 'STRICT' => $input_strict,
0720 'ANSWERS' => $input_answers,
0721 ));
0722 }
0723
0724 if ($submit && check_form_key($form_key))
0725 {
0726 $data = $this->acp_get_question_input();
0727
0728 if (!$this->validate_input($data))
0729 {
0730 $template->assign_vars(array(
0731 'S_ERROR' => true,
0732 ));
0733 }
0734 else
0735 {
0736 if ($question_id)
0737 {
0738 $this->acp_update_question($data, $question_id);
0739 }
0740 else
0741 {
0742 $this->acp_add_question($data);
0743 }
0744
0745 add_log('admin', 'LOG_CONFIG_VISUAL');
0746 trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($list_url));
0747 }
0748 }
0749 else if ($submit)
0750 {
0751 trigger_error($user->lang['FORM_INVALID'] . adm_back_link($list_url), E_USER_WARNING);
0752 }
0753 }
0754 }
0755
0756 /**
0757 * This handles the list overview
0758 */
0759 function acp_question_list(&$module)
0760 {
0761 global $db, $template;
0762
0763 $sql = 'SELECT *
0764 FROM ' . $this->table_captcha_questions;
0765 $result = $db->sql_query($sql);
0766
0767 $template->assign_vars(array(
0768 'S_LIST' => true,
0769 ));
0770
0771 while ($row = $db->sql_fetchrow($result))
0772 {
0773 $url = $module->u_action . "&question_id={$row['question_id']}&configure=1&select_captcha=" . $this->get_service_name() . '&';
0774
0775 $template->assign_block_vars('questions', array(
0776 'QUESTION_TEXT' => $row['question_text'],
0777 'QUESTION_ID' => $row['question_id'],
0778 'QUESTION_LANG' => $row['lang_iso'],
0779 'U_DELETE' => "{$url}action=delete",
0780 'U_EDIT' => "{$url}action=edit",
0781 ));
0782 }
0783 $db->sql_freeresult($result);
0784 }
0785
0786 /**
0787 * Grab a question and bring it into a format the editor understands
0788 */
0789 function acp_get_question_data($question_id)
0790 {
0791 global $db;
0792
0793 if ($question_id)
0794 {
0795 $sql = 'SELECT *
0796 FROM ' . $this->table_captcha_questions . '
0797 WHERE question_id = ' . $question_id;
0798 $result = $db->sql_query($sql);
0799 $question = $db->sql_fetchrow($result);
0800 $db->sql_freeresult($result);
0801
0802 if (!$question)
0803 {
0804 return false;
0805 }
0806
0807 $question['answers'] = array();
0808
0809 $sql = 'SELECT *
0810 FROM ' . $this->table_captcha_answers . '
0811 WHERE question_id = ' . $question_id;
0812 $result = $db->sql_query($sql);
0813
0814 while ($row = $db->sql_fetchrow($result))
0815 {
0816 $question['answers'][] = $row['answer_text'];
0817 }
0818 $db->sql_freeresult($result);
0819
0820 return $question;
0821 }
0822 }
0823
0824 /**
0825 * Grab a question from input and bring it into a format the editor understands
0826 */
0827 function acp_get_question_input()
0828 {
0829 $answers = utf8_normalize_nfc(request_var('answers', '', true));
0830 $question = array(
0831 'question_text' => request_var('question_text', '', true),
0832 'strict' => request_var('strict', false),
0833 'lang_iso' => request_var('lang_iso', ''),
0834 'answers' => (strlen($answers)) ? explode("\n", $answers) : '',
0835 );
0836
0837 return $question;
0838 }
0839
0840 /**
0841 * Update a question.
0842 * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data
0843 */
0844 function acp_update_question($data, $question_id)
0845 {
0846 global $db, $cache;
0847
0848 // easier to delete all answers than to figure out which to update
0849 $sql = 'DELETE FROM ' . $this->table_captcha_answers . " WHERE question_id = $question_id";
0850 $db->sql_query($sql);
0851
0852 $langs = $this->get_languages();
0853 $question_ary = $data;
0854 $question_ary['lang_id'] = $langs[$question_ary['lang_iso']]['id'];
0855 unset($question_ary['answers']);
0856
0857 $sql = 'UPDATE ' . $this->table_captcha_questions . '
0858 SET ' . $db->sql_build_array('UPDATE', $question_ary) . "
0859 WHERE question_id = $question_id";
0860 $db->sql_query($sql);
0861
0862 $this->acp_insert_answers($data, $question_id);
0863
0864 $cache->destroy('sql', $this->table_captcha_questions);
0865 }
0866
0867 /**
0868 * Insert a question.
0869 * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data
0870 */
0871 function acp_add_question($data)
0872 {
0873 global $db, $cache;
0874
0875 $langs = $this->get_languages();
0876 $question_ary = $data;
0877
0878 $question_ary['lang_id'] = $langs[$data['lang_iso']]['id'];
0879 unset($question_ary['answers']);
0880
0881 $sql = 'INSERT INTO ' . $this->table_captcha_questions . ' ' . $db->sql_build_array('INSERT', $question_ary);
0882 $db->sql_query($sql);
0883
0884 $question_id = $db->sql_nextid();
0885
0886 $this->acp_insert_answers($data, $question_id);
0887
0888 $cache->destroy('sql', $this->table_captcha_questions);
0889 }
0890
0891 /**
0892 * Insert the answers.
0893 * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data
0894 */
0895 function acp_insert_answers($data, $question_id)
0896 {
0897 global $db, $cache;
0898
0899 foreach ($data['answers'] as $answer)
0900 {
0901 $answer_ary = array(
0902 'question_id' => $question_id,
0903 'answer_text' => $answer,
0904 );
0905
0906 $sql = 'INSERT INTO ' . $this->table_captcha_answers . ' ' . $db->sql_build_array('INSERT', $answer_ary);
0907 $db->sql_query($sql);
0908 }
0909
0910 $cache->destroy('sql', $this->table_captcha_answers);
0911 }
0912
0913 /**
0914 * Delete a question.
0915 */
0916 function acp_delete_question($question_id)
0917 {
0918 global $db, $cache;
0919
0920 $tables = array($this->table_captcha_questions, $this->table_captcha_answers);
0921
0922 foreach ($tables as $table)
0923 {
0924 $sql = "DELETE FROM $table
0925 WHERE question_id = $question_id";
0926 $db->sql_query($sql);
0927 }
0928
0929 $cache->destroy('sql', $tables);
0930 }
0931
0932 /**
0933 * Check if the entered data can be inserted/used
0934 * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data
0935 */
0936 function validate_input($question_data)
0937 {
0938 $langs = $this->get_languages();
0939
0940 if (!isset($question_data['lang_iso']) ||
0941 !isset($question_data['question_text']) ||
0942 !isset($question_data['strict']) ||
0943 !isset($question_data['answers']))
0944 {
0945 return false;
0946 }
0947
0948 if (!isset($langs[$question_data['lang_iso']]) ||
0949 !strlen($question_data['question_text']) ||
0950 !sizeof($question_data['answers']) ||
0951 !is_array($question_data['answers']))
0952 {
0953 return false;
0954 }
0955
0956 return true;
0957 }
0958
0959 /**
0960 * List the installed language packs
0961 */
0962 function get_languages()
0963 {
0964 global $db;
0965
0966 $sql = 'SELECT *
0967 FROM ' . LANG_TABLE;
0968 $result = $db->sql_query($sql);
0969
0970 $langs = array();
0971 while ($row = $db->sql_fetchrow($result))
0972 {
0973 $langs[$row['lang_iso']] = array(
0974 'name' => $row['lang_local_name'],
0975 'id' => (int) $row['lang_id'],
0976 );
0977 }
0978 $db->sql_freeresult($result);
0979
0980 return $langs;
0981 }
0982
0983
0984
0985 /**
0986 * See if there is a question other than the one we have
0987 */
0988 function acp_is_last($question_id)
0989 {
0990 global $config, $db;
0991
0992 if ($question_id)
0993 {
0994 $sql = 'SELECT question_id
0995 FROM ' . $this->table_captcha_questions . "
0996 WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'
0997 AND question_id <> " . (int) $question_id;
0998 $result = $db->sql_query_limit($sql, 1);
0999 $question = $db->sql_fetchrow($result);
1000 $db->sql_freeresult($result);
1001
1002 if (!$question)
1003 {
1004 return true;
1005 }
1006 return false;
1007 }
1008 }
1009 }
1010