Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

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

functions_posting.php

Zuletzt modifiziert: 02.04.2025, 15:01 - Dateigröße: 91.67 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  if (!defined('IN_PHPBB'))
0018  {
0019      exit;
0020  }
0021   
0022  /**
0023  * Fill smiley templates (or just the variables) with smilies, either in a window or inline
0024  */
0025  function generate_smilies($mode, $forum_id)
0026  {
0027      global $db, $user, $config, $template, $phpbb_dispatcher, $request;
0028      global $phpEx, $phpbb_root_path, $phpbb_container, $phpbb_path_helper;
0029   
0030      /* @var $pagination \phpbb\pagination */
0031      $pagination = $phpbb_container->get('pagination');
0032      $base_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&amp;f=' . $forum_id);
0033      $start = $request->variable('start', 0);
0034   
0035      if ($mode == 'window')
0036      {
0037          if ($forum_id)
0038          {
0039              $sql = 'SELECT forum_style
0040                  FROM ' . FORUMS_TABLE . "
0041                  WHERE forum_id = $forum_id";
0042              $result = $db->sql_query_limit($sql, 1);
0043              $row = $db->sql_fetchrow($result);
0044              $db->sql_freeresult($result);
0045   
0046              $user->setup('posting', (int) $row['forum_style']);
0047          }
0048          else
0049          {
0050              $user->setup('posting');
0051          }
0052   
0053          page_header($user->lang['SMILIES']);
0054   
0055          $sql_ary = [
0056              'SELECT'    => 'COUNT(s.smiley_id) AS item_count',
0057              'FROM'        => [
0058                  SMILIES_TABLE => 's',
0059              ],
0060              'GROUP_BY'    => 's.smiley_url',
0061          ];
0062   
0063          /**
0064          * Modify SQL query that fetches the total number of smilies in window mode
0065          *
0066          * @event core.generate_smilies_count_sql_before
0067          * @var int        forum_id    Forum where smilies are generated
0068          * @var array    sql_ary        Array with the SQL query
0069          * @var string    base_url    URL for the "More smilies" link and its pagination
0070          * @since 3.2.9-RC1
0071          * @changed 3.2.10-RC1 Added base_url
0072          */
0073          $vars = [
0074              'forum_id',
0075              'sql_ary',
0076              'base_url',
0077          ];
0078          extract($phpbb_dispatcher->trigger_event('core.generate_smilies_count_sql_before', compact($vars)));
0079   
0080          $sql = $db->sql_build_query('SELECT', $sql_ary);
0081          $result = $db->sql_query($sql, 3600);
0082   
0083          $smiley_count = 0;
0084          while ($row = $db->sql_fetchrow($result))
0085          {
0086              ++$smiley_count;
0087          }
0088          $db->sql_freeresult($result);
0089   
0090          $template->set_filenames(array(
0091              'body' => 'posting_smilies.html')
0092          );
0093   
0094          $start = $pagination->validate_start($start, $config['smilies_per_page'], $smiley_count);
0095          $pagination->generate_template_pagination($base_url, 'pagination', 'start', $smiley_count, $config['smilies_per_page'], $start);
0096      }
0097   
0098      $display_link = false;
0099      if ($mode == 'inline')
0100      {
0101          $sql = 'SELECT smiley_id
0102              FROM ' . SMILIES_TABLE . '
0103              WHERE display_on_posting = 0';
0104          $result = $db->sql_query_limit($sql, 1, 0, 3600);
0105   
0106          if ($row = $db->sql_fetchrow($result))
0107          {
0108              $display_link = true;
0109          }
0110          $db->sql_freeresult($result);
0111      }
0112   
0113      if ($mode == 'window')
0114      {
0115          $sql_ary = [
0116              'SELECT'    => 's.smiley_url, MIN(s.emotion) AS emotion, MIN(s.code) AS code, s.smiley_width, s.smiley_height, MIN(s.smiley_order) AS min_smiley_order',
0117              'FROM'        => [
0118                  SMILIES_TABLE => 's',
0119              ],
0120              'GROUP_BY'    => 's.smiley_url, s.smiley_width, s.smiley_height',
0121              'ORDER_BY'    => $db->sql_quote('min_smiley_order'),
0122          ];
0123      }
0124      else
0125      {
0126          $sql_ary = [
0127              'SELECT'    => 's.*',
0128              'FROM'        => [
0129                  SMILIES_TABLE => 's',
0130              ],
0131              'WHERE'        => 's.display_on_posting = 1',
0132              'ORDER_BY'    => 's.smiley_order',
0133          ];
0134      }
0135   
0136      /**
0137      * Modify the SQL query that fetches the smilies
0138      *
0139      * @event core.generate_smilies_modify_sql
0140      * @var string    mode        Smiley mode, either window or inline
0141      * @var int        forum_id    Forum where smilies are generated, or 0 if composing a private message
0142      * @var array    sql_ary        Array with SQL query data
0143      * @since 3.2.10-RC1
0144      * @since 3.3.1-RC1
0145      */
0146      $vars = [
0147          'mode',
0148          'forum_id',
0149          'sql_ary',
0150      ];
0151      extract($phpbb_dispatcher->trigger_event('core.generate_smilies_modify_sql', compact($vars)));
0152   
0153      $sql = $db->sql_build_query('SELECT', $sql_ary);
0154   
0155      if ($mode == 'window')
0156      {
0157          $result = $db->sql_query_limit($sql, $config['smilies_per_page'], $start, 3600);
0158      }
0159      else
0160      {
0161          $result = $db->sql_query($sql, 3600);
0162      }
0163   
0164      $smilies = array();
0165      while ($row = $db->sql_fetchrow($result))
0166      {
0167          if (empty($smilies[$row['smiley_url']]))
0168          {
0169              $smilies[$row['smiley_url']] = $row;
0170          }
0171      }
0172      $db->sql_freeresult($result);
0173   
0174      /**
0175      * Modify smilies before they are assigned to the template
0176      *
0177      * @event core.generate_smilies_modify_rowset
0178      * @var string    mode        Smiley mode, either window or inline
0179      * @var int        forum_id    Forum where smilies are generated, or 0 if composing a private message
0180      * @var array    smilies        Smiley rows fetched from the database
0181      * @since 3.2.9-RC1
0182      */
0183      $vars = [
0184          'mode',
0185          'forum_id',
0186          'smilies',
0187      ];
0188      extract($phpbb_dispatcher->trigger_event('core.generate_smilies_modify_rowset', compact($vars)));
0189   
0190      if (count($smilies))
0191      {
0192          $root_path = $phpbb_path_helper->get_web_root_path();
0193   
0194          foreach ($smilies as $row)
0195          {
0196              /**
0197              * Modify smiley root path before populating smiley list
0198              *
0199              * @event core.generate_smilies_before
0200              * @var string  root_path root_path for smilies
0201              * @since 3.1.11-RC1
0202              */
0203              $vars = array('root_path');
0204              extract($phpbb_dispatcher->trigger_event('core.generate_smilies_before', compact($vars)));
0205              $template->assign_block_vars('smiley', array(
0206                  'SMILEY_CODE'    => $row['code'],
0207                  'A_SMILEY_CODE'    => addslashes($row['code']),
0208                  'SMILEY_IMG'    => $root_path . $config['smilies_path'] . '/' . $row['smiley_url'],
0209                  'SMILEY_WIDTH'    => $row['smiley_width'],
0210                  'SMILEY_HEIGHT'    => $row['smiley_height'],
0211                  'SMILEY_DESC'    => $row['emotion'])
0212              );
0213          }
0214      }
0215   
0216      /**
0217      * This event is called after the smilies are populated
0218      *
0219      * @event core.generate_smilies_after
0220      * @var    string    mode            Mode of the smilies: window|inline
0221      * @var    int        forum_id        The forum ID we are currently in
0222      * @var    bool    display_link    Shall we display the "more smilies" link?
0223      * @var string    base_url        URL for the "More smilies" link and its pagination
0224      * @since 3.1.0-a1
0225      * @changed 3.2.10-RC1 Added base_url
0226      */
0227      $vars = [
0228          'mode',
0229          'forum_id',
0230          'display_link',
0231          'base_url',
0232      ];
0233      extract($phpbb_dispatcher->trigger_event('core.generate_smilies_after', compact($vars)));
0234   
0235      if ($mode == 'inline' && $display_link)
0236      {
0237          $template->assign_vars(array(
0238              'S_SHOW_SMILEY_LINK'     => true,
0239              'U_MORE_SMILIES'         => $base_url,
0240          ));
0241      }
0242   
0243      if ($mode == 'window')
0244      {
0245          page_footer();
0246      }
0247  }
0248   
0249  /**
0250  * Update last post information
0251  * Should be used instead of sync() if only the last post information are out of sync... faster
0252  *
0253  * @param    string    $type                Can be forum|topic
0254  * @param    mixed    $ids                topic/forum ids
0255  * @param    bool    $return_update_sql    true: SQL query shall be returned, false: execute SQL
0256  */
0257  function update_post_information($type, $ids, $return_update_sql = false)
0258  {
0259      global $db, $phpbb_dispatcher;
0260   
0261      if (empty($ids))
0262      {
0263          return;
0264      }
0265      if (!is_array($ids))
0266      {
0267          $ids = array($ids);
0268      }
0269   
0270      $update_sql = $empty_forums = $not_empty_forums = array();
0271   
0272      if ($type != 'topic')
0273      {
0274          $topic_join = ', ' . TOPICS_TABLE . ' t';
0275          $topic_condition = 'AND t.topic_id = p.topic_id AND t.topic_visibility = ' . ITEM_APPROVED;
0276      }
0277      else
0278      {
0279          $topic_join = '';
0280          $topic_condition = '';
0281      }
0282   
0283      if (count($ids) == 1)
0284      {
0285          $sql = 'SELECT p.post_id as last_post_id
0286              FROM ' . POSTS_TABLE . " p $topic_join
0287              WHERE " . $db->sql_in_set('p.' . $type . '_id', $ids) . "
0288                  $topic_condition
0289                  AND p.post_visibility = " . ITEM_APPROVED . "
0290              ORDER BY p.post_id DESC";
0291          $result = $db->sql_query_limit($sql, 1);
0292      }
0293      else
0294      {
0295          $sql = 'SELECT p.' . $type . '_id, MAX(p.post_id) as last_post_id
0296              FROM ' . POSTS_TABLE . " p $topic_join
0297              WHERE " . $db->sql_in_set('p.' . $type . '_id', $ids) . "
0298                  $topic_condition
0299                  AND p.post_visibility = " . ITEM_APPROVED . "
0300              GROUP BY p.{$type}_id";
0301          $result = $db->sql_query($sql);
0302      }
0303   
0304      $last_post_ids = array();
0305      while ($row = $db->sql_fetchrow($result))
0306      {
0307          if (count($ids) == 1)
0308          {
0309              $row[$type . '_id'] = $ids[0];
0310          }
0311   
0312          if ($type == 'forum')
0313          {
0314              $not_empty_forums[] = $row['forum_id'];
0315   
0316              if (empty($row['last_post_id']))
0317              {
0318                  $empty_forums[] = $row['forum_id'];
0319              }
0320          }
0321   
0322          $last_post_ids[] = $row['last_post_id'];
0323      }
0324      $db->sql_freeresult($result);
0325   
0326      if ($type == 'forum')
0327      {
0328          $empty_forums = array_merge($empty_forums, array_diff($ids, $not_empty_forums));
0329   
0330          foreach ($empty_forums as $void => $forum_id)
0331          {
0332              $update_sql[$forum_id][] = 'forum_last_post_id = 0';
0333              $update_sql[$forum_id][] = "forum_last_post_subject = ''";
0334              $update_sql[$forum_id][] = 'forum_last_post_time = 0';
0335              $update_sql[$forum_id][] = 'forum_last_poster_id = 0';
0336              $update_sql[$forum_id][] = "forum_last_poster_name = ''";
0337              $update_sql[$forum_id][] = "forum_last_poster_colour = ''";
0338          }
0339      }
0340   
0341      if (count($last_post_ids))
0342      {
0343          $sql_ary = array(
0344              'SELECT'    => 'p.' . $type . '_id, p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour',
0345              'FROM'        => array(
0346                  POSTS_TABLE    => 'p',
0347                  USERS_TABLE => 'u',
0348              ),
0349              'WHERE'        => $db->sql_in_set('p.post_id', $last_post_ids) . '
0350                  AND p.poster_id = u.user_id',
0351          );
0352   
0353          /**
0354          * Event to modify the SQL array to get the post and user data from all last posts
0355          *
0356          * @event core.update_post_info_modify_posts_sql
0357          * @var    string    type                The table being updated (forum or topic)
0358          * @var    array    sql_ary                SQL array to get some of the last posts' data
0359          * @since 3.3.5-RC1
0360          */
0361          $vars = [
0362              'type',
0363              'sql_ary',
0364          ];
0365          extract($phpbb_dispatcher->trigger_event('core.update_post_info_modify_posts_sql', compact($vars)));
0366          $result = $db->sql_query($db->sql_build_query('SELECT', $sql_ary));
0367   
0368          $rowset = array();
0369          while ($row = $db->sql_fetchrow($result))
0370          {
0371              $rowset[] = $row;
0372              $update_sql[$row["{$type}_id"]][] = $type . '_last_post_id = ' . (int) $row['post_id'];
0373              $update_sql[$row["{$type}_id"]][] = "{$type}_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'";
0374              $update_sql[$row["{$type}_id"]][] = $type . '_last_post_time = ' . (int) $row['post_time'];
0375              $update_sql[$row["{$type}_id"]][] = $type . '_last_poster_id = ' . (int) $row['poster_id'];
0376              $update_sql[$row["{$type}_id"]][] = "{$type}_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'";
0377              $update_sql[$row["{$type}_id"]][] = "{$type}_last_poster_name = '" . (($row['poster_id'] == ANONYMOUS) ? $db->sql_escape($row['post_username']) : $db->sql_escape($row['username'])) . "'";
0378          }
0379          $db->sql_freeresult($result);
0380   
0381          /**
0382          * Event to modify the update_sql array to add new update data for forum or topic last posts
0383          *
0384          * @event core.update_post_info_modify_sql
0385          * @var    string    type                The table being updated (forum or topic)
0386          * @var    array    rowset                Array with the posts data
0387          * @var    array    update_sql            Array with SQL data to update the forums or topics table with
0388          * @since 3.3.5-RC1
0389          */
0390          $vars = [
0391              'type',
0392              'rowset',
0393              'update_sql',
0394          ];
0395          extract($phpbb_dispatcher->trigger_event('core.update_post_info_modify_sql', compact($vars)));
0396          unset($rowset);
0397      }
0398      unset($empty_forums, $ids, $last_post_ids);
0399   
0400      if ($return_update_sql || !count($update_sql))
0401      {
0402          return $update_sql;
0403      }
0404   
0405      $table = ($type == 'forum') ? FORUMS_TABLE : TOPICS_TABLE;
0406   
0407      foreach ($update_sql as $update_id => $update_sql_ary)
0408      {
0409          $sql = "UPDATE $table
0410              SET " . implode(', ', $update_sql_ary) . "
0411              WHERE {$type}_id = $update_id";
0412          $db->sql_query($sql);
0413      }
0414   
0415      return;
0416  }
0417   
0418  /**
0419  * Generate Topic Icons for display
0420  */
0421  function posting_gen_topic_icons($mode, $icon_id)
0422  {
0423      global $phpbb_root_path, $phpbb_path_helper, $config, $template, $cache;
0424   
0425      // Grab icons
0426      $icons = $cache->obtain_icons();
0427   
0428      if (!$icon_id)
0429      {
0430          $template->assign_var('S_NO_ICON_CHECKED', ' checked="checked"');
0431      }
0432   
0433      if (count($icons))
0434      {
0435          $root_path = $phpbb_path_helper->get_web_root_path();
0436   
0437          foreach ($icons as $id => $data)
0438          {
0439              if ($data['display'])
0440              {
0441                  $template->assign_block_vars('topic_icon', array(
0442                      'ICON_ID'        => $id,
0443                      'ICON_IMG'        => $root_path . $config['icons_path'] . '/' . $data['img'],
0444                      'ICON_WIDTH'    => $data['width'],
0445                      'ICON_HEIGHT'    => $data['height'],
0446                      'ICON_ALT'        => $data['alt'],
0447   
0448                      'S_CHECKED'            => ($id == $icon_id) ? true : false,
0449                      'S_ICON_CHECKED'    => ($id == $icon_id) ? ' checked="checked"' : '')
0450                  );
0451              }
0452          }
0453   
0454          return true;
0455      }
0456   
0457      return false;
0458  }
0459   
0460  /**
0461  * Build topic types able to be selected
0462  */
0463  function posting_gen_topic_types($forum_id, $cur_topic_type = POST_NORMAL)
0464  {
0465      global $auth, $user, $template;
0466   
0467      $toggle = false;
0468   
0469      $topic_types = array(
0470          'sticky'            => array('const' => POST_STICKY, 'lang' => 'POST_STICKY'),
0471          'announce'            => array('const' => POST_ANNOUNCE, 'lang' => 'POST_ANNOUNCEMENT'),
0472          'announce_global'    => array('const' => POST_GLOBAL, 'lang' => 'POST_GLOBAL')
0473      );
0474   
0475      $topic_type_array = array();
0476   
0477      foreach ($topic_types as $auth_key => $topic_value)
0478      {
0479          if ($auth->acl_get('f_' . $auth_key, $forum_id))
0480          {
0481              $toggle = true;
0482   
0483              $topic_type_array[] = array(
0484                  'VALUE'            => $topic_value['const'],
0485                  'S_CHECKED'        => ($cur_topic_type == $topic_value['const']) ? ' checked="checked"' : '',
0486                  'L_TOPIC_TYPE'    => $user->lang[$topic_value['lang']]
0487              );
0488          }
0489      }
0490   
0491      if ($toggle)
0492      {
0493          $topic_type_array = array_merge(array(0 => array(
0494              'VALUE'            => POST_NORMAL,
0495              'S_CHECKED'        => ($cur_topic_type == POST_NORMAL) ? ' checked="checked"' : '',
0496              'L_TOPIC_TYPE'    => $user->lang['POST_NORMAL'])),
0497   
0498              $topic_type_array
0499          );
0500   
0501          foreach ($topic_type_array as $array)
0502          {
0503              $template->assign_block_vars('topic_type', $array);
0504          }
0505   
0506          $template->assign_vars(array(
0507              'S_TOPIC_TYPE_STICKY'    => ($auth->acl_get('f_sticky', $forum_id)),
0508              'S_TOPIC_TYPE_ANNOUNCE'    => ($auth->acl_gets('f_announce', 'f_announce_global', $forum_id)),
0509          ));
0510      }
0511   
0512      return $toggle;
0513  }
0514   
0515  //
0516  // Attachment related functions
0517  //
0518  /**
0519  * Calculate the needed size for Thumbnail
0520  */
0521  function get_img_size_format($width, $height)
0522  {
0523      global $config;
0524   
0525      // Maximum Width the Image can take
0526      $max_width = ($config['img_max_thumb_width']) ? $config['img_max_thumb_width'] : 400;
0527   
0528      if ($width > $height)
0529      {
0530          return array(
0531              round($width * ($max_width / $width)),
0532              round($height * ($max_width / $width))
0533          );
0534      }
0535      else
0536      {
0537          return array(
0538              round($width * ($max_width / $height)),
0539              round($height * ($max_width / $height))
0540          );
0541      }
0542  }
0543   
0544  /**
0545  * Return supported image types
0546  */
0547  function get_supported_image_types($type = false)
0548  {
0549      if (@extension_loaded('gd'))
0550      {
0551          $format = imagetypes();
0552          $new_type = 0;
0553   
0554          if ($type !== false)
0555          {
0556              // Type is one of the IMAGETYPE constants - it is fetched from getimagesize()
0557              switch ($type)
0558              {
0559                  // GIF
0560                  case IMAGETYPE_GIF:
0561                      $new_type = ($format & IMG_GIF) ? IMG_GIF : false;
0562                  break;
0563   
0564                  // JPG, JPC, JP2
0565                  case IMAGETYPE_JPEG:
0566                  case IMAGETYPE_JPC:
0567                  case IMAGETYPE_JPEG2000:
0568                  case IMAGETYPE_JP2:
0569                  case IMAGETYPE_JPX:
0570                  case IMAGETYPE_JB2:
0571                      $new_type = ($format & IMG_JPG) ? IMG_JPG : false;
0572                  break;
0573   
0574                  // PNG
0575                  case IMAGETYPE_PNG:
0576                      $new_type = ($format & IMG_PNG) ? IMG_PNG : false;
0577                  break;
0578   
0579                  // WBMP
0580                  case IMAGETYPE_WBMP:
0581                      $new_type = ($format & IMG_WBMP) ? IMG_WBMP : false;
0582                  break;
0583   
0584                  // WEBP
0585                  case IMAGETYPE_WEBP:
0586                      $new_type = ($format & IMG_WEBP) ? IMG_WEBP : false;
0587                  break;
0588              }
0589          }
0590          else
0591          {
0592              $new_type = [];
0593              $go_through_types = [IMG_GIF, IMG_JPG, IMG_PNG, IMG_WBMP, IMG_WEBP];
0594   
0595              foreach ($go_through_types as $check_type)
0596              {
0597                  if ($format & $check_type)
0598                  {
0599                      $new_type[] = $check_type;
0600                  }
0601              }
0602          }
0603   
0604          return [
0605              'gd'        => ($new_type) ? true : false,
0606              'format'    => $new_type,
0607              'version'    => (function_exists('imagecreatetruecolor')) ? 2 : 1
0608          ];
0609      }
0610   
0611      return ['gd' => false];
0612  }
0613   
0614  /**
0615  * Create Thumbnail
0616  */
0617  function create_thumbnail($source, $destination, $mimetype)
0618  {
0619      global $config, $phpbb_filesystem, $phpbb_dispatcher;
0620   
0621      $min_filesize = (int) $config['img_min_thumb_filesize'];
0622      $img_filesize = (file_exists($source)) ? @filesize($source) : false;
0623   
0624      if (!$img_filesize || $img_filesize <= $min_filesize)
0625      {
0626          return false;
0627      }
0628   
0629      $dimension = @getimagesize($source);
0630   
0631      if ($dimension === false)
0632      {
0633          return false;
0634      }
0635   
0636      list($width, $height, $type, ) = $dimension;
0637   
0638      if (empty($width) || empty($height))
0639      {
0640          return false;
0641      }
0642   
0643      list($new_width, $new_height) = get_img_size_format($width, $height);
0644   
0645      // Do not create a thumbnail if the resulting width/height is bigger than the original one
0646      if ($new_width >= $width && $new_height >= $height)
0647      {
0648          return false;
0649      }
0650   
0651      $thumbnail_created = false;
0652   
0653      /**
0654       * Create thumbnail event to replace GD thumbnail creation with for example ImageMagick
0655       *
0656       * @event core.thumbnail_create_before
0657       * @var    string    source                Image source path
0658       * @var    string    destination            Thumbnail destination path
0659       * @var    string    mimetype            Image mime type
0660       * @var    float    new_width            Calculated thumbnail width
0661       * @var    float    new_height            Calculated thumbnail height
0662       * @var    bool    thumbnail_created    Set to true to skip default GD thumbnail creation
0663       * @since 3.2.4
0664       */
0665      $vars = array(
0666          'source',
0667          'destination',
0668          'mimetype',
0669          'new_width',
0670          'new_height',
0671          'thumbnail_created',
0672      );
0673      extract($phpbb_dispatcher->trigger_event('core.thumbnail_create_before', compact($vars)));
0674   
0675      if (!$thumbnail_created)
0676      {
0677          $type = get_supported_image_types($type);
0678   
0679          if ($type['gd'])
0680          {
0681              // If the type is not supported, we are not able to create a thumbnail
0682              if ($type['format'] === false)
0683              {
0684                  return false;
0685              }
0686   
0687              switch ($type['format'])
0688              {
0689                  case IMG_GIF:
0690                      $image = @imagecreatefromgif($source);
0691                  break;
0692   
0693                  case IMG_JPG:
0694                      @ini_set('gd.jpeg_ignore_warning', 1);
0695                      $image = @imagecreatefromjpeg($source);
0696                  break;
0697   
0698                  case IMG_PNG:
0699                      $image = @imagecreatefrompng($source);
0700                  break;
0701   
0702                  case IMG_WBMP:
0703                      $image = @imagecreatefromwbmp($source);
0704                  break;
0705   
0706                  case IMG_WEBP:
0707                      $image = @imagecreatefromwebp($source);
0708                  break;
0709              }
0710   
0711              if (empty($image))
0712              {
0713                  return false;
0714              }
0715   
0716              if ($type['version'] == 1)
0717              {
0718                  $new_image = imagecreate($new_width, $new_height);
0719   
0720                  if ($new_image === false)
0721                  {
0722                      return false;
0723                  }
0724   
0725                  imagecopyresized($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
0726              }
0727              else
0728              {
0729                  $new_image = imagecreatetruecolor($new_width, $new_height);
0730   
0731                  if ($new_image === false)
0732                  {
0733                      return false;
0734                  }
0735   
0736                  // Preserve alpha transparency (png for example)
0737                  @imagealphablending($new_image, false);
0738                  @imagesavealpha($new_image, true);
0739   
0740                  imagecopyresampled($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
0741              }
0742   
0743              switch ($type['format'])
0744              {
0745                  case IMG_GIF:
0746                      imagegif($new_image, $destination);
0747                  break;
0748   
0749                  case IMG_JPG:
0750                      imagejpeg($new_image, $destination, 90);
0751                  break;
0752   
0753                  case IMG_PNG:
0754                      imagepng($new_image, $destination);
0755                  break;
0756   
0757                  case IMG_WBMP:
0758                      imagewbmp($new_image, $destination);
0759                  break;
0760   
0761                  case IMG_WEBP:
0762                      imagewebp($new_image, $destination);
0763                  break;
0764              }
0765   
0766              imagedestroy($new_image);
0767          }
0768          else
0769          {
0770              return false;
0771          }
0772      }
0773   
0774      if (!file_exists($destination))
0775      {
0776          return false;
0777      }
0778   
0779      try
0780      {
0781          $phpbb_filesystem->phpbb_chmod($destination, \phpbb\filesystem\filesystem_interface::CHMOD_READ | \phpbb\filesystem\filesystem_interface::CHMOD_WRITE);
0782      }
0783      catch (\phpbb\filesystem\exception\filesystem_exception $e)
0784      {
0785          // Do nothing
0786      }
0787   
0788      return true;
0789  }
0790   
0791  /**
0792  * Assign Inline attachments (build option fields)
0793  */
0794  function posting_gen_inline_attachments(&$attachment_data)
0795  {
0796      global $template;
0797   
0798      if (count($attachment_data))
0799      {
0800          $s_inline_attachment_options = '';
0801   
0802          foreach ($attachment_data as $i => $attachment)
0803          {
0804              $s_inline_attachment_options .= '<option value="' . $i . '">' . utf8_basename($attachment['real_filename']) . '</option>';
0805          }
0806   
0807          $template->assign_var('S_INLINE_ATTACHMENT_OPTIONS', $s_inline_attachment_options);
0808   
0809          return true;
0810      }
0811   
0812      return false;
0813  }
0814   
0815  /**
0816   * Generate inline attachment entry
0817   *
0818   * @param array        $attachment_data    The attachment data
0819   * @param string    $filename_data        The filename data (filecomment)
0820   * @param bool        $show_attach_box    Whether to show the attach box
0821   * @param mixed        $forum_id            The forum id to check or false if private message
0822   * @return int
0823   */
0824  function posting_gen_attachment_entry($attachment_data, &$filename_data, $show_attach_box = true, $forum_id = false)
0825  {
0826      global $template, $cache, $config, $phpbb_root_path, $phpEx, $user, $phpbb_dispatcher;
0827   
0828      $allowed_attachments = array_keys($cache->obtain_attach_extensions($forum_id)['_allowed_']);
0829   
0830      // Some default template variables
0831      $default_vars = [
0832          'S_SHOW_ATTACH_BOX'                => $show_attach_box,
0833          'S_HAS_ATTACHMENTS'                => count($attachment_data),
0834          'FILESIZE'                        => $config['max_filesize'],
0835          'FILE_COMMENT'                    => (isset($filename_data['filecomment'])) ? $filename_data['filecomment'] : '',
0836          'MAX_ATTACHMENT_FILESIZE'        => $config['max_filesize'] > 0 ? $user->lang('MAX_ATTACHMENT_FILESIZE', get_formatted_filesize($config['max_filesize'])) : '',
0837          'ALLOWED_ATTACHMENTS'            => !empty($allowed_attachments) ? '.' . implode(',.', $allowed_attachments) : '',
0838      ];
0839   
0840      /**
0841       * Modify default attachments template vars
0842       *
0843       * @event core.modify_default_attachments_template_vars
0844       * @var    array    allowed_attachments        Array containing allowed attachments data
0845       * @var    array    default_vars            Array containing default attachments template vars
0846       * @since 3.3.6-RC1
0847       */
0848      $vars = ['allowed_attachments', 'default_vars'];
0849      extract($phpbb_dispatcher->trigger_event('core.modify_default_attachments_template_vars', compact($vars)));
0850   
0851      $template->assign_vars($default_vars);
0852   
0853      if (count($attachment_data))
0854      {
0855          // We display the posted attachments within the desired order.
0856          ($config['display_order']) ? krsort($attachment_data) : ksort($attachment_data);
0857   
0858          $attachrow_template_vars = [];
0859   
0860          foreach ($attachment_data as $count => $attach_row)
0861          {
0862              $hidden = '';
0863              $attach_row['real_filename'] = utf8_basename($attach_row['real_filename']);
0864   
0865              foreach ($attach_row as $key => $value)
0866              {
0867                  $hidden .= '<input type="hidden" name="attachment_data[' . $count . '][' . $key . ']" value="' . $value . '" />';
0868              }
0869   
0870              $download_link = append_sid("{$phpbb_root_path}download/file.$phpEx", 'mode=view&amp;id=' . (int) $attach_row['attach_id'], true, ($attach_row['is_orphan']) ? $user->session_id : false);
0871   
0872              $attachrow_template_vars[(int) $attach_row['attach_id']] = array(
0873                  'FILENAME'            => utf8_basename($attach_row['real_filename']),
0874                  'A_FILENAME'        => addslashes(utf8_basename($attach_row['real_filename'])),
0875                  'FILE_COMMENT'        => $attach_row['attach_comment'],
0876                  'ATTACH_ID'            => $attach_row['attach_id'],
0877                  'S_IS_ORPHAN'        => $attach_row['is_orphan'],
0878                  'ASSOC_INDEX'        => $count,
0879                  'FILESIZE'            => get_formatted_filesize($attach_row['filesize']),
0880   
0881                  'U_VIEW_ATTACHMENT'    => $download_link,
0882                  'S_HIDDEN'            => $hidden,
0883              );
0884          }
0885   
0886          /**
0887          * Modify inline attachments template vars
0888          *
0889          * @event core.modify_inline_attachments_template_vars
0890          * @var    array    attachment_data                Array containing attachments data
0891          * @var    array    attachrow_template_vars        Array containing attachments template vars
0892          * @since 3.2.2-RC1
0893          */
0894          $vars = array('attachment_data', 'attachrow_template_vars');
0895          extract($phpbb_dispatcher->trigger_event('core.modify_inline_attachments_template_vars', compact($vars)));
0896   
0897          $template->assign_block_vars_array('attach_row', $attachrow_template_vars);
0898      }
0899   
0900      return count($attachment_data);
0901  }
0902   
0903  //
0904  // General Post functions
0905  //
0906   
0907  /**
0908  * Load Drafts
0909  */
0910  function load_drafts($topic_id = 0, $forum_id = 0, $id = 0, $pm_action = '', $msg_id = 0)
0911  {
0912      global $user, $db, $template, $auth;
0913      global $phpbb_root_path, $phpbb_dispatcher, $phpEx;
0914   
0915      $topic_ids = $forum_ids = $draft_rows = array();
0916   
0917      // Load those drafts not connected to forums/topics
0918      // If forum_id == 0 AND topic_id == 0 then this is a PM draft
0919      if (!$topic_id && !$forum_id)
0920      {
0921          $sql_and = ' AND d.forum_id = 0 AND d.topic_id = 0';
0922      }
0923      else
0924      {
0925          $sql_and = '';
0926          $sql_and .= ($forum_id) ? ' AND d.forum_id = ' . (int) $forum_id : '';
0927          $sql_and .= ($topic_id) ? ' AND d.topic_id = ' . (int) $topic_id : '';
0928      }
0929   
0930      $sql = 'SELECT d.*, f.forum_id, f.forum_name
0931          FROM ' . DRAFTS_TABLE . ' d
0932          LEFT JOIN ' . FORUMS_TABLE . ' f ON (f.forum_id = d.forum_id)
0933              WHERE d.user_id = ' . $user->data['user_id'] . "
0934              $sql_and
0935          ORDER BY d.save_time DESC";
0936      $result = $db->sql_query($sql);
0937   
0938      while ($row = $db->sql_fetchrow($result))
0939      {
0940          if ($row['topic_id'])
0941          {
0942              $topic_ids[] = (int) $row['topic_id'];
0943          }
0944          $draft_rows[] = $row;
0945      }
0946      $db->sql_freeresult($result);
0947   
0948      if (!count($draft_rows))
0949      {
0950          return;
0951      }
0952   
0953      $topic_rows = array();
0954      if (count($topic_ids))
0955      {
0956          $sql = 'SELECT topic_id, forum_id, topic_title, topic_poster
0957              FROM ' . TOPICS_TABLE . '
0958              WHERE ' . $db->sql_in_set('topic_id', array_unique($topic_ids));
0959          $result = $db->sql_query($sql);
0960   
0961          while ($row = $db->sql_fetchrow($result))
0962          {
0963              $topic_rows[$row['topic_id']] = $row;
0964          }
0965          $db->sql_freeresult($result);
0966      }
0967   
0968      /**
0969      * Drafts found and their topics
0970      * Edit $draft_rows in order to add or remove drafts loaded
0971      *
0972      * @event core.load_drafts_draft_list_result
0973      * @var    array    draft_rows            The drafts query result. Includes its forum id and everything about the draft
0974      * @var    array    topic_ids            The list of topics got from the topics table
0975      * @var    array    topic_rows            The topics that draft_rows references
0976      * @since 3.1.0-RC3
0977      */
0978      $vars = array('draft_rows', 'topic_ids', 'topic_rows');
0979      extract($phpbb_dispatcher->trigger_event('core.load_drafts_draft_list_result', compact($vars)));
0980   
0981      unset($topic_ids);
0982   
0983      $template->assign_var('S_SHOW_DRAFTS', true);
0984   
0985      foreach ($draft_rows as $draft)
0986      {
0987          $link_topic = $link_forum = $link_pm = false;
0988          $view_url = $title = '';
0989   
0990          if (isset($topic_rows[$draft['topic_id']])
0991              && (
0992                  ($topic_rows[$draft['topic_id']]['forum_id'] && $auth->acl_get('f_read', $topic_rows[$draft['topic_id']]['forum_id']))
0993                  ||
0994                  (!$topic_rows[$draft['topic_id']]['forum_id'] && $auth->acl_getf_global('f_read'))
0995              ))
0996          {
0997              $topic_forum_id = ($topic_rows[$draft['topic_id']]['forum_id']) ? $topic_rows[$draft['topic_id']]['forum_id'] : $forum_id;
0998   
0999              $link_topic = true;
1000              $view_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=' . $draft['topic_id']);
1001              $title = $topic_rows[$draft['topic_id']]['topic_title'];
1002   
1003              $insert_url = append_sid("{$phpbb_root_path}posting.$phpEx", 't=' . $draft['topic_id'] . '&amp;mode=reply&amp;d=' . $draft['draft_id']);
1004          }
1005          else if ($draft['forum_id'] && $auth->acl_get('f_read', $draft['forum_id']))
1006          {
1007              $link_forum = true;
1008              $view_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $draft['forum_id']);
1009              $title = $draft['forum_name'];
1010   
1011              $insert_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'f=' . $draft['forum_id'] . '&amp;mode=post&amp;d=' . $draft['draft_id']);
1012          }
1013          else
1014          {
1015              // Either display as PM draft if forum_id and topic_id are empty or if access to the forums has been denied afterwards...
1016              $link_pm = true;
1017              $insert_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=$id&amp;mode=compose&amp;d={$draft['draft_id']}" . (($pm_action) ? "&amp;action=$pm_action" : '') . (($msg_id) ? "&amp;p=$msg_id" : ''));
1018          }
1019   
1020          $template->assign_block_vars('draftrow', array(
1021              'DRAFT_ID'        => $draft['draft_id'],
1022              'DATE'            => $user->format_date($draft['save_time']),
1023              'DRAFT_SUBJECT'    => $draft['draft_subject'],
1024   
1025              'TITLE'            => $title,
1026              'U_VIEW'        => $view_url,
1027              'U_INSERT'        => $insert_url,
1028   
1029              'S_LINK_PM'        => $link_pm,
1030              'S_LINK_TOPIC'    => $link_topic,
1031              'S_LINK_FORUM'    => $link_forum)
1032          );
1033      }
1034  }
1035   
1036  /**
1037  * Topic Review
1038  */
1039  function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id = 0, $show_quote_button = true)
1040  {
1041      global $user, $auth, $db, $template;
1042      global $config, $phpbb_root_path, $phpEx, $phpbb_container, $phpbb_dispatcher;
1043   
1044      /* @var $phpbb_content_visibility \phpbb\content_visibility */
1045      $phpbb_content_visibility = $phpbb_container->get('content.visibility');
1046      $sql_sort = ($mode == 'post_review') ? 'ASC' : 'DESC';
1047   
1048      // Go ahead and pull all data for this topic
1049      $sql = 'SELECT p.post_id
1050          FROM ' . POSTS_TABLE . ' p' . "
1051          WHERE p.topic_id = $topic_id
1052              AND " . $phpbb_content_visibility->get_visibility_sql('post', $forum_id, 'p.') . '
1053              ' . (($mode == 'post_review') ? " AND p.post_id > $cur_post_id" : '') . '
1054              ' . (($mode == 'post_review_edit') ? " AND p.post_id = $cur_post_id" : '') . '
1055          ORDER BY p.post_time ' . $sql_sort . ', p.post_id ' . $sql_sort;
1056      $result = $db->sql_query_limit($sql, $config['posts_per_page']);
1057   
1058      $post_list = array();
1059   
1060      while ($row = $db->sql_fetchrow($result))
1061      {
1062          $post_list[] = $row['post_id'];
1063      }
1064   
1065      $db->sql_freeresult($result);
1066   
1067      if (!count($post_list))
1068      {
1069          return false;
1070      }
1071   
1072      // Handle 'post_review_edit' like 'post_review' from now on
1073      if ($mode == 'post_review_edit')
1074      {
1075          $mode = 'post_review';
1076      }
1077   
1078      $sql_ary = array(
1079          'SELECT'    => 'u.username, u.user_id, u.user_colour, p.*, z.friend, z.foe, uu.username as post_delete_username, uu.user_colour as post_delete_user_colour',
1080   
1081          'FROM'        => array(
1082              USERS_TABLE        => 'u',
1083              POSTS_TABLE        => 'p',
1084          ),
1085   
1086          'LEFT_JOIN'    => array(
1087              array(
1088                  'FROM'    => array(ZEBRA_TABLE => 'z'),
1089                  'ON'    => 'z.user_id = ' . $user->data['user_id'] . ' AND z.zebra_id = p.poster_id',
1090              ),
1091              array(
1092                  'FROM'    => array(USERS_TABLE => 'uu'),
1093                  'ON'    => 'uu.user_id = p.post_delete_user',
1094              ),
1095          ),
1096   
1097          'WHERE'        => $db->sql_in_set('p.post_id', $post_list) . '
1098              AND u.user_id = p.poster_id',
1099      );
1100   
1101      /**
1102      * Event to modify the SQL query for topic reviews
1103      *
1104      * @event core.topic_review_modify_sql_ary
1105      * @var    int        topic_id            The topic ID that is being reviewed
1106      * @var    int        forum_id            The topic's forum ID
1107      * @var    string    mode                The topic review mode
1108      * @var    int        cur_post_id            Post offset ID
1109      * @var    bool    show_quote_button    Flag indicating if the quote button should be displayed
1110      * @var    array    post_list            Array with the post IDs
1111      * @var    array    sql_ary                Array with the SQL query
1112      * @since 3.2.8-RC1
1113      */
1114      $vars = array(
1115          'topic_id',
1116          'forum_id',
1117          'mode',
1118          'cur_post_id',
1119          'show_quote_button',
1120          'post_list',
1121          'sql_ary',
1122      );
1123      extract($phpbb_dispatcher->trigger_event('core.topic_review_modify_sql_ary', compact($vars)));
1124   
1125      $sql = $db->sql_build_query('SELECT', $sql_ary);
1126      $result = $db->sql_query($sql);
1127   
1128      $rowset = array();
1129      $has_attachments = false;
1130      while ($row = $db->sql_fetchrow($result))
1131      {
1132          $rowset[$row['post_id']] = $row;
1133   
1134          if ($row['post_attachment'])
1135          {
1136              $has_attachments = true;
1137          }
1138      }
1139      $db->sql_freeresult($result);
1140   
1141      // Grab extensions
1142      $attachments = array();
1143      if ($has_attachments && $auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id))
1144      {
1145          // Get attachments...
1146          $sql = 'SELECT *
1147              FROM ' . ATTACHMENTS_TABLE . '
1148              WHERE ' . $db->sql_in_set('post_msg_id', $post_list) . '
1149                  AND in_message = 0
1150              ORDER BY filetime DESC, post_msg_id ASC';
1151          $result = $db->sql_query($sql);
1152   
1153          while ($row = $db->sql_fetchrow($result))
1154          {
1155              $attachments[$row['post_msg_id']][] = $row;
1156          }
1157          $db->sql_freeresult($result);
1158      }
1159   
1160      /**
1161      * Event to modify the posts list for topic reviews
1162      *
1163      * @event core.topic_review_modify_post_list
1164      * @var    array    attachments            Array with the post attachments data
1165      * @var    int        cur_post_id            Post offset ID
1166      * @var    int        forum_id            The topic's forum ID
1167      * @var    string    mode                The topic review mode
1168      * @var    array    post_list            Array with the post IDs
1169      * @var    array    rowset                Array with the posts data
1170      * @var    bool    show_quote_button    Flag indicating if the quote button should be displayed
1171      * @var    int        topic_id            The topic ID that is being reviewed
1172      * @since 3.1.9-RC1
1173      */
1174      $vars = array(
1175          'attachments',
1176          'cur_post_id',
1177          'forum_id',
1178          'mode',
1179          'post_list',
1180          'rowset',
1181          'show_quote_button',
1182          'topic_id',
1183      );
1184      extract($phpbb_dispatcher->trigger_event('core.topic_review_modify_post_list', compact($vars)));
1185   
1186      for ($i = 0, $end = count($post_list); $i < $end; ++$i)
1187      {
1188          // A non-existing rowset only happens if there was no user present for the entered poster_id
1189          // This could be a broken posts table.
1190          if (!isset($rowset[$post_list[$i]]))
1191          {
1192              continue;
1193          }
1194   
1195          $row = $rowset[$post_list[$i]];
1196   
1197          $poster_id        = $row['user_id'];
1198          $post_subject    = $row['post_subject'];
1199   
1200          $decoded_message = false;
1201   
1202          if ($show_quote_button && $auth->acl_get('f_reply', $forum_id))
1203          {
1204              $decoded_message = censor_text($row['post_text']);
1205              decode_message($decoded_message, $row['bbcode_uid']);
1206   
1207              $decoded_message = bbcode_nl2br($decoded_message);
1208          }
1209   
1210          $parse_flags = ($row['bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0);
1211          $parse_flags |= ($row['enable_smilies'] ? OPTION_FLAG_SMILIES : 0);
1212          $message = generate_text_for_display($row['post_text'], $row['bbcode_uid'], $row['bbcode_bitfield'], $parse_flags, true);
1213   
1214          if (!empty($attachments[$row['post_id']]))
1215          {
1216              $update_count = array();
1217              parse_attachments($forum_id, $message, $attachments[$row['post_id']], $update_count);
1218          }
1219   
1220          $post_subject = censor_text($post_subject);
1221   
1222          $post_anchor = ($mode == 'post_review') ? 'ppr' . $row['post_id'] : 'pr' . $row['post_id'];
1223          $u_show_post = append_sid($phpbb_root_path . 'viewtopic.' . $phpEx, "t=$topic_id&amp;p={$row['post_id']}&amp;view=show#p{$row['post_id']}");
1224   
1225          $l_deleted_message = '';
1226          if ($row['post_visibility'] == ITEM_DELETED)
1227          {
1228              $display_postername = get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']);
1229   
1230              // User having deleted the post also being the post author?
1231              if (!$row['post_delete_user'] || $row['post_delete_user'] == $poster_id)
1232              {
1233                  $display_username = $display_postername;
1234              }
1235              else
1236              {
1237                  $display_username = get_username_string('full', $row['post_delete_user'], $row['post_delete_username'], $row['post_delete_user_colour']);
1238              }
1239   
1240              if ($row['post_delete_reason'])
1241              {
1242                  $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']);
1243              }
1244              else
1245              {
1246                  $l_deleted_message = $user->lang('POST_DELETED_BY', $display_postername, $display_username, $user->format_date($row['post_delete_time'], false, true));
1247              }
1248          }
1249   
1250          $post_row = array(
1251              'POST_AUTHOR_FULL'        => get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
1252              'POST_AUTHOR_COLOUR'    => get_username_string('colour', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
1253              'POST_AUTHOR'            => get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
1254              'U_POST_AUTHOR'            => get_username_string('profile', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
1255   
1256              'S_HAS_ATTACHMENTS'    => !empty($attachments[$row['post_id']]),
1257              'S_FRIEND'            => (bool) $row['friend'],
1258              'S_IGNORE_POST'        => (bool) $row['foe'],
1259              'L_IGNORE_POST'        => $row['foe'] ? $user->lang('POST_BY_FOE', get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), "<a href=\"{$u_show_post}\" onclick=\"phpbb.toggleDisplay('{$post_anchor}', 1); return false;\">", '</a>') : '',
1260              'S_POST_DELETED'    => $row['post_visibility'] == ITEM_DELETED,
1261              'L_DELETE_POST'        => $l_deleted_message,
1262   
1263              'POST_SUBJECT'        => $post_subject,
1264              'MINI_POST_IMG'        => $user->img('icon_post_target', $user->lang['POST']),
1265              'POST_DATE'            => $user->format_date($row['post_time']),
1266              'MESSAGE'            => $message,
1267              'DECODED_MESSAGE'    => $decoded_message,
1268              'POST_ID'            => $row['post_id'],
1269              'POST_TIME'            => $row['post_time'],
1270              'USER_ID'            => $row['user_id'],
1271              'U_MINI_POST'        => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'p=' . $row['post_id']) . '#p' . $row['post_id'],
1272              'U_MCP_DETAILS'        => ($auth->acl_get('m_info', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&amp;mode=post_details&amp;p=' . $row['post_id'], true, $user->session_id) : '',
1273              'POSTER_QUOTE'        => ($show_quote_button && $auth->acl_get('f_reply', $forum_id)) ? addslashes(get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username'])) : '',
1274          );
1275   
1276          $current_row_number = $i;
1277   
1278          /**
1279          * Event to modify the template data block for topic reviews
1280          *
1281          * @event core.topic_review_modify_row
1282          * @var    string    mode                The review mode
1283          * @var    int        topic_id            The topic that is being reviewed
1284          * @var    int        forum_id            The topic's forum
1285          * @var    int        cur_post_id            Post offset id
1286          * @var    int        current_row_number    Number of the current row being iterated
1287          * @var    array    post_row            Template block array of the current post
1288          * @var    array    row                    Array with original post and user data
1289          * @since 3.1.4-RC1
1290          */
1291          $vars = array(
1292              'mode',
1293              'topic_id',
1294              'forum_id',
1295              'cur_post_id',
1296              'current_row_number',
1297              'post_row',
1298              'row',
1299          );
1300          extract($phpbb_dispatcher->trigger_event('core.topic_review_modify_row', compact($vars)));
1301   
1302          $template->assign_block_vars($mode . '_row', $post_row);
1303   
1304          // Display not already displayed Attachments for this post, we already parsed them. ;)
1305          if (!empty($attachments[$row['post_id']]))
1306          {
1307              foreach ($attachments[$row['post_id']] as $attachment)
1308              {
1309                  $template->assign_block_vars($mode . '_row.attachment', array(
1310                      'DISPLAY_ATTACHMENT'    => $attachment)
1311                  );
1312              }
1313          }
1314   
1315          unset($rowset[$post_list[$i]]);
1316      }
1317   
1318      if ($mode == 'topic_review')
1319      {
1320          $template->assign_var('QUOTE_IMG', $user->img('icon_post_quote', $user->lang['REPLY_WITH_QUOTE']));
1321      }
1322   
1323      return true;
1324  }
1325   
1326  //
1327  // Post handling functions
1328  //
1329   
1330  /**
1331  * Delete Post
1332  */
1333  function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $softdelete_reason = '')
1334  {
1335      global $db, $user, $phpbb_container, $phpbb_dispatcher;
1336      global $config, $phpEx, $phpbb_root_path;
1337   
1338      // Specify our post mode
1339      $post_mode = 'delete';
1340      if (($data['topic_first_post_id'] === $data['topic_last_post_id']) && ($data['topic_posts_approved'] + $data['topic_posts_unapproved'] + $data['topic_posts_softdeleted'] == 1))
1341      {
1342          $post_mode = 'delete_topic';
1343      }
1344      else if ($data['topic_first_post_id'] == $post_id)
1345      {
1346          $post_mode = 'delete_first_post';
1347      }
1348      else if ($data['topic_last_post_id'] <= $post_id)
1349      {
1350          $post_mode = 'delete_last_post';
1351      }
1352      $sql_data = array();
1353      $next_post_id = false;
1354   
1355      include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
1356   
1357      $db->sql_transaction('begin');
1358   
1359      // we must make sure to update forums that contain the shadow'd topic
1360      if ($post_mode == 'delete_topic')
1361      {
1362          $shadow_forum_ids = array();
1363   
1364          $sql = 'SELECT forum_id
1365              FROM ' . TOPICS_TABLE . '
1366              WHERE ' . $db->sql_in_set('topic_moved_id', $topic_id);
1367          $result = $db->sql_query($sql);
1368          while ($row = $db->sql_fetchrow($result))
1369          {
1370              if (!isset($shadow_forum_ids[(int) $row['forum_id']]))
1371              {
1372                  $shadow_forum_ids[(int) $row['forum_id']] = 1;
1373              }
1374              else
1375              {
1376                  $shadow_forum_ids[(int) $row['forum_id']]++;
1377              }
1378          }
1379          $db->sql_freeresult($result);
1380      }
1381   
1382      /* @var $phpbb_content_visibility \phpbb\content_visibility */
1383      $phpbb_content_visibility = $phpbb_container->get('content.visibility');
1384   
1385      // (Soft) delete the post
1386      if ($is_soft && ($post_mode != 'delete_topic'))
1387      {
1388          $phpbb_content_visibility->set_post_visibility(ITEM_DELETED, $post_id, $topic_id, $forum_id, $user->data['user_id'], time(), $softdelete_reason, ($data['topic_first_post_id'] == $post_id), ($data['topic_last_post_id'] == $post_id));
1389      }
1390      else if (!$is_soft)
1391      {
1392          if (!delete_posts('post_id', array($post_id), false, false, false))
1393          {
1394              // Try to delete topic, we may had an previous error causing inconsistency
1395              if ($post_mode == 'delete_topic')
1396              {
1397                  delete_topics('topic_id', array($topic_id), false);
1398              }
1399              trigger_error('ALREADY_DELETED');
1400          }
1401      }
1402   
1403      $db->sql_transaction('commit');
1404   
1405      // Collect the necessary information for updating the tables
1406      $sql_data[FORUMS_TABLE] = $sql_data[TOPICS_TABLE] = '';
1407      switch ($post_mode)
1408      {
1409          case 'delete_topic':
1410   
1411              foreach ($shadow_forum_ids as $updated_forum => $topic_count)
1412              {
1413                  // counting is fun! we only have to do count($forum_ids) number of queries,
1414                  // even if the topic is moved back to where its shadow lives (we count how many times it is in a forum)
1415                  $sql = 'UPDATE ' . FORUMS_TABLE . '
1416                      SET forum_topics_approved = forum_topics_approved - ' . $topic_count . '
1417                      WHERE forum_id = ' . $updated_forum;
1418                  $db->sql_query($sql);
1419                  update_post_information('forum', $updated_forum);
1420              }
1421   
1422              if ($is_soft)
1423              {
1424                  $phpbb_content_visibility->set_topic_visibility(ITEM_DELETED, $topic_id, $forum_id, $user->data['user_id'], time(), $softdelete_reason);
1425              }
1426              else
1427              {
1428                  delete_topics('topic_id', array($topic_id), false);
1429   
1430                  $phpbb_content_visibility->remove_topic_from_statistic($data, $sql_data);
1431                  $config->increment('num_posts', -1, false);
1432   
1433                  $update_sql = update_post_information('forum', $forum_id, true);
1434                  if (count($update_sql))
1435                  {
1436                      $sql_data[FORUMS_TABLE] .= ($sql_data[FORUMS_TABLE]) ? ', ' : '';
1437                      $sql_data[FORUMS_TABLE] .= implode(', ', $update_sql[$forum_id]);
1438                  }
1439              }
1440   
1441          break;
1442   
1443          case 'delete_first_post':
1444              $sql = 'SELECT p.post_id, p.poster_id, p.post_time, p.post_username, u.username, u.user_colour
1445                  FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u
1446                  WHERE p.topic_id = $topic_id
1447                      AND p.poster_id = u.user_id
1448                      AND p.post_visibility = " . ITEM_APPROVED . '
1449                  ORDER BY p.post_time ASC, p.post_id ASC';
1450              $result = $db->sql_query_limit($sql, 1);
1451              $row = $db->sql_fetchrow($result);
1452              $db->sql_freeresult($result);
1453   
1454              if (!$row)
1455              {
1456                  // No approved post, so the first is a not-approved post (unapproved or soft deleted)
1457                  $sql = 'SELECT p.post_id, p.poster_id, p.post_time, p.post_username, u.username, u.user_colour
1458                      FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u
1459                      WHERE p.topic_id = $topic_id
1460                          AND p.poster_id = u.user_id
1461                      ORDER BY p.post_time ASC, p.post_id ASC";
1462                  $result = $db->sql_query_limit($sql, 1);
1463                  $row = $db->sql_fetchrow($result);
1464                  $db->sql_freeresult($result);
1465              }
1466   
1467              $next_post_id = (int) $row['post_id'];
1468   
1469              $sql_data[TOPICS_TABLE] = $db->sql_build_array('UPDATE', array(
1470                  'topic_poster'                => (int) $row['poster_id'],
1471                  'topic_first_post_id'        => (int) $row['post_id'],
1472                  'topic_first_poster_colour'    => $row['user_colour'],
1473                  'topic_first_poster_name'    => ($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username'],
1474                  'topic_time'                => (int) $row['post_time'],
1475              ));
1476          break;
1477   
1478          case 'delete_last_post':
1479              if (!$is_soft)
1480              {
1481                  // Update last post information when hard deleting. Soft delete already did that by itself.
1482                  $update_sql = update_post_information('forum', $forum_id, true);
1483                  if (count($update_sql))
1484                  {
1485                      $sql_data[FORUMS_TABLE] = (($sql_data[FORUMS_TABLE]) ? $sql_data[FORUMS_TABLE] . ', ' : '') . implode(', ', $update_sql[$forum_id]);
1486                  }
1487   
1488                  $sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_bumped = 0, topic_bumper = 0';
1489   
1490                  $update_sql = update_post_information('topic', $topic_id, true);
1491                  if (!empty($update_sql))
1492                  {
1493                      $sql_data[TOPICS_TABLE] .= ', ' . implode(', ', $update_sql[$topic_id]);
1494                      $next_post_id = (int) str_replace('topic_last_post_id = ', '', $update_sql[$topic_id][0]);
1495                  }
1496              }
1497   
1498              if (!$next_post_id)
1499              {
1500                  $sql = 'SELECT MAX(post_id) as last_post_id
1501                      FROM ' . POSTS_TABLE . "
1502                      WHERE topic_id = $topic_id
1503                          AND " . $phpbb_content_visibility->get_visibility_sql('post', $forum_id);
1504                  $result = $db->sql_query($sql);
1505                  $next_post_id = (int) $db->sql_fetchfield('last_post_id');
1506                  $db->sql_freeresult($result);
1507              }
1508          break;
1509   
1510          case 'delete':
1511              $sql = 'SELECT post_id
1512                  FROM ' . POSTS_TABLE . "
1513                  WHERE topic_id = $topic_id
1514                      AND " . $phpbb_content_visibility->get_visibility_sql('post', $forum_id) . '
1515                      AND post_time > ' . $data['post_time'] . '
1516                  ORDER BY post_time ASC, post_id ASC';
1517              $result = $db->sql_query_limit($sql, 1);
1518              $next_post_id = (int) $db->sql_fetchfield('post_id');
1519              $db->sql_freeresult($result);
1520          break;
1521      }
1522   
1523      if (($post_mode == 'delete') || ($post_mode == 'delete_last_post') || ($post_mode == 'delete_first_post'))
1524      {
1525          if (!$is_soft)
1526          {
1527              $phpbb_content_visibility->remove_post_from_statistic($data, $sql_data);
1528          }
1529   
1530          $sql = 'SELECT 1 AS has_attachments
1531              FROM ' . ATTACHMENTS_TABLE . '
1532              WHERE topic_id = ' . $topic_id;
1533          $result = $db->sql_query_limit($sql, 1);
1534          $has_attachments = (int) $db->sql_fetchfield('has_attachments');
1535          $db->sql_freeresult($result);
1536   
1537          if (!$has_attachments)
1538          {
1539              $sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_attachment = 0';
1540          }
1541      }
1542   
1543      $db->sql_transaction('begin');
1544   
1545      $where_sql = array(
1546          FORUMS_TABLE    => "forum_id = $forum_id",
1547          TOPICS_TABLE    => "topic_id = $topic_id",
1548          USERS_TABLE        => 'user_id = ' . $data['poster_id'],
1549      );
1550   
1551      foreach ($sql_data as $table => $update_sql)
1552      {
1553          if ($update_sql)
1554          {
1555              $db->sql_query("UPDATE $table SET $update_sql WHERE " . $where_sql[$table]);
1556          }
1557      }
1558   
1559      // Adjust posted info for this user by looking for a post by him/her within this topic...
1560      if ($post_mode != 'delete_topic' && $config['load_db_track'] && $data['poster_id'] != ANONYMOUS)
1561      {
1562          $sql = 'SELECT poster_id
1563              FROM ' . POSTS_TABLE . '
1564              WHERE topic_id = ' . $topic_id . '
1565                  AND poster_id = ' . $data['poster_id'];
1566          $result = $db->sql_query_limit($sql, 1);
1567          $poster_id = (int) $db->sql_fetchfield('poster_id');
1568          $db->sql_freeresult($result);
1569   
1570          // The user is not having any more posts within this topic
1571          if (!$poster_id)
1572          {
1573              $sql = 'DELETE FROM ' . TOPICS_POSTED_TABLE . '
1574                  WHERE topic_id = ' . $topic_id . '
1575                      AND user_id = ' . $data['poster_id'];
1576              $db->sql_query($sql);
1577          }
1578      }
1579   
1580      $db->sql_transaction('commit');
1581   
1582      if ($data['post_reported'] && ($post_mode != 'delete_topic'))
1583      {
1584          sync('topic_reported', 'topic_id', array($topic_id));
1585      }
1586   
1587      /**
1588      * This event is used for performing actions directly after a post or topic
1589      * has been deleted.
1590      *
1591      * @event core.delete_post_after
1592      * @var    int        forum_id            Post forum ID
1593      * @var    int        topic_id            Post topic ID
1594      * @var    int        post_id                Post ID
1595      * @var    array    data                Post data
1596      * @var    bool    is_soft                Soft delete flag
1597      * @var    string    softdelete_reason    Soft delete reason
1598      * @var    string    post_mode            delete_topic, delete_first_post, delete_last_post or delete
1599      * @var    mixed    next_post_id        Next post ID in the topic (post ID or false)
1600      *
1601      * @since 3.1.11-RC1
1602      */
1603      $vars = array(
1604          'forum_id',
1605          'topic_id',
1606          'post_id',
1607          'data',
1608          'is_soft',
1609          'softdelete_reason',
1610          'post_mode',
1611          'next_post_id',
1612      );
1613      extract($phpbb_dispatcher->trigger_event('core.delete_post_after', compact($vars)));
1614   
1615      return $next_post_id;
1616  }
1617   
1618  /**
1619  * Submit Post
1620  * @todo Split up and create lightweight, simple API for this.
1621  */
1622  function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data_ary, $update_message = true, $update_search_index = true)
1623  {
1624      global $db, $auth, $user, $config, $phpEx, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher, $phpbb_log, $request;
1625   
1626      $poll = $poll_ary;
1627      $data = $data_ary;
1628      /**
1629      * Modify the data for post submitting
1630      *
1631      * @event core.modify_submit_post_data
1632      * @var    string    mode                Variable containing posting mode value
1633      * @var    string    subject                Variable containing post subject value
1634      * @var    string    username            Variable containing post author name
1635      * @var    int        topic_type            Variable containing topic type value
1636      * @var    array    poll                Array with the poll data for the post
1637      * @var    array    data                Array with the data for the post
1638      * @var    bool    update_message        Flag indicating if the post will be updated
1639      * @var    bool    update_search_index    Flag indicating if the search index will be updated
1640      * @since 3.1.0-a4
1641      */
1642      $vars = array(
1643          'mode',
1644          'subject',
1645          'username',
1646          'topic_type',
1647          'poll',
1648          'data',
1649          'update_message',
1650          'update_search_index',
1651      );
1652      extract($phpbb_dispatcher->trigger_event('core.modify_submit_post_data', compact($vars)));
1653      $poll_ary = $poll;
1654      $data_ary = $data;
1655      unset($poll);
1656      unset($data);
1657   
1658      // We do not handle erasing posts here
1659      if ($mode == 'delete')
1660      {
1661          return false;
1662      }
1663   
1664      if (!empty($data_ary['post_time']))
1665      {
1666          $current_time = $data_ary['post_time'];
1667      }
1668      else
1669      {
1670          $current_time = time();
1671      }
1672   
1673      if ($mode == 'post')
1674      {
1675          $post_mode = 'post';
1676          $update_message = true;
1677      }
1678      else if ($mode != 'edit')
1679      {
1680          $post_mode = 'reply';
1681          $update_message = true;
1682      }
1683      else if ($mode == 'edit')
1684      {
1685          $post_mode = ($data_ary['topic_posts_approved'] + $data_ary['topic_posts_unapproved'] + $data_ary['topic_posts_softdeleted'] == 1) ? 'edit_topic' : (($data_ary['topic_first_post_id'] == $data_ary['post_id']) ? 'edit_first_post' : (($data_ary['topic_last_post_id'] == $data_ary['post_id']) ? 'edit_last_post' : 'edit'));
1686      }
1687   
1688      // First of all make sure the subject and topic title are having the correct length.
1689      // To achieve this without cutting off between special chars we convert to an array and then count the elements.
1690      $subject = truncate_string($subject, 120);
1691      $data_ary['topic_title'] = truncate_string($data_ary['topic_title'], 120);
1692   
1693      // Collect some basic information about which tables and which rows to update/insert
1694      $sql_data = $topic_row = array();
1695      $poster_id = ($mode == 'edit') ? $data_ary['poster_id'] : (int) $user->data['user_id'];
1696   
1697      // Retrieve some additional information if not present
1698      if ($mode == 'edit' && (!isset($data_ary['post_visibility']) || !isset($data_ary['topic_visibility']) || $data_ary['post_visibility'] === false || $data_ary['topic_visibility'] === false))
1699      {
1700          $sql = 'SELECT p.post_visibility, t.topic_type, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, t.topic_visibility
1701              FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p
1702              WHERE t.topic_id = p.topic_id
1703                  AND p.post_id = ' . $data_ary['post_id'];
1704          $result = $db->sql_query($sql);
1705          $topic_row = $db->sql_fetchrow($result);
1706          $db->sql_freeresult($result);
1707   
1708          $data_ary['topic_visibility'] = $topic_row['topic_visibility'];
1709          $data_ary['post_visibility'] = $topic_row['post_visibility'];
1710      }
1711   
1712      // This variable indicates if the user is able to post or put into the queue
1713      $post_visibility = ITEM_APPROVED;
1714   
1715      // Check the permissions for post approval.
1716      // Moderators must go through post approval like ordinary users.
1717      if (!$auth->acl_get('f_noapprove', $data_ary['forum_id']))
1718      {
1719          // Post not approved, but in queue
1720          $post_visibility = ITEM_UNAPPROVED;
1721          switch ($post_mode)
1722          {
1723              case 'edit_first_post':
1724              case 'edit':
1725              case 'edit_last_post':
1726              case 'edit_topic':
1727                  $post_visibility = ITEM_REAPPROVE;
1728              break;
1729          }
1730      }
1731      else if (isset($data_ary['post_visibility']) && $data_ary['post_visibility'] !== false)
1732      {
1733          $post_visibility = $data_ary['post_visibility'];
1734      }
1735   
1736      // MODs/Extensions are able to force any visibility on posts
1737      if (isset($data_ary['force_approved_state']))
1738      {
1739          $post_visibility = (in_array((int) $data_ary['force_approved_state'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE))) ? (int) $data_ary['force_approved_state'] : $post_visibility;
1740      }
1741      if (isset($data_ary['force_visibility']))
1742      {
1743          $post_visibility = (in_array((int) $data_ary['force_visibility'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE))) ? (int) $data_ary['force_visibility'] : $post_visibility;
1744      }
1745   
1746      // Start the transaction here
1747      $db->sql_transaction('begin');
1748   
1749      // Collect Information
1750      switch ($post_mode)
1751      {
1752          case 'post':
1753          case 'reply':
1754              $sql_data[POSTS_TABLE]['sql'] = array(
1755                  'forum_id'            => $data_ary['forum_id'],
1756                  'poster_id'            => (int) $user->data['user_id'],
1757                  'icon_id'            => $data_ary['icon_id'],
1758                  'poster_ip'            => $user->ip,
1759                  'post_time'            => $current_time,
1760                  'post_visibility'    => $post_visibility,
1761                  'enable_bbcode'        => $data_ary['enable_bbcode'],
1762                  'enable_smilies'    => $data_ary['enable_smilies'],
1763                  'enable_magic_url'    => $data_ary['enable_urls'],
1764                  'enable_sig'        => $data_ary['enable_sig'],
1765                  'post_username'        => (!$user->data['is_registered']) ? $username : '',
1766                  'post_subject'        => $subject,
1767                  'post_text'            => $data_ary['message'],
1768                  'post_checksum'        => $data_ary['message_md5'],
1769                  'post_attachment'    => (!empty($data_ary['attachment_data'])) ? 1 : 0,
1770                  'bbcode_bitfield'    => $data_ary['bbcode_bitfield'],
1771                  'bbcode_uid'        => $data_ary['bbcode_uid'],
1772                  'post_postcount'    => ($auth->acl_get('f_postcount', $data_ary['forum_id'])) ? 1 : 0,
1773                  'post_edit_locked'    => $data_ary['post_edit_locked']
1774              );
1775          break;
1776   
1777          case 'edit_first_post':
1778          case 'edit':
1779   
1780          case 'edit_last_post':
1781          case 'edit_topic':
1782   
1783              // If edit reason is given always display edit info
1784   
1785              // If editing last post then display no edit info
1786              // If m_edit permission then display no edit info
1787              // If normal edit display edit info
1788   
1789              // Display edit info if edit reason given or user is editing his post, which is not the last within the topic.
1790              if ($data_ary['post_edit_reason'] || (!$auth->acl_get('m_edit', $data_ary['forum_id']) && ($post_mode == 'edit' || $post_mode == 'edit_first_post')))
1791              {
1792                  $data_ary['post_edit_reason']        = truncate_string($data_ary['post_edit_reason'], 255, 255, false);
1793   
1794                  $sql_data[POSTS_TABLE]['sql']    = array(
1795                      'post_edit_time'    => $current_time,
1796                      'post_edit_reason'    => $data_ary['post_edit_reason'],
1797                      'post_edit_user'    => (int) $data_ary['post_edit_user'],
1798                  );
1799   
1800                  $sql_data[POSTS_TABLE]['stat'][] = 'post_edit_count = post_edit_count + 1';
1801              }
1802              else if (!$data_ary['post_edit_reason'] && $mode == 'edit' && $auth->acl_get('m_edit', $data_ary['forum_id']))
1803              {
1804                  $sql_data[POSTS_TABLE]['sql'] = array(
1805                      'post_edit_reason'    => '',
1806                  );
1807              }
1808   
1809              // If the person editing this post is different to the one having posted then we will add a log entry stating the edit
1810              // Could be simplified by only adding to the log if the edit is not tracked - but this may confuse admins/mods
1811              if ($user->data['user_id'] != $poster_id)
1812              {
1813                  $log_subject = ($subject) ? $subject : $data_ary['topic_title'];
1814                  $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_POST_EDITED', false, array(
1815                      'forum_id' => $data_ary['forum_id'],
1816                      'topic_id' => $data_ary['topic_id'],
1817                      'post_id'  => $data_ary['post_id'],
1818                      $log_subject,
1819                      (!empty($username)) ? $username : $user->lang['GUEST'],
1820                      $data_ary['post_edit_reason']
1821                  ));
1822              }
1823   
1824              if (!isset($sql_data[POSTS_TABLE]['sql']))
1825              {
1826                  $sql_data[POSTS_TABLE]['sql'] = array();
1827              }
1828   
1829              $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array(
1830                  'forum_id'            => $data_ary['forum_id'],
1831                  'poster_id'            => $data_ary['poster_id'],
1832                  'icon_id'            => $data_ary['icon_id'],
1833                  // We will change the visibility later
1834                  //'post_visibility'    => $post_visibility,
1835                  'enable_bbcode'        => $data_ary['enable_bbcode'],
1836                  'enable_smilies'    => $data_ary['enable_smilies'],
1837                  'enable_magic_url'    => $data_ary['enable_urls'],
1838                  'enable_sig'        => $data_ary['enable_sig'],
1839                  'post_username'        => ($username && $data_ary['poster_id'] == ANONYMOUS) ? $username : '',
1840                  'post_subject'        => $subject,
1841                  'post_checksum'        => $data_ary['message_md5'],
1842                  'post_attachment'    => (!empty($data_ary['attachment_data'])) ? 1 : 0,
1843                  'bbcode_bitfield'    => $data_ary['bbcode_bitfield'],
1844                  'bbcode_uid'        => $data_ary['bbcode_uid'],
1845                  'post_edit_locked'    => $data_ary['post_edit_locked'])
1846              );
1847   
1848              if ($update_message)
1849              {
1850                  $sql_data[POSTS_TABLE]['sql']['post_text'] = $data_ary['message'];
1851              }
1852   
1853          break;
1854      }
1855   
1856      // And the topic ladies and gentlemen
1857      switch ($post_mode)
1858      {
1859          case 'post':
1860              $sql_data[TOPICS_TABLE]['sql'] = array(
1861                  'topic_poster'                => (int) $user->data['user_id'],
1862                  'topic_time'                => $current_time,
1863                  'topic_last_view_time'        => $current_time,
1864                  'forum_id'                    => $data_ary['forum_id'],
1865                  'icon_id'                    => $data_ary['icon_id'],
1866                  'topic_posts_approved'        => ($post_visibility == ITEM_APPROVED) ? 1 : 0,
1867                  'topic_posts_softdeleted'    => ($post_visibility == ITEM_DELETED) ? 1 : 0,
1868                  'topic_posts_unapproved'    => ($post_visibility == ITEM_UNAPPROVED) ? 1 : 0,
1869                  'topic_visibility'            => $post_visibility,
1870                  'topic_delete_user'            => ($post_visibility != ITEM_APPROVED) ? (int) $user->data['user_id'] : 0,
1871                  'topic_title'                => $subject,
1872                  'topic_first_poster_name'    => (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : ''),
1873                  'topic_first_poster_colour'    => $user->data['user_colour'],
1874                  'topic_type'                => $topic_type,
1875                  'topic_time_limit'            => $topic_type != POST_NORMAL ? ($data_ary['topic_time_limit'] * 86400) : 0,
1876                  'topic_attachment'            => (!empty($data_ary['attachment_data'])) ? 1 : 0,
1877                  'topic_status'                => (isset($data_ary['topic_status'])) ? $data_ary['topic_status'] : ITEM_UNLOCKED,
1878              );
1879   
1880              if (isset($poll_ary['poll_options']) && !empty($poll_ary['poll_options']))
1881              {
1882                  $poll_start = ($poll_ary['poll_start']) ? $poll_ary['poll_start'] : $current_time;
1883                  $poll_length = $poll_ary['poll_length'] * 86400;
1884                  if ($poll_length < 0)
1885                  {
1886                      $poll_start = $poll_start + $poll_length;
1887                      if ($poll_start < 0)
1888                      {
1889                          $poll_start = 0;
1890                      }
1891                      $poll_length = 1;
1892                  }
1893   
1894                  $sql_data[TOPICS_TABLE]['sql'] = array_merge($sql_data[TOPICS_TABLE]['sql'], array(
1895                      'poll_title'        => $poll_ary['poll_title'],
1896                      'poll_start'        => $poll_start,
1897                      'poll_max_options'    => $poll_ary['poll_max_options'],
1898                      'poll_length'        => $poll_length,
1899                      'poll_vote_change'    => $poll_ary['poll_vote_change'])
1900                  );
1901              }
1902   
1903              $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data_ary['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : '');
1904   
1905              if ($post_visibility == ITEM_APPROVED)
1906              {
1907                  $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_approved = forum_topics_approved + 1';
1908                  $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_approved = forum_posts_approved + 1';
1909              }
1910              else if ($post_visibility == ITEM_UNAPPROVED)
1911              {
1912                  $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_unapproved = forum_topics_unapproved + 1';
1913                  $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_unapproved = forum_posts_unapproved + 1';
1914              }
1915              else if ($post_visibility == ITEM_DELETED)
1916              {
1917                  $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_softdeleted = forum_topics_softdeleted + 1';
1918                  $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_softdeleted = forum_posts_softdeleted + 1';
1919              }
1920          break;
1921   
1922          case 'reply':
1923              $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_view_time = ' . $current_time . ',
1924                  topic_bumped = 0,
1925                  topic_bumper = 0' .
1926                  (($post_visibility == ITEM_APPROVED) ? ', topic_posts_approved = topic_posts_approved + 1' : '') .
1927                  (($post_visibility == ITEM_UNAPPROVED) ? ', topic_posts_unapproved = topic_posts_unapproved + 1' : '') .
1928                  (($post_visibility == ITEM_DELETED) ? ', topic_posts_softdeleted = topic_posts_softdeleted + 1' : '') .
1929                  ((!empty($data_ary['attachment_data']) || (isset($data_ary['topic_attachment']) && $data_ary['topic_attachment'])) ? ', topic_attachment = 1' : '');
1930   
1931              $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data_ary['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : '');
1932   
1933              if ($post_visibility == ITEM_APPROVED)
1934              {
1935                  $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_approved = forum_posts_approved + 1';
1936              }
1937              else if ($post_visibility == ITEM_UNAPPROVED)
1938              {
1939                  $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_unapproved = forum_posts_unapproved + 1';
1940              }
1941              else if ($post_visibility == ITEM_DELETED)
1942              {
1943                  $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_softdeleted = forum_posts_softdeleted + 1';
1944              }
1945          break;
1946   
1947          case 'edit_topic':
1948          case 'edit_first_post':
1949              if (isset($poll_ary['poll_options']))
1950              {
1951                  $poll_start = ($poll_ary['poll_start'] || empty($poll_ary['poll_options'])) ? $poll_ary['poll_start'] : $current_time;
1952                  $poll_length = $poll_ary['poll_length'] * 86400;
1953                  if ($poll_length < 0)
1954                  {
1955                      $poll_start = $poll_start + $poll_length;
1956                      if ($poll_start < 0)
1957                      {
1958                          $poll_start = 0;
1959                      }
1960                      $poll_length = 1;
1961                  }
1962              }
1963   
1964              $sql_data[TOPICS_TABLE]['sql'] = array(
1965                  'forum_id'                    => $data_ary['forum_id'],
1966                  'icon_id'                    => $data_ary['icon_id'],
1967                  'topic_title'                => $subject,
1968                  'topic_first_poster_name'    => $username,
1969                  'topic_type'                => $topic_type,
1970                  'topic_time_limit'            => $topic_type != POST_NORMAL ? ($data_ary['topic_time_limit'] * 86400) : 0,
1971                  'poll_title'                => (isset($poll_ary['poll_options'])) ? $poll_ary['poll_title'] : '',
1972                  'poll_start'                => (isset($poll_ary['poll_options'])) ? $poll_start : 0,
1973                  'poll_max_options'            => (isset($poll_ary['poll_options'])) ? $poll_ary['poll_max_options'] : 1,
1974                  'poll_length'                => (isset($poll_ary['poll_options'])) ? $poll_length : 0,
1975                  'poll_vote_change'            => (isset($poll_ary['poll_vote_change'])) ? $poll_ary['poll_vote_change'] : 0,
1976                  'topic_last_view_time'        => $current_time,
1977   
1978                  'topic_attachment'            => (!empty($data_ary['attachment_data'])) ? 1 : (isset($data_ary['topic_attachment']) ? $data_ary['topic_attachment'] : 0),
1979              );
1980   
1981          break;
1982      }
1983   
1984      $poll = $poll_ary;
1985      $data = $data_ary;
1986      /**
1987      * Modify sql query data for post submitting
1988      *
1989      * @event core.submit_post_modify_sql_data
1990      * @var    array    data                Array with the data for the post
1991      * @var    array    poll                Array with the poll data for the post
1992      * @var    string    post_mode            Variable containing posting mode value
1993      * @var    bool    sql_data            Array with the data for the posting SQL query
1994      * @var    string    subject                Variable containing post subject value
1995      * @var    int        topic_type            Variable containing topic type value
1996      * @var    string    username            Variable containing post author name
1997      * @since 3.1.3-RC1
1998      */
1999      $vars = array(
2000          'data',
2001          'poll',
2002          'post_mode',
2003          'sql_data',
2004          'subject',
2005          'topic_type',
2006          'username',
2007      );
2008      extract($phpbb_dispatcher->trigger_event('core.submit_post_modify_sql_data', compact($vars)));
2009      $poll_ary = $poll;
2010      $data_ary = $data;
2011      unset($poll);
2012      unset($data);
2013   
2014      // Submit new topic
2015      if ($post_mode == 'post')
2016      {
2017          $sql = 'INSERT INTO ' . TOPICS_TABLE . ' ' .
2018              $db->sql_build_array('INSERT', $sql_data[TOPICS_TABLE]['sql']);
2019          $db->sql_query($sql);
2020   
2021          $data_ary['topic_id'] = $db->sql_nextid();
2022   
2023          $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array(
2024              'topic_id' => $data_ary['topic_id'])
2025          );
2026          unset($sql_data[TOPICS_TABLE]['sql']);
2027      }
2028   
2029      // Submit new post
2030      if ($post_mode == 'post' || $post_mode == 'reply')
2031      {
2032          if ($post_mode == 'reply')
2033          {
2034              $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array(
2035                  'topic_id' => $data_ary['topic_id'],
2036              ));
2037          }
2038   
2039          $sql = 'INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data[POSTS_TABLE]['sql']);
2040          $db->sql_query($sql);
2041          $data_ary['post_id'] = $db->sql_nextid();
2042   
2043          if ($post_mode == 'post' || $post_visibility == ITEM_APPROVED)
2044          {
2045              $sql_data[TOPICS_TABLE]['sql'] = array(
2046                  'topic_last_post_id'        => $data_ary['post_id'],
2047                  'topic_last_post_time'        => $current_time,
2048                  'topic_last_poster_id'        => $sql_data[POSTS_TABLE]['sql']['poster_id'],
2049                  'topic_last_poster_name'    => ($user->data['user_id'] == ANONYMOUS) ? $sql_data[POSTS_TABLE]['sql']['post_username'] : $user->data['username'],
2050                  'topic_last_poster_colour'    => $user->data['user_colour'],
2051                  'topic_last_post_subject'    => (string) $subject,
2052              );
2053          }
2054   
2055          if ($post_mode == 'post')
2056          {
2057              $sql_data[TOPICS_TABLE]['sql']['topic_first_post_id'] = $data_ary['post_id'];
2058          }
2059   
2060          // Update total post count and forum information
2061          if ($post_visibility == ITEM_APPROVED)
2062          {
2063              if ($post_mode == 'post')
2064              {
2065                  $config->increment('num_topics', 1, false);
2066              }
2067              $config->increment('num_posts', 1, false);
2068   
2069              $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . $data_ary['post_id'];
2070              $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'";
2071              $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . $current_time;
2072              $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $user->data['user_id'];
2073              $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape((!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : '')) . "'";
2074              $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($user->data['user_colour']) . "'";
2075          }
2076   
2077          unset($sql_data[POSTS_TABLE]['sql']);
2078      }
2079   
2080      // Update the topics table
2081      if (isset($sql_data[TOPICS_TABLE]['sql']))
2082      {
2083          $sql = 'UPDATE ' . TOPICS_TABLE . '
2084              SET ' . $db->sql_build_array('UPDATE', $sql_data[TOPICS_TABLE]['sql']) . '
2085              WHERE topic_id = ' . $data_ary['topic_id'];
2086          $db->sql_query($sql);
2087   
2088          unset($sql_data[TOPICS_TABLE]['sql']);
2089      }
2090   
2091      // Update the posts table
2092      if (isset($sql_data[POSTS_TABLE]['sql']))
2093      {
2094          $sql = 'UPDATE ' . POSTS_TABLE . '
2095              SET ' . $db->sql_build_array('UPDATE', $sql_data[POSTS_TABLE]['sql']) . '
2096              WHERE post_id = ' . $data_ary['post_id'];
2097          $db->sql_query($sql);
2098   
2099          unset($sql_data[POSTS_TABLE]['sql']);
2100      }
2101   
2102      // Update Poll Tables
2103      if (isset($poll_ary['poll_options']))
2104      {
2105          $cur_poll_options = array();
2106   
2107          if ($mode == 'edit')
2108          {
2109              $sql = 'SELECT *
2110                  FROM ' . POLL_OPTIONS_TABLE . '
2111                  WHERE topic_id = ' . $data_ary['topic_id'] . '
2112                  ORDER BY poll_option_id';
2113              $result = $db->sql_query($sql);
2114   
2115              $cur_poll_options = array();
2116              while ($row = $db->sql_fetchrow($result))
2117              {
2118                  $cur_poll_options[] = $row;
2119              }
2120              $db->sql_freeresult($result);
2121          }
2122   
2123          $sql_insert_ary = array();
2124   
2125          for ($i = 0, $size = count($poll_ary['poll_options']); $i < $size; $i++)
2126          {
2127              if (strlen(trim($poll_ary['poll_options'][$i])))
2128              {
2129                  if (empty($cur_poll_options[$i]))
2130                  {
2131                      // If we add options we need to put them to the end to be able to preserve votes...
2132                      $sql_insert_ary[] = array(
2133                          'poll_option_id'    => (int) count($cur_poll_options) + 1 + count($sql_insert_ary),
2134                          'topic_id'            => (int) $data_ary['topic_id'],
2135                          'poll_option_text'    => (string) $poll_ary['poll_options'][$i]
2136                      );
2137                  }
2138                  else if ($poll_ary['poll_options'][$i] != $cur_poll_options[$i])
2139                  {
2140                      $sql = 'UPDATE ' . POLL_OPTIONS_TABLE . "
2141                          SET poll_option_text = '" . $db->sql_escape($poll_ary['poll_options'][$i]) . "'
2142                          WHERE poll_option_id = " . $cur_poll_options[$i]['poll_option_id'] . '
2143                              AND topic_id = ' . $data_ary['topic_id'];
2144                      $db->sql_query($sql);
2145                  }
2146              }
2147          }
2148   
2149          $db->sql_multi_insert(POLL_OPTIONS_TABLE, $sql_insert_ary);
2150   
2151          if (count($poll_ary['poll_options']) < count($cur_poll_options))
2152          {
2153              $sql = 'DELETE FROM ' . POLL_OPTIONS_TABLE . '
2154                  WHERE poll_option_id > ' . count($poll_ary['poll_options']) . '
2155                      AND topic_id = ' . $data_ary['topic_id'];
2156              $db->sql_query($sql);
2157          }
2158   
2159          // If edited, we would need to reset votes (since options can be re-ordered above, you can't be sure if the change is for changing the text or adding an option
2160          if ($mode == 'edit' && count($poll_ary['poll_options']) != count($cur_poll_options))
2161          {
2162              $db->sql_query('DELETE FROM ' . POLL_VOTES_TABLE . ' WHERE topic_id = ' . $data_ary['topic_id']);
2163              $db->sql_query('UPDATE ' . POLL_OPTIONS_TABLE . ' SET poll_option_total = 0 WHERE topic_id = ' . $data_ary['topic_id']);
2164          }
2165      }
2166   
2167      // Submit Attachments
2168      if (!empty($data_ary['attachment_data']) && $data_ary['post_id'] && in_array($mode, array('post', 'reply', 'quote', 'edit')))
2169      {
2170          $space_taken = $files_added = 0;
2171          $orphan_rows = array();
2172   
2173          foreach ($data_ary['attachment_data'] as $pos => $attach_row)
2174          {
2175              $orphan_rows[(int) $attach_row['attach_id']] = array();
2176          }
2177   
2178          if (count($orphan_rows))
2179          {
2180              $sql = 'SELECT attach_id, filesize, physical_filename
2181                  FROM ' . ATTACHMENTS_TABLE . '
2182                  WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . '
2183                      AND is_orphan = 1
2184                      AND poster_id = ' . $user->data['user_id'];
2185              $result = $db->sql_query($sql);
2186   
2187              $orphan_rows = array();
2188              while ($row = $db->sql_fetchrow($result))
2189              {
2190                  $orphan_rows[$row['attach_id']] = $row;
2191              }
2192              $db->sql_freeresult($result);
2193          }
2194   
2195          foreach ($data_ary['attachment_data'] as $pos => $attach_row)
2196          {
2197              if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']]))
2198              {
2199                  continue;
2200              }
2201   
2202              if (preg_match('/[\x{10000}-\x{10FFFF}]/u', $attach_row['attach_comment']))
2203              {
2204                  trigger_error('ATTACH_COMMENT_NO_EMOJIS');
2205              }
2206   
2207              if (!$attach_row['is_orphan'])
2208              {
2209                  // update entry in db if attachment already stored in db and filespace
2210                  $sql = 'UPDATE ' . ATTACHMENTS_TABLE . "
2211                      SET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "'
2212                      WHERE attach_id = " . (int) $attach_row['attach_id'] . '
2213                          AND is_orphan = 0';
2214                  $db->sql_query($sql);
2215              }
2216              else
2217              {
2218                  // insert attachment into db
2219                  if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($orphan_rows[$attach_row['attach_id']]['physical_filename'])))
2220                  {
2221                      continue;
2222                  }
2223   
2224                  $space_taken += $orphan_rows[$attach_row['attach_id']]['filesize'];
2225                  $files_added++;
2226   
2227                  $attach_sql = array(
2228                      'post_msg_id'        => $data_ary['post_id'],
2229                      'topic_id'            => $data_ary['topic_id'],
2230                      'is_orphan'            => 0,
2231                      'poster_id'            => $poster_id,
2232                      'attach_comment'    => $attach_row['attach_comment'],
2233                  );
2234   
2235                  $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . '
2236                      WHERE attach_id = ' . $attach_row['attach_id'] . '
2237                          AND is_orphan = 1
2238                          AND poster_id = ' . $user->data['user_id'];
2239                  $db->sql_query($sql);
2240              }
2241          }
2242   
2243          if ($space_taken && $files_added)
2244          {
2245              $config->increment('upload_dir_size', $space_taken, false);
2246              $config->increment('num_files', $files_added, false);
2247          }
2248      }
2249   
2250      $first_post_has_topic_info = ($post_mode == 'edit_first_post' &&
2251              (($post_visibility == ITEM_DELETED && $data_ary['topic_posts_softdeleted'] == 1) ||
2252              ($post_visibility == ITEM_UNAPPROVED && $data_ary['topic_posts_unapproved'] == 1) ||
2253              ($post_visibility == ITEM_REAPPROVE && $data_ary['topic_posts_unapproved'] == 1) ||
2254              ($post_visibility == ITEM_APPROVED && $data_ary['topic_posts_approved'] == 1)));
2255      // Fix the post's and topic's visibility and first/last post information, when the post is edited
2256      if (($post_mode != 'post' && $post_mode != 'reply') && $data_ary['post_visibility'] != $post_visibility)
2257      {
2258          // If the post was not approved, it could also be the starter,
2259          // so we sync the starter after approving/restoring, to ensure that the stats are correct
2260          // Same applies for the last post
2261          $is_starter = ($post_mode == 'edit_first_post' || $post_mode == 'edit_topic' || $data_ary['post_visibility'] != ITEM_APPROVED);
2262          $is_latest = ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $data_ary['post_visibility'] != ITEM_APPROVED);
2263   
2264          /* @var $phpbb_content_visibility \phpbb\content_visibility */
2265          $phpbb_content_visibility = $phpbb_container->get('content.visibility');
2266          $phpbb_content_visibility->set_post_visibility($post_visibility, $data_ary['post_id'], $data_ary['topic_id'], $data_ary['forum_id'], $user->data['user_id'], time(), '', $is_starter, $is_latest);
2267      }
2268      else if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $first_post_has_topic_info)
2269      {
2270          if ($post_visibility == ITEM_APPROVED || $data_ary['topic_visibility'] == $post_visibility)
2271          {
2272              // only the subject can be changed from edit
2273              $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($subject) . "'";
2274   
2275              // Maybe not only the subject, but also changing anonymous usernames. ;)
2276              if ($data_ary['poster_id'] == ANONYMOUS)
2277              {
2278                  $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape($username) . "'";
2279              }
2280   
2281              if ($post_visibility == ITEM_APPROVED)
2282              {
2283                  // this does not _necessarily_ mean that we must update the info again,
2284                  // it just means that we might have to
2285                  $sql = 'SELECT forum_last_post_id, forum_last_post_subject
2286                      FROM ' . FORUMS_TABLE . '
2287                      WHERE forum_id = ' . (int) $data_ary['forum_id'];
2288                  $result = $db->sql_query($sql);
2289                  $row = $db->sql_fetchrow($result);
2290                  $db->sql_freeresult($result);
2291   
2292                  // this post is the latest post in the forum, better update
2293                  if ($row['forum_last_post_id'] == $data_ary['post_id'] && ($row['forum_last_post_subject'] !== $subject || $data_ary['poster_id'] == ANONYMOUS))
2294                  {
2295                      // the post's subject changed
2296                      if ($row['forum_last_post_subject'] !== $subject)
2297                      {
2298                          $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'";
2299                      }
2300   
2301                      // Update the user name if poster is anonymous... just in case a moderator changed it
2302                      if ($data_ary['poster_id'] == ANONYMOUS)
2303                      {
2304                          $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($username) . "'";
2305                      }
2306                  }
2307              }
2308          }
2309      }
2310   
2311      // Update forum stats
2312      $where_sql = array(
2313          POSTS_TABLE        => 'post_id = ' . $data_ary['post_id'],
2314          TOPICS_TABLE    => 'topic_id = ' . $data_ary['topic_id'],
2315          FORUMS_TABLE    => 'forum_id = ' . $data_ary['forum_id'],
2316          USERS_TABLE        => 'user_id = ' . $poster_id
2317      );
2318   
2319      foreach ($sql_data as $table => $update_ary)
2320      {
2321          if (isset($update_ary['stat']) && implode('', $update_ary['stat']))
2322          {
2323              $sql = "UPDATE $table SET " . implode(', ', $update_ary['stat']) . ' WHERE ' . $where_sql[$table];
2324              $db->sql_query($sql);
2325          }
2326      }
2327   
2328      // Delete topic shadows (if any exist). We do not need a shadow topic for an global announcement
2329      if ($topic_type == POST_GLOBAL)
2330      {
2331          $sql = 'DELETE FROM ' . TOPICS_TABLE . '
2332              WHERE topic_moved_id = ' . $data_ary['topic_id'];
2333          $db->sql_query($sql);
2334      }
2335   
2336      // Committing the transaction before updating search index
2337      $db->sql_transaction('commit');
2338   
2339      // Delete draft if post was loaded...
2340      $draft_id = $request->variable('draft_loaded', 0);
2341      if ($draft_id)
2342      {
2343          $sql = 'DELETE FROM ' . DRAFTS_TABLE . "
2344              WHERE draft_id = $draft_id
2345                  AND user_id = {$user->data['user_id']}";
2346          $db->sql_query($sql);
2347      }
2348   
2349      // Index message contents
2350      if ($update_search_index && $data_ary['enable_indexing'])
2351      {
2352          // Select the search method and do some additional checks to ensure it can actually be utilised
2353          $search_type = $config['search_type'];
2354   
2355          if (!class_exists($search_type))
2356          {
2357              trigger_error('NO_SUCH_SEARCH_MODULE');
2358          }
2359   
2360          $error = false;
2361          $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher);
2362   
2363          if ($error)
2364          {
2365              trigger_error($error);
2366          }
2367   
2368          $search->index($mode, $data_ary['post_id'], $data_ary['message'], $subject, $poster_id, $data_ary['forum_id']);
2369      }
2370   
2371      // Topic Notification, do not change if moderator is changing other users posts...
2372      if ($user->data['user_id'] == $poster_id)
2373      {
2374          if (!$data_ary['notify_set'] && $data_ary['notify'])
2375          {
2376              $sql = 'INSERT INTO ' . TOPICS_WATCH_TABLE . ' (user_id, topic_id)
2377                  VALUES (' . $user->data['user_id'] . ', ' . $data_ary['topic_id'] . ')';
2378              $db->sql_query($sql);
2379          }
2380          else if (($config['email_enable'] || $config['jab_enable']) && $data_ary['notify_set'] && !$data_ary['notify'])
2381          {
2382              $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . '
2383                  WHERE user_id = ' . $user->data['user_id'] . '
2384                      AND topic_id = ' . $data_ary['topic_id'];
2385              $db->sql_query($sql);
2386          }
2387      }
2388   
2389      if ($mode == 'post' || $mode == 'reply' || $mode == 'quote')
2390      {
2391          // Mark this topic as posted to
2392          markread('post', $data_ary['forum_id'], $data_ary['topic_id']);
2393      }
2394   
2395      // Mark this topic as read
2396      // We do not use post_time here, this is intended (post_time can have a date in the past if editing a message)
2397      markread('topic', $data_ary['forum_id'], $data_ary['topic_id'], time());
2398   
2399      //
2400      if ($config['load_db_lastread'] && $user->data['is_registered'])
2401      {
2402          $sql = 'SELECT mark_time
2403              FROM ' . FORUMS_TRACK_TABLE . '
2404              WHERE user_id = ' . $user->data['user_id'] . '
2405                  AND forum_id = ' . $data_ary['forum_id'];
2406          $result = $db->sql_query($sql);
2407          $f_mark_time = (int) $db->sql_fetchfield('mark_time');
2408          $db->sql_freeresult($result);
2409      }
2410      else if ($config['load_anon_lastread'] || $user->data['is_registered'])
2411      {
2412          $f_mark_time = false;
2413      }
2414   
2415      if (($config['load_db_lastread'] && $user->data['is_registered']) || $config['load_anon_lastread'] || $user->data['is_registered'])
2416      {
2417          // Update forum info
2418          $sql = 'SELECT forum_last_post_time
2419              FROM ' . FORUMS_TABLE . '
2420              WHERE forum_id = ' . $data_ary['forum_id'];
2421          $result = $db->sql_query($sql);
2422          $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time');
2423          $db->sql_freeresult($result);
2424   
2425          update_forum_tracking_info($data_ary['forum_id'], $forum_last_post_time, $f_mark_time, false);
2426      }
2427   
2428      // If a username was supplied or the poster is a guest, we will use the supplied username.
2429      // Doing it this way we can use "...post by guest-username..." in notifications when
2430      // "guest-username" is supplied or ommit the username if it is not.
2431      $username = ($username !== '' || !$user->data['is_registered']) ? $username : $user->data['username'];
2432   
2433      // Send Notifications
2434      $notification_data = array_merge($data_ary, array(
2435          'topic_title'        => (isset($data_ary['topic_title'])) ? $data_ary['topic_title'] : $subject,
2436          'post_username'        => $username,
2437          'poster_id'            => $poster_id,
2438          'post_text'            => $data_ary['message'],
2439          'post_time'            => $current_time,
2440          'post_subject'        => $subject,
2441      ));
2442   
2443      /**
2444      * This event allows you to modify the notification data upon submission
2445      *
2446      * @event core.modify_submit_notification_data
2447      * @var    array    notification_data    The notification data to be inserted in to the database
2448      * @var    array    data_ary            The data array with a lot of the post submission data
2449      * @var     string    mode                The posting mode
2450      * @var    int        poster_id            The poster id
2451      * @since 3.2.4-RC1
2452      */
2453      $vars = array('notification_data', 'data_ary', 'mode', 'poster_id');
2454      extract($phpbb_dispatcher->trigger_event('core.modify_submit_notification_data', compact($vars)));
2455   
2456      /* @var $phpbb_notifications \phpbb\notification\manager */
2457      $phpbb_notifications = $phpbb_container->get('notification_manager');
2458   
2459      if ($post_visibility == ITEM_APPROVED)
2460      {
2461          switch ($mode)
2462          {
2463              case 'post':
2464                  $phpbb_notifications->add_notifications(array(
2465                      'notification.type.quote',
2466                      'notification.type.topic',
2467                  ), $notification_data);
2468              break;
2469   
2470              case 'reply':
2471              case 'quote':
2472                  $phpbb_notifications->add_notifications(array(
2473                      'notification.type.quote',
2474                      'notification.type.bookmark',
2475                      'notification.type.post',
2476                      'notification.type.forum',
2477                  ), $notification_data);
2478              break;
2479   
2480              case 'edit_topic':
2481              case 'edit_first_post':
2482              case 'edit':
2483              case 'edit_last_post':
2484                  if ($user->data['user_id'] == $poster_id)
2485                  {
2486                      $phpbb_notifications->update_notifications(array(
2487                          'notification.type.quote',
2488                      ), $notification_data);
2489                  }
2490   
2491                  $phpbb_notifications->update_notifications(array(
2492                      'notification.type.bookmark',
2493                      'notification.type.topic',
2494                      'notification.type.post',
2495                      'notification.type.forum',
2496                  ), $notification_data);
2497              break;
2498          }
2499      }
2500      else if ($post_visibility == ITEM_UNAPPROVED)
2501      {
2502          switch ($mode)
2503          {
2504              case 'post':
2505                  $phpbb_notifications->add_notifications('notification.type.topic_in_queue', $notification_data);
2506              break;
2507   
2508              case 'reply':
2509              case 'quote':
2510                  $phpbb_notifications->add_notifications('notification.type.post_in_queue', $notification_data);
2511              break;
2512   
2513              case 'edit_topic':
2514              case 'edit_first_post':
2515              case 'edit':
2516              case 'edit_last_post':
2517                  // Nothing to do here
2518              break;
2519          }
2520      }
2521      else if ($post_visibility == ITEM_REAPPROVE)
2522      {
2523          switch ($mode)
2524          {
2525              case 'edit_topic':
2526              case 'edit_first_post':
2527                  $phpbb_notifications->add_notifications('notification.type.topic_in_queue', $notification_data);
2528   
2529                  // Delete the approve_post notification so we can notify the user again,
2530                  // when his post got reapproved
2531                  $phpbb_notifications->delete_notifications('notification.type.approve_post', $notification_data['post_id']);
2532              break;
2533   
2534              case 'edit':
2535              case 'edit_last_post':
2536                  $phpbb_notifications->add_notifications('notification.type.post_in_queue', $notification_data);
2537   
2538                  // Delete the approve_post notification so we can notify the user again,
2539                  // when his post got reapproved
2540                  $phpbb_notifications->delete_notifications('notification.type.approve_post', $notification_data['post_id']);
2541              break;
2542   
2543              case 'post':
2544              case 'reply':
2545              case 'quote':
2546                  // Nothing to do here
2547              break;
2548          }
2549      }
2550      else if ($post_visibility == ITEM_DELETED)
2551      {
2552          switch ($mode)
2553          {
2554              case 'post':
2555              case 'reply':
2556              case 'quote':
2557              case 'edit_topic':
2558              case 'edit_first_post':
2559              case 'edit':
2560              case 'edit_last_post':
2561                  // Nothing to do here
2562              break;
2563          }
2564      }
2565   
2566      $params = [];
2567      $add_anchor = '';
2568      $url = "{$phpbb_root_path}viewtopic.$phpEx";
2569   
2570      if ($post_visibility == ITEM_APPROVED ||
2571          ($auth->acl_get('m_softdelete', $data_ary['forum_id']) && $post_visibility == ITEM_DELETED) ||
2572          ($auth->acl_get('m_approve', $data_ary['forum_id']) && in_array($post_visibility, array(ITEM_UNAPPROVED, ITEM_REAPPROVE))))
2573      {
2574          if ($mode != 'post')
2575          {
2576              $params['p'] = $data_ary['post_id'];
2577              $add_anchor = '#p' . $data_ary['post_id'];
2578          }
2579          else
2580          {
2581              $params['t'] = $data_ary['topic_id'];
2582          }
2583      }
2584      else if ($mode != 'post' && $post_mode != 'edit_first_post' && $post_mode != 'edit_topic')
2585      {
2586          $params['t'] = $data_ary['topic_id'];
2587      }
2588      else
2589      {
2590          $url = "{$phpbb_root_path}viewforum.$phpEx";
2591          $params['f'] = $data_ary['forum_id'];
2592      }
2593   
2594      $url = append_sid($url, $params) . $add_anchor;
2595   
2596      $poll = $poll_ary;
2597      $data = $data_ary;
2598      /**
2599      * This event is used for performing actions directly after a post or topic
2600      * has been submitted. When a new topic is posted, the topic ID is
2601      * available in the $data array.
2602      *
2603      * The only action that can be done by altering data made available to this
2604      * event is to modify the return URL ($url).
2605      *
2606      * @event core.submit_post_end
2607      * @var    string    mode                Variable containing posting mode value
2608      * @var    string    subject                Variable containing post subject value
2609      * @var    string    username            Variable containing post author name
2610      * @var    int        topic_type            Variable containing topic type value
2611      * @var    array    poll                Array with the poll data for the post
2612      * @var    array    data                Array with the data for the post
2613      * @var    int        post_visibility        Variable containing up to date post visibility
2614      * @var    bool    update_message        Flag indicating if the post will be updated
2615      * @var    bool    update_search_index    Flag indicating if the search index will be updated
2616      * @var    string    url                    The "Return to topic" URL
2617      *
2618      * @since 3.1.0-a3
2619      * @changed 3.1.0-RC3 Added vars mode, subject, username, topic_type,
2620      *        poll, update_message, update_search_index
2621      */
2622      $vars = array(
2623          'mode',
2624          'subject',
2625          'username',
2626          'topic_type',
2627          'poll',
2628          'data',
2629          'post_visibility',
2630          'update_message',
2631          'update_search_index',
2632          'url',
2633      );
2634      extract($phpbb_dispatcher->trigger_event('core.submit_post_end', compact($vars)));
2635      $data_ary = $data;
2636      $poll_ary = $poll;
2637      unset($data);
2638      unset($poll);
2639   
2640      return $url;
2641  }
2642   
2643  /**
2644  * Handle topic bumping
2645  * @param int $forum_id The ID of the forum the topic is being bumped belongs to
2646  * @param int $topic_id The ID of the topic is being bumping
2647  * @param array $post_data Passes some topic parameters:
2648  *                - 'topic_title'
2649  *                - 'topic_last_post_id'
2650  *                - 'topic_last_poster_id'
2651  *                - 'topic_last_post_subject'
2652  *                - 'topic_last_poster_name'
2653  *                - 'topic_last_poster_colour'
2654  * @param int $bump_time The time at which topic was bumped, usually it is a current time as obtained via time().
2655  * @return string An URL to the bumped topic, example: ./viewtopic.php?p=3#p3
2656  */
2657  function phpbb_bump_topic($forum_id, $topic_id, $post_data, $bump_time = false)
2658  {
2659      global $config, $db, $user, $phpEx, $phpbb_root_path, $phpbb_log;
2660   
2661      if ($bump_time === false)
2662      {
2663          $bump_time = time();
2664      }
2665   
2666      // Begin bumping
2667      $db->sql_transaction('begin');
2668   
2669      // Update the topic's last post post_time
2670      $sql = 'UPDATE ' . POSTS_TABLE . "
2671          SET post_time = $bump_time
2672          WHERE post_id = {$post_data['topic_last_post_id']}
2673              AND topic_id = $topic_id";
2674      $db->sql_query($sql);
2675   
2676      // Sync the topic's last post time, the rest of the topic's last post data isn't changed
2677      $sql = 'UPDATE ' . TOPICS_TABLE . "
2678          SET topic_last_post_time = $bump_time,
2679              topic_bumped = 1,
2680              topic_bumper = " . $user->data['user_id'] . "
2681          WHERE topic_id = $topic_id";
2682      $db->sql_query($sql);
2683   
2684      // Update the forum's last post info
2685      $sql = 'UPDATE ' . FORUMS_TABLE . "
2686          SET forum_last_post_id = " . $post_data['topic_last_post_id'] . ",
2687              forum_last_poster_id = " . $post_data['topic_last_poster_id'] . ",
2688              forum_last_post_subject = '" . $db->sql_escape($post_data['topic_last_post_subject']) . "',
2689              forum_last_post_time = $bump_time,
2690              forum_last_poster_name = '" . $db->sql_escape($post_data['topic_last_poster_name']) . "',
2691              forum_last_poster_colour = '" . $db->sql_escape($post_data['topic_last_poster_colour']) . "'
2692          WHERE forum_id = $forum_id";
2693      $db->sql_query($sql);
2694   
2695      // Update bumper's time of the last posting to prevent flood
2696      $sql = 'UPDATE ' . USERS_TABLE . "
2697          SET user_lastpost_time = $bump_time
2698          WHERE user_id = " . $user->data['user_id'];
2699      $db->sql_query($sql);
2700   
2701      $db->sql_transaction('commit');
2702   
2703      // Mark this topic as posted to
2704      markread('post', $forum_id, $topic_id, $bump_time);
2705   
2706      // Mark this topic as read
2707      markread('topic', $forum_id, $topic_id, $bump_time);
2708   
2709      // Update forum tracking info
2710      if ($config['load_db_lastread'] && $user->data['is_registered'])
2711      {
2712          $sql = 'SELECT mark_time
2713              FROM ' . FORUMS_TRACK_TABLE . '
2714              WHERE user_id = ' . $user->data['user_id'] . '
2715                  AND forum_id = ' . $forum_id;
2716          $result = $db->sql_query($sql);
2717          $f_mark_time = (int) $db->sql_fetchfield('mark_time');
2718          $db->sql_freeresult($result);
2719      }
2720      else if ($config['load_anon_lastread'] || $user->data['is_registered'])
2721      {
2722          $f_mark_time = false;
2723      }
2724   
2725      if (($config['load_db_lastread'] && $user->data['is_registered']) || $config['load_anon_lastread'] || $user->data['is_registered'])
2726      {
2727          // Update forum info
2728          $sql = 'SELECT forum_last_post_time
2729              FROM ' . FORUMS_TABLE . '
2730              WHERE forum_id = ' . $forum_id;
2731          $result = $db->sql_query($sql);
2732          $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time');
2733          $db->sql_freeresult($result);
2734   
2735          update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_time, false);
2736      }
2737   
2738      $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_BUMP_TOPIC', false, array(
2739          'forum_id' => $forum_id,
2740          'topic_id' => $topic_id,
2741          $post_data['topic_title']
2742      ));
2743   
2744      $url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "p={$post_data['topic_last_post_id']}") . "#p{$post_data['topic_last_post_id']}";
2745   
2746      return $url;
2747  }
2748   
2749  /**
2750  * Show upload popup (progress bar)
2751  */
2752  function phpbb_upload_popup($forum_style = 0)
2753  {
2754      global $template, $user;
2755   
2756      ($forum_style) ? $user->setup('posting', $forum_style) : $user->setup('posting');
2757   
2758      page_header($user->lang['PROGRESS_BAR']);
2759   
2760      $template->set_filenames(array(
2761              'popup'    => 'posting_progress_bar.html')
2762      );
2763   
2764      $template->assign_vars(array(
2765              'PROGRESS_BAR'    => $user->img('upload_bar', $user->lang['UPLOAD_IN_PROGRESS']))
2766      );
2767   
2768      $template->display('popup');
2769   
2770      garbage_collection();
2771      exit_handler();
2772  }
2773   
2774  /**
2775  * Do the various checks required for removing posts as well as removing it
2776  *
2777  * @param int        $forum_id        The id of the forum
2778  * @param int        $topic_id        The id of the topic
2779  * @param int        $post_id        The id of the post
2780  * @param array        $post_data        Array with the post data
2781  * @param bool        $is_soft        The flag indicating whether it is the soft delete mode
2782  * @param string        $delete_reason    Description for the post deletion reason
2783  *
2784  * @return null
2785  */
2786  function phpbb_handle_post_delete($forum_id, $topic_id, $post_id, &$post_data, $is_soft = false, $delete_reason = '')
2787  {
2788      global $user, $auth, $config, $request;
2789      global $phpbb_root_path, $phpEx, $phpbb_log, $phpbb_dispatcher;
2790   
2791      $force_delete_allowed = $force_softdelete_allowed = false;
2792      $perm_check = ($is_soft) ? 'softdelete' : 'delete';
2793   
2794      /**
2795      * This event allows to modify the conditions for the post deletion
2796      *
2797      * @event core.handle_post_delete_conditions
2798      * @var    int        forum_id        The id of the forum
2799      * @var    int        topic_id        The id of the topic
2800      * @var    int        post_id            The id of the post
2801      * @var    array    post_data        Array with the post data
2802      * @var    bool    is_soft            The flag indicating whether it is the soft delete mode
2803      * @var    string    delete_reason    Description for the post deletion reason
2804      * @var    bool    force_delete_allowed        Allow the user to delete the post (all permissions and conditions are ignored)
2805      * @var    bool    force_softdelete_allowed    Allow the user to softdelete the post (all permissions and conditions are ignored)
2806      * @var    string    perm_check        The deletion mode softdelete|delete
2807      * @since 3.1.11-RC1
2808      */
2809      $vars = array(
2810          'forum_id',
2811          'topic_id',
2812          'post_id',
2813          'post_data',
2814          'is_soft',
2815          'delete_reason',
2816          'force_delete_allowed',
2817          'force_softdelete_allowed',
2818          'perm_check',
2819      );
2820      extract($phpbb_dispatcher->trigger_event('core.handle_post_delete_conditions', compact($vars)));
2821   
2822      // If moderator removing post or user itself removing post, present a confirmation screen
2823      if ($force_delete_allowed || ($is_soft && $force_softdelete_allowed) || $auth->acl_get("m_$perm_check", $forum_id) || ($post_data['poster_id'] == $user->data['user_id'] && $user->data['is_registered'] && $auth->acl_get("f_$perm_check", $forum_id) && $post_id == $post_data['topic_last_post_id'] && !$post_data['post_edit_locked'] && ($post_data['post_time'] > time() - ($config['delete_time'] * 60) || !$config['delete_time'])))
2824      {
2825          $s_hidden_fields = array(
2826              'p'        => $post_id,
2827              'f'        => $forum_id,
2828              'mode'    => ($is_soft) ? 'soft_delete' : 'delete',
2829          );
2830   
2831          if (confirm_box(true))
2832          {
2833              $data = array(
2834                  'topic_first_post_id'    => $post_data['topic_first_post_id'],
2835                  'topic_last_post_id'    => $post_data['topic_last_post_id'],
2836                  'topic_posts_approved'        => $post_data['topic_posts_approved'],
2837                  'topic_posts_unapproved'    => $post_data['topic_posts_unapproved'],
2838                  'topic_posts_softdeleted'    => $post_data['topic_posts_softdeleted'],
2839                  'topic_visibility'        => $post_data['topic_visibility'],
2840                  'topic_type'            => $post_data['topic_type'],
2841                  'post_visibility'        => $post_data['post_visibility'],
2842                  'post_reported'            => $post_data['post_reported'],
2843                  'post_time'                => $post_data['post_time'],
2844                  'poster_id'                => $post_data['poster_id'],
2845                  'post_postcount'        => $post_data['post_postcount'],
2846              );
2847   
2848              $next_post_id = delete_post($forum_id, $topic_id, $post_id, $data, $is_soft, $delete_reason);
2849              $post_username = ($post_data['poster_id'] == ANONYMOUS && !empty($post_data['post_username'])) ? $post_data['post_username'] : $post_data['username'];
2850   
2851              if ($next_post_id === false)
2852              {
2853                  $phpbb_log->add('mod', $user->data['user_id'], $user->ip, (($is_soft) ? 'LOG_SOFTDELETE_TOPIC' : 'LOG_DELETE_TOPIC'), false, array(
2854                      'forum_id' => $forum_id,
2855                      'topic_id' => $topic_id,
2856                      $post_data['topic_title'],
2857                      $post_username,
2858                      $delete_reason
2859                  ));
2860   
2861                  $meta_info = append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id");
2862                  $message = $user->lang['POST_DELETED'];
2863              }
2864              else
2865              {
2866                  $phpbb_log->add('mod', $user->data['user_id'], $user->ip, (($is_soft) ? 'LOG_SOFTDELETE_POST' : 'LOG_DELETE_POST'), false, array(
2867                      'forum_id' => $forum_id,
2868                      'topic_id' => $topic_id,
2869                      'post_id'  => $post_id,
2870                      $post_data['post_subject'],
2871                      $post_username,
2872                      $delete_reason
2873                  ));
2874   
2875                  if ($next_post_id > 0)
2876                  {
2877                      $meta_info = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "p=$next_post_id") . "#p$next_post_id";
2878                  }
2879                  else
2880                  {
2881                      $meta_info = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "t=$topic_id");
2882                  }
2883                  $message = $user->lang['POST_DELETED'];
2884   
2885                  if (!$request->is_ajax())
2886                  {
2887                      $message .= '<br /><br />' . $user->lang('RETURN_TOPIC', '<a href="' . $meta_info . '">', '</a>');
2888                  }
2889              }
2890   
2891              meta_refresh(3, $meta_info);
2892              if (!$request->is_ajax())
2893              {
2894                  $message .= '<br /><br />' . $user->lang('RETURN_FORUM', '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id) . '">', '</a>');
2895              }
2896              trigger_error($message);
2897          }
2898          else
2899          {
2900              global $template;
2901   
2902              $can_delete = $force_delete_allowed || ($auth->acl_get('m_delete', $forum_id) || ($post_data['poster_id'] == $user->data['user_id'] && $user->data['is_registered'] && $auth->acl_get('f_delete', $forum_id)));
2903              $can_softdelete = $force_softdelete_allowed || ($auth->acl_get('m_softdelete', $forum_id) || ($post_data['poster_id'] == $user->data['user_id'] && $user->data['is_registered'] && $auth->acl_get('f_softdelete', $forum_id)));
2904   
2905              $template->assign_vars(array(
2906                  'S_SOFTDELETED'            => $post_data['post_visibility'] == ITEM_DELETED,
2907                  'S_CHECKED_PERMANENT'    => $request->is_set_post('delete_permanent') ? ' checked="checked"' : '',
2908                  'S_ALLOWED_DELETE'        => $can_delete,
2909                  'S_ALLOWED_SOFTDELETE'    => $can_softdelete,
2910              ));
2911   
2912              $l_confirm = 'DELETE_POST';
2913              if ($post_data['post_visibility'] == ITEM_DELETED)
2914              {
2915                  $l_confirm .= '_PERMANENTLY';
2916                  $s_hidden_fields['delete_permanent'] = '1';
2917              }
2918              else if (!$can_softdelete)
2919              {
2920                  $s_hidden_fields['delete_permanent'] = '1';
2921              }
2922   
2923              confirm_box(false, [$l_confirm, 1], build_hidden_fields($s_hidden_fields), 'confirm_delete_body.html');
2924          }
2925      }
2926   
2927      // If we are here the user is not able to delete - present the correct error message
2928      if ($post_data['poster_id'] != $user->data['user_id'] && $auth->acl_get('f_delete', $forum_id))
2929      {
2930          trigger_error('DELETE_OWN_POSTS');
2931      }
2932   
2933      if ($post_data['poster_id'] == $user->data['user_id'] && $auth->acl_get('f_delete', $forum_id) && $post_id != $post_data['topic_last_post_id'])
2934      {
2935          trigger_error('CANNOT_DELETE_REPLIED');
2936      }
2937   
2938      trigger_error('USER_CANNOT_DELETE');
2939  }
2940