Verzeichnisstruktur phpBB-3.1.0


Veröffentlicht
27.10.2014

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

functions_posting.php

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