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

log.php

Zuletzt modifiziert: 09.10.2024, 12:52 - Dateigröße: 22.98 KiB


001  <?php
002  /**
003  *
004  * This file is part of the phpBB Forum Software package.
005  *
006  * @copyright (c) phpBB Limited <https://www.phpbb.com>
007  * @license GNU General Public License, version 2 (GPL-2.0)
008  *
009  * For full copyright and license information, please see
010  * the docs/CREDITS.txt file.
011  *
012  */
013   
014  namespace phpbb\log;
015   
016  /**
017  * This class is used to add entries into the log table.
018  */
019  class log implements \phpbb\log\log_interface
020  {
021      /**
022      * If set, administrative user profile links will be returned and messages
023      * will not be censored.
024      * @var bool
025      */
026      protected $is_in_admin;
027   
028      /**
029      * An array with the disabled log types. Logs of such types will not be
030      * added when add_log() is called.
031      * @var array
032      */
033      protected $disabled_types;
034   
035      /**
036      * Keeps the total log count of the last call to get_logs()
037      * @var int
038      */
039      protected $entry_count;
040   
041      /**
042      * Keeps the offset of the last valid page of the last call to get_logs()
043      * @var int
044      */
045      protected $last_page_offset;
046   
047      /**
048      * The table we use to store our logs.
049      * @var string
050      */
051      protected $log_table;
052   
053      /**
054      * Database object
055      * @var \phpbb\db\driver\driver
056      */
057      protected $db;
058   
059      /**
060      * User object
061      * @var \phpbb\user
062      */
063      protected $user;
064   
065      /**
066      * Auth object
067      * @var \phpbb\auth\auth
068      */
069      protected $auth;
070   
071      /**
072      * Event dispatcher object
073      * @var \phpbb\event\dispatcher_interface
074      */
075      protected $dispatcher;
076   
077      /**
078      * phpBB root path
079      * @var string
080      */
081      protected $phpbb_root_path;
082   
083      /**
084      * Admin root path
085      * @var string
086      */
087      protected $phpbb_admin_path;
088   
089      /**
090      * PHP Extension
091      * @var string
092      */
093      protected $php_ext;
094   
095      /**
096      * Constructor
097      *
098      * @param    \phpbb\db\driver\driver_interface    $db        Database object
099      * @param    \phpbb\user        $user    User object
100      * @param    \phpbb\auth\auth        $auth    Auth object
101      * @param    \phpbb\event\dispatcher_interface    $phpbb_dispatcher    Event dispatcher
102      * @param    string        $phpbb_root_path        Root path
103      * @param    string        $relative_admin_path    Relative admin root path
104      * @param    string        $php_ext            PHP Extension
105      * @param    string        $log_table        Name of the table we use to store our logs
106      */
107      public function __construct($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, $relative_admin_path, $php_ext, $log_table)
108      {
109          $this->db = $db;
110          $this->user = $user;
111          $this->auth = $auth;
112          $this->dispatcher = $phpbb_dispatcher;
113          $this->phpbb_root_path = $phpbb_root_path;
114          $this->phpbb_admin_path = $this->phpbb_root_path . $relative_admin_path;
115          $this->php_ext = $php_ext;
116          $this->log_table = $log_table;
117   
118          /*
119          * IN_ADMIN is set after the session is created,
120          * so we need to take ADMIN_START into account as well, otherwise
121          * it will not work for the \phpbb\log\log object we create in common.php
122          */
123          $this->set_is_admin((defined('ADMIN_START') && ADMIN_START) || (defined('IN_ADMIN') && IN_ADMIN));
124          $this->enable();
125      }
126   
127      /**
128      * Set is_in_admin in order to return administrative user profile links
129      * in get_logs()
130      *
131      * @param    bool    $is_in_admin        Are we called from within the acp?
132      * @return    null
133      */
134      public function set_is_admin($is_in_admin)
135      {
136          $this->is_in_admin = (bool) $is_in_admin;
137      }
138   
139      /**
140      * Returns the is_in_admin option
141      *
142      * @return    bool
143      */
144      public function get_is_admin()
145      {
146          return $this->is_in_admin;
147      }
148   
149      /**
150      * Set table name
151      *
152      * @param    string    $log_table        Can overwrite the table to use for the logs
153      * @return    null
154      */
155      public function set_log_table($log_table)
156      {
157          $this->log_table = $log_table;
158      }
159   
160      /**
161      * {@inheritDoc}
162      */
163      public function is_enabled($type = '')
164      {
165          if ($type == '' || $type == 'all')
166          {
167              return !isset($this->disabled_types['all']);
168          }
169          return !isset($this->disabled_types[$type]) && !isset($this->disabled_types['all']);
170      }
171   
172      /**
173      * {@inheritDoc}
174      */
175      public function disable($type = '')
176      {
177          if (is_array($type))
178          {
179              foreach ($type as $disable_type)
180              {
181                  $this->disable($disable_type);
182              }
183              return;
184          }
185   
186          // Empty string is an equivalent for all types.
187          if ($type == '')
188          {
189              $type = 'all';
190          }
191          $this->disabled_types[$type] = true;
192      }
193   
194      /**
195      * {@inheritDoc}
196      */
197      public function enable($type = '')
198      {
199          if (is_array($type))
200          {
201              foreach ($type as $enable_type)
202              {
203                  $this->enable($enable_type);
204              }
205              return;
206          }
207   
208          if ($type == '' || $type == 'all')
209          {
210              $this->disabled_types = array();
211              return;
212          }
213          unset($this->disabled_types[$type]);
214      }
215   
216      /**
217      * {@inheritDoc}
218      */
219      public function add($mode, $user_id, $log_ip, $log_operation, $log_time = false, $additional_data = array())
220      {
221          if (!$this->is_enabled($mode))
222          {
223              return false;
224          }
225   
226          if ($log_time == false)
227          {
228              $log_time = time();
229          }
230   
231          $sql_ary = array(
232              'user_id'        => $user_id,
233              'log_ip'        => $log_ip,
234              'log_time'        => $log_time,
235              'log_operation'    => $log_operation,
236          );
237   
238          switch ($mode)
239          {
240              case 'admin':
241                  $sql_ary += array(
242                      'log_type'        => LOG_ADMIN,
243                      'log_data'        => (!empty($additional_data)) ? serialize($additional_data) : '',
244                  );
245              break;
246   
247              case 'mod':
248                  $forum_id = isset($additional_data['forum_id']) ? (int) $additional_data['forum_id'] : 0;
249                  unset($additional_data['forum_id']);
250                  $topic_id = isset($additional_data['topic_id']) ? (int) $additional_data['topic_id'] : 0;
251                  unset($additional_data['topic_id']);
252                  $sql_ary += array(
253                      'log_type'        => LOG_MOD,
254                      'forum_id'        => $forum_id,
255                      'topic_id'        => $topic_id,
256                      'log_data'        => (!empty($additional_data)) ? serialize($additional_data) : '',
257                  );
258              break;
259   
260              case 'user':
261                  $reportee_id = (int) $additional_data['reportee_id'];
262                  unset($additional_data['reportee_id']);
263   
264                  $sql_ary += array(
265                      'log_type'        => LOG_USERS,
266                      'reportee_id'    => $reportee_id,
267                      'log_data'        => (!empty($additional_data)) ? serialize($additional_data) : '',
268                  );
269              break;
270   
271              case 'critical':
272                  $sql_ary += array(
273                      'log_type'        => LOG_CRITICAL,
274                      'log_data'        => (!empty($additional_data)) ? serialize($additional_data) : '',
275                  );
276              break;
277          }
278   
279          /**
280          * Allows to modify log data before we add it to the database
281          *
282          * NOTE: if sql_ary does not contain a log_type value, the entry will
283          * not be stored in the database. So ensure to set it, if needed.
284          *
285          * @event core.add_log
286          * @var    string    mode            Mode of the entry we log
287          * @var    int        user_id            ID of the user who triggered the log
288          * @var    string    log_ip            IP of the user who triggered the log
289          * @var    string    log_operation    Language key of the log operation
290          * @var    int        log_time        Timestamp, when the log was added
291          * @var    array    additional_data    Array with additional log data
292          * @var    array    sql_ary            Array with log data we insert into the
293          *                            database. If sql_ary[log_type] is not set,
294          *                            we won't add the entry to the database.
295          * @since 3.1.0-a1
296          */
297          $vars = array(
298              'mode',
299              'user_id',
300              'log_ip',
301              'log_operation',
302              'log_time',
303              'additional_data',
304              'sql_ary',
305          );
306          extract($this->dispatcher->trigger_event('core.add_log', compact($vars)));
307   
308          // We didn't find a log_type, so we don't save it in the database.
309          if (!isset($sql_ary['log_type']))
310          {
311              return false;
312          }
313   
314          $this->db->sql_query('INSERT INTO ' . $this->log_table . ' ' . $this->db->sql_build_array('INSERT', $sql_ary));
315   
316          return $this->db->sql_nextid();
317      }
318   
319      /**
320      * {@inheritDoc}
321      */
322      public function delete($mode, $conditions = array())
323      {
324          switch ($mode)
325          {
326              case 'admin':
327                  $log_type = LOG_ADMIN;
328                  break;
329   
330              case 'mod':
331                  $log_type = LOG_MOD;
332                  break;
333   
334              case 'user':
335                  $log_type = LOG_USERS;
336                  break;
337   
338              case 'users':
339                  $log_type = LOG_USERS;
340                  break;
341   
342              case 'critical':
343                  $log_type = LOG_CRITICAL;
344                  break;
345   
346              default:
347                  $log_type = false;
348          }
349   
350          /**
351          * Allows to modify log data before we delete it from the database
352          *
353          * NOTE: if sql_ary does not contain a log_type value, the entry will
354          * not be deleted in the database. So ensure to set it, if needed.
355          *
356          * @event core.delete_log
357          * @var    string    mode            Mode of the entry we log
358          * @var    string    log_type        Type ID of the log (should be different than false)
359          * @var    array    conditions        An array of conditions, 3 different  forms are accepted
360          *                                 1) <key> => <value> transformed into 'AND <key> = <value>' (value should be an integer)
361          *                                2) <key> => array(<operator>, <value>) transformed into 'AND <key> <operator> <value>' (values can't be an array)
362          *                                3) <key> => array('IN' => array(<values>)) transformed into 'AND <key> IN <values>'
363          *                                A special field, keywords, can also be defined. In this case only the log entries that have the keywords in log_operation or log_data will be deleted.
364          * @since 3.1.0-b4
365          */
366          $vars = array(
367              'mode',
368              'log_type',
369              'conditions',
370          );
371          extract($this->dispatcher->trigger_event('core.delete_log', compact($vars)));
372   
373          if ($log_type === false)
374          {
375              return;
376          }
377   
378          $sql_where = 'WHERE log_type = ' . $log_type;
379   
380          if (isset($conditions['keywords']))
381          {
382              $sql_where .= $this->generate_sql_keyword($conditions['keywords'], '');
383   
384              unset($conditions['keywords']);
385          }
386   
387          foreach ($conditions as $field => $field_value)
388          {
389              $sql_where .= ' AND ';
390   
391              if (is_array($field_value) && sizeof($field_value) == 2 && !is_array($field_value[1]))
392              {
393                  $sql_where .= $field . ' ' . $field_value[0] . ' ' . $field_value[1];
394              }
395              else if (is_array($field_value) && isset($field_value['IN']) && is_array($field_value['IN']))
396              {
397                  $sql_where .= $this->db->sql_in_set($field, $field_value['IN']);
398              }
399              else
400              {
401                  $sql_where .= $field . ' = ' . $field_value;
402              }
403          }
404   
405          $sql = 'DELETE FROM ' . LOG_TABLE . "
406                      $sql_where";
407          $this->db->sql_query($sql);
408   
409          $this->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CLEAR_' . strtoupper($mode));
410      }
411   
412      /**
413      * {@inheritDoc}
414      */
415      public function get_logs($mode, $count_logs = true, $limit = 0, $offset = 0, $forum_id = 0, $topic_id = 0, $user_id = 0, $log_time = 0, $sort_by = 'l.log_time DESC', $keywords = '')
416      {
417          $this->entry_count = 0;
418          $this->last_page_offset = $offset;
419   
420          $topic_id_list = $reportee_id_list = array();
421   
422          $profile_url = ($this->get_is_admin() && $this->phpbb_admin_path) ? append_sid("{$this->phpbb_admin_path}index.{$this->php_ext}", 'i=users&amp;mode=overview') : append_sid("{$this->phpbb_root_path}memberlist.{$this->php_ext}", 'mode=viewprofile');
423   
424          switch ($mode)
425          {
426              case 'admin':
427                  $log_type = LOG_ADMIN;
428                  $sql_additional = '';
429              break;
430   
431              case 'mod':
432                  $log_type = LOG_MOD;
433                  $sql_additional = '';
434   
435                  if ($topic_id)
436                  {
437                      $sql_additional = 'AND l.topic_id = ' . (int) $topic_id;
438                  }
439                  else if (is_array($forum_id))
440                  {
441                      $sql_additional = 'AND ' . $this->db->sql_in_set('l.forum_id', array_map('intval', $forum_id));
442                  }
443                  else if ($forum_id)
444                  {
445                      $sql_additional = 'AND l.forum_id = ' . (int) $forum_id;
446                  }
447              break;
448   
449              case 'user':
450                  $log_type = LOG_USERS;
451                  $sql_additional = 'AND l.reportee_id = ' . (int) $user_id;
452              break;
453   
454              case 'users':
455                  $log_type = LOG_USERS;
456                  $sql_additional = '';
457              break;
458   
459              case 'critical':
460                  $log_type = LOG_CRITICAL;
461                  $sql_additional = '';
462              break;
463   
464              default:
465                  $log_type = false;
466                  $sql_additional = '';
467          }
468   
469          /**
470          * Overwrite log type and limitations before we count and get the logs
471          *
472          * NOTE: if log_type is false, no entries will be returned.
473          *
474          * @event core.get_logs_modify_type
475          * @var    string    mode        Mode of the entries we display
476          * @var    bool    count_logs    Do we count all matching entries?
477          * @var    int        limit        Limit the number of entries
478          * @var    int        offset        Offset when fetching the entries
479          * @var    mixed    forum_id    Limit entries to the forum_id,
480          *                            can also be an array of forum_ids
481          * @var    int        topic_id    Limit entries to the topic_id
482          * @var    int        user_id        Limit entries to the user_id
483          * @var    int        log_time    Limit maximum age of log entries
484          * @var    string    sort_by        SQL order option
485          * @var    string    keywords    Will only return entries that have the
486          *                            keywords in log_operation or log_data
487          * @var    string    profile_url    URL to the users profile
488          * @var    int        log_type    Limit logs to a certain type. If log_type
489          *                            is false, no entries will be returned.
490          * @var    string    sql_additional    Additional conditions for the entries,
491          *                                e.g.: 'AND l.forum_id = 1'
492          * @since 3.1.0-a1
493          */
494          $vars = array(
495              'mode',
496              'count_logs',
497              'limit',
498              'offset',
499              'forum_id',
500              'topic_id',
501              'user_id',
502              'log_time',
503              'sort_by',
504              'keywords',
505              'profile_url',
506              'log_type',
507              'sql_additional',
508          );
509          extract($this->dispatcher->trigger_event('core.get_logs_modify_type', compact($vars)));
510   
511          if ($log_type === false)
512          {
513              $this->last_page_offset = 0;
514              return array();
515          }
516   
517          $sql_keywords = '';
518          if (!empty($keywords))
519          {
520              // Get the SQL condition for our keywords
521              $sql_keywords = $this->generate_sql_keyword($keywords);
522          }
523   
524          if ($count_logs)
525          {
526              $sql = 'SELECT COUNT(l.log_id) AS total_entries
527                  FROM ' . $this->log_table . ' l, ' . USERS_TABLE . ' u
528                  WHERE l.log_type = ' . (int) $log_type . '
529                      AND l.user_id = u.user_id
530                      AND l.log_time >= ' . (int) $log_time . "
531                      $sql_keywords
532                      $sql_additional";
533              $result = $this->db->sql_query($sql);
534              $this->entry_count = (int) $this->db->sql_fetchfield('total_entries');
535              $this->db->sql_freeresult($result);
536   
537              if ($this->entry_count == 0)
538              {
539                  // Save the queries, because there are no logs to display
540                  $this->last_page_offset = 0;
541                  return array();
542              }
543   
544              // Return the user to the last page that is valid
545              while ($this->last_page_offset >= $this->entry_count)
546              {
547                  $this->last_page_offset = max(0, $this->last_page_offset - $limit);
548              }
549          }
550   
551          $sql = 'SELECT l.*, u.username, u.username_clean, u.user_colour
552              FROM ' . $this->log_table . ' l, ' . USERS_TABLE . ' u
553              WHERE l.log_type = ' . (int) $log_type . '
554                  AND u.user_id = l.user_id
555                  ' . (($log_time) ? 'AND l.log_time >= ' . (int) $log_time : '') . "
556                  $sql_keywords
557                  $sql_additional
558              ORDER BY $sort_by";
559          $result = $this->db->sql_query_limit($sql, $limit, $this->last_page_offset);
560   
561          $i = 0;
562          $log = array();
563          while ($row = $this->db->sql_fetchrow($result))
564          {
565              $row['forum_id'] = (int) $row['forum_id'];
566              if ($row['topic_id'])
567              {
568                  $topic_id_list[] = (int) $row['topic_id'];
569              }
570   
571              if ($row['reportee_id'])
572              {
573                  $reportee_id_list[] = (int) $row['reportee_id'];
574              }
575   
576              $log_entry_data = array(
577                  'id'                => (int) $row['log_id'],
578   
579                  'reportee_id'            => (int) $row['reportee_id'],
580                  'reportee_username'        => '',
581                  'reportee_username_full'=> '',
582   
583                  'user_id'            => (int) $row['user_id'],
584                  'username'            => $row['username'],
585                  'username_full'        => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], false, $profile_url),
586   
587                  'ip'                => $row['log_ip'],
588                  'time'                => (int) $row['log_time'],
589                  'forum_id'            => (int) $row['forum_id'],
590                  'topic_id'            => (int) $row['topic_id'],
591   
592                  'viewforum'            => ($row['forum_id'] && $this->auth->acl_get('f_read', $row['forum_id'])) ? append_sid("{$this->phpbb_root_path}viewforum.{$this->php_ext}", 'f=' . $row['forum_id']) : false,
593                  'action'            => (isset($this->user->lang[$row['log_operation']])) ? $row['log_operation'] : '{' . ucfirst(str_replace('_', ' ', $row['log_operation'])) . '}',
594              );
595   
596              /**
597              * Modify the entry's data before it is returned
598              *
599              * @event core.get_logs_modify_entry_data
600              * @var    array    row            Entry data from the database
601              * @var    array    log_entry_data    Entry's data which is returned
602              * @since 3.1.0-a1
603              */
604              $vars = array('row', 'log_entry_data');
605              extract($this->dispatcher->trigger_event('core.get_logs_modify_entry_data', compact($vars)));
606   
607              $log[$i] = $log_entry_data;
608   
609              if (!empty($row['log_data']))
610              {
611                  $log_data_ary = unserialize($row['log_data']);
612                  $log_data_ary = ($log_data_ary !== false) ? $log_data_ary : array();
613   
614                  if (isset($this->user->lang[$row['log_operation']]))
615                  {
616                      // Check if there are more occurrences of % than
617                      // arguments, if there are we fill out the arguments
618                      // array. It doesn't matter if we add more arguments than
619                      // placeholders.
620                      $num_args = 0;
621                      if (!is_array($this->user->lang[$row['log_operation']]))
622                      {
623                          $num_args = substr_count($this->user->lang[$row['log_operation']], '%');
624                      }
625                      else
626                      {
627                          foreach ($this->user->lang[$row['log_operation']] as $case => $plural_string)
628                          {
629                              $num_args = max($num_args, substr_count($plural_string, '%'));
630                          }
631                      }
632   
633                      if (($num_args - sizeof($log_data_ary)) > 0)
634                      {
635                          $log_data_ary = array_merge($log_data_ary, array_fill(0, $num_args - sizeof($log_data_ary), ''));
636                      }
637   
638                      $lang_arguments = array_merge(array($log[$i]['action']), $log_data_ary);
639                      $log[$i]['action'] = call_user_func_array(array($this->user, 'lang'), $lang_arguments);
640   
641                      // If within the admin panel we do not censor text out
642                      if ($this->get_is_admin())
643                      {
644                          $log[$i]['action'] = bbcode_nl2br($log[$i]['action']);
645                      }
646                      else
647                      {
648                          $log[$i]['action'] = bbcode_nl2br(censor_text($log[$i]['action']));
649                      }
650                  }
651                  else if (!empty($log_data_ary))
652                  {
653                      $log[$i]['action'] .= '<br />' . implode('', $log_data_ary);
654                  }
655   
656                  /* Apply make_clickable... has to be seen if it is for good. :/
657                  // Seems to be not for the moment, reconsider later...
658                  $log[$i]['action'] = make_clickable($log[$i]['action']);
659                  */
660              }
661              else
662              {
663                  $log[$i]['action'] = $this->user->lang($log[$i]['action']);
664              }
665   
666              $i++;
667          }
668          $this->db->sql_freeresult($result);
669   
670          /**
671          * Get some additional data after we got all log entries
672          *
673          * @event core.get_logs_get_additional_data
674          * @var    array    log            Array with all our log entries
675          * @var    array    topic_id_list        Array of topic ids, for which we
676          *                                    get the permission data
677          * @var    array    reportee_id_list    Array of additional user IDs we
678          *                                    get the username strings for
679          * @since 3.1.0-a1
680          */
681          $vars = array('log', 'topic_id_list', 'reportee_id_list');
682          extract($this->dispatcher->trigger_event('core.get_logs_get_additional_data', compact($vars)));
683   
684          if (sizeof($topic_id_list))
685          {
686              $topic_auth = $this->get_topic_auth($topic_id_list);
687   
688              foreach ($log as $key => $row)
689              {
690                  $log[$key]['viewtopic'] = (isset($topic_auth['f_read'][$row['topic_id']])) ? append_sid("{$this->phpbb_root_path}viewtopic.{$this->php_ext}", 'f=' . $topic_auth['f_read'][$row['topic_id']] . '&amp;t=' . $row['topic_id']) : false;
691                  $log[$key]['viewlogs'] = (isset($topic_auth['m_'][$row['topic_id']])) ? append_sid("{$this->phpbb_root_path}mcp.{$this->php_ext}", 'i=logs&amp;mode=topic_logs&amp;t=' . $row['topic_id'], true, $this->user->session_id) : false;
692              }
693          }
694   
695          if (sizeof($reportee_id_list))
696          {
697              $reportee_data_list = $this->get_reportee_data($reportee_id_list);
698   
699              foreach ($log as $key => $row)
700              {
701                  if (!isset($reportee_data_list[$row['reportee_id']]))
702                  {
703                      continue;
704                  }
705   
706                  $log[$key]['reportee_username'] = $reportee_data_list[$row['reportee_id']]['username'];
707                  $log[$key]['reportee_username_full'] = get_username_string('full', $row['reportee_id'], $reportee_data_list[$row['reportee_id']]['username'], $reportee_data_list[$row['reportee_id']]['user_colour'], false, $profile_url);
708              }
709          }
710   
711          return $log;
712      }
713   
714      /**
715      * Generates a sql condition for the specified keywords
716      *
717      * @param    string    $keywords            The keywords the user specified to search for
718      * @param    string    $table_alias        The alias of the logs' table ('l.' by default)
719      * @param    string    $statement_operator    The operator used to prefix the statement ('AND' by default)
720      *
721      * @return    string        Returns the SQL condition searching for the keywords
722      */
723      protected function generate_sql_keyword($keywords, $table_alias = 'l.', $statement_operator = 'AND')
724      {
725          // Use no preg_quote for $keywords because this would lead to sole
726          // backslashes being added. We also use an OR connection here for
727          // spaces and the | string. Currently, regex is not supported for
728          // searching (but may come later).
729          $keywords = preg_split('#[\s|]+#u', utf8_strtolower($keywords), 0, PREG_SPLIT_NO_EMPTY);
730          $sql_keywords = '';
731   
732          if (!empty($keywords))
733          {
734              $keywords_pattern = array();
735   
736              // Build pattern and keywords...
737              for ($i = 0, $num_keywords = sizeof($keywords); $i < $num_keywords; $i++)
738              {
739                  $keywords_pattern[] = preg_quote($keywords[$i], '#');
740                  $keywords[$i] = $this->db->sql_like_expression($this->db->get_any_char() . $keywords[$i] . $this->db->get_any_char());
741              }
742   
743              $keywords_pattern = '#' . implode('|', $keywords_pattern) . '#ui';
744   
745              $operations = array();
746              foreach ($this->user->lang as $key => $value)
747              {
748                  if (substr($key, 0, 4) == 'LOG_')
749                  {
750                      if (is_array($value))
751                      {
752                          foreach ($value as $plural_value)
753                          {
754                              if (preg_match($keywords_pattern, $plural_value))
755                              {
756                                  $operations[] = $key;
757                                  break;
758                              }
759                          }
760                      }
761                      else if (preg_match($keywords_pattern, $value))
762                      {
763                          $operations[] = $key;
764                      }
765                  }
766              }
767   
768              $sql_keywords = ' ' . $statement_operator . ' (';
769              if (!empty($operations))
770              {
771                  $sql_keywords .= $this->db->sql_in_set($table_alias . 'log_operation', $operations) . ' OR ';
772              }
773              $sql_lower = $this->db->sql_lower_text($table_alias . 'log_data');
774              $sql_keywords .= " $sql_lower " . implode(" OR $sql_lower ", $keywords) . ')';
775          }
776   
777          return $sql_keywords;
778      }
779   
780      /**
781      * Determine whether the user is allowed to read and/or moderate the forum of the topic
782      *
783      * @param    array    $topic_ids    Array with the topic ids
784      *
785      * @return    array        Returns an array with two keys 'm_' and 'read_f' which are also an array of topic_id => forum_id sets when the permissions are given. Sample:
786      *                        array(
787      *                            'permission' => array(
788      *                                topic_id => forum_id
789      *                            ),
790      *                        ),
791      */
792      protected function get_topic_auth(array $topic_ids)
793      {
794          $forum_auth = array('f_read' => array(), 'm_' => array());
795          $topic_ids = array_unique($topic_ids);
796   
797          $sql = 'SELECT topic_id, forum_id
798              FROM ' . TOPICS_TABLE . '
799              WHERE ' . $this->db->sql_in_set('topic_id', array_map('intval', $topic_ids));
800          $result = $this->db->sql_query($sql);
801   
802          while ($row = $this->db->sql_fetchrow($result))
803          {
804              $row['topic_id'] = (int) $row['topic_id'];
805              $row['forum_id'] = (int) $row['forum_id'];
806   
807              if ($this->auth->acl_get('f_read', $row['forum_id']))
808              {
809                  $forum_auth['f_read'][$row['topic_id']] = $row['forum_id'];
810              }
811   
812              if ($this->auth->acl_gets('a_', 'm_', $row['forum_id']))
813              {
814                  $forum_auth['m_'][$row['topic_id']] = $row['forum_id'];
815              }
816          }
817          $this->db->sql_freeresult($result);
818   
819          return $forum_auth;
820      }
821   
822      /**
823      * Get the data for all reportee from the database
824      *
825      * @param    array    $reportee_ids    Array with the user ids of the reportees
826      *
827      * @return    array        Returns an array with the reportee data
828      */
829      protected function get_reportee_data(array $reportee_ids)
830      {
831          $reportee_ids = array_unique($reportee_ids);
832          $reportee_data_list = array();
833   
834          $sql = 'SELECT user_id, username, user_colour
835              FROM ' . USERS_TABLE . '
836              WHERE ' . $this->db->sql_in_set('user_id', $reportee_ids);
837          $result = $this->db->sql_query($sql);
838   
839          while ($row = $this->db->sql_fetchrow($result))
840          {
841              $reportee_data_list[$row['user_id']] = $row;
842          }
843          $this->db->sql_freeresult($result);
844   
845          return $reportee_data_list;
846      }
847   
848      /**
849      * {@inheritDoc}
850      */
851      public function get_log_count()
852      {
853          return ($this->entry_count) ? $this->entry_count : 0;
854      }
855   
856      /**
857      * {@inheritDoc}
858      */
859      public function get_valid_offset()
860      {
861          return ($this->last_page_offset) ? $this->last_page_offset : 0;
862      }
863  }
864