[ Index ] |
PHP Cross Reference of phpBB-3.2.11-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * 4 * This file is part of the phpBB Forum Software package. 5 * 6 * @copyright (c) phpBB Limited <https://www.phpbb.com> 7 * @license GNU General Public License, version 2 (GPL-2.0) 8 * 9 * For full copyright and license information, please see 10 * the docs/CREDITS.txt file. 11 * 12 */ 13 14 namespace phpbb\captcha\plugins; 15 16 /** 17 * And now to something completely different. Let's make a captcha without extending the abstract class. 18 * QA CAPTCHA sample implementation 19 */ 20 class qa 21 { 22 var $confirm_id; 23 var $answer; 24 var $question_ids = []; 25 var $question_text; 26 var $question_lang; 27 var $question_strict; 28 var $attempts = 0; 29 var $type; 30 // dirty trick: 0 is false, but can still encode that the captcha is not yet validated 31 var $solved = 0; 32 33 protected $table_captcha_questions; 34 protected $table_captcha_answers; 35 protected $table_qa_confirm; 36 37 /** 38 * @var string name of the service. 39 */ 40 protected $service_name; 41 42 /** 43 * Constructor 44 * 45 * @param string $table_captcha_questions 46 * @param string $table_captcha_answers 47 * @param string $table_qa_confirm 48 */ 49 function __construct($table_captcha_questions, $table_captcha_answers, $table_qa_confirm) 50 { 51 $this->table_captcha_questions = $table_captcha_questions; 52 $this->table_captcha_answers = $table_captcha_answers; 53 $this->table_qa_confirm = $table_qa_confirm; 54 } 55 56 /** 57 * @param int $type as per the CAPTCHA API docs, the type 58 */ 59 function init($type) 60 { 61 global $config, $db, $user, $request; 62 63 // load our language file 64 $user->add_lang('captcha_qa'); 65 66 // read input 67 $this->confirm_id = $request->variable('qa_confirm_id', ''); 68 $this->answer = $request->variable('qa_answer', '', true); 69 70 $this->type = (int) $type; 71 $this->question_lang = $user->lang_name; 72 73 // we need all defined questions - shouldn't be too many, so we can just grab them 74 // try the user's lang first 75 $sql = 'SELECT question_id 76 FROM ' . $this->table_captcha_questions . " 77 WHERE lang_iso = '" . $db->sql_escape($user->lang_name) . "'"; 78 $result = $db->sql_query($sql, 3600); 79 80 while ($row = $db->sql_fetchrow($result)) 81 { 82 $this->question_ids[$row['question_id']] = $row['question_id']; 83 } 84 $db->sql_freeresult($result); 85 86 // fallback to the board default lang 87 if (!count($this->question_ids)) 88 { 89 $this->question_lang = $config['default_lang']; 90 91 $sql = 'SELECT question_id 92 FROM ' . $this->table_captcha_questions . " 93 WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'"; 94 $result = $db->sql_query($sql, 7200); 95 96 while ($row = $db->sql_fetchrow($result)) 97 { 98 $this->question_ids[$row['question_id']] = $row['question_id']; 99 } 100 $db->sql_freeresult($result); 101 } 102 103 // final fallback to any language 104 if (!count($this->question_ids)) 105 { 106 $this->question_lang = ''; 107 108 $sql = 'SELECT q.question_id, q.lang_iso 109 FROM ' . $this->table_captcha_questions . ' q, ' . $this->table_captcha_answers . ' a 110 WHERE q.question_id = a.question_id'; 111 $result = $db->sql_query($sql, 7200); 112 113 while ($row = $db->sql_fetchrow($result)) 114 { 115 if (empty($this->question_lang)) 116 { 117 $this->question_lang = $row['lang_iso']; 118 } 119 $this->question_ids[$row['question_id']] = $row['question_id']; 120 } 121 $db->sql_freeresult($result); 122 } 123 124 // okay, if there is a confirm_id, we try to load that confirm's state. If not, we try to find one 125 if (!$this->load_answer() && (!$this->load_confirm_id() || !$this->load_answer())) 126 { 127 // we have no valid confirm ID, better get ready to ask something 128 $this->select_question(); 129 } 130 } 131 132 /** 133 * See if the captcha has created its tables. 134 */ 135 public function is_installed() 136 { 137 global $phpbb_container; 138 139 $db_tool = $phpbb_container->get('dbal.tools'); 140 141 return $db_tool->sql_table_exists($this->table_captcha_questions); 142 } 143 144 /** 145 * 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 146 */ 147 public function is_available() 148 { 149 global $config, $db, $user; 150 151 // load language file for pretty display in the ACP dropdown 152 $user->add_lang('captcha_qa'); 153 154 if (!$this->is_installed()) 155 { 156 return false; 157 } 158 159 $sql = 'SELECT COUNT(question_id) AS question_count 160 FROM ' . $this->table_captcha_questions . " 161 WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'"; 162 $result = $db->sql_query($sql); 163 $row = $db->sql_fetchrow($result); 164 $db->sql_freeresult($result); 165 166 return ((bool) $row['question_count']); 167 } 168 169 /** 170 * API function 171 */ 172 function has_config() 173 { 174 return true; 175 } 176 177 /** 178 * API function 179 */ 180 static public function get_name() 181 { 182 return 'CAPTCHA_QA'; 183 } 184 185 /** 186 * @return string the name of the service corresponding to the plugin 187 */ 188 function get_service_name() 189 { 190 return $this->service_name; 191 } 192 193 /** 194 * Set the name of the plugin 195 * 196 * @param string $name 197 */ 198 public function set_name($name) 199 { 200 $this->service_name = $name; 201 } 202 203 /** 204 * API function - not needed as we don't display an image 205 */ 206 function execute_demo() 207 { 208 } 209 210 /** 211 * API function - not needed as we don't display an image 212 */ 213 function execute() 214 { 215 } 216 217 /** 218 * API function - send the question to the template 219 */ 220 function get_template() 221 { 222 global $phpbb_log, $template, $user; 223 224 if ($this->is_solved()) 225 { 226 return false; 227 } 228 else if (empty($this->question_text) || !count($this->question_ids)) 229 { 230 /** @var \phpbb\log\log_interface $phpbb_log */ 231 $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_ERROR_CAPTCHA', time(), array($user->lang('CONFIRM_QUESTION_MISSING'))); 232 return false; 233 } 234 else 235 { 236 $template->assign_vars(array( 237 'QA_CONFIRM_QUESTION' => $this->question_text, 238 'QA_CONFIRM_ID' => $this->confirm_id, 239 'S_CONFIRM_CODE' => true, 240 'S_TYPE' => $this->type, 241 )); 242 243 return 'captcha_qa.html'; 244 } 245 } 246 247 /** 248 * API function - we just display a mockup so that the captcha doesn't need to be installed 249 */ 250 function get_demo_template() 251 { 252 global $config, $db, $template; 253 254 if ($this->is_available()) 255 { 256 $sql = 'SELECT question_text 257 FROM ' . $this->table_captcha_questions . " 258 WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'"; 259 $result = $db->sql_query_limit($sql, 1); 260 if ($row = $db->sql_fetchrow($result)) 261 { 262 $template->assign_vars(array( 263 'QA_CONFIRM_QUESTION' => $row['question_text'], 264 )); 265 } 266 $db->sql_freeresult($result); 267 } 268 return 'captcha_qa_acp_demo.html'; 269 } 270 271 /** 272 * API function 273 */ 274 function get_hidden_fields() 275 { 276 $hidden_fields = array(); 277 278 // this is required - otherwise we would forget about the captcha being already solved 279 if ($this->solved) 280 { 281 $hidden_fields['qa_answer'] = $this->answer; 282 } 283 $hidden_fields['qa_confirm_id'] = $this->confirm_id; 284 285 return $hidden_fields; 286 } 287 288 /** 289 * API function 290 */ 291 function garbage_collect($type = 0) 292 { 293 global $db; 294 295 $sql = 'SELECT c.confirm_id 296 FROM ' . $this->table_qa_confirm . ' c 297 LEFT JOIN ' . SESSIONS_TABLE . ' s 298 ON (c.session_id = s.session_id) 299 WHERE s.session_id IS NULL' . 300 ((empty($type)) ? '' : ' AND c.confirm_type = ' . (int) $type); 301 $result = $db->sql_query($sql); 302 303 if ($row = $db->sql_fetchrow($result)) 304 { 305 $sql_in = array(); 306 307 do 308 { 309 $sql_in[] = (string) $row['confirm_id']; 310 } 311 while ($row = $db->sql_fetchrow($result)); 312 313 if (count($sql_in)) 314 { 315 $sql = 'DELETE FROM ' . $this->table_qa_confirm . ' 316 WHERE ' . $db->sql_in_set('confirm_id', $sql_in); 317 $db->sql_query($sql); 318 } 319 } 320 $db->sql_freeresult($result); 321 } 322 323 /** 324 * API function - we don't drop the tables here, as that would cause the loss of all entered questions. 325 */ 326 function uninstall() 327 { 328 $this->garbage_collect(0); 329 } 330 331 /** 332 * API function - set up shop 333 */ 334 function install() 335 { 336 global $phpbb_container; 337 338 $db_tool = $phpbb_container->get('dbal.tools'); 339 $schemas = array( 340 $this->table_captcha_questions => array ( 341 'COLUMNS' => array( 342 'question_id' => array('UINT', null, 'auto_increment'), 343 'strict' => array('BOOL', 0), 344 'lang_id' => array('UINT', 0), 345 'lang_iso' => array('VCHAR:30', ''), 346 'question_text' => array('TEXT_UNI', ''), 347 ), 348 'PRIMARY_KEY' => 'question_id', 349 'KEYS' => array( 350 'lang' => array('INDEX', 'lang_iso'), 351 ), 352 ), 353 $this->table_captcha_answers => array ( 354 'COLUMNS' => array( 355 'question_id' => array('UINT', 0), 356 'answer_text' => array('STEXT_UNI', ''), 357 ), 358 'KEYS' => array( 359 'qid' => array('INDEX', 'question_id'), 360 ), 361 ), 362 $this->table_qa_confirm => array ( 363 'COLUMNS' => array( 364 'session_id' => array('CHAR:32', ''), 365 'confirm_id' => array('CHAR:32', ''), 366 'lang_iso' => array('VCHAR:30', ''), 367 'question_id' => array('UINT', 0), 368 'attempts' => array('UINT', 0), 369 'confirm_type' => array('USINT', 0), 370 ), 371 'KEYS' => array( 372 'session_id' => array('INDEX', 'session_id'), 373 'lookup' => array('INDEX', array('confirm_id', 'session_id', 'lang_iso')), 374 ), 375 'PRIMARY_KEY' => 'confirm_id', 376 ), 377 ); 378 379 foreach ($schemas as $table => $schema) 380 { 381 if (!$db_tool->sql_table_exists($table)) 382 { 383 $db_tool->sql_create_table($table, $schema); 384 } 385 } 386 } 387 388 /** 389 * API function - see what has to be done to validate 390 */ 391 function validate() 392 { 393 global $phpbb_log, $user; 394 395 $error = ''; 396 397 if (!count($this->question_ids)) 398 { 399 /** @var \phpbb\log\log_interface $phpbb_log */ 400 $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_ERROR_CAPTCHA', time(), array($user->lang('CONFIRM_QUESTION_MISSING'))); 401 return $user->lang('CONFIRM_QUESTION_MISSING'); 402 } 403 404 if (!$this->confirm_id) 405 { 406 $error = $user->lang['CONFIRM_QUESTION_WRONG']; 407 } 408 else 409 { 410 if ($this->check_answer()) 411 { 412 $this->solved = true; 413 } 414 else 415 { 416 $error = $user->lang['CONFIRM_QUESTION_WRONG']; 417 } 418 } 419 420 if (strlen($error)) 421 { 422 // okay, incorrect answer. Let's ask a new question. 423 $this->new_attempt(); 424 $this->solved = false; 425 426 return $error; 427 } 428 else 429 { 430 return false; 431 } 432 } 433 434 /** 435 * Select a question 436 */ 437 function select_question() 438 { 439 global $db, $user; 440 441 if (!count($this->question_ids)) 442 { 443 return; 444 } 445 $this->confirm_id = md5(unique_id($user->ip)); 446 $this->question = (int) array_rand($this->question_ids); 447 448 $sql = 'INSERT INTO ' . $this->table_qa_confirm . ' ' . $db->sql_build_array('INSERT', array( 449 'confirm_id' => (string) $this->confirm_id, 450 'session_id' => (string) $user->session_id, 451 'lang_iso' => (string) $this->question_lang, 452 'confirm_type' => (int) $this->type, 453 'question_id' => (int) $this->question, 454 )); 455 $db->sql_query($sql); 456 457 $this->load_answer(); 458 } 459 460 /** 461 * New Question, if desired. 462 */ 463 function reselect_question() 464 { 465 global $db, $user; 466 467 if (!count($this->question_ids)) 468 { 469 return; 470 } 471 472 $this->question = (int) array_rand($this->question_ids); 473 $this->solved = 0; 474 475 $sql = 'UPDATE ' . $this->table_qa_confirm . ' 476 SET question_id = ' . (int) $this->question . " 477 WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "' 478 AND session_id = '" . $db->sql_escape($user->session_id) . "'"; 479 $db->sql_query($sql); 480 481 $this->load_answer(); 482 } 483 484 /** 485 * Wrong answer, so we increase the attempts and use a different question. 486 */ 487 function new_attempt() 488 { 489 global $db, $user; 490 491 // yah, I would prefer a stronger rand, but this should work 492 $this->question = (int) array_rand($this->question_ids); 493 $this->solved = 0; 494 495 $sql = 'UPDATE ' . $this->table_qa_confirm . ' 496 SET question_id = ' . (int) $this->question . ", 497 attempts = attempts + 1 498 WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "' 499 AND session_id = '" . $db->sql_escape($user->session_id) . "'"; 500 $db->sql_query($sql); 501 502 $this->load_answer(); 503 } 504 505 506 /** 507 * See if there is already an entry for the current session. 508 */ 509 function load_confirm_id() 510 { 511 global $db, $user; 512 513 $sql = 'SELECT confirm_id 514 FROM ' . $this->table_qa_confirm . " 515 WHERE 516 session_id = '" . $db->sql_escape($user->session_id) . "' 517 AND lang_iso = '" . $db->sql_escape($this->question_lang) . "' 518 AND confirm_type = " . $this->type; 519 $result = $db->sql_query_limit($sql, 1); 520 $row = $db->sql_fetchrow($result); 521 $db->sql_freeresult($result); 522 523 if ($row) 524 { 525 $this->confirm_id = $row['confirm_id']; 526 return true; 527 } 528 return false; 529 } 530 531 /** 532 * Look up everything we need and populate the instance variables. 533 */ 534 function load_answer() 535 { 536 global $db, $user; 537 538 if (!strlen($this->confirm_id) || !count($this->question_ids)) 539 { 540 return false; 541 } 542 543 $sql = 'SELECT con.question_id, attempts, question_text, strict 544 FROM ' . $this->table_qa_confirm . ' con, ' . $this->table_captcha_questions . " qes 545 WHERE con.question_id = qes.question_id 546 AND confirm_id = '" . $db->sql_escape($this->confirm_id) . "' 547 AND session_id = '" . $db->sql_escape($user->session_id) . "' 548 AND qes.lang_iso = '" . $db->sql_escape($this->question_lang) . "' 549 AND confirm_type = " . $this->type; 550 $result = $db->sql_query($sql); 551 $row = $db->sql_fetchrow($result); 552 $db->sql_freeresult($result); 553 554 if ($row) 555 { 556 $this->question = $row['question_id']; 557 558 $this->attempts = $row['attempts']; 559 $this->question_strict = $row['strict']; 560 $this->question_text = $row['question_text']; 561 562 return true; 563 } 564 565 return false; 566 } 567 568 /** 569 * The actual validation 570 */ 571 function check_answer() 572 { 573 global $db, $request; 574 575 $answer = ($this->question_strict) ? $request->variable('qa_answer', '', true) : utf8_clean_string($request->variable('qa_answer', '', true)); 576 577 $sql = 'SELECT answer_text 578 FROM ' . $this->table_captcha_answers . ' 579 WHERE question_id = ' . (int) $this->question; 580 $result = $db->sql_query($sql); 581 582 while ($row = $db->sql_fetchrow($result)) 583 { 584 $solution = ($this->question_strict) ? $row['answer_text'] : utf8_clean_string($row['answer_text']); 585 586 if ($solution === $answer) 587 { 588 $this->solved = true; 589 590 break; 591 } 592 } 593 $db->sql_freeresult($result); 594 595 return $this->solved; 596 } 597 598 /** 599 * API function 600 */ 601 function get_attempt_count() 602 { 603 return $this->attempts; 604 } 605 606 /** 607 * API function 608 */ 609 function reset() 610 { 611 global $db, $user; 612 613 $sql = 'DELETE FROM ' . $this->table_qa_confirm . " 614 WHERE session_id = '" . $db->sql_escape($user->session_id) . "' 615 AND confirm_type = " . (int) $this->type; 616 $db->sql_query($sql); 617 618 // we leave the class usable by generating a new question 619 $this->select_question(); 620 } 621 622 /** 623 * API function 624 */ 625 function is_solved() 626 { 627 global $request; 628 629 if ($request->variable('qa_answer', false) && $this->solved === 0) 630 { 631 $this->validate(); 632 } 633 634 return (bool) $this->solved; 635 } 636 637 /** 638 * API function - The ACP backend, this marks the end of the easy methods 639 */ 640 function acp_page($id, $module) 641 { 642 global $config, $request, $phpbb_log, $template, $user; 643 644 $user->add_lang('acp/board'); 645 $user->add_lang('captcha_qa'); 646 647 if (!self::is_installed()) 648 { 649 $this->install(); 650 } 651 652 $module->tpl_name = 'captcha_qa_acp'; 653 $module->page_title = 'ACP_VC_SETTINGS'; 654 $form_key = 'acp_captcha'; 655 add_form_key($form_key); 656 657 $submit = $request->variable('submit', false); 658 $question_id = $request->variable('question_id', 0); 659 $action = $request->variable('action', ''); 660 661 // we have two pages, so users might want to navigate from one to the other 662 $list_url = $module->u_action . "&configure=1&select_captcha=" . $this->get_service_name(); 663 664 $template->assign_vars(array( 665 'U_ACTION' => $module->u_action, 666 'QUESTION_ID' => $question_id , 667 'CLASS' => $this->get_service_name(), 668 )); 669 670 // show the list? 671 if (!$question_id && $action != 'add') 672 { 673 $this->acp_question_list($module); 674 } 675 else if ($question_id && $action == 'delete') 676 { 677 if ($this->get_service_name() !== $config['captcha_plugin'] || !$this->acp_is_last($question_id)) 678 { 679 if (confirm_box(true)) 680 { 681 $this->acp_delete_question($question_id); 682 683 trigger_error($user->lang['QUESTION_DELETED'] . adm_back_link($list_url)); 684 } 685 else 686 { 687 confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( 688 'question_id' => $question_id, 689 'action' => $action, 690 'configure' => 1, 691 'select_captcha' => $this->get_service_name(), 692 )) 693 ); 694 } 695 } 696 else 697 { 698 trigger_error($user->lang['QA_LAST_QUESTION'] . adm_back_link($list_url), E_USER_WARNING); 699 } 700 } 701 else 702 { 703 // okay, show the editor 704 $question_input = $this->acp_get_question_input(); 705 $langs = $this->get_languages(); 706 707 foreach ($langs as $lang => $entry) 708 { 709 $template->assign_block_vars('langs', array( 710 'ISO' => $lang, 711 'NAME' => $entry['name'], 712 )); 713 } 714 715 $template->assign_vars(array( 716 'U_LIST' => $list_url, 717 )); 718 719 if ($question_id) 720 { 721 if ($question = $this->acp_get_question_data($question_id)) 722 { 723 $template->assign_vars(array( 724 'QUESTION_TEXT' => ($question_input['question_text']) ? $question_input['question_text'] : $question['question_text'], 725 'LANG_ISO' => ($question_input['lang_iso']) ? $question_input['lang_iso'] : $question['lang_iso'], 726 'STRICT' => (isset($_REQUEST['strict'])) ? $question_input['strict'] : $question['strict'], 727 'ANSWERS' => implode("\n", $question['answers']), 728 )); 729 } 730 else 731 { 732 trigger_error($user->lang['FORM_INVALID'] . adm_back_link($list_url)); 733 } 734 } 735 else 736 { 737 $template->assign_vars(array( 738 'QUESTION_TEXT' => $question_input['question_text'], 739 'LANG_ISO' => $question_input['lang_iso'], 740 'STRICT' => $question_input['strict'], 741 'ANSWERS' => (is_array($question_input['answers'])) ? implode("\n", $question_input['answers']) : '', 742 )); 743 } 744 745 if ($submit && check_form_key($form_key)) 746 { 747 if (!$this->validate_input($question_input)) 748 { 749 $template->assign_vars(array( 750 'S_ERROR' => true, 751 )); 752 } 753 else 754 { 755 if ($question_id) 756 { 757 $this->acp_update_question($question_input, $question_id); 758 } 759 else 760 { 761 $this->acp_add_question($question_input); 762 } 763 764 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_VISUAL'); 765 trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($list_url)); 766 } 767 } 768 else if ($submit) 769 { 770 trigger_error($user->lang['FORM_INVALID'] . adm_back_link($list_url), E_USER_WARNING); 771 } 772 } 773 } 774 775 /** 776 * This handles the list overview 777 */ 778 function acp_question_list($module) 779 { 780 global $db, $template; 781 782 $sql = 'SELECT * 783 FROM ' . $this->table_captcha_questions; 784 $result = $db->sql_query($sql); 785 786 $template->assign_vars(array( 787 'S_LIST' => true, 788 )); 789 790 while ($row = $db->sql_fetchrow($result)) 791 { 792 $url = $module->u_action . "&question_id={$row['question_id']}&configure=1&select_captcha=" . $this->get_service_name() . '&'; 793 794 $template->assign_block_vars('questions', array( 795 'QUESTION_TEXT' => $row['question_text'], 796 'QUESTION_ID' => $row['question_id'], 797 'QUESTION_LANG' => $row['lang_iso'], 798 'U_DELETE' => "{$url}action=delete", 799 'U_EDIT' => "{$url}action=edit", 800 )); 801 } 802 $db->sql_freeresult($result); 803 } 804 805 /** 806 * Grab a question and bring it into a format the editor understands 807 */ 808 function acp_get_question_data($question_id) 809 { 810 global $db; 811 812 if ($question_id) 813 { 814 $sql = 'SELECT * 815 FROM ' . $this->table_captcha_questions . ' 816 WHERE question_id = ' . $question_id; 817 $result = $db->sql_query($sql); 818 $question = $db->sql_fetchrow($result); 819 $db->sql_freeresult($result); 820 821 if (!$question) 822 { 823 return false; 824 } 825 826 $question['answers'] = array(); 827 828 $sql = 'SELECT * 829 FROM ' . $this->table_captcha_answers . ' 830 WHERE question_id = ' . $question_id; 831 $result = $db->sql_query($sql); 832 833 while ($row = $db->sql_fetchrow($result)) 834 { 835 $question['answers'][] = $row['answer_text']; 836 } 837 $db->sql_freeresult($result); 838 839 return $question; 840 } 841 842 return false; 843 } 844 845 /** 846 * Grab a question from input and bring it into a format the editor understands 847 */ 848 function acp_get_question_input() 849 { 850 global $request; 851 852 $answers = $request->variable('answers', '', true); 853 854 // Convert answers into array and filter if answers are set 855 if (strlen($answers)) 856 { 857 $answers = array_filter(array_map('trim', explode("\n", $answers)), function ($value) { 858 return $value !== ''; 859 }); 860 } 861 862 $question = array( 863 'question_text' => $request->variable('question_text', '', true), 864 'strict' => $request->variable('strict', false), 865 'lang_iso' => $request->variable('lang_iso', ''), 866 'answers' => $answers, 867 ); 868 return $question; 869 } 870 871 /** 872 * Update a question. 873 * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data 874 */ 875 function acp_update_question($data, $question_id) 876 { 877 global $db, $cache; 878 879 // easier to delete all answers than to figure out which to update 880 $sql = 'DELETE FROM ' . $this->table_captcha_answers . " WHERE question_id = $question_id"; 881 $db->sql_query($sql); 882 883 $langs = $this->get_languages(); 884 $question_ary = $data; 885 $question_ary['lang_id'] = $langs[$question_ary['lang_iso']]['id']; 886 unset($question_ary['answers']); 887 888 $sql = 'UPDATE ' . $this->table_captcha_questions . ' 889 SET ' . $db->sql_build_array('UPDATE', $question_ary) . " 890 WHERE question_id = $question_id"; 891 $db->sql_query($sql); 892 893 $this->acp_insert_answers($data, $question_id); 894 895 $cache->destroy('sql', $this->table_captcha_questions); 896 } 897 898 /** 899 * Insert a question. 900 * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data 901 */ 902 function acp_add_question($data) 903 { 904 global $db, $cache; 905 906 $langs = $this->get_languages(); 907 $question_ary = $data; 908 909 $question_ary['lang_id'] = $langs[$data['lang_iso']]['id']; 910 unset($question_ary['answers']); 911 912 $sql = 'INSERT INTO ' . $this->table_captcha_questions . ' ' . $db->sql_build_array('INSERT', $question_ary); 913 $db->sql_query($sql); 914 915 $question_id = $db->sql_nextid(); 916 917 $this->acp_insert_answers($data, $question_id); 918 919 $cache->destroy('sql', $this->table_captcha_questions); 920 } 921 922 /** 923 * Insert the answers. 924 * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data 925 */ 926 function acp_insert_answers($data, $question_id) 927 { 928 global $db, $cache; 929 930 foreach ($data['answers'] as $answer) 931 { 932 $answer_ary = array( 933 'question_id' => $question_id, 934 'answer_text' => $answer, 935 ); 936 937 $sql = 'INSERT INTO ' . $this->table_captcha_answers . ' ' . $db->sql_build_array('INSERT', $answer_ary); 938 $db->sql_query($sql); 939 } 940 941 $cache->destroy('sql', $this->table_captcha_answers); 942 } 943 944 /** 945 * Delete a question. 946 */ 947 function acp_delete_question($question_id) 948 { 949 global $db, $cache; 950 951 $tables = array($this->table_captcha_questions, $this->table_captcha_answers); 952 953 foreach ($tables as $table) 954 { 955 $sql = "DELETE FROM $table 956 WHERE question_id = $question_id"; 957 $db->sql_query($sql); 958 } 959 960 $cache->destroy('sql', $tables); 961 } 962 963 /** 964 * Check if the entered data can be inserted/used 965 * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data 966 */ 967 function validate_input($question_data) 968 { 969 $langs = $this->get_languages(); 970 971 if (!isset($question_data['lang_iso']) || 972 !isset($question_data['question_text']) || 973 !isset($question_data['strict']) || 974 !isset($question_data['answers'])) 975 { 976 return false; 977 } 978 979 if (!isset($langs[$question_data['lang_iso']]) || 980 !strlen($question_data['question_text']) || 981 !count($question_data['answers']) || 982 !is_array($question_data['answers'])) 983 { 984 return false; 985 } 986 987 return true; 988 } 989 990 /** 991 * List the installed language packs 992 */ 993 function get_languages() 994 { 995 global $db; 996 997 $sql = 'SELECT * 998 FROM ' . LANG_TABLE; 999 $result = $db->sql_query($sql); 1000 1001 $langs = array(); 1002 while ($row = $db->sql_fetchrow($result)) 1003 { 1004 $langs[$row['lang_iso']] = array( 1005 'name' => $row['lang_local_name'], 1006 'id' => (int) $row['lang_id'], 1007 ); 1008 } 1009 $db->sql_freeresult($result); 1010 1011 return $langs; 1012 } 1013 1014 1015 1016 /** 1017 * See if there is a question other than the one we have 1018 */ 1019 function acp_is_last($question_id) 1020 { 1021 global $config, $db; 1022 1023 if ($question_id) 1024 { 1025 $sql = 'SELECT question_id 1026 FROM ' . $this->table_captcha_questions . " 1027 WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "' 1028 AND question_id <> " . (int) $question_id; 1029 $result = $db->sql_query_limit($sql, 1); 1030 $question = $db->sql_fetchrow($result); 1031 $db->sql_freeresult($result); 1032 1033 if (!$question) 1034 { 1035 return true; 1036 } 1037 return false; 1038 } 1039 } 1040 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Nov 11 20:33:01 2020 | Cross-referenced by PHPXref 0.7.1 |