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