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