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.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

qa.php

Zuletzt modifiziert: 09.10.2024, 12:54 - Dateigröße: 23.06 KiB


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 . "&amp;configure=1&amp;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 . "&amp;question_id={$row['question_id']}&amp;configure=1&amp;select_captcha=" . $this->get_service_name() . '&amp;';
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