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

viewtopic.php

Zuletzt modifiziert: 09.10.2024, 12:50 - Dateigröße: 80.58 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  /**
 0015  * @ignore
 0016  */
 0017  define('IN_PHPBB', true);
 0018  $phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './';
 0019  $phpEx = substr(strrchr(__FILE__, '.'), 1);
 0020  include($phpbb_root_path . 'common.' . $phpEx);
 0021  include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
 0022  include($phpbb_root_path . 'includes/bbcode.' . $phpEx);
 0023  include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
 0024   
 0025  // Start session management
 0026  $user->session_begin();
 0027  $auth->acl($user->data);
 0028   
 0029  // Initial var setup
 0030  $forum_id    = request_var('f', 0);
 0031  $topic_id    = request_var('t', 0);
 0032  $post_id    = request_var('p', 0);
 0033  $voted_id    = request_var('vote_id', array('' => 0));
 0034   
 0035  $voted_id = (sizeof($voted_id) > 1) ? array_unique($voted_id) : $voted_id;
 0036   
 0037   
 0038  $start        = request_var('start', 0);
 0039  $view        = request_var('view', '');
 0040   
 0041  $default_sort_days    = (!empty($user->data['user_post_show_days'])) ? $user->data['user_post_show_days'] : 0;
 0042  $default_sort_key    = (!empty($user->data['user_post_sortby_type'])) ? $user->data['user_post_sortby_type'] : 't';
 0043  $default_sort_dir    = (!empty($user->data['user_post_sortby_dir'])) ? $user->data['user_post_sortby_dir'] : 'a';
 0044   
 0045  $sort_days    = request_var('st', $default_sort_days);
 0046  $sort_key    = request_var('sk', $default_sort_key);
 0047  $sort_dir    = request_var('sd', $default_sort_dir);
 0048   
 0049  $update        = request_var('update', false);
 0050   
 0051  $pagination = $phpbb_container->get('pagination');
 0052   
 0053  $s_can_vote = false;
 0054  /**
 0055  * @todo normalize?
 0056  */
 0057  $hilit_words    = request_var('hilit', '', true);
 0058   
 0059  // Do we have a topic or post id?
 0060  if (!$topic_id && !$post_id)
 0061  {
 0062      trigger_error('NO_TOPIC');
 0063  }
 0064   
 0065  $phpbb_content_visibility = $phpbb_container->get('content.visibility');
 0066   
 0067  // Find topic id if user requested a newer or older topic
 0068  if ($view && !$post_id)
 0069  {
 0070      if (!$forum_id)
 0071      {
 0072          $sql = 'SELECT forum_id
 0073              FROM ' . TOPICS_TABLE . "
 0074              WHERE topic_id = $topic_id";
 0075          $result = $db->sql_query($sql);
 0076          $forum_id = (int) $db->sql_fetchfield('forum_id');
 0077          $db->sql_freeresult($result);
 0078   
 0079          if (!$forum_id)
 0080          {
 0081              trigger_error('NO_TOPIC');
 0082          }
 0083      }
 0084   
 0085      if ($view == 'unread')
 0086      {
 0087          // Get topic tracking info
 0088          $topic_tracking_info = get_complete_topic_tracking($forum_id, $topic_id);
 0089          $topic_last_read = (isset($topic_tracking_info[$topic_id])) ? $topic_tracking_info[$topic_id] : 0;
 0090   
 0091          $sql = 'SELECT post_id, topic_id, forum_id
 0092              FROM ' . POSTS_TABLE . "
 0093              WHERE topic_id = $topic_id
 0094                  AND " . $phpbb_content_visibility->get_visibility_sql('post', $forum_id) . "
 0095                  AND post_time > $topic_last_read
 0096                  AND forum_id = $forum_id
 0097              ORDER BY post_time ASC, post_id ASC";
 0098          $result = $db->sql_query_limit($sql, 1);
 0099          $row = $db->sql_fetchrow($result);
 0100          $db->sql_freeresult($result);
 0101   
 0102          if (!$row)
 0103          {
 0104              $sql = 'SELECT topic_last_post_id as post_id, topic_id, forum_id
 0105                  FROM ' . TOPICS_TABLE . '
 0106                  WHERE topic_id = ' . $topic_id;
 0107              $result = $db->sql_query($sql);
 0108              $row = $db->sql_fetchrow($result);
 0109              $db->sql_freeresult($result);
 0110          }
 0111   
 0112          if (!$row)
 0113          {
 0114              // Setup user environment so we can process lang string
 0115              $user->setup('viewtopic');
 0116   
 0117              trigger_error('NO_TOPIC');
 0118          }
 0119   
 0120          $post_id = $row['post_id'];
 0121          $topic_id = $row['topic_id'];
 0122      }
 0123      else if ($view == 'next' || $view == 'previous')
 0124      {
 0125          $sql_condition = ($view == 'next') ? '>' : '<';
 0126          $sql_ordering = ($view == 'next') ? 'ASC' : 'DESC';
 0127   
 0128          $sql = 'SELECT forum_id, topic_last_post_time
 0129              FROM ' . TOPICS_TABLE . '
 0130              WHERE topic_id = ' . $topic_id;
 0131          $result = $db->sql_query($sql);
 0132          $row = $db->sql_fetchrow($result);
 0133          $db->sql_freeresult($result);
 0134   
 0135          if (!$row)
 0136          {
 0137              $user->setup('viewtopic');
 0138              // OK, the topic doesn't exist. This error message is not helpful, but technically correct.
 0139              trigger_error(($view == 'next') ? 'NO_NEWER_TOPICS' : 'NO_OLDER_TOPICS');
 0140          }
 0141          else
 0142          {
 0143              $sql = 'SELECT topic_id, forum_id
 0144                  FROM ' . TOPICS_TABLE . '
 0145                  WHERE forum_id = ' . $row['forum_id'] . "
 0146                      AND topic_moved_id = 0
 0147                      AND topic_last_post_time $sql_condition {$row['topic_last_post_time']}
 0148                      AND " . $phpbb_content_visibility->get_visibility_sql('topic', $row['forum_id']) . "
 0149                  ORDER BY topic_last_post_time $sql_ordering, topic_last_post_id $sql_ordering";
 0150              $result = $db->sql_query_limit($sql, 1);
 0151              $row = $db->sql_fetchrow($result);
 0152              $db->sql_freeresult($result);
 0153   
 0154              if (!$row)
 0155              {
 0156                  $sql = 'SELECT forum_style
 0157                      FROM ' . FORUMS_TABLE . "
 0158                      WHERE forum_id = $forum_id";
 0159                  $result = $db->sql_query($sql);
 0160                  $forum_style = (int) $db->sql_fetchfield('forum_style');
 0161                  $db->sql_freeresult($result);
 0162   
 0163                  $user->setup('viewtopic', $forum_style);
 0164                  trigger_error(($view == 'next') ? 'NO_NEWER_TOPICS' : 'NO_OLDER_TOPICS');
 0165              }
 0166              else
 0167              {
 0168                  $topic_id = $row['topic_id'];
 0169                  $forum_id = $row['forum_id'];
 0170              }
 0171          }
 0172      }
 0173   
 0174      if (isset($row) && $row['forum_id'])
 0175      {
 0176          $forum_id = $row['forum_id'];
 0177      }
 0178  }
 0179   
 0180  // This rather complex gaggle of code handles querying for topics but
 0181  // also allows for direct linking to a post (and the calculation of which
 0182  // page the post is on and the correct display of viewtopic)
 0183  $sql_array = array(
 0184      'SELECT'    => 't.*, f.*',
 0185   
 0186      'FROM'        => array(FORUMS_TABLE => 'f'),
 0187  );
 0188   
 0189  // The FROM-Order is quite important here, else t.* columns can not be correctly bound.
 0190  if ($post_id)
 0191  {
 0192      $sql_array['SELECT'] .= ', p.post_visibility, p.post_time, p.post_id';
 0193      $sql_array['FROM'][POSTS_TABLE] = 'p';
 0194  }
 0195   
 0196  // Topics table need to be the last in the chain
 0197  $sql_array['FROM'][TOPICS_TABLE] = 't';
 0198   
 0199  if ($user->data['is_registered'])
 0200  {
 0201      $sql_array['SELECT'] .= ', tw.notify_status';
 0202      $sql_array['LEFT_JOIN'] = array();
 0203   
 0204      $sql_array['LEFT_JOIN'][] = array(
 0205          'FROM'    => array(TOPICS_WATCH_TABLE => 'tw'),
 0206          'ON'    => 'tw.user_id = ' . $user->data['user_id'] . ' AND t.topic_id = tw.topic_id'
 0207      );
 0208   
 0209      if ($config['allow_bookmarks'])
 0210      {
 0211          $sql_array['SELECT'] .= ', bm.topic_id as bookmarked';
 0212          $sql_array['LEFT_JOIN'][] = array(
 0213              'FROM'    => array(BOOKMARKS_TABLE => 'bm'),
 0214              'ON'    => 'bm.user_id = ' . $user->data['user_id'] . ' AND t.topic_id = bm.topic_id'
 0215          );
 0216      }
 0217   
 0218      if ($config['load_db_lastread'])
 0219      {
 0220          $sql_array['SELECT'] .= ', tt.mark_time, ft.mark_time as forum_mark_time';
 0221   
 0222          $sql_array['LEFT_JOIN'][] = array(
 0223              'FROM'    => array(TOPICS_TRACK_TABLE => 'tt'),
 0224              'ON'    => 'tt.user_id = ' . $user->data['user_id'] . ' AND t.topic_id = tt.topic_id'
 0225          );
 0226   
 0227          $sql_array['LEFT_JOIN'][] = array(
 0228              'FROM'    => array(FORUMS_TRACK_TABLE => 'ft'),
 0229              'ON'    => 'ft.user_id = ' . $user->data['user_id'] . ' AND t.forum_id = ft.forum_id'
 0230          );
 0231      }
 0232  }
 0233   
 0234  if (!$post_id)
 0235  {
 0236      $sql_array['WHERE'] = "t.topic_id = $topic_id";
 0237  }
 0238  else
 0239  {
 0240      $sql_array['WHERE'] = "p.post_id = $post_id AND t.topic_id = p.topic_id";
 0241  }
 0242   
 0243  $sql_array['WHERE'] .= ' AND f.forum_id = t.forum_id';
 0244   
 0245  $sql = $db->sql_build_query('SELECT', $sql_array);
 0246  $result = $db->sql_query($sql);
 0247  $topic_data = $db->sql_fetchrow($result);
 0248  $db->sql_freeresult($result);
 0249   
 0250  // link to unapproved post or incorrect link
 0251  if (!$topic_data)
 0252  {
 0253      // If post_id was submitted, we try at least to display the topic as a last resort...
 0254      if ($post_id && $topic_id)
 0255      {
 0256          redirect(append_sid("{$phpbb_root_path}viewtopic.$phpEx", "t=$topic_id" . (($forum_id) ? "&amp;f=$forum_id" : '')));
 0257      }
 0258   
 0259      trigger_error('NO_TOPIC');
 0260  }
 0261   
 0262  $forum_id = (int) $topic_data['forum_id'];
 0263   
 0264  // Now we know the forum_id and can check the permissions
 0265  if ($topic_data['topic_visibility'] != ITEM_APPROVED && !$auth->acl_get('m_approve', $forum_id))
 0266  {
 0267      trigger_error('NO_TOPIC');
 0268  }
 0269   
 0270  // This is for determining where we are (page)
 0271  if ($post_id)
 0272  {
 0273      // are we where we are supposed to be?
 0274      if (($topic_data['post_visibility'] == ITEM_UNAPPROVED || $topic_data['post_visibility'] == ITEM_REAPPROVE) && !$auth->acl_get('m_approve', $topic_data['forum_id']))
 0275      {
 0276          // If post_id was submitted, we try at least to display the topic as a last resort...
 0277          if ($topic_id)
 0278          {
 0279              redirect(append_sid("{$phpbb_root_path}viewtopic.$phpEx", "t=$topic_id" . (($forum_id) ? "&amp;f=$forum_id" : '')));
 0280          }
 0281   
 0282          trigger_error('NO_TOPIC');
 0283      }
 0284      if ($post_id == $topic_data['topic_first_post_id'] || $post_id == $topic_data['topic_last_post_id'])
 0285      {
 0286          $check_sort = ($post_id == $topic_data['topic_first_post_id']) ? 'd' : 'a';
 0287   
 0288          if ($sort_dir == $check_sort)
 0289          {
 0290              $topic_data['prev_posts'] = $phpbb_content_visibility->get_count('topic_posts', $topic_data, $forum_id) - 1;
 0291          }
 0292          else
 0293          {
 0294              $topic_data['prev_posts'] = 0;
 0295          }
 0296      }
 0297      else
 0298      {
 0299          $sql = 'SELECT COUNT(p.post_id) AS prev_posts
 0300              FROM ' . POSTS_TABLE . " p
 0301              WHERE p.topic_id = {$topic_data['topic_id']}
 0302                  AND " . $phpbb_content_visibility->get_visibility_sql('post', $forum_id, 'p.');
 0303   
 0304          if ($sort_dir == 'd')
 0305          {
 0306              $sql .= " AND (p.post_time > {$topic_data['post_time']} OR (p.post_time = {$topic_data['post_time']} AND p.post_id >= {$topic_data['post_id']}))";
 0307          }
 0308          else
 0309          {
 0310              $sql .= " AND (p.post_time < {$topic_data['post_time']} OR (p.post_time = {$topic_data['post_time']} AND p.post_id <= {$topic_data['post_id']}))";
 0311          }
 0312   
 0313          $result = $db->sql_query($sql);
 0314          $row = $db->sql_fetchrow($result);
 0315          $db->sql_freeresult($result);
 0316   
 0317          $topic_data['prev_posts'] = $row['prev_posts'] - 1;
 0318      }
 0319  }
 0320   
 0321  $topic_id = (int) $topic_data['topic_id'];
 0322  $topic_replies = $phpbb_content_visibility->get_count('topic_posts', $topic_data, $forum_id) - 1;
 0323   
 0324  // Check sticky/announcement time limit
 0325  if (($topic_data['topic_type'] == POST_STICKY || $topic_data['topic_type'] == POST_ANNOUNCE) && $topic_data['topic_time_limit'] && ($topic_data['topic_time'] + $topic_data['topic_time_limit']) < time())
 0326  {
 0327      $sql = 'UPDATE ' . TOPICS_TABLE . '
 0328          SET topic_type = ' . POST_NORMAL . ', topic_time_limit = 0
 0329          WHERE topic_id = ' . $topic_id;
 0330      $db->sql_query($sql);
 0331   
 0332      $topic_data['topic_type'] = POST_NORMAL;
 0333      $topic_data['topic_time_limit'] = 0;
 0334  }
 0335   
 0336  // Setup look and feel
 0337  $user->setup('viewtopic', $topic_data['forum_style']);
 0338   
 0339  // Start auth check
 0340  if (!$auth->acl_get('f_read', $forum_id))
 0341  {
 0342      if ($user->data['user_id'] != ANONYMOUS)
 0343      {
 0344          trigger_error('SORRY_AUTH_READ');
 0345      }
 0346   
 0347      login_box('', $user->lang['LOGIN_VIEWFORUM']);
 0348  }
 0349   
 0350  // Forum is passworded ... check whether access has been granted to this
 0351  // user this session, if not show login box
 0352  if ($topic_data['forum_password'])
 0353  {
 0354      login_forum_box($topic_data);
 0355  }
 0356   
 0357  // Redirect to login upon emailed notification links if user is not logged in.
 0358  if (isset($_GET['e']) && $user->data['user_id'] == ANONYMOUS)
 0359  {
 0360      login_box(build_url('e') . '#unread', $user->lang['LOGIN_NOTIFY_TOPIC']);
 0361  }
 0362   
 0363  // What is start equal to?
 0364  if ($post_id)
 0365  {
 0366      $start = floor(($topic_data['prev_posts']) / $config['posts_per_page']) * $config['posts_per_page'];
 0367  }
 0368   
 0369  // Get topic tracking info
 0370  if (!isset($topic_tracking_info))
 0371  {
 0372      $topic_tracking_info = array();
 0373   
 0374      // Get topic tracking info
 0375      if ($config['load_db_lastread'] && $user->data['is_registered'])
 0376      {
 0377          $tmp_topic_data = array($topic_id => $topic_data);
 0378          $topic_tracking_info = get_topic_tracking($forum_id, $topic_id, $tmp_topic_data, array($forum_id => $topic_data['forum_mark_time']));
 0379          unset($tmp_topic_data);
 0380      }
 0381      else if ($config['load_anon_lastread'] || $user->data['is_registered'])
 0382      {
 0383          $topic_tracking_info = get_complete_topic_tracking($forum_id, $topic_id);
 0384      }
 0385  }
 0386   
 0387  // Post ordering options
 0388  $limit_days = array(0 => $user->lang['ALL_POSTS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
 0389   
 0390  $sort_by_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 's' => $user->lang['SUBJECT']);
 0391  $sort_by_sql = array('a' => array('u.username_clean', 'p.post_id'), 't' => array('p.post_time', 'p.post_id'), 's' => array('p.post_subject', 'p.post_id'));
 0392  $join_user_sql = array('a' => true, 't' => false, 's' => false);
 0393   
 0394  $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = '';
 0395   
 0396  gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param, $default_sort_days, $default_sort_key, $default_sort_dir);
 0397   
 0398  // Obtain correct post count and ordering SQL if user has
 0399  // requested anything different
 0400  if ($sort_days)
 0401  {
 0402      $min_post_time = time() - ($sort_days * 86400);
 0403   
 0404      $sql = 'SELECT COUNT(post_id) AS num_posts
 0405          FROM ' . POSTS_TABLE . "
 0406          WHERE topic_id = $topic_id
 0407              AND post_time >= $min_post_time
 0408                  AND " . $phpbb_content_visibility->get_visibility_sql('post', $forum_id);
 0409      $result = $db->sql_query($sql);
 0410      $total_posts = (int) $db->sql_fetchfield('num_posts');
 0411      $db->sql_freeresult($result);
 0412   
 0413      $limit_posts_time = "AND p.post_time >= $min_post_time ";
 0414   
 0415      if (isset($_POST['sort']))
 0416      {
 0417          $start = 0;
 0418      }
 0419  }
 0420  else
 0421  {
 0422      $total_posts = $topic_replies + 1;
 0423      $limit_posts_time = '';
 0424  }
 0425   
 0426  // Was a highlight request part of the URI?
 0427  $highlight_match = $highlight = '';
 0428  if ($hilit_words)
 0429  {
 0430      $highlight_match = phpbb_clean_search_string($hilit_words);
 0431      $highlight = urlencode($highlight_match);
 0432      $highlight_match = str_replace('\*', '\w+?', preg_quote($highlight_match, '#'));
 0433      $highlight_match = preg_replace('#(?<=^|\s)\\\\w\*\?(?=\s|$)#', '\w+?', $highlight_match);
 0434      $highlight_match = str_replace(' ', '|', $highlight_match);
 0435  }
 0436   
 0437  // Make sure $start is set to the last page if it exceeds the amount
 0438  $start = $pagination->validate_start($start, $config['posts_per_page'], $total_posts);
 0439   
 0440  // General Viewtopic URL for return links
 0441  $viewtopic_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id" . (($start == 0) ? '' : "&amp;start=$start") . ((strlen($u_sort_param)) ? "&amp;$u_sort_param" : '') . (($highlight_match) ? "&amp;hilit=$highlight" : ''));
 0442   
 0443  // Are we watching this topic?
 0444  $s_watching_topic = array(
 0445      'link'            => '',
 0446      'link_toggle'    => '',
 0447      'title'            => '',
 0448      'title_toggle'    => '',
 0449      'is_watching'    => false,
 0450  );
 0451   
 0452  if ($config['allow_topic_notify'])
 0453  {
 0454      $notify_status = (isset($topic_data['notify_status'])) ? $topic_data['notify_status'] : null;
 0455      watch_topic_forum('topic', $s_watching_topic, $user->data['user_id'], $forum_id, $topic_id, $notify_status, $start, $topic_data['topic_title']);
 0456   
 0457      // Reset forum notification if forum notify is set
 0458      if ($config['allow_forum_notify'] && $auth->acl_get('f_subscribe', $forum_id))
 0459      {
 0460          $s_watching_forum = $s_watching_topic;
 0461          watch_topic_forum('forum', $s_watching_forum, $user->data['user_id'], $forum_id, 0);
 0462      }
 0463  }
 0464   
 0465  // Bookmarks
 0466  if ($config['allow_bookmarks'] && $user->data['is_registered'] && request_var('bookmark', 0))
 0467  {
 0468      if (check_link_hash(request_var('hash', ''), "topic_$topic_id"))
 0469      {
 0470          if (!$topic_data['bookmarked'])
 0471          {
 0472              $sql = 'INSERT INTO ' . BOOKMARKS_TABLE . ' ' . $db->sql_build_array('INSERT', array(
 0473                  'user_id'    => $user->data['user_id'],
 0474                  'topic_id'    => $topic_id,
 0475              ));
 0476              $db->sql_query($sql);
 0477          }
 0478          else
 0479          {
 0480              $sql = 'DELETE FROM ' . BOOKMARKS_TABLE . "
 0481                  WHERE user_id = {$user->data['user_id']}
 0482                      AND topic_id = $topic_id";
 0483              $db->sql_query($sql);
 0484          }
 0485          $message = (($topic_data['bookmarked']) ? $user->lang['BOOKMARK_REMOVED'] : $user->lang['BOOKMARK_ADDED']);
 0486   
 0487          if (!$request->is_ajax())
 0488          {
 0489              $message .= '<br /><br />' . $user->lang('RETURN_TOPIC', '<a href="' . $viewtopic_url . '">', '</a>');
 0490          }
 0491      }
 0492      else
 0493      {
 0494          $message = $user->lang['BOOKMARK_ERR'];
 0495   
 0496          if (!$request->is_ajax())
 0497          {
 0498              $message .= '<br /><br />' . $user->lang('RETURN_TOPIC', '<a href="' . $viewtopic_url . '">', '</a>');
 0499          }
 0500      }
 0501      meta_refresh(3, $viewtopic_url);
 0502   
 0503      trigger_error($message);
 0504  }
 0505   
 0506  // Grab ranks
 0507  $ranks = $cache->obtain_ranks();
 0508   
 0509  // Grab icons
 0510  $icons = $cache->obtain_icons();
 0511   
 0512  // Grab extensions
 0513  $extensions = array();
 0514  if ($topic_data['topic_attachment'])
 0515  {
 0516      $extensions = $cache->obtain_attach_extensions($forum_id);
 0517  }
 0518   
 0519  // Forum rules listing
 0520  $s_forum_rules = '';
 0521  gen_forum_auth_level('topic', $forum_id, $topic_data['forum_status']);
 0522   
 0523  // Quick mod tools
 0524  $allow_change_type = ($auth->acl_get('m_', $forum_id) || ($user->data['is_registered'] && $user->data['user_id'] == $topic_data['topic_poster'])) ? true : false;
 0525   
 0526  $s_quickmod_action = append_sid(
 0527      "{$phpbb_root_path}mcp.$phpEx",
 0528      array(
 0529          'f'    => $forum_id,
 0530          't'    => $topic_id,
 0531          'start'        => $start,
 0532          'quickmod'    => 1,
 0533          'redirect'    => urlencode(str_replace('&amp;', '&', $viewtopic_url)),
 0534      ),
 0535      true,
 0536      $user->session_id
 0537  );
 0538   
 0539  $quickmod_array = array(
 0540  //    'key'            => array('LANG_KEY', $userHasPermissions),
 0541   
 0542      'lock'                    => array('LOCK_TOPIC', ($topic_data['topic_status'] == ITEM_UNLOCKED) && ($auth->acl_get('m_lock', $forum_id) || ($auth->acl_get('f_user_lock', $forum_id) && $user->data['is_registered'] && $user->data['user_id'] == $topic_data['topic_poster']))),
 0543      'unlock'                => array('UNLOCK_TOPIC', ($topic_data['topic_status'] != ITEM_UNLOCKED) && ($auth->acl_get('m_lock', $forum_id))),
 0544      'delete_topic'        => array('DELETE_TOPIC', ($auth->acl_get('m_delete', $forum_id) || (($topic_data['topic_visibility'] != ITEM_DELETED) && $auth->acl_get('m_softdelete', $forum_id)))),
 0545      'restore_topic'        => array('RESTORE_TOPIC', (($topic_data['topic_visibility'] == ITEM_DELETED) && $auth->acl_get('m_approve', $forum_id))),
 0546      'move'                    => array('MOVE_TOPIC', $auth->acl_get('m_move', $forum_id) && $topic_data['topic_status'] != ITEM_MOVED),
 0547      'split'                    => array('SPLIT_TOPIC', $auth->acl_get('m_split', $forum_id)),
 0548      'merge'                    => array('MERGE_POSTS', $auth->acl_get('m_merge', $forum_id)),
 0549      'merge_topic'        => array('MERGE_TOPIC', $auth->acl_get('m_merge', $forum_id)),
 0550      'fork'                    => array('FORK_TOPIC', $auth->acl_get('m_move', $forum_id)),
 0551      'make_normal'        => array('MAKE_NORMAL', ($allow_change_type && $auth->acl_gets('f_sticky', 'f_announce', $forum_id) && $topic_data['topic_type'] != POST_NORMAL)),
 0552      'make_sticky'        => array('MAKE_STICKY', ($allow_change_type && $auth->acl_get('f_sticky', $forum_id) && $topic_data['topic_type'] != POST_STICKY)),
 0553      'make_announce'    => array('MAKE_ANNOUNCE', ($allow_change_type && $auth->acl_get('f_announce', $forum_id) && $topic_data['topic_type'] != POST_ANNOUNCE)),
 0554      'make_global'        => array('MAKE_GLOBAL', ($allow_change_type && $auth->acl_get('f_announce', $forum_id) && $topic_data['topic_type'] != POST_GLOBAL)),
 0555      'topic_logs'            => array('VIEW_TOPIC_LOGS', $auth->acl_get('m_', $forum_id)),
 0556  );
 0557   
 0558  foreach($quickmod_array as $option => $qm_ary)
 0559  {
 0560      if (!empty($qm_ary[1]))
 0561      {
 0562          phpbb_add_quickmod_option($s_quickmod_action, $option, $qm_ary[0]);
 0563      }
 0564  }
 0565   
 0566  // Navigation links
 0567  generate_forum_nav($topic_data);
 0568   
 0569  // Forum Rules
 0570  generate_forum_rules($topic_data);
 0571   
 0572  // Moderators
 0573  $forum_moderators = array();
 0574  if ($config['load_moderators'])
 0575  {
 0576      get_moderators($forum_moderators, $forum_id);
 0577  }
 0578   
 0579  // This is only used for print view so ...
 0580  $server_path = (!$view) ? $phpbb_root_path : generate_board_url() . '/';
 0581   
 0582  // Replace naughty words in title
 0583  $topic_data['topic_title'] = censor_text($topic_data['topic_title']);
 0584   
 0585  $s_search_hidden_fields = array(
 0586      't' => $topic_id,
 0587      'sf' => 'msgonly',
 0588  );
 0589  if ($_SID)
 0590  {
 0591      $s_search_hidden_fields['sid'] = $_SID;
 0592  }
 0593   
 0594  if (!empty($_EXTRA_URL))
 0595  {
 0596      foreach ($_EXTRA_URL as $url_param)
 0597      {
 0598          $url_param = explode('=', $url_param, 2);
 0599          $s_search_hidden_fields[$url_param[0]] = $url_param[1];
 0600      }
 0601  }
 0602   
 0603  // If we've got a hightlight set pass it on to pagination.
 0604  $base_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id" . ((strlen($u_sort_param)) ? "&amp;$u_sort_param" : '') . (($highlight_match) ? "&amp;hilit=$highlight" : ''));
 0605   
 0606  /**
 0607  * Event to modify data before template variables are being assigned
 0608  *
 0609  * @event core.viewtopic_assign_template_vars_before
 0610  * @var    string    base_url            URL to be passed to generate pagination
 0611  * @var    int        forum_id            Forum ID
 0612  * @var    int        post_id                Post ID
 0613  * @var    array    quickmod_array        Array with quick moderation options data
 0614  * @var    int        start                Pagination information
 0615  * @var    array    topic_data            Array with topic data
 0616  * @var    int        topic_id            Topic ID
 0617  * @var    array    topic_tracking_info    Array with topic tracking data
 0618  * @var    int        total_posts            Topic total posts count
 0619  * @since 3.1.0-RC4
 0620  */
 0621  $vars = array(
 0622      'base_url',
 0623      'forum_id',
 0624      'post_id',
 0625      'quickmod_array',
 0626      'start',
 0627      'topic_data',
 0628      'topic_id',
 0629      'topic_tracking_info',
 0630      'total_posts',
 0631  );
 0632  extract($phpbb_dispatcher->trigger_event('core.viewtopic_assign_template_vars_before', compact($vars)));
 0633   
 0634  $pagination->generate_template_pagination($base_url, 'pagination', 'start', $total_posts, $config['posts_per_page'], $start);
 0635   
 0636  // Send vars to template
 0637  $template->assign_vars(array(
 0638      'FORUM_ID'         => $forum_id,
 0639      'FORUM_NAME'     => $topic_data['forum_name'],
 0640      'FORUM_DESC'    => generate_text_for_display($topic_data['forum_desc'], $topic_data['forum_desc_uid'], $topic_data['forum_desc_bitfield'], $topic_data['forum_desc_options']),
 0641      'TOPIC_ID'         => $topic_id,
 0642      'TOPIC_TITLE'     => $topic_data['topic_title'],
 0643      'TOPIC_POSTER'    => $topic_data['topic_poster'],
 0644   
 0645      'TOPIC_AUTHOR_FULL'        => get_username_string('full', $topic_data['topic_poster'], $topic_data['topic_first_poster_name'], $topic_data['topic_first_poster_colour']),
 0646      'TOPIC_AUTHOR_COLOUR'    => get_username_string('colour', $topic_data['topic_poster'], $topic_data['topic_first_poster_name'], $topic_data['topic_first_poster_colour']),
 0647      'TOPIC_AUTHOR'            => get_username_string('username', $topic_data['topic_poster'], $topic_data['topic_first_poster_name'], $topic_data['topic_first_poster_colour']),
 0648   
 0649      'TOTAL_POSTS'    => $user->lang('VIEW_TOPIC_POSTS', (int) $total_posts),
 0650      'U_MCP'         => ($auth->acl_get('m_', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "i=main&amp;mode=topic_view&amp;f=$forum_id&amp;t=$topic_id" . (($start == 0) ? '' : "&amp;start=$start") . ((strlen($u_sort_param)) ? "&amp;$u_sort_param" : ''), true, $user->session_id) : '',
 0651      'MODERATORS'    => (isset($forum_moderators[$forum_id]) && sizeof($forum_moderators[$forum_id])) ? implode($user->lang['COMMA_SEPARATOR'], $forum_moderators[$forum_id]) : '',
 0652   
 0653      'POST_IMG'             => ($topic_data['forum_status'] == ITEM_LOCKED) ? $user->img('button_topic_locked', 'FORUM_LOCKED') : $user->img('button_topic_new', 'POST_NEW_TOPIC'),
 0654      'QUOTE_IMG'         => $user->img('icon_post_quote', 'REPLY_WITH_QUOTE'),
 0655      'REPLY_IMG'            => ($topic_data['forum_status'] == ITEM_LOCKED || $topic_data['topic_status'] == ITEM_LOCKED) ? $user->img('button_topic_locked', 'TOPIC_LOCKED') : $user->img('button_topic_reply', 'REPLY_TO_TOPIC'),
 0656      'EDIT_IMG'             => $user->img('icon_post_edit', 'EDIT_POST'),
 0657      'DELETE_IMG'         => $user->img('icon_post_delete', 'DELETE_POST'),
 0658      'DELETED_IMG'        => $user->img('icon_topic_deleted', 'POST_DELETED_RESTORE'),
 0659      'INFO_IMG'             => $user->img('icon_post_info', 'VIEW_INFO'),
 0660      'PROFILE_IMG'        => $user->img('icon_user_profile', 'READ_PROFILE'),
 0661      'SEARCH_IMG'         => $user->img('icon_user_search', 'SEARCH_USER_POSTS'),
 0662      'PM_IMG'             => $user->img('icon_contact_pm', 'SEND_PRIVATE_MESSAGE'),
 0663      'EMAIL_IMG'         => $user->img('icon_contact_email', 'SEND_EMAIL'),
 0664      'JABBER_IMG'        => $user->img('icon_contact_jabber', 'JABBER') ,
 0665      'REPORT_IMG'        => $user->img('icon_post_report', 'REPORT_POST'),
 0666      'REPORTED_IMG'        => $user->img('icon_topic_reported', 'POST_REPORTED'),
 0667      'UNAPPROVED_IMG'    => $user->img('icon_topic_unapproved', 'POST_UNAPPROVED'),
 0668      'WARN_IMG'            => $user->img('icon_user_warn', 'WARN_USER'),
 0669   
 0670      'S_IS_LOCKED'            => ($topic_data['topic_status'] == ITEM_UNLOCKED && $topic_data['forum_status'] == ITEM_UNLOCKED) ? false : true,
 0671      'S_SELECT_SORT_DIR'     => $s_sort_dir,
 0672      'S_SELECT_SORT_KEY'     => $s_sort_key,
 0673      'S_SELECT_SORT_DAYS'     => $s_limit_days,
 0674      'S_SINGLE_MODERATOR'    => (!empty($forum_moderators[$forum_id]) && sizeof($forum_moderators[$forum_id]) > 1) ? false : true,
 0675      'S_TOPIC_ACTION'         => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id" . (($start == 0) ? '' : "&amp;start=$start")),
 0676      'S_MOD_ACTION'             => $s_quickmod_action,
 0677   
 0678      'L_RETURN_TO_FORUM'        => $user->lang('RETURN_TO', $topic_data['forum_name']),
 0679      'S_VIEWTOPIC'            => true,
 0680      'S_UNREAD_VIEW'            => $view == 'unread',
 0681      'S_DISPLAY_SEARCHBOX'    => ($auth->acl_get('u_search') && $auth->acl_get('f_search', $forum_id) && $config['load_search']) ? true : false,
 0682      'S_SEARCHBOX_ACTION'    => append_sid("{$phpbb_root_path}search.$phpEx"),
 0683      'S_SEARCH_LOCAL_HIDDEN_FIELDS'    => build_hidden_fields($s_search_hidden_fields),
 0684   
 0685      'S_DISPLAY_POST_INFO'    => ($topic_data['forum_type'] == FORUM_POST && ($auth->acl_get('f_post', $forum_id) || $user->data['user_id'] == ANONYMOUS)) ? true : false,
 0686      'S_DISPLAY_REPLY_INFO'    => ($topic_data['forum_type'] == FORUM_POST && ($auth->acl_get('f_reply', $forum_id) || $user->data['user_id'] == ANONYMOUS)) ? true : false,
 0687      'S_ENABLE_FEEDS_TOPIC'    => ($config['feed_topic'] && !phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $topic_data['forum_options'])) ? true : false,
 0688   
 0689      'U_TOPIC'                => "{$server_path}viewtopic.$phpEx?f=$forum_id&amp;t=$topic_id",
 0690      'U_FORUM'                => $server_path,
 0691      'U_VIEW_TOPIC'             => $viewtopic_url,
 0692      'U_CANONICAL'            => generate_board_url() . '/' . append_sid("viewtopic.$phpEx", "t=$topic_id" . ((strlen($u_sort_param)) ? "&amp;$u_sort_param" : '') . (($start) ? "&amp;start=$start" : ''), true, ''),
 0693      'U_VIEW_FORUM'             => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id),
 0694      'U_VIEW_OLDER_TOPIC'    => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id&amp;view=previous"),
 0695      'U_VIEW_NEWER_TOPIC'    => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id&amp;view=next"),
 0696      'U_PRINT_TOPIC'            => ($auth->acl_get('f_print', $forum_id)) ? $viewtopic_url . '&amp;view=print' : '',
 0697      'U_EMAIL_TOPIC'            => ($auth->acl_get('f_email', $forum_id) && $config['email_enable']) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=email&amp;t=$topic_id") : '',
 0698   
 0699      'U_WATCH_TOPIC'            => $s_watching_topic['link'],
 0700      'U_WATCH_TOPIC_TOGGLE'    => $s_watching_topic['link_toggle'],
 0701      'S_WATCH_TOPIC_TITLE'    => $s_watching_topic['title'],
 0702      'S_WATCH_TOPIC_TOGGLE'    => $s_watching_topic['title_toggle'],
 0703      'S_WATCHING_TOPIC'        => $s_watching_topic['is_watching'],
 0704   
 0705      'U_BOOKMARK_TOPIC'        => ($user->data['is_registered'] && $config['allow_bookmarks']) ? $viewtopic_url . '&amp;bookmark=1&amp;hash=' . generate_link_hash("topic_$topic_id") : '',
 0706      'S_BOOKMARK_TOPIC'        => ($user->data['is_registered'] && $config['allow_bookmarks'] && $topic_data['bookmarked']) ? $user->lang['BOOKMARK_TOPIC_REMOVE'] : $user->lang['BOOKMARK_TOPIC'],
 0707      'S_BOOKMARK_TOGGLE'        => (!$user->data['is_registered'] || !$config['allow_bookmarks'] || !$topic_data['bookmarked']) ? $user->lang['BOOKMARK_TOPIC_REMOVE'] : $user->lang['BOOKMARK_TOPIC'],
 0708      'S_BOOKMARKED_TOPIC'    => ($user->data['is_registered'] && $config['allow_bookmarks'] && $topic_data['bookmarked']) ? true : false,
 0709   
 0710      'U_POST_NEW_TOPIC'         => ($auth->acl_get('f_post', $forum_id) || $user->data['user_id'] == ANONYMOUS) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=post&amp;f=$forum_id") : '',
 0711      'U_POST_REPLY_TOPIC'     => ($auth->acl_get('f_reply', $forum_id) || $user->data['user_id'] == ANONYMOUS) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=reply&amp;f=$forum_id&amp;t=$topic_id") : '',
 0712      'U_BUMP_TOPIC'            => (bump_topic_allowed($forum_id, $topic_data['topic_bumped'], $topic_data['topic_last_post_time'], $topic_data['topic_poster'], $topic_data['topic_last_poster_id'])) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=bump&amp;f=$forum_id&amp;t=$topic_id&amp;hash=" . generate_link_hash("topic_$topic_id")) : '')
 0713  );
 0714   
 0715  // Does this topic contain a poll?
 0716  if (!empty($topic_data['poll_start']))
 0717  {
 0718      $sql = 'SELECT o.*, p.bbcode_bitfield, p.bbcode_uid
 0719          FROM ' . POLL_OPTIONS_TABLE . ' o, ' . POSTS_TABLE . " p
 0720          WHERE o.topic_id = $topic_id
 0721              AND p.post_id = {$topic_data['topic_first_post_id']}
 0722              AND p.topic_id = o.topic_id
 0723          ORDER BY o.poll_option_id";
 0724      $result = $db->sql_query($sql);
 0725   
 0726      $poll_info = $vote_counts = array();
 0727      while ($row = $db->sql_fetchrow($result))
 0728      {
 0729          $poll_info[] = $row;
 0730          $option_id = (int) $row['poll_option_id'];
 0731          $vote_counts[$option_id] = (int) $row['poll_option_total'];
 0732      }
 0733      $db->sql_freeresult($result);
 0734   
 0735      $cur_voted_id = array();
 0736      if ($user->data['is_registered'])
 0737      {
 0738          $sql = 'SELECT poll_option_id
 0739              FROM ' . POLL_VOTES_TABLE . '
 0740              WHERE topic_id = ' . $topic_id . '
 0741                  AND vote_user_id = ' . $user->data['user_id'];
 0742          $result = $db->sql_query($sql);
 0743   
 0744          while ($row = $db->sql_fetchrow($result))
 0745          {
 0746              $cur_voted_id[] = $row['poll_option_id'];
 0747          }
 0748          $db->sql_freeresult($result);
 0749      }
 0750      else
 0751      {
 0752          // Cookie based guest tracking ... I don't like this but hum ho
 0753          // it's oft requested. This relies on "nice" users who don't feel
 0754          // the need to delete cookies to mess with results.
 0755          if ($request->is_set($config['cookie_name'] . '_poll_' . $topic_id, \phpbb\request\request_interface::COOKIE))
 0756          {
 0757              $cur_voted_id = explode(',', $request->variable($config['cookie_name'] . '_poll_' . $topic_id, '', true, \phpbb\request\request_interface::COOKIE));
 0758              $cur_voted_id = array_map('intval', $cur_voted_id);
 0759          }
 0760      }
 0761   
 0762      // Can not vote at all if no vote permission
 0763      $s_can_vote = ($auth->acl_get('f_vote', $forum_id) &&
 0764          (($topic_data['poll_length'] != 0 && $topic_data['poll_start'] + $topic_data['poll_length'] > time()) || $topic_data['poll_length'] == 0) &&
 0765          $topic_data['topic_status'] != ITEM_LOCKED &&
 0766          $topic_data['forum_status'] != ITEM_LOCKED &&
 0767          (!sizeof($cur_voted_id) ||
 0768          ($auth->acl_get('f_votechg', $forum_id) && $topic_data['poll_vote_change']))) ? true : false;
 0769      $s_display_results = (!$s_can_vote || ($s_can_vote && sizeof($cur_voted_id)) || $view == 'viewpoll') ? true : false;
 0770   
 0771      if ($update && $s_can_vote)
 0772      {
 0773   
 0774          if (!sizeof($voted_id) || sizeof($voted_id) > $topic_data['poll_max_options'] || in_array(VOTE_CONVERTED, $cur_voted_id) || !check_form_key('posting'))
 0775          {
 0776              $redirect_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id" . (($start == 0) ? '' : "&amp;start=$start"));
 0777   
 0778              meta_refresh(5, $redirect_url);
 0779              if (!sizeof($voted_id))
 0780              {
 0781                  $message = 'NO_VOTE_OPTION';
 0782              }
 0783              else if (sizeof($voted_id) > $topic_data['poll_max_options'])
 0784              {
 0785                  $message = 'TOO_MANY_VOTE_OPTIONS';
 0786              }
 0787              else if (in_array(VOTE_CONVERTED, $cur_voted_id))
 0788              {
 0789                  $message = 'VOTE_CONVERTED';
 0790              }
 0791              else
 0792              {
 0793                  $message = 'FORM_INVALID';
 0794              }
 0795   
 0796              $message = $user->lang[$message] . '<br /><br />' . sprintf($user->lang['RETURN_TOPIC'], '<a href="' . $redirect_url . '">', '</a>');
 0797              trigger_error($message);
 0798          }
 0799   
 0800          foreach ($voted_id as $option)
 0801          {
 0802              if (in_array($option, $cur_voted_id))
 0803              {
 0804                  continue;
 0805              }
 0806   
 0807              $sql = 'UPDATE ' . POLL_OPTIONS_TABLE . '
 0808                  SET poll_option_total = poll_option_total + 1
 0809                  WHERE poll_option_id = ' . (int) $option . '
 0810                      AND topic_id = ' . (int) $topic_id;
 0811              $db->sql_query($sql);
 0812   
 0813              $vote_counts[$option]++;
 0814   
 0815              if ($user->data['is_registered'])
 0816              {
 0817                  $sql_ary = array(
 0818                      'topic_id'            => (int) $topic_id,
 0819                      'poll_option_id'    => (int) $option,
 0820                      'vote_user_id'        => (int) $user->data['user_id'],
 0821                      'vote_user_ip'        => (string) $user->ip,
 0822                  );
 0823   
 0824                  $sql = 'INSERT INTO ' . POLL_VOTES_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
 0825                  $db->sql_query($sql);
 0826              }
 0827          }
 0828   
 0829          foreach ($cur_voted_id as $option)
 0830          {
 0831              if (!in_array($option, $voted_id))
 0832              {
 0833                  $sql = 'UPDATE ' . POLL_OPTIONS_TABLE . '
 0834                      SET poll_option_total = poll_option_total - 1
 0835                      WHERE poll_option_id = ' . (int) $option . '
 0836                          AND topic_id = ' . (int) $topic_id;
 0837                  $db->sql_query($sql);
 0838   
 0839                  $vote_counts[$option]--;
 0840   
 0841                  if ($user->data['is_registered'])
 0842                  {
 0843                      $sql = 'DELETE FROM ' . POLL_VOTES_TABLE . '
 0844                          WHERE topic_id = ' . (int) $topic_id . '
 0845                              AND poll_option_id = ' . (int) $option . '
 0846                              AND vote_user_id = ' . (int) $user->data['user_id'];
 0847                      $db->sql_query($sql);
 0848                  }
 0849              }
 0850          }
 0851   
 0852          if ($user->data['user_id'] == ANONYMOUS && !$user->data['is_bot'])
 0853          {
 0854              $user->set_cookie('poll_' . $topic_id, implode(',', $voted_id), time() + 31536000);
 0855          }
 0856   
 0857          $sql = 'UPDATE ' . TOPICS_TABLE . '
 0858              SET poll_last_vote = ' . time() . "
 0859              WHERE topic_id = $topic_id";
 0860          //, topic_last_post_time = ' . time() . " -- for bumping topics with new votes, ignore for now
 0861          $db->sql_query($sql);
 0862   
 0863          $redirect_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id" . (($start == 0) ? '' : "&amp;start=$start"));
 0864          $message = $user->lang['VOTE_SUBMITTED'] . '<br /><br />' . sprintf($user->lang['RETURN_TOPIC'], '<a href="' . $redirect_url . '">', '</a>');
 0865   
 0866          if ($request->is_ajax())
 0867          {
 0868              // Filter out invalid options
 0869              $valid_user_votes = array_intersect(array_keys($vote_counts), $voted_id);
 0870   
 0871              $data = array(
 0872                  'NO_VOTES'            => $user->lang['NO_VOTES'],
 0873                  'success'            => true,
 0874                  'user_votes'        => array_flip($valid_user_votes),
 0875                  'vote_counts'        => $vote_counts,
 0876                  'total_votes'        => array_sum($vote_counts),
 0877                  'can_vote'            => !sizeof($valid_user_votes) || ($auth->acl_get('f_votechg', $forum_id) && $topic_data['poll_vote_change']),
 0878              );
 0879              $json_response = new \phpbb\json_response();
 0880              $json_response->send($data);
 0881          }
 0882   
 0883          meta_refresh(5, $redirect_url);
 0884          trigger_error($message);
 0885      }
 0886   
 0887      $poll_total = 0;
 0888      $poll_most = 0;
 0889      foreach ($poll_info as $poll_option)
 0890      {
 0891          $poll_total += $poll_option['poll_option_total'];
 0892          $poll_most = ($poll_option['poll_option_total'] >= $poll_most) ? $poll_option['poll_option_total'] : $poll_most;
 0893      }
 0894   
 0895      $parse_flags = ($poll_info[0]['bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0) | OPTION_FLAG_SMILIES;
 0896   
 0897      for ($i = 0, $size = sizeof($poll_info); $i < $size; $i++)
 0898      {
 0899          $poll_info[$i]['poll_option_text'] = generate_text_for_display($poll_info[$i]['poll_option_text'], $poll_info[$i]['bbcode_uid'], $poll_option['bbcode_bitfield'], $parse_flags, true);
 0900      }
 0901   
 0902      $topic_data['poll_title'] = generate_text_for_display($topic_data['poll_title'], $poll_info[0]['bbcode_uid'], $poll_info[0]['bbcode_bitfield'], $parse_flags, true);
 0903   
 0904      foreach ($poll_info as $poll_option)
 0905      {
 0906          $option_pct = ($poll_total > 0) ? $poll_option['poll_option_total'] / $poll_total : 0;
 0907          $option_pct_txt = sprintf("%.1d%%", round($option_pct * 100));
 0908          $option_pct_rel = ($poll_most > 0) ? $poll_option['poll_option_total'] / $poll_most : 0;
 0909          $option_pct_rel_txt = sprintf("%.1d%%", round($option_pct_rel * 100));
 0910          $option_most_votes = ($poll_option['poll_option_total'] > 0 && $poll_option['poll_option_total'] == $poll_most) ? true : false;
 0911   
 0912          $template->assign_block_vars('poll_option', array(
 0913              'POLL_OPTION_ID'             => $poll_option['poll_option_id'],
 0914              'POLL_OPTION_CAPTION'         => $poll_option['poll_option_text'],
 0915              'POLL_OPTION_RESULT'         => $poll_option['poll_option_total'],
 0916              'POLL_OPTION_PERCENT'         => $option_pct_txt,
 0917              'POLL_OPTION_PERCENT_REL'     => $option_pct_rel_txt,
 0918              'POLL_OPTION_PCT'            => round($option_pct * 100),
 0919              'POLL_OPTION_WIDTH'         => round($option_pct * 250),
 0920              'POLL_OPTION_VOTED'            => (in_array($poll_option['poll_option_id'], $cur_voted_id)) ? true : false,
 0921              'POLL_OPTION_MOST_VOTES'    => $option_most_votes,
 0922          ));
 0923      }
 0924   
 0925      $poll_end = $topic_data['poll_length'] + $topic_data['poll_start'];
 0926   
 0927      $template->assign_vars(array(
 0928          'POLL_QUESTION'        => $topic_data['poll_title'],
 0929          'TOTAL_VOTES'         => $poll_total,
 0930          'POLL_LEFT_CAP_IMG'    => $user->img('poll_left'),
 0931          'POLL_RIGHT_CAP_IMG'=> $user->img('poll_right'),
 0932   
 0933          'L_MAX_VOTES'        => $user->lang('MAX_OPTIONS_SELECT', (int) $topic_data['poll_max_options']),
 0934          'L_POLL_LENGTH'        => ($topic_data['poll_length']) ? sprintf($user->lang[($poll_end > time()) ? 'POLL_RUN_TILL' : 'POLL_ENDED_AT'], $user->format_date($poll_end)) : '',
 0935   
 0936          'S_HAS_POLL'        => true,
 0937          'S_CAN_VOTE'        => $s_can_vote,
 0938          'S_DISPLAY_RESULTS'    => $s_display_results,
 0939          'S_IS_MULTI_CHOICE'    => ($topic_data['poll_max_options'] > 1) ? true : false,
 0940          'S_POLL_ACTION'        => $viewtopic_url,
 0941   
 0942          'U_VIEW_RESULTS'    => $viewtopic_url . '&amp;view=viewpoll',
 0943      ));
 0944   
 0945      unset($poll_end, $poll_info, $voted_id);
 0946  }
 0947   
 0948  // If the user is trying to reach the second half of the topic, fetch it starting from the end
 0949  $store_reverse = false;
 0950  $sql_limit = $config['posts_per_page'];
 0951  $sql_sort_order = $direction = '';
 0952   
 0953  if ($start > $total_posts / 2)
 0954  {
 0955      $store_reverse = true;
 0956   
 0957      // Select the sort order
 0958      $direction = (($sort_dir == 'd') ? 'ASC' : 'DESC');
 0959   
 0960      $sql_limit = $pagination->reverse_limit($start, $sql_limit, $total_posts);
 0961      $sql_start = $pagination->reverse_start($start, $sql_limit, $total_posts);
 0962  }
 0963  else
 0964  {
 0965      // Select the sort order
 0966      $direction = (($sort_dir == 'd') ? 'DESC' : 'ASC');
 0967      $sql_start = $start;
 0968  }
 0969   
 0970  if (is_array($sort_by_sql[$sort_key]))
 0971  {
 0972      $sql_sort_order = implode(' ' . $direction . ', ', $sort_by_sql[$sort_key]) . ' ' . $direction;
 0973  }
 0974  else
 0975  {
 0976      $sql_sort_order = $sort_by_sql[$sort_key] . ' ' . $direction;
 0977  }
 0978   
 0979  // Container for user details, only process once
 0980  $post_list = $user_cache = $id_cache = $attachments = $attach_list = $rowset = $update_count = $post_edit_list = $post_delete_list = array();
 0981  $has_unapproved_attachments = $has_approved_attachments = $display_notice = false;
 0982  $bbcode_bitfield = '';
 0983  $i = $i_total = 0;
 0984   
 0985  // Go ahead and pull all data for this topic
 0986  $sql = 'SELECT p.post_id
 0987      FROM ' . POSTS_TABLE . ' p' . (($join_user_sql[$sort_key]) ? ', ' . USERS_TABLE . ' u': '') . "
 0988      WHERE p.topic_id = $topic_id
 0989          AND " . $phpbb_content_visibility->get_visibility_sql('post', $forum_id, 'p.') . "
 0990          " . (($join_user_sql[$sort_key]) ? 'AND u.user_id = p.poster_id': '') . "
 0991          $limit_posts_time
 0992      ORDER BY $sql_sort_order";
 0993  $result = $db->sql_query_limit($sql, $sql_limit, $sql_start);
 0994   
 0995  $i = ($store_reverse) ? $sql_limit - 1 : 0;
 0996  while ($row = $db->sql_fetchrow($result))
 0997  {
 0998      $post_list[$i] = (int) $row['post_id'];
 0999      ($store_reverse) ? $i-- : $i++;
 1000  }
 1001  $db->sql_freeresult($result);
 1002   
 1003  if (!sizeof($post_list))
 1004  {
 1005      if ($sort_days)
 1006      {
 1007          trigger_error('NO_POSTS_TIME_FRAME');
 1008      }
 1009      else
 1010      {
 1011          trigger_error('NO_TOPIC');
 1012      }
 1013  }
 1014   
 1015  // Holding maximum post time for marking topic read
 1016  // We need to grab it because we do reverse ordering sometimes
 1017  $max_post_time = 0;
 1018   
 1019  $sql_ary = array(
 1020      'SELECT'    => 'u.*, z.friend, z.foe, p.*',
 1021   
 1022      'FROM'        => array(
 1023          USERS_TABLE        => 'u',
 1024          POSTS_TABLE        => 'p',
 1025      ),
 1026   
 1027      'LEFT_JOIN'    => array(
 1028          array(
 1029              'FROM'    => array(ZEBRA_TABLE => 'z'),
 1030              'ON'    => 'z.user_id = ' . $user->data['user_id'] . ' AND z.zebra_id = p.poster_id',
 1031          ),
 1032      ),
 1033   
 1034      'WHERE'        => $db->sql_in_set('p.post_id', $post_list) . '
 1035          AND u.user_id = p.poster_id',
 1036  );
 1037   
 1038  /**
 1039  * Event to modify the SQL query before the post and poster data is retrieved
 1040  *
 1041  * @event core.viewtopic_get_post_data
 1042  * @var    int        forum_id    Forum ID
 1043  * @var    int        topic_id    Topic ID
 1044  * @var    array    topic_data    Array with topic data
 1045  * @var    array    post_list    Array with post_ids we are going to retrieve
 1046  * @var    int        sort_days    Display posts of previous x days
 1047  * @var    string    sort_key    Key the posts are sorted by
 1048  * @var    string    sort_dir    Direction the posts are sorted by
 1049  * @var    int        start        Pagination information
 1050  * @var    array    sql_ary        The SQL array to get the data of posts and posters
 1051  * @since 3.1.0-a1
 1052  * @change 3.1.0-a2 Added vars forum_id, topic_id, topic_data, post_list, sort_days, sort_key, sort_dir, start
 1053  */
 1054  $vars = array(
 1055      'forum_id',
 1056      'topic_id',
 1057      'topic_data',
 1058      'post_list',
 1059      'sort_days',
 1060      'sort_key',
 1061      'sort_dir',
 1062      'start',
 1063      'sql_ary',
 1064  );
 1065  extract($phpbb_dispatcher->trigger_event('core.viewtopic_get_post_data', compact($vars)));
 1066   
 1067  $sql = $db->sql_build_query('SELECT', $sql_ary);
 1068  $result = $db->sql_query($sql);
 1069   
 1070  $now = $user->create_datetime();
 1071  $now = phpbb_gmgetdate($now->getTimestamp() + $now->getOffset());
 1072   
 1073  // Posts are stored in the $rowset array while $attach_list, $user_cache
 1074  // and the global bbcode_bitfield are built
 1075  while ($row = $db->sql_fetchrow($result))
 1076  {
 1077      // Set max_post_time
 1078      if ($row['post_time'] > $max_post_time)
 1079      {
 1080          $max_post_time = $row['post_time'];
 1081      }
 1082   
 1083      $poster_id = (int) $row['poster_id'];
 1084   
 1085      // Does post have an attachment? If so, add it to the list
 1086      if ($row['post_attachment'] && $config['allow_attachments'])
 1087      {
 1088          $attach_list[] = (int) $row['post_id'];
 1089   
 1090          if ($row['post_visibility'] == ITEM_UNAPPROVED || $row['post_visibility'] == ITEM_REAPPROVE)
 1091          {
 1092              $has_unapproved_attachments = true;
 1093          }
 1094          else if ($row['post_visibility'] == ITEM_APPROVED)
 1095          {
 1096              $has_approved_attachments = true;
 1097          }
 1098      }
 1099   
 1100      $rowset_data = array(
 1101          'hide_post'            => (($row['foe'] || $row['post_visibility'] == ITEM_DELETED) && ($view != 'show' || $post_id != $row['post_id'])) ? true : false,
 1102   
 1103          'post_id'            => $row['post_id'],
 1104          'post_time'            => $row['post_time'],
 1105          'user_id'            => $row['user_id'],
 1106          'username'            => $row['username'],
 1107          'user_colour'        => $row['user_colour'],
 1108          'topic_id'            => $row['topic_id'],
 1109          'forum_id'            => $row['forum_id'],
 1110          'post_subject'        => $row['post_subject'],
 1111          'post_edit_count'    => $row['post_edit_count'],
 1112          'post_edit_time'    => $row['post_edit_time'],
 1113          'post_edit_reason'    => $row['post_edit_reason'],
 1114          'post_edit_user'    => $row['post_edit_user'],
 1115          'post_edit_locked'    => $row['post_edit_locked'],
 1116          'post_delete_time'    => $row['post_delete_time'],
 1117          'post_delete_reason'=> $row['post_delete_reason'],
 1118          'post_delete_user'    => $row['post_delete_user'],
 1119   
 1120          // Make sure the icon actually exists
 1121          'icon_id'            => (isset($icons[$row['icon_id']]['img'], $icons[$row['icon_id']]['height'], $icons[$row['icon_id']]['width'])) ? $row['icon_id'] : 0,
 1122          'post_attachment'    => $row['post_attachment'],
 1123          'post_visibility'    => $row['post_visibility'],
 1124          'post_reported'        => $row['post_reported'],
 1125          'post_username'        => $row['post_username'],
 1126          'post_text'            => $row['post_text'],
 1127          'bbcode_uid'        => $row['bbcode_uid'],
 1128          'bbcode_bitfield'    => $row['bbcode_bitfield'],
 1129          'enable_smilies'    => $row['enable_smilies'],
 1130          'enable_sig'        => $row['enable_sig'],
 1131          'friend'            => $row['friend'],
 1132          'foe'                => $row['foe'],
 1133      );
 1134   
 1135      /**
 1136      * Modify the post rowset containing data to be displayed with posts
 1137      *
 1138      * @event core.viewtopic_post_rowset_data
 1139      * @var    array    rowset_data    Array with the rowset data for this post
 1140      * @var    array    row            Array with original user and post data
 1141      * @since 3.1.0-a1
 1142      */
 1143      $vars = array('rowset_data', 'row');
 1144      extract($phpbb_dispatcher->trigger_event('core.viewtopic_post_rowset_data', compact($vars)));
 1145   
 1146      $rowset[$row['post_id']] = $rowset_data;
 1147   
 1148      // Define the global bbcode bitfield, will be used to load bbcodes
 1149      $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']);
 1150   
 1151      // Is a signature attached? Are we going to display it?
 1152      if ($row['enable_sig'] && $config['allow_sig'] && $user->optionget('viewsigs'))
 1153      {
 1154          $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['user_sig_bbcode_bitfield']);
 1155      }
 1156   
 1157      // Cache various user specific data ... so we don't have to recompute
 1158      // this each time the same user appears on this page
 1159      if (!isset($user_cache[$poster_id]))
 1160      {
 1161          if ($poster_id == ANONYMOUS)
 1162          {
 1163              $user_cache_data = array(
 1164                  'user_type'        => USER_IGNORE,
 1165                  'joined'        => '',
 1166                  'posts'            => '',
 1167   
 1168                  'sig'                    => '',
 1169                  'sig_bbcode_uid'        => '',
 1170                  'sig_bbcode_bitfield'    => '',
 1171   
 1172                  'online'            => false,
 1173                  'avatar'            => ($user->optionget('viewavatars')) ? phpbb_get_user_avatar($row) : '',
 1174                  'rank_title'        => '',
 1175                  'rank_image'        => '',
 1176                  'rank_image_src'    => '',
 1177                  'sig'                => '',
 1178                  'pm'                => '',
 1179                  'email'                => '',
 1180                  'jabber'            => '',
 1181                  'search'            => '',
 1182                  'age'                => '',
 1183   
 1184                  'username'            => $row['username'],
 1185                  'user_colour'        => $row['user_colour'],
 1186                  'contact_user'        => '',
 1187   
 1188                  'warnings'            => 0,
 1189                  'allow_pm'            => 0,
 1190              );
 1191   
 1192              /**
 1193              * Modify the guest user's data displayed with the posts
 1194              *
 1195              * @event core.viewtopic_cache_guest_data
 1196              * @var    array    user_cache_data    Array with the user's data
 1197              * @var    int        poster_id        Poster's user id
 1198              * @var    array    row                Array with original user and post data
 1199              * @since 3.1.0-a1
 1200              */
 1201              $vars = array('user_cache_data', 'poster_id', 'row');
 1202              extract($phpbb_dispatcher->trigger_event('core.viewtopic_cache_guest_data', compact($vars)));
 1203   
 1204              $user_cache[$poster_id] = $user_cache_data;
 1205   
 1206              $user_rank_data = phpbb_get_user_rank($row, false);
 1207              $user_cache[$poster_id]['rank_title'] = $user_rank_data['title'];
 1208              $user_cache[$poster_id]['rank_image'] = $user_rank_data['img'];
 1209              $user_cache[$poster_id]['rank_image_src'] = $user_rank_data['img_src'];
 1210          }
 1211          else
 1212          {
 1213              $user_sig = '';
 1214   
 1215              // We add the signature to every posters entry because enable_sig is post dependent
 1216              if ($row['user_sig'] && $config['allow_sig'] && $user->optionget('viewsigs'))
 1217              {
 1218                  $user_sig = $row['user_sig'];
 1219              }
 1220   
 1221              $id_cache[] = $poster_id;
 1222   
 1223              $user_cache_data = array(
 1224                  'user_type'                    => $row['user_type'],
 1225                  'user_inactive_reason'        => $row['user_inactive_reason'],
 1226   
 1227                  'joined'        => $user->format_date($row['user_regdate']),
 1228                  'posts'            => $row['user_posts'],
 1229                  'warnings'        => (isset($row['user_warnings'])) ? $row['user_warnings'] : 0,
 1230   
 1231                  'sig'                    => $user_sig,
 1232                  'sig_bbcode_uid'        => (!empty($row['user_sig_bbcode_uid'])) ? $row['user_sig_bbcode_uid'] : '',
 1233                  'sig_bbcode_bitfield'    => (!empty($row['user_sig_bbcode_bitfield'])) ? $row['user_sig_bbcode_bitfield'] : '',
 1234   
 1235                  'viewonline'    => $row['user_allow_viewonline'],
 1236                  'allow_pm'        => $row['user_allow_pm'],
 1237   
 1238                  'avatar'        => ($user->optionget('viewavatars')) ? phpbb_get_user_avatar($row) : '',
 1239                  'age'            => '',
 1240   
 1241                  'rank_title'        => '',
 1242                  'rank_image'        => '',
 1243                  'rank_image_src'    => '',
 1244   
 1245                  'username'            => $row['username'],
 1246                  'user_colour'        => $row['user_colour'],
 1247                  'contact_user'         => $user->lang('CONTACT_USER', get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['username'])),
 1248   
 1249                  'online'        => false,
 1250                  'jabber'        => ($row['user_jabber'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=contact&amp;action=jabber&amp;u=$poster_id") : '',
 1251                  'search'        => ($config['load_search'] && $auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", "author_id=$poster_id&amp;sr=posts") : '',
 1252   
 1253                  'author_full'        => get_username_string('full', $poster_id, $row['username'], $row['user_colour']),
 1254                  'author_colour'        => get_username_string('colour', $poster_id, $row['username'], $row['user_colour']),
 1255                  'author_username'    => get_username_string('username', $poster_id, $row['username'], $row['user_colour']),
 1256                  'author_profile'    => get_username_string('profile', $poster_id, $row['username'], $row['user_colour']),
 1257              );
 1258   
 1259              /**
 1260              * Modify the users' data displayed with their posts
 1261              *
 1262              * @event core.viewtopic_cache_user_data
 1263              * @var    array    user_cache_data    Array with the user's data
 1264              * @var    int        poster_id        Poster's user id
 1265              * @var    array    row                Array with original user and post data
 1266              * @since 3.1.0-a1
 1267              */
 1268              $vars = array('user_cache_data', 'poster_id', 'row');
 1269              extract($phpbb_dispatcher->trigger_event('core.viewtopic_cache_user_data', compact($vars)));
 1270   
 1271              $user_cache[$poster_id] = $user_cache_data;
 1272   
 1273              $user_rank_data = phpbb_get_user_rank($row, $row['user_posts']);
 1274              $user_cache[$poster_id]['rank_title'] = $user_rank_data['title'];
 1275              $user_cache[$poster_id]['rank_image'] = $user_rank_data['img'];
 1276              $user_cache[$poster_id]['rank_image_src'] = $user_rank_data['img_src'];
 1277   
 1278              if ((!empty($row['user_allow_viewemail']) && $auth->acl_get('u_sendemail')) || $auth->acl_get('a_email'))
 1279              {
 1280                  $user_cache[$poster_id]['email'] = ($config['board_email_form'] && $config['email_enable']) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=email&amp;u=$poster_id") : (($config['board_hide_emails'] && !$auth->acl_get('a_email')) ? '' : 'mailto:' . $row['user_email']);
 1281              }
 1282              else
 1283              {
 1284                  $user_cache[$poster_id]['email'] = '';
 1285              }
 1286   
 1287              if ($config['allow_birthdays'] && !empty($row['user_birthday']))
 1288              {
 1289                  list($bday_day, $bday_month, $bday_year) = array_map('intval', explode('-', $row['user_birthday']));
 1290   
 1291                  if ($bday_year)
 1292                  {
 1293                      $diff = $now['mon'] - $bday_month;
 1294                      if ($diff == 0)
 1295                      {
 1296                          $diff = ($now['mday'] - $bday_day < 0) ? 1 : 0;
 1297                      }
 1298                      else
 1299                      {
 1300                          $diff = ($diff < 0) ? 1 : 0;
 1301                      }
 1302   
 1303                      $user_cache[$poster_id]['age'] = (int) ($now['year'] - $bday_year - $diff);
 1304                  }
 1305              }
 1306          }
 1307      }
 1308  }
 1309  $db->sql_freeresult($result);
 1310   
 1311  // Load custom profile fields
 1312  if ($config['load_cpf_viewtopic'])
 1313  {
 1314      $cp = $phpbb_container->get('profilefields.manager');
 1315   
 1316      // Grab all profile fields from users in id cache for later use - similar to the poster cache
 1317      $profile_fields_tmp = $cp->grab_profile_fields_data($id_cache);
 1318   
 1319      // filter out fields not to be displayed on viewtopic. Yes, it's a hack, but this shouldn't break any MODs.
 1320      $profile_fields_cache = array();
 1321      foreach ($profile_fields_tmp as $profile_user_id => $profile_fields)
 1322      {
 1323          $profile_fields_cache[$profile_user_id] = array();
 1324          foreach ($profile_fields as $used_ident => $profile_field)
 1325          {
 1326              if ($profile_field['data']['field_show_on_vt'])
 1327              {
 1328                  $profile_fields_cache[$profile_user_id][$used_ident] = $profile_field;
 1329              }
 1330          }
 1331      }
 1332      unset($profile_fields_tmp);
 1333  }
 1334   
 1335  // Generate online information for user
 1336  if ($config['load_onlinetrack'] && sizeof($id_cache))
 1337  {
 1338      $sql = 'SELECT session_user_id, MAX(session_time) as online_time, MIN(session_viewonline) AS viewonline
 1339          FROM ' . SESSIONS_TABLE . '
 1340          WHERE ' . $db->sql_in_set('session_user_id', $id_cache) . '
 1341          GROUP BY session_user_id';
 1342      $result = $db->sql_query($sql);
 1343   
 1344      $update_time = $config['load_online_time'] * 60;
 1345      while ($row = $db->sql_fetchrow($result))
 1346      {
 1347          $user_cache[$row['session_user_id']]['online'] = (time() - $update_time < $row['online_time'] && (($row['viewonline']) || $auth->acl_get('u_viewonline'))) ? true : false;
 1348      }
 1349      $db->sql_freeresult($result);
 1350  }
 1351  unset($id_cache);
 1352   
 1353  // Pull attachment data
 1354  if (sizeof($attach_list))
 1355  {
 1356      if ($auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id))
 1357      {
 1358          $sql = 'SELECT *
 1359              FROM ' . ATTACHMENTS_TABLE . '
 1360              WHERE ' . $db->sql_in_set('post_msg_id', $attach_list) . '
 1361                  AND in_message = 0
 1362              ORDER BY filetime DESC, post_msg_id ASC';
 1363          $result = $db->sql_query($sql);
 1364   
 1365          while ($row = $db->sql_fetchrow($result))
 1366          {
 1367              $attachments[$row['post_msg_id']][] = $row;
 1368          }
 1369          $db->sql_freeresult($result);
 1370   
 1371          // No attachments exist, but post table thinks they do so go ahead and reset post_attach flags
 1372          if (!sizeof($attachments))
 1373          {
 1374              $sql = 'UPDATE ' . POSTS_TABLE . '
 1375                  SET post_attachment = 0
 1376                  WHERE ' . $db->sql_in_set('post_id', $attach_list);
 1377              $db->sql_query($sql);
 1378   
 1379              // We need to update the topic indicator too if the complete topic is now without an attachment
 1380              if (sizeof($rowset) != $total_posts)
 1381              {
 1382                  // Not all posts are displayed so we query the db to find if there's any attachment for this topic
 1383                  $sql = 'SELECT a.post_msg_id as post_id
 1384                      FROM ' . ATTACHMENTS_TABLE . ' a, ' . POSTS_TABLE . " p
 1385                      WHERE p.topic_id = $topic_id
 1386                          AND p.post_visibility = " . ITEM_APPROVED . '
 1387                          AND p.topic_id = a.topic_id';
 1388                  $result = $db->sql_query_limit($sql, 1);
 1389                  $row = $db->sql_fetchrow($result);
 1390                  $db->sql_freeresult($result);
 1391   
 1392                  if (!$row)
 1393                  {
 1394                      $sql = 'UPDATE ' . TOPICS_TABLE . "
 1395                          SET topic_attachment = 0
 1396                          WHERE topic_id = $topic_id";
 1397                      $db->sql_query($sql);
 1398                  }
 1399              }
 1400              else
 1401              {
 1402                  $sql = 'UPDATE ' . TOPICS_TABLE . "
 1403                      SET topic_attachment = 0
 1404                      WHERE topic_id = $topic_id";
 1405                  $db->sql_query($sql);
 1406              }
 1407          }
 1408          else if ($has_approved_attachments && !$topic_data['topic_attachment'])
 1409          {
 1410              // Topic has approved attachments but its flag is wrong
 1411              $sql = 'UPDATE ' . TOPICS_TABLE . "
 1412                  SET topic_attachment = 1
 1413                  WHERE topic_id = $topic_id";
 1414              $db->sql_query($sql);
 1415   
 1416              $topic_data['topic_attachment'] = 1;
 1417          }
 1418          else if ($has_unapproved_attachments && !$topic_data['topic_attachment'])
 1419          {
 1420              // Topic has only unapproved attachments but we have the right to see and download them
 1421              $topic_data['topic_attachment'] = 1;
 1422          }
 1423      }
 1424      else
 1425      {
 1426          $display_notice = true;
 1427      }
 1428  }
 1429   
 1430  // Instantiate BBCode if need be
 1431  if ($bbcode_bitfield !== '')
 1432  {
 1433      $bbcode = new bbcode(base64_encode($bbcode_bitfield));
 1434  }
 1435   
 1436  // Get the list of users who can receive private messages
 1437  $can_receive_pm_list = $auth->acl_get_list(array_keys($user_cache), 'u_readpm');
 1438  $can_receive_pm_list = (empty($can_receive_pm_list) || !isset($can_receive_pm_list[0]['u_readpm'])) ? array() : $can_receive_pm_list[0]['u_readpm'];
 1439   
 1440  // Get the list of permanently banned users
 1441  $permanently_banned_users = phpbb_get_banned_user_ids(array_keys($user_cache), false);
 1442   
 1443  $i_total = sizeof($rowset) - 1;
 1444  $prev_post_id = '';
 1445   
 1446  $template->assign_vars(array(
 1447      'S_HAS_ATTACHMENTS' => $topic_data['topic_attachment'],
 1448      'S_NUM_POSTS' => sizeof($post_list))
 1449  );
 1450   
 1451  /**
 1452  * Event to modify the post, poster and attachment data before assigning the posts
 1453  *
 1454  * @event core.viewtopic_modify_post_data
 1455  * @var    int        forum_id    Forum ID
 1456  * @var    int        topic_id    Topic ID
 1457  * @var    array    topic_data    Array with topic data
 1458  * @var    array    post_list    Array with post_ids we are going to display
 1459  * @var    array    rowset        Array with post_id => post data
 1460  * @var    array    user_cache    Array with prepared user data
 1461  * @var    int        start        Pagination information
 1462  * @var    int        sort_days    Display posts of previous x days
 1463  * @var    string    sort_key    Key the posts are sorted by
 1464  * @var    string    sort_dir    Direction the posts are sorted by
 1465  * @var    bool    display_notice                Shall we display a notice instead of attachments
 1466  * @var    bool    has_approved_attachments    Does the topic have approved attachments
 1467  * @var    array    attachments                    List of attachments post_id => array of attachments
 1468  * @var    array    permanently_banned_users    List of permanently banned users
 1469  * @var    array    can_receive_pm_list            Array with posters that can receive pms
 1470  * @since 3.1.0-RC3
 1471  */
 1472  $vars = array(
 1473      'forum_id',
 1474      'topic_id',
 1475      'topic_data',
 1476      'post_list',
 1477      'rowset',
 1478      'user_cache',
 1479      'sort_days',
 1480      'sort_key',
 1481      'sort_dir',
 1482      'start',
 1483      'permanently_banned_users',
 1484      'can_receive_pm_list',
 1485      'display_notice',
 1486      'has_approved_attachments',
 1487      'attachments',
 1488  );
 1489  extract($phpbb_dispatcher->trigger_event('core.viewtopic_modify_post_data', compact($vars)));
 1490   
 1491  // Output the posts
 1492  $first_unread = $post_unread = false;
 1493  for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i)
 1494  {
 1495      // A non-existing rowset only happens if there was no user present for the entered poster_id
 1496      // This could be a broken posts table.
 1497      if (!isset($rowset[$post_list[$i]]))
 1498      {
 1499          continue;
 1500      }
 1501   
 1502      $row = $rowset[$post_list[$i]];
 1503      $poster_id = $row['user_id'];
 1504   
 1505      // End signature parsing, only if needed
 1506      if ($user_cache[$poster_id]['sig'] && $row['enable_sig'] && empty($user_cache[$poster_id]['sig_parsed']))
 1507      {
 1508          $parse_flags = ($user_cache[$poster_id]['sig_bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0) | OPTION_FLAG_SMILIES;
 1509          $user_cache[$poster_id]['sig'] = generate_text_for_display($user_cache[$poster_id]['sig'], $user_cache[$poster_id]['sig_bbcode_uid'], $user_cache[$poster_id]['sig_bbcode_bitfield'],  $parse_flags, true);
 1510      }
 1511   
 1512      // Parse the message and subject
 1513      $parse_flags = ($row['bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0) | OPTION_FLAG_SMILIES;
 1514      $message = generate_text_for_display($row['post_text'], $row['bbcode_uid'], $row['bbcode_bitfield'], $parse_flags, true);
 1515   
 1516      if (!empty($attachments[$row['post_id']]))
 1517      {
 1518          parse_attachments($forum_id, $message, $attachments[$row['post_id']], $update_count);
 1519      }
 1520   
 1521      // Replace naughty words such as farty pants
 1522      $row['post_subject'] = censor_text($row['post_subject']);
 1523   
 1524      // Highlight active words (primarily for search)
 1525      if ($highlight_match)
 1526      {
 1527          $message = preg_replace('#(?!<.*)(?<!\w)(' . $highlight_match . ')(?!\w|[^<>]*(?:</s(?:cript|tyle))?>)#is', '<span class="posthilit">\1</span>', $message);
 1528          $row['post_subject'] = preg_replace('#(?!<.*)(?<!\w)(' . $highlight_match . ')(?!\w|[^<>]*(?:</s(?:cript|tyle))?>)#is', '<span class="posthilit">\1</span>', $row['post_subject']);
 1529      }
 1530   
 1531      // Editing information
 1532      if (($row['post_edit_count'] && $config['display_last_edited']) || $row['post_edit_reason'])
 1533      {
 1534          // Get usernames for all following posts if not already stored
 1535          if (!sizeof($post_edit_list) && ($row['post_edit_reason'] || ($row['post_edit_user'] && !isset($user_cache[$row['post_edit_user']]))))
 1536          {
 1537              // Remove all post_ids already parsed (we do not have to check them)
 1538              $post_storage_list = (!$store_reverse) ? array_slice($post_list, $i) : array_slice(array_reverse($post_list), $i);
 1539   
 1540              $sql = 'SELECT DISTINCT u.user_id, u.username, u.user_colour
 1541                  FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
 1542                  WHERE ' . $db->sql_in_set('p.post_id', $post_storage_list) . '
 1543                      AND p.post_edit_count <> 0
 1544                      AND p.post_edit_user <> 0
 1545                      AND p.post_edit_user = u.user_id';
 1546              $result2 = $db->sql_query($sql);
 1547              while ($user_edit_row = $db->sql_fetchrow($result2))
 1548              {
 1549                  $post_edit_list[$user_edit_row['user_id']] = $user_edit_row;
 1550              }
 1551              $db->sql_freeresult($result2);
 1552   
 1553              unset($post_storage_list);
 1554          }
 1555   
 1556          if ($row['post_edit_reason'])
 1557          {
 1558              // User having edited the post also being the post author?
 1559              if (!$row['post_edit_user'] || $row['post_edit_user'] == $poster_id)
 1560              {
 1561                  $display_username = get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']);
 1562              }
 1563              else
 1564              {
 1565                  $display_username = get_username_string('full', $row['post_edit_user'], $post_edit_list[$row['post_edit_user']]['username'], $post_edit_list[$row['post_edit_user']]['user_colour']);
 1566              }
 1567   
 1568              $l_edited_by = $user->lang('EDITED_TIMES_TOTAL', (int) $row['post_edit_count'], $display_username, $user->format_date($row['post_edit_time'], false, true));
 1569          }
 1570          else
 1571          {
 1572              if ($row['post_edit_user'] && !isset($user_cache[$row['post_edit_user']]))
 1573              {
 1574                  $user_cache[$row['post_edit_user']] = $post_edit_list[$row['post_edit_user']];
 1575              }
 1576   
 1577              // User having edited the post also being the post author?
 1578              if (!$row['post_edit_user'] || $row['post_edit_user'] == $poster_id)
 1579              {
 1580                  $display_username = get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']);
 1581              }
 1582              else
 1583              {
 1584                  $display_username = get_username_string('full', $row['post_edit_user'], $user_cache[$row['post_edit_user']]['username'], $user_cache[$row['post_edit_user']]['user_colour']);
 1585              }
 1586   
 1587              $l_edited_by = $user->lang('EDITED_TIMES_TOTAL', (int) $row['post_edit_count'], $display_username, $user->format_date($row['post_edit_time'], false, true));
 1588          }
 1589      }
 1590      else
 1591      {
 1592          $l_edited_by = '';
 1593      }
 1594   
 1595      // Deleting information
 1596      if ($row['post_visibility'] == ITEM_DELETED && $row['post_delete_user'])
 1597      {
 1598          // Get usernames for all following posts if not already stored
 1599          if (!sizeof($post_delete_list) && ($row['post_delete_reason'] || ($row['post_delete_user'] && !isset($user_cache[$row['post_delete_user']]))))
 1600          {
 1601              // Remove all post_ids already parsed (we do not have to check them)
 1602              $post_storage_list = (!$store_reverse) ? array_slice($post_list, $i) : array_slice(array_reverse($post_list), $i);
 1603   
 1604              $sql = 'SELECT DISTINCT u.user_id, u.username, u.user_colour
 1605                  FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
 1606                  WHERE ' . $db->sql_in_set('p.post_id', $post_storage_list) . '
 1607                      AND p.post_delete_user <> 0
 1608                      AND p.post_delete_user = u.user_id';
 1609              $result2 = $db->sql_query($sql);
 1610              while ($user_delete_row = $db->sql_fetchrow($result2))
 1611              {
 1612                  $post_delete_list[$user_delete_row['user_id']] = $user_delete_row;
 1613              }
 1614              $db->sql_freeresult($result2);
 1615   
 1616              unset($post_storage_list);
 1617          }
 1618   
 1619          if ($row['post_delete_user'] && !isset($user_cache[$row['post_delete_user']]))
 1620          {
 1621              $user_cache[$row['post_delete_user']] = $post_delete_list[$row['post_delete_user']];
 1622          }
 1623   
 1624          $display_postername = get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']);
 1625   
 1626          // User having deleted the post also being the post author?
 1627          if (!$row['post_delete_user'] || $row['post_delete_user'] == $poster_id)
 1628          {
 1629              $display_username = $display_postername;
 1630          }
 1631          else
 1632          {
 1633              $display_username = get_username_string('full', $row['post_delete_user'], $user_cache[$row['post_delete_user']]['username'], $user_cache[$row['post_delete_user']]['user_colour']);
 1634          }
 1635   
 1636          if ($row['post_delete_reason'])
 1637          {
 1638              $l_deleted_message = $user->lang('POST_DELETED_BY_REASON', $display_postername, $display_username, $user->format_date($row['post_delete_time'], false, true), $row['post_delete_reason']);
 1639          }
 1640          else
 1641          {
 1642              $l_deleted_message = $user->lang('POST_DELETED_BY', $display_postername, $display_username, $user->format_date($row['post_delete_time'], false, true));
 1643          }
 1644          $l_deleted_by = $user->lang('DELETED_INFORMATION', $display_username, $user->format_date($row['post_delete_time'], false, true));
 1645      }
 1646      else
 1647      {
 1648          $l_deleted_by = $l_deleted_message = '';
 1649      }
 1650   
 1651      // Bump information
 1652      if ($topic_data['topic_bumped'] && $row['post_id'] == $topic_data['topic_last_post_id'] && isset($user_cache[$topic_data['topic_bumper']]) )
 1653      {
 1654          // It is safe to grab the username from the user cache array, we are at the last
 1655          // post and only the topic poster and last poster are allowed to bump.
 1656          // Admins and mods are bound to the above rules too...
 1657          $l_bumped_by = sprintf($user->lang['BUMPED_BY'], $user_cache[$topic_data['topic_bumper']]['username'], $user->format_date($topic_data['topic_last_post_time'], false, true));
 1658      }
 1659      else
 1660      {
 1661          $l_bumped_by = '';
 1662      }
 1663   
 1664      $cp_row = array();
 1665   
 1666      //
 1667      if ($config['load_cpf_viewtopic'])
 1668      {
 1669          $cp_row = (isset($profile_fields_cache[$poster_id])) ? $cp->generate_profile_fields_template_data($profile_fields_cache[$poster_id]) : array();
 1670      }
 1671   
 1672      $post_unread = (isset($topic_tracking_info[$topic_id]) && $row['post_time'] > $topic_tracking_info[$topic_id]) ? true : false;
 1673   
 1674      $s_first_unread = false;
 1675      if (!$first_unread && $post_unread)
 1676      {
 1677          $s_first_unread = $first_unread = true;
 1678      }
 1679   
 1680      $force_edit_allowed = $force_delete_allowed = false;
 1681   
 1682      $s_cannot_edit = !$auth->acl_get('f_edit', $forum_id) || $user->data['user_id'] != $poster_id;
 1683      $s_cannot_edit_time = $config['edit_time'] && $row['post_time'] <= time() - ($config['edit_time'] * 60);
 1684      $s_cannot_edit_locked = $topic_data['topic_status'] == ITEM_LOCKED || $row['post_edit_locked'];
 1685   
 1686      $s_cannot_delete = $user->data['user_id'] != $poster_id || (
 1687              !$auth->acl_get('f_delete', $forum_id) &&
 1688              (!$auth->acl_get('f_softdelete', $forum_id) || $row['post_visibility'] == ITEM_DELETED)
 1689      );
 1690      $s_cannot_delete_lastpost = $topic_data['topic_last_post_id'] != $row['post_id'];
 1691      $s_cannot_delete_time = $config['delete_time'] && $row['post_time'] <= time() - ($config['delete_time'] * 60);
 1692      // we do not want to allow removal of the last post if a moderator locked it!
 1693      $s_cannot_delete_locked = $topic_data['topic_status'] == ITEM_LOCKED || $row['post_edit_locked'];
 1694   
 1695      /**
 1696      * This event allows you to modify the conditions for the "can edit post" and "can delete post" checks
 1697      *
 1698      * @event core.viewtopic_modify_post_action_conditions
 1699      * @var    array    row            Array with post data
 1700      * @var    array    topic_data    Array with topic data
 1701      * @var    bool    force_edit_allowed        Allow the user to edit the post (all permissions and conditions are ignored)
 1702      * @var    bool    s_cannot_edit            User can not edit the post because it's not his
 1703      * @var    bool    s_cannot_edit_locked    User can not edit the post because it's locked
 1704      * @var    bool    s_cannot_edit_time        User can not edit the post because edit_time has passed
 1705      * @var    bool    force_delete_allowed        Allow the user to delete the post (all permissions and conditions are ignored)
 1706      * @var    bool    s_cannot_delete                User can not delete the post because it's not his
 1707      * @var    bool    s_cannot_delete_lastpost    User can not delete the post because it's not the last post of the topic
 1708      * @var    bool    s_cannot_delete_locked        User can not delete the post because it's locked
 1709      * @var    bool    s_cannot_delete_time        User can not delete the post because edit_time has passed
 1710      * @since 3.1.0-b4
 1711      */
 1712      $vars = array(
 1713          'row',
 1714          'topic_data',
 1715          'force_edit_allowed',
 1716          's_cannot_edit',
 1717          's_cannot_edit_locked',
 1718          's_cannot_edit_time',
 1719          'force_delete_allowed',
 1720          's_cannot_delete',
 1721          's_cannot_delete_lastpost',
 1722          's_cannot_delete_locked',
 1723          's_cannot_delete_time',
 1724      );
 1725      extract($phpbb_dispatcher->trigger_event('core.viewtopic_modify_post_action_conditions', compact($vars)));
 1726   
 1727      $edit_allowed = $force_edit_allowed || ($user->data['is_registered'] && ($auth->acl_get('m_edit', $forum_id) || (
 1728          !$s_cannot_edit &&
 1729          !$s_cannot_edit_time &&
 1730          !$s_cannot_edit_locked
 1731      )));
 1732   
 1733      $quote_allowed = $auth->acl_get('m_edit', $forum_id) || ($topic_data['topic_status'] != ITEM_LOCKED &&
 1734          ($user->data['user_id'] == ANONYMOUS || $auth->acl_get('f_reply', $forum_id))
 1735      );
 1736   
 1737      $delete_allowed = $force_delete_allowed || ($user->data['is_registered'] && (
 1738          ($auth->acl_get('m_delete', $forum_id) || ($auth->acl_get('m_softdelete', $forum_id) && $row['post_visibility'] != ITEM_DELETED)) ||
 1739          (!$s_cannot_delete && !$s_cannot_delete_lastpost && !$s_cannot_delete_time && !$s_cannot_delete_locked)
 1740      ));
 1741   
 1742      // Can this user receive a Private Message?
 1743      $can_receive_pm = (
 1744          // They must be a "normal" user
 1745          $user_cache[$poster_id]['user_type'] != USER_IGNORE &&
 1746   
 1747          // They must not be deactivated by the administrator
 1748          ($user_cache[$poster_id]['user_type'] != USER_INACTIVE || $user_cache[$poster_id]['user_inactive_reason'] != INACTIVE_MANUAL) &&
 1749   
 1750          // They must be able to read PMs
 1751          in_array($poster_id, $can_receive_pm_list) &&
 1752   
 1753          // They must not be permanently banned
 1754          !in_array($poster_id, $permanently_banned_users) &&
 1755   
 1756          // They must allow users to contact via PM
 1757          (($auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_')) || $user_cache[$poster_id]['allow_pm'])
 1758      );
 1759   
 1760      $u_pm = '';
 1761   
 1762      if ($config['allow_privmsg'] && $auth->acl_get('u_sendpm') && $can_receive_pm)
 1763      {
 1764          $u_pm = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;mode=compose&amp;action=quotepost&amp;p=' . $row['post_id']);
 1765      }
 1766   
 1767      //
 1768      $post_row = array(
 1769          'POST_AUTHOR_FULL'        => ($poster_id != ANONYMOUS) ? $user_cache[$poster_id]['author_full'] : get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
 1770          'POST_AUTHOR_COLOUR'    => ($poster_id != ANONYMOUS) ? $user_cache[$poster_id]['author_colour'] : get_username_string('colour', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
 1771          'POST_AUTHOR'            => ($poster_id != ANONYMOUS) ? $user_cache[$poster_id]['author_username'] : get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
 1772          'U_POST_AUTHOR'            => ($poster_id != ANONYMOUS) ? $user_cache[$poster_id]['author_profile'] : get_username_string('profile', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
 1773   
 1774          'RANK_TITLE'        => $user_cache[$poster_id]['rank_title'],
 1775          'RANK_IMG'            => $user_cache[$poster_id]['rank_image'],
 1776          'RANK_IMG_SRC'        => $user_cache[$poster_id]['rank_image_src'],
 1777          'POSTER_JOINED'        => $user_cache[$poster_id]['joined'],
 1778          'POSTER_POSTS'        => $user_cache[$poster_id]['posts'],
 1779          'POSTER_AVATAR'        => $user_cache[$poster_id]['avatar'],
 1780          'POSTER_WARNINGS'    => $auth->acl_get('m_warn') ? $user_cache[$poster_id]['warnings'] : '',
 1781          'POSTER_AGE'        => $user_cache[$poster_id]['age'],
 1782          'CONTACT_USER'        => $user_cache[$poster_id]['contact_user'],
 1783   
 1784          'POST_DATE'            => $user->format_date($row['post_time'], false, ($view == 'print') ? true : false),
 1785          'POST_SUBJECT'        => $row['post_subject'],
 1786          'MESSAGE'            => $message,
 1787          'SIGNATURE'            => ($row['enable_sig']) ? $user_cache[$poster_id]['sig'] : '',
 1788          'EDITED_MESSAGE'    => $l_edited_by,
 1789          'EDIT_REASON'        => $row['post_edit_reason'],
 1790          'DELETED_MESSAGE'    => $l_deleted_by,
 1791          'DELETE_REASON'        => $row['post_delete_reason'],
 1792          'BUMPED_MESSAGE'    => $l_bumped_by,
 1793   
 1794          'MINI_POST_IMG'            => ($post_unread) ? $user->img('icon_post_target_unread', 'UNREAD_POST') : $user->img('icon_post_target', 'POST'),
 1795          'POST_ICON_IMG'            => ($topic_data['enable_icons'] && !empty($row['icon_id'])) ? $icons[$row['icon_id']]['img'] : '',
 1796          'POST_ICON_IMG_WIDTH'    => ($topic_data['enable_icons'] && !empty($row['icon_id'])) ? $icons[$row['icon_id']]['width'] : '',
 1797          'POST_ICON_IMG_HEIGHT'    => ($topic_data['enable_icons'] && !empty($row['icon_id'])) ? $icons[$row['icon_id']]['height'] : '',
 1798          'ONLINE_IMG'            => ($poster_id == ANONYMOUS || !$config['load_onlinetrack']) ? '' : (($user_cache[$poster_id]['online']) ? $user->img('icon_user_online', 'ONLINE') : $user->img('icon_user_offline', 'OFFLINE')),
 1799          'S_ONLINE'                => ($poster_id == ANONYMOUS || !$config['load_onlinetrack']) ? false : (($user_cache[$poster_id]['online']) ? true : false),
 1800   
 1801          'U_EDIT'            => ($edit_allowed) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=edit&amp;f=$forum_id&amp;p={$row['post_id']}") : '',
 1802          'U_QUOTE'            => ($quote_allowed) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=quote&amp;f=$forum_id&amp;p={$row['post_id']}") : '',
 1803          'U_INFO'            => ($auth->acl_get('m_info', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "i=main&amp;mode=post_details&amp;f=$forum_id&amp;p=" . $row['post_id'], true, $user->session_id) : '',
 1804          'U_DELETE'            => ($delete_allowed) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=delete&amp;f=$forum_id&amp;p={$row['post_id']}") : '',
 1805   
 1806          'U_SEARCH'        => $user_cache[$poster_id]['search'],
 1807          'U_PM'            => $u_pm,
 1808          'U_EMAIL'        => $user_cache[$poster_id]['email'],
 1809          'U_JABBER'        => $user_cache[$poster_id]['jabber'],
 1810   
 1811          'U_APPROVE_ACTION'        => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=queue&amp;p={$row['post_id']}&amp;f=$forum_id&amp;redirect=" . urlencode(str_replace('&amp;', '&', $viewtopic_url . '&amp;p=' . $row['post_id'] . '#p' . $row['post_id']))),
 1812          'U_REPORT'            => ($auth->acl_get('f_report', $forum_id)) ? append_sid("{$phpbb_root_path}report.$phpEx", 'f=' . $forum_id . '&amp;p=' . $row['post_id']) : '',
 1813          'U_MCP_REPORT'        => ($auth->acl_get('m_report', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&amp;mode=report_details&amp;f=' . $forum_id . '&amp;p=' . $row['post_id'], true, $user->session_id) : '',
 1814          'U_MCP_APPROVE'        => ($auth->acl_get('m_approve', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&amp;mode=approve_details&amp;f=' . $forum_id . '&amp;p=' . $row['post_id'], true, $user->session_id) : '',
 1815          'U_MCP_RESTORE'        => ($auth->acl_get('m_approve', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&amp;mode=' . (($topic_data['topic_visibility'] != ITEM_DELETED) ? 'deleted_posts' : 'deleted_topics') . '&amp;f=' . $forum_id . '&amp;p=' . $row['post_id'], true, $user->session_id) : '',
 1816          'U_MINI_POST'        => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'p=' . $row['post_id']) . '#p' . $row['post_id'],
 1817          'U_NEXT_POST_ID'    => ($i < $i_total && isset($rowset[$post_list[$i + 1]])) ? $rowset[$post_list[$i + 1]]['post_id'] : '',
 1818          'U_PREV_POST_ID'    => $prev_post_id,
 1819          'U_NOTES'            => ($auth->acl_getf_global('m_')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&amp;mode=user_notes&amp;u=' . $poster_id, true, $user->session_id) : '',
 1820          'U_WARN'            => ($auth->acl_get('m_warn') && $poster_id != $user->data['user_id'] && $poster_id != ANONYMOUS) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&amp;mode=warn_post&amp;f=' . $forum_id . '&amp;p=' . $row['post_id'], true, $user->session_id) : '',
 1821   
 1822          'POST_ID'            => $row['post_id'],
 1823          'POST_NUMBER'        => $i + $start + 1,
 1824          'POSTER_ID'            => $poster_id,
 1825   
 1826          'S_HAS_ATTACHMENTS'    => (!empty($attachments[$row['post_id']])) ? true : false,
 1827          'S_MULTIPLE_ATTACHMENTS'    => !empty($attachments[$row['post_id']]) && sizeof($attachments[$row['post_id']]) > 1,
 1828          'S_POST_UNAPPROVED'    => ($row['post_visibility'] == ITEM_UNAPPROVED || $row['post_visibility'] == ITEM_REAPPROVE) ? true : false,
 1829          'S_POST_DELETED'    => ($row['post_visibility'] == ITEM_DELETED) ? true : false,
 1830          'L_POST_DELETED_MESSAGE'    => $l_deleted_message,
 1831          'S_POST_REPORTED'    => ($row['post_reported'] && $auth->acl_get('m_report', $forum_id)) ? true : false,
 1832          'S_DISPLAY_NOTICE'    => $display_notice && $row['post_attachment'],
 1833          'S_FRIEND'            => ($row['friend']) ? true : false,
 1834          'S_UNREAD_POST'        => $post_unread,
 1835          'S_FIRST_UNREAD'    => $s_first_unread,
 1836          'S_CUSTOM_FIELDS'    => (isset($cp_row['row']) && sizeof($cp_row['row'])) ? true : false,
 1837          'S_TOPIC_POSTER'    => ($topic_data['topic_poster'] == $poster_id) ? true : false,
 1838   
 1839          'S_IGNORE_POST'        => ($row['foe']) ? true : false,
 1840          'L_IGNORE_POST'        => ($row['foe']) ? sprintf($user->lang['POST_BY_FOE'], get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username'])) : '',
 1841          'S_POST_HIDDEN'        => $row['hide_post'],
 1842          'L_POST_DISPLAY'    => ($row['hide_post']) ? $user->lang('POST_DISPLAY', '<a class="display_post" data-post-id="' . $row['post_id'] . '" href="' . $viewtopic_url . "&amp;p={$row['post_id']}&amp;view=show#p{$row['post_id']}" . '">', '</a>') : '',
 1843      );
 1844   
 1845      $user_poster_data = $user_cache[$poster_id];
 1846   
 1847      $current_row_number = $i;
 1848   
 1849      /**
 1850      * Modify the posts template block
 1851      *
 1852      * @event core.viewtopic_modify_post_row
 1853      * @var    int        start                Start item of this page
 1854      * @var    int        current_row_number    Number of the post on this page
 1855      * @var    int        end                    Number of posts on this page
 1856      * @var    int        total_posts            Total posts count
 1857      * @var    int        poster_id            Post author id
 1858      * @var    array    row                    Array with original post and user data
 1859      * @var    array    cp_row                Custom profile field data of the poster
 1860      * @var    array    attachments            List of attachments
 1861      * @var    array    user_poster_data    Poster's data from user cache
 1862      * @var    array    post_row            Template block array of the post
 1863      * @var    array    topic_data            Array with topic data
 1864      * @since 3.1.0-a1
 1865      * @change 3.1.0-a3 Added vars start, current_row_number, end, attachments
 1866      * @change 3.1.0-b3 Added topic_data array, total_posts
 1867      * @change 3.1.0-RC3 Added poster_id
 1868      */
 1869      $vars = array(
 1870          'start',
 1871          'current_row_number',
 1872          'end',
 1873          'total_posts',
 1874          'poster_id',
 1875          'row',
 1876          'cp_row',
 1877          'attachments',
 1878          'user_poster_data',
 1879          'post_row',
 1880          'topic_data',
 1881      );
 1882      extract($phpbb_dispatcher->trigger_event('core.viewtopic_modify_post_row', compact($vars)));
 1883   
 1884      $i = $current_row_number;
 1885   
 1886      if (isset($cp_row['row']) && sizeof($cp_row['row']))
 1887      {
 1888          $post_row = array_merge($post_row, $cp_row['row']);
 1889      }
 1890   
 1891      // Dump vars into template
 1892      $template->assign_block_vars('postrow', $post_row);
 1893   
 1894      $contact_fields = array(
 1895          array(
 1896              'ID'        => 'pm',
 1897              'NAME'         => $user->lang['SEND_PRIVATE_MESSAGE'],
 1898              'U_CONTACT'    => $u_pm,
 1899          ),
 1900          array(
 1901              'ID'        => 'email',
 1902              'NAME'        => $user->lang['SEND_EMAIL'],
 1903              'U_CONTACT'    => $user_cache[$poster_id]['email'],
 1904          ),
 1905          array(
 1906              'ID'        => 'jabber',
 1907              'NAME'        => $user->lang['JABBER'],
 1908              'U_CONTACT'    => $user_cache[$poster_id]['jabber'],
 1909          ),
 1910      );
 1911   
 1912      foreach ($contact_fields as $field)
 1913      {
 1914          if ($field['U_CONTACT'])
 1915          {
 1916              $template->assign_block_vars('postrow.contact', $field);
 1917          }
 1918      }
 1919   
 1920      if (!empty($cp_row['blockrow']))
 1921      {
 1922          foreach ($cp_row['blockrow'] as $field_data)
 1923          {
 1924              $template->assign_block_vars('postrow.custom_fields', $field_data);
 1925   
 1926              if ($field_data['S_PROFILE_CONTACT'])
 1927              {
 1928                  $template->assign_block_vars('postrow.contact', array(
 1929                      'ID'        => $field_data['PROFILE_FIELD_IDENT'],
 1930                      'NAME'        => $field_data['PROFILE_FIELD_NAME'],
 1931                      'U_CONTACT'    => $field_data['PROFILE_FIELD_CONTACT'],
 1932                  ));
 1933              }
 1934          }
 1935      }
 1936   
 1937      // Display not already displayed Attachments for this post, we already parsed them. ;)
 1938      if (!empty($attachments[$row['post_id']]))
 1939      {
 1940          foreach ($attachments[$row['post_id']] as $attachment)
 1941          {
 1942              $template->assign_block_vars('postrow.attachment', array(
 1943                  'DISPLAY_ATTACHMENT'    => $attachment)
 1944              );
 1945          }
 1946      }
 1947   
 1948      $current_row_number = $i;
 1949   
 1950      /**
 1951      * Event after the post data has been assigned to the template
 1952      *
 1953      * @event core.viewtopic_post_row_after
 1954      * @var    int        start                Start item of this page
 1955      * @var    int        current_row_number    Number of the post on this page
 1956      * @var    int        end                    Number of posts on this page
 1957      * @var    int        total_posts            Total posts count
 1958      * @var    array    row                    Array with original post and user data
 1959      * @var    array    cp_row                Custom profile field data of the poster
 1960      * @var    array    attachments            List of attachments
 1961      * @var    array    user_poster_data    Poster's data from user cache
 1962      * @var    array    post_row            Template block array of the post
 1963      * @var    array    topic_data            Array with topic data
 1964      * @since 3.1.0-a3
 1965      * @change 3.1.0-b3 Added topic_data array, total_posts
 1966      */
 1967      $vars = array(
 1968          'start',
 1969          'current_row_number',
 1970          'end',
 1971          'total_posts',
 1972          'row',
 1973          'cp_row',
 1974          'attachments',
 1975          'user_poster_data',
 1976          'post_row',
 1977          'topic_data',
 1978      );
 1979      extract($phpbb_dispatcher->trigger_event('core.viewtopic_post_row_after', compact($vars)));
 1980   
 1981      $i = $current_row_number;
 1982   
 1983      $prev_post_id = $row['post_id'];
 1984   
 1985      unset($rowset[$post_list[$i]]);
 1986      unset($attachments[$row['post_id']]);
 1987  }
 1988  unset($rowset, $user_cache);
 1989   
 1990  // Update topic view and if necessary attachment view counters ... but only for humans and if this is the first 'page view'
 1991  if (isset($user->data['session_page']) && !$user->data['is_bot'] && (strpos($user->data['session_page'], '&t=' . $topic_id) === false || isset($user->data['session_created'])))
 1992  {
 1993      $sql = 'UPDATE ' . TOPICS_TABLE . '
 1994          SET topic_views = topic_views + 1, topic_last_view_time = ' . time() . "
 1995          WHERE topic_id = $topic_id";
 1996      $db->sql_query($sql);
 1997   
 1998      // Update the attachment download counts
 1999      if (sizeof($update_count))
 2000      {
 2001          $sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
 2002              SET download_count = download_count + 1
 2003              WHERE ' . $db->sql_in_set('attach_id', array_unique($update_count));
 2004          $db->sql_query($sql);
 2005      }
 2006  }
 2007   
 2008  // Only mark topic if it's currently unread. Also make sure we do not set topic tracking back if earlier pages are viewed.
 2009  if (isset($topic_tracking_info[$topic_id]) && $topic_data['topic_last_post_time'] > $topic_tracking_info[$topic_id] && $max_post_time > $topic_tracking_info[$topic_id])
 2010  {
 2011      markread('topic', $forum_id, $topic_id, $max_post_time);
 2012   
 2013      // Update forum info
 2014      $all_marked_read = update_forum_tracking_info($forum_id, $topic_data['forum_last_post_time'], (isset($topic_data['forum_mark_time'])) ? $topic_data['forum_mark_time'] : false, false);
 2015  }
 2016  else
 2017  {
 2018      $all_marked_read = true;
 2019  }
 2020   
 2021  // If there are absolutely no more unread posts in this forum
 2022  // and unread posts shown, we can safely show the #unread link
 2023  if ($all_marked_read)
 2024  {
 2025      if ($post_unread)
 2026      {
 2027          $template->assign_vars(array(
 2028              'U_VIEW_UNREAD_POST'    => '#unread',
 2029          ));
 2030      }
 2031      else if (isset($topic_tracking_info[$topic_id]) && $topic_data['topic_last_post_time'] > $topic_tracking_info[$topic_id])
 2032      {
 2033          $template->assign_vars(array(
 2034              'U_VIEW_UNREAD_POST'    => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id&amp;view=unread") . '#unread',
 2035          ));
 2036      }
 2037  }
 2038  else if (!$all_marked_read)
 2039  {
 2040      $last_page = ((floor($start / $config['posts_per_page']) + 1) == max(ceil($total_posts / $config['posts_per_page']), 1)) ? true : false;
 2041   
 2042      // What can happen is that we are at the last displayed page. If so, we also display the #unread link based in $post_unread
 2043      if ($last_page && $post_unread)
 2044      {
 2045          $template->assign_vars(array(
 2046              'U_VIEW_UNREAD_POST'    => '#unread',
 2047          ));
 2048      }
 2049      else if (!$last_page)
 2050      {
 2051          $template->assign_vars(array(
 2052              'U_VIEW_UNREAD_POST'    => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id&amp;view=unread") . '#unread',
 2053          ));
 2054      }
 2055  }
 2056   
 2057  // let's set up quick_reply
 2058  $s_quick_reply = false;
 2059  if ($user->data['is_registered'] && $config['allow_quick_reply'] && ($topic_data['forum_flags'] & FORUM_FLAG_QUICK_REPLY) && $auth->acl_get('f_reply', $forum_id))
 2060  {
 2061      // Quick reply enabled forum
 2062      $s_quick_reply = (($topic_data['forum_status'] == ITEM_UNLOCKED && $topic_data['topic_status'] == ITEM_UNLOCKED) || $auth->acl_get('m_edit', $forum_id)) ? true : false;
 2063  }
 2064   
 2065  if ($s_can_vote || $s_quick_reply)
 2066  {
 2067      add_form_key('posting');
 2068   
 2069      if ($s_quick_reply)
 2070      {
 2071          $s_attach_sig    = $config['allow_sig'] && $user->optionget('attachsig') && $auth->acl_get('f_sigs', $forum_id) && $auth->acl_get('u_sig');
 2072          $s_smilies        = $config['allow_smilies'] && $user->optionget('smilies') && $auth->acl_get('f_smilies', $forum_id);
 2073          $s_bbcode        = $config['allow_bbcode'] && $user->optionget('bbcode') && $auth->acl_get('f_bbcode', $forum_id);
 2074          $s_notify        = $config['allow_topic_notify'] && ($user->data['user_notify'] || $s_watching_topic['is_watching']);
 2075   
 2076          $qr_hidden_fields = array(
 2077              'topic_cur_post_id'        => (int) $topic_data['topic_last_post_id'],
 2078              'lastclick'                => (int) time(),
 2079              'topic_id'                => (int) $topic_data['topic_id'],
 2080              'forum_id'                => (int) $forum_id,
 2081          );
 2082   
 2083          // Originally we use checkboxes and check with isset(), so we only provide them if they would be checked
 2084          (!$s_bbcode)                    ? $qr_hidden_fields['disable_bbcode'] = 1        : true;
 2085          (!$s_smilies)                    ? $qr_hidden_fields['disable_smilies'] = 1        : true;
 2086          (!$config['allow_post_links'])    ? $qr_hidden_fields['disable_magic_url'] = 1    : true;
 2087          ($s_attach_sig)                    ? $qr_hidden_fields['attach_sig'] = 1            : true;
 2088          ($s_notify)                        ? $qr_hidden_fields['notify'] = 1                : true;
 2089          ($topic_data['topic_status'] == ITEM_LOCKED) ? $qr_hidden_fields['lock_topic'] = 1 : true;
 2090   
 2091          $template->assign_vars(array(
 2092              'S_QUICK_REPLY'            => true,
 2093              'U_QR_ACTION'            => append_sid("{$phpbb_root_path}posting.$phpEx", "mode=reply&amp;f=$forum_id&amp;t=$topic_id"),
 2094              'QR_HIDDEN_FIELDS'        => build_hidden_fields($qr_hidden_fields),
 2095              'SUBJECT'                => 'Re: ' . censor_text($topic_data['topic_title']),
 2096          ));
 2097      }
 2098  }
 2099  // now I have the urge to wash my hands :(
 2100   
 2101   
 2102  // We overwrite $_REQUEST['f'] if there is no forum specified
 2103  // to be able to display the correct online list.
 2104  // One downside is that the user currently viewing this topic/post is not taken into account.
 2105  if (!request_var('f', 0))
 2106  {
 2107      $request->overwrite('f', $forum_id);
 2108  }
 2109   
 2110  // We need to do the same with the topic_id. See #53025.
 2111  if (!request_var('t', 0) && !empty($topic_id))
 2112  {
 2113      $request->overwrite('t', $topic_id);
 2114  }
 2115   
 2116  $page_title = $topic_data['topic_title'] . ($start ? ' - ' . sprintf($user->lang['PAGE_TITLE_NUMBER'], $pagination->get_on_page($config['posts_per_page'], $start)) : '');
 2117   
 2118  /**
 2119  * You can use this event to modify the page title of the viewtopic page
 2120  *
 2121  * @event core.viewtopic_modify_page_title
 2122  * @var    string    page_title        Title of the viewtopic page
 2123  * @var    array    topic_data        Array with topic data
 2124  * @var    int        forum_id        Forum ID of the topic
 2125  * @var    int        start            Start offset used to calculate the page
 2126  * @var    array    post_list        Array with post_ids we are going to display
 2127  * @since 3.1.0-a1
 2128  * @change 3.1.0-RC4 Added post_list var
 2129  */
 2130  $vars = array('page_title', 'topic_data', 'forum_id', 'start', 'post_list');
 2131  extract($phpbb_dispatcher->trigger_event('core.viewtopic_modify_page_title', compact($vars)));
 2132   
 2133  // Output the page
 2134  page_header($page_title, true, $forum_id);
 2135   
 2136  $template->set_filenames(array(
 2137      'body' => ($view == 'print') ? 'viewtopic_print.html' : 'viewtopic_body.html')
 2138  );
 2139  make_jumpbox(append_sid("{$phpbb_root_path}viewforum.$phpEx"), $forum_id);
 2140   
 2141  page_footer();
 2142