Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

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