[ Index ]

PHP Cross Reference of phpBB-3.2.11-deutsch

title

Body

[close]

/includes/ -> functions_posting.php (source)

   1  <?php
   2  /**
   3  *
   4  * This file is part of the phpBB Forum Software package.
   5  *
   6  * @copyright (c) phpBB Limited <https://www.phpbb.com>
   7  * @license GNU General Public License, version 2 (GPL-2.0)
   8  *
   9  * For full copyright and license information, please see
  10  * the docs/CREDITS.txt file.
  11  *
  12  */
  13  
  14  /**
  15  * @ignore
  16  */
  17  if (!defined('IN_PHPBB'))
  18  {
  19      exit;
  20  }
  21  
  22  /**
  23  * Fill smiley templates (or just the variables) with smilies, either in a window or inline
  24  */
  25  function generate_smilies($mode, $forum_id)
  26  {
  27      global $db, $user, $config, $template, $phpbb_dispatcher, $request;
  28      global $phpEx, $phpbb_root_path, $phpbb_container, $phpbb_path_helper;
  29  
  30      /* @var $pagination \phpbb\pagination */
  31      $pagination = $phpbb_container->get('pagination');
  32      $base_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&amp;f=' . $forum_id);
  33      $start = $request->variable('start', 0);
  34  
  35      if ($mode == 'window')
  36      {
  37          if ($forum_id)
  38          {
  39              $sql = 'SELECT forum_style
  40                  FROM ' . FORUMS_TABLE . "
  41                  WHERE forum_id = $forum_id";
  42              $result = $db->sql_query_limit($sql, 1);
  43              $row = $db->sql_fetchrow($result);
  44              $db->sql_freeresult($result);
  45  
  46              $user->setup('posting', (int) $row['forum_style']);
  47          }
  48          else
  49          {
  50              $user->setup('posting');
  51          }
  52  
  53          page_header($user->lang['SMILIES']);
  54  
  55          $sql_ary = [
  56              'SELECT'    => 'COUNT(s.smiley_id) AS item_count',
  57              'FROM'        => [
  58                  SMILIES_TABLE => 's',
  59              ],
  60              'GROUP_BY'    => 's.smiley_url',
  61          ];
  62  
  63          /**
  64          * Modify SQL query that fetches the total number of smilies in window mode
  65          *
  66          * @event core.generate_smilies_count_sql_before
  67          * @var int        forum_id    Forum where smilies are generated
  68          * @var array    sql_ary        Array with the SQL query
  69          * @var string    base_url    URL for the "More smilies" link and its pagination
  70          * @since 3.2.9-RC1
  71          * @changed 3.2.10-RC1 Added base_url
  72          */
  73          $vars = [
  74              'forum_id',
  75              'sql_ary',
  76              'base_url',
  77          ];
  78          extract($phpbb_dispatcher->trigger_event('core.generate_smilies_count_sql_before', compact($vars)));
  79  
  80          $sql = $db->sql_build_query('SELECT', $sql_ary);
  81          $result = $db->sql_query($sql, 3600);
  82  
  83          $smiley_count = 0;
  84          while ($row = $db->sql_fetchrow($result))
  85          {
  86              ++$smiley_count;
  87          }
  88          $db->sql_freeresult($result);
  89  
  90          $template->set_filenames(array(
  91              'body' => 'posting_smilies.html')
  92          );
  93  
  94          $start = $pagination->validate_start($start, $config['smilies_per_page'], $smiley_count);
  95          $pagination->generate_template_pagination($base_url, 'pagination', 'start', $smiley_count, $config['smilies_per_page'], $start);
  96      }
  97  
  98      $display_link = false;
  99      if ($mode == 'inline')
 100      {
 101          $sql = 'SELECT smiley_id
 102              FROM ' . SMILIES_TABLE . '
 103              WHERE display_on_posting = 0';
 104          $result = $db->sql_query_limit($sql, 1, 0, 3600);
 105  
 106          if ($row = $db->sql_fetchrow($result))
 107          {
 108              $display_link = true;
 109          }
 110          $db->sql_freeresult($result);
 111      }
 112  
 113      if ($mode == 'window')
 114      {
 115          $sql_ary = [
 116              'SELECT'    => 's.smiley_url, MIN(s.emotion) AS emotion, MIN(s.code) AS code, s.smiley_width, s.smiley_height, MIN(s.smiley_order) AS min_smiley_order',
 117              'FROM'        => [
 118                  SMILIES_TABLE => 's',
 119              ],
 120              'GROUP_BY'    => 's.smiley_url, s.smiley_width, s.smiley_height',
 121              'ORDER_BY'    => 'min_smiley_order',
 122          ];
 123      }
 124      else
 125      {
 126          $sql_ary = [
 127              'SELECT'    => 's.*',
 128              'FROM'        => [
 129                  SMILIES_TABLE => 's',
 130              ],
 131              'WHERE'        => 's.display_on_posting = 1',
 132              'ORDER_BY'    => 's.smiley_order',
 133          ];
 134      }
 135  
 136      /**
 137      * Modify the SQL query that fetches the smilies
 138      *
 139      * @event core.generate_smilies_modify_sql
 140      * @var string    mode        Smiley mode, either window or inline
 141      * @var int        forum_id    Forum where smilies are generated, or 0 if composing a private message
 142      * @var array    sql_ary        Array with SQL query data
 143      * @since 3.2.10-RC1
 144      * @since 3.3.1-RC1
 145      */
 146      $vars = [
 147          'mode',
 148          'forum_id',
 149          'sql_ary',
 150      ];
 151      extract($phpbb_dispatcher->trigger_event('core.generate_smilies_modify_sql', compact($vars)));
 152  
 153      $sql = $db->sql_build_query('SELECT', $sql_ary);
 154  
 155      if ($mode == 'window')
 156      {
 157          $result = $db->sql_query_limit($sql, $config['smilies_per_page'], $start, 3600);
 158      }
 159      else
 160      {
 161          $result = $db->sql_query($sql, 3600);
 162      }
 163  
 164      $smilies = array();
 165      while ($row = $db->sql_fetchrow($result))
 166      {
 167          if (empty($smilies[$row['smiley_url']]))
 168          {
 169              $smilies[$row['smiley_url']] = $row;
 170          }
 171      }
 172      $db->sql_freeresult($result);
 173  
 174      /**
 175      * Modify smilies before they are assigned to the template
 176      *
 177      * @event core.generate_smilies_modify_rowset
 178      * @var string    mode        Smiley mode, either window or inline
 179      * @var int        forum_id    Forum where smilies are generated, or 0 if composing a private message
 180      * @var array    smilies        Smiley rows fetched from the database
 181      * @since 3.2.9-RC1
 182      */
 183      $vars = [
 184          'mode',
 185          'forum_id',
 186          'smilies',
 187      ];
 188      extract($phpbb_dispatcher->trigger_event('core.generate_smilies_modify_rowset', compact($vars)));
 189  
 190      if (count($smilies))
 191      {
 192          $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_path_helper->get_web_root_path();
 193  
 194          foreach ($smilies as $row)
 195          {
 196              /**
 197              * Modify smiley root path before populating smiley list
 198              *
 199              * @event core.generate_smilies_before
 200              * @var string  root_path root_path for smilies
 201              * @since 3.1.11-RC1
 202              */
 203              $vars = array('root_path');
 204              extract($phpbb_dispatcher->trigger_event('core.generate_smilies_before', compact($vars)));
 205              $template->assign_block_vars('smiley', array(
 206                  'SMILEY_CODE'    => $row['code'],
 207                  'A_SMILEY_CODE'    => addslashes($row['code']),
 208                  'SMILEY_IMG'    => $root_path . $config['smilies_path'] . '/' . $row['smiley_url'],
 209                  'SMILEY_WIDTH'    => $row['smiley_width'],
 210                  'SMILEY_HEIGHT'    => $row['smiley_height'],
 211                  'SMILEY_DESC'    => $row['emotion'])
 212              );
 213          }
 214      }
 215  
 216      /**
 217      * This event is called after the smilies are populated
 218      *
 219      * @event core.generate_smilies_after
 220      * @var    string    mode            Mode of the smilies: window|inline
 221      * @var    int        forum_id        The forum ID we are currently in
 222      * @var    bool    display_link    Shall we display the "more smilies" link?
 223      * @var string    base_url        URL for the "More smilies" link and its pagination
 224      * @since 3.1.0-a1
 225      * @changed 3.2.10-RC1 Added base_url
 226      */
 227      $vars = [
 228          'mode',
 229          'forum_id',
 230          'display_link',
 231          'base_url',
 232      ];
 233      extract($phpbb_dispatcher->trigger_event('core.generate_smilies_after', compact($vars)));
 234  
 235      if ($mode == 'inline' && $display_link)
 236      {
 237          $template->assign_vars(array(
 238              'S_SHOW_SMILEY_LINK'     => true,
 239              'U_MORE_SMILIES'         => $base_url,
 240          ));
 241      }
 242  
 243      if ($mode == 'window')
 244      {
 245          page_footer();
 246      }
 247  }
 248  
 249  /**
 250  * Update last post information
 251  * Should be used instead of sync() if only the last post information are out of sync... faster
 252  *
 253  * @param    string    $type                Can be forum|topic
 254  * @param    mixed    $ids                topic/forum ids
 255  * @param    bool    $return_update_sql    true: SQL query shall be returned, false: execute SQL
 256  */
 257  function update_post_information($type, $ids, $return_update_sql = false)
 258  {
 259      global $db;
 260  
 261      if (empty($ids))
 262      {
 263          return;
 264      }
 265      if (!is_array($ids))
 266      {
 267          $ids = array($ids);
 268      }
 269  
 270      $update_sql = $empty_forums = $not_empty_forums = array();
 271  
 272      if ($type != 'topic')
 273      {
 274          $topic_join = ', ' . TOPICS_TABLE . ' t';
 275          $topic_condition = 'AND t.topic_id = p.topic_id AND t.topic_visibility = ' . ITEM_APPROVED;
 276      }
 277      else
 278      {
 279          $topic_join = '';
 280          $topic_condition = '';
 281      }
 282  
 283      if (count($ids) == 1)
 284      {
 285          $sql = 'SELECT p.post_id as last_post_id
 286              FROM ' . POSTS_TABLE . " p $topic_join
 287              WHERE " . $db->sql_in_set('p.' . $type . '_id', $ids) . "
 288                  $topic_condition
 289                  AND p.post_visibility = " . ITEM_APPROVED . "
 290              ORDER BY p.post_id DESC";
 291          $result = $db->sql_query_limit($sql, 1);
 292      }
 293      else
 294      {
 295          $sql = 'SELECT p.' . $type . '_id, MAX(p.post_id) as last_post_id
 296              FROM ' . POSTS_TABLE . " p $topic_join
 297              WHERE " . $db->sql_in_set('p.' . $type . '_id', $ids) . "
 298                  $topic_condition
 299                  AND p.post_visibility = " . ITEM_APPROVED . "
 300              GROUP BY p.{$type}_id";
 301          $result = $db->sql_query($sql);
 302      }
 303  
 304      $last_post_ids = array();
 305      while ($row = $db->sql_fetchrow($result))
 306      {
 307          if (count($ids) == 1)
 308          {
 309              $row[$type . '_id'] = $ids[0];
 310          }
 311  
 312          if ($type == 'forum')
 313          {
 314              $not_empty_forums[] = $row['forum_id'];
 315  
 316              if (empty($row['last_post_id']))
 317              {
 318                  $empty_forums[] = $row['forum_id'];
 319              }
 320          }
 321  
 322          $last_post_ids[] = $row['last_post_id'];
 323      }
 324      $db->sql_freeresult($result);
 325  
 326      if ($type == 'forum')
 327      {
 328          $empty_forums = array_merge($empty_forums, array_diff($ids, $not_empty_forums));
 329  
 330          foreach ($empty_forums as $void => $forum_id)
 331          {
 332              $update_sql[$forum_id][] = 'forum_last_post_id = 0';
 333              $update_sql[$forum_id][] = "forum_last_post_subject = ''";
 334              $update_sql[$forum_id][] = 'forum_last_post_time = 0';
 335              $update_sql[$forum_id][] = 'forum_last_poster_id = 0';
 336              $update_sql[$forum_id][] = "forum_last_poster_name = ''";
 337              $update_sql[$forum_id][] = "forum_last_poster_colour = ''";
 338          }
 339      }
 340  
 341      if (count($last_post_ids))
 342      {
 343          $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
 344              FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
 345              WHERE p.poster_id = u.user_id
 346                  AND ' . $db->sql_in_set('p.post_id', $last_post_ids);
 347          $result = $db->sql_query($sql);
 348  
 349          while ($row = $db->sql_fetchrow($result))
 350          {
 351              $update_sql[$row["{$type}_id"]][] = $type . '_last_post_id = ' . (int) $row['post_id'];
 352              $update_sql[$row["{$type}_id"]][] = "{$type}_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'";
 353              $update_sql[$row["{$type}_id"]][] = $type . '_last_post_time = ' . (int) $row['post_time'];
 354              $update_sql[$row["{$type}_id"]][] = $type . '_last_poster_id = ' . (int) $row['poster_id'];
 355              $update_sql[$row["{$type}_id"]][] = "{$type}_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'";
 356              $update_sql[$row["{$type}_id"]][] = "{$type}_last_poster_name = '" . (($row['poster_id'] == ANONYMOUS) ? $db->sql_escape($row['post_username']) : $db->sql_escape($row['username'])) . "'";
 357          }
 358          $db->sql_freeresult($result);
 359      }
 360      unset($empty_forums, $ids, $last_post_ids);
 361  
 362      if ($return_update_sql || !count($update_sql))
 363      {
 364          return $update_sql;
 365      }
 366  
 367      $table = ($type == 'forum') ? FORUMS_TABLE : TOPICS_TABLE;
 368  
 369      foreach ($update_sql as $update_id => $update_sql_ary)
 370      {
 371          $sql = "UPDATE $table
 372              SET " . implode(', ', $update_sql_ary) . "
 373              WHERE {$type}_id = $update_id";
 374          $db->sql_query($sql);
 375      }
 376  
 377      return;
 378  }
 379  
 380  /**
 381  * Generate Topic Icons for display
 382  */
 383  function posting_gen_topic_icons($mode, $icon_id)
 384  {
 385      global $phpbb_root_path, $config, $template, $cache;
 386  
 387      // Grab icons
 388      $icons = $cache->obtain_icons();
 389  
 390      if (!$icon_id)
 391      {
 392          $template->assign_var('S_NO_ICON_CHECKED', ' checked="checked"');
 393      }
 394  
 395      if (count($icons))
 396      {
 397          $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path;
 398  
 399          foreach ($icons as $id => $data)
 400          {
 401              if ($data['display'])
 402              {
 403                  $template->assign_block_vars('topic_icon', array(
 404                      'ICON_ID'        => $id,
 405                      'ICON_IMG'        => $root_path . $config['icons_path'] . '/' . $data['img'],
 406                      'ICON_WIDTH'    => $data['width'],
 407                      'ICON_HEIGHT'    => $data['height'],
 408                      'ICON_ALT'        => $data['alt'],
 409  
 410                      'S_CHECKED'            => ($id == $icon_id) ? true : false,
 411                      'S_ICON_CHECKED'    => ($id == $icon_id) ? ' checked="checked"' : '')
 412                  );
 413              }
 414          }
 415  
 416          return true;
 417      }
 418  
 419      return false;
 420  }
 421  
 422  /**
 423  * Build topic types able to be selected
 424  */
 425  function posting_gen_topic_types($forum_id, $cur_topic_type = POST_NORMAL)
 426  {
 427      global $auth, $user, $template;
 428  
 429      $toggle = false;
 430  
 431      $topic_types = array(
 432          'sticky'            => array('const' => POST_STICKY, 'lang' => 'POST_STICKY'),
 433          'announce'            => array('const' => POST_ANNOUNCE, 'lang' => 'POST_ANNOUNCEMENT'),
 434          'announce_global'    => array('const' => POST_GLOBAL, 'lang' => 'POST_GLOBAL')
 435      );
 436  
 437      $topic_type_array = array();
 438  
 439      foreach ($topic_types as $auth_key => $topic_value)
 440      {
 441          if ($auth->acl_get('f_' . $auth_key, $forum_id))
 442          {
 443              $toggle = true;
 444  
 445              $topic_type_array[] = array(
 446                  'VALUE'            => $topic_value['const'],
 447                  'S_CHECKED'        => ($cur_topic_type == $topic_value['const']) ? ' checked="checked"' : '',
 448                  'L_TOPIC_TYPE'    => $user->lang[$topic_value['lang']]
 449              );
 450          }
 451      }
 452  
 453      if ($toggle)
 454      {
 455          $topic_type_array = array_merge(array(0 => array(
 456              'VALUE'            => POST_NORMAL,
 457              'S_CHECKED'        => ($cur_topic_type == POST_NORMAL) ? ' checked="checked"' : '',
 458              'L_TOPIC_TYPE'    => $user->lang['POST_NORMAL'])),
 459  
 460              $topic_type_array
 461          );
 462  
 463          foreach ($topic_type_array as $array)
 464          {
 465              $template->assign_block_vars('topic_type', $array);
 466          }
 467  
 468          $template->assign_vars(array(
 469              'S_TOPIC_TYPE_STICKY'    => ($auth->acl_get('f_sticky', $forum_id)),
 470              'S_TOPIC_TYPE_ANNOUNCE'    => ($auth->acl_gets('f_announce', 'f_announce_global', $forum_id)),
 471          ));
 472      }
 473  
 474      return $toggle;
 475  }
 476  
 477  //
 478  // Attachment related functions
 479  //
 480  
 481  /**
 482  * Upload Attachment - filedata is generated here
 483  * Uses upload class
 484  *
 485  * @deprecated 3.2.0-a1 (To be removed: 3.4.0)
 486  *
 487  * @param string            $form_name        The form name of the file upload input
 488  * @param int            $forum_id        The id of the forum
 489  * @param bool            $local            Whether the file is local or not
 490  * @param string            $local_storage    The path to the local file
 491  * @param bool            $is_message        Whether it is a PM or not
 492  * @param array            $local_filedata    A filespec object created for the local file
 493  *
 494  * @return array File data array
 495  */
 496  function upload_attachment($form_name, $forum_id, $local = false, $local_storage = '', $is_message = false, $local_filedata = false)
 497  {
 498      global $phpbb_container;
 499  
 500      /** @var \phpbb\attachment\manager $attachment_manager */
 501      $attachment_manager = $phpbb_container->get('attachment.manager');
 502      $file = $attachment_manager->upload($form_name, $forum_id, $local, $local_storage, $is_message, $local_filedata);
 503      unset($attachment_manager);
 504  
 505      return $file;
 506  }
 507  
 508  /**
 509  * Calculate the needed size for Thumbnail
 510  */
 511  function get_img_size_format($width, $height)
 512  {
 513      global $config;
 514  
 515      // Maximum Width the Image can take
 516      $max_width = ($config['img_max_thumb_width']) ? $config['img_max_thumb_width'] : 400;
 517  
 518      if ($width > $height)
 519      {
 520          return array(
 521              round($width * ($max_width / $width)),
 522              round($height * ($max_width / $width))
 523          );
 524      }
 525      else
 526      {
 527          return array(
 528              round($width * ($max_width / $height)),
 529              round($height * ($max_width / $height))
 530          );
 531      }
 532  }
 533  
 534  /**
 535  * Return supported image types
 536  */
 537  function get_supported_image_types($type = false)
 538  {
 539      if (@extension_loaded('gd'))
 540      {
 541          $format = imagetypes();
 542          $new_type = 0;
 543  
 544          if ($type !== false)
 545          {
 546              // Type is one of the IMAGETYPE constants - it is fetched from getimagesize()
 547              switch ($type)
 548              {
 549                  // GIF
 550                  case IMAGETYPE_GIF:
 551                      $new_type = ($format & IMG_GIF) ? IMG_GIF : false;
 552                  break;
 553  
 554                  // JPG, JPC, JP2
 555                  case IMAGETYPE_JPEG:
 556                  case IMAGETYPE_JPC:
 557                  case IMAGETYPE_JPEG2000:
 558                  case IMAGETYPE_JP2:
 559                  case IMAGETYPE_JPX:
 560                  case IMAGETYPE_JB2:
 561                      $new_type = ($format & IMG_JPG) ? IMG_JPG : false;
 562                  break;
 563  
 564                  // PNG
 565                  case IMAGETYPE_PNG:
 566                      $new_type = ($format & IMG_PNG) ? IMG_PNG : false;
 567                  break;
 568  
 569                  // WBMP
 570                  case IMAGETYPE_WBMP:
 571                      $new_type = ($format & IMG_WBMP) ? IMG_WBMP : false;
 572                  break;
 573              }
 574          }
 575          else
 576          {
 577              $new_type = array();
 578              $go_through_types = array(IMG_GIF, IMG_JPG, IMG_PNG, IMG_WBMP);
 579  
 580              foreach ($go_through_types as $check_type)
 581              {
 582                  if ($format & $check_type)
 583                  {
 584                      $new_type[] = $check_type;
 585                  }
 586              }
 587          }
 588  
 589          return array(
 590              'gd'        => ($new_type) ? true : false,
 591              'format'    => $new_type,
 592              'version'    => (function_exists('imagecreatetruecolor')) ? 2 : 1
 593          );
 594      }
 595  
 596      return array('gd' => false);
 597  }
 598  
 599  /**
 600  * Create Thumbnail
 601  */
 602  function create_thumbnail($source, $destination, $mimetype)
 603  {
 604      global $config, $phpbb_filesystem, $phpbb_dispatcher;
 605  
 606      $min_filesize = (int) $config['img_min_thumb_filesize'];
 607      $img_filesize = (file_exists($source)) ? @filesize($source) : false;
 608  
 609      if (!$img_filesize || $img_filesize <= $min_filesize)
 610      {
 611          return false;
 612      }
 613  
 614      $dimension = @getimagesize($source);
 615  
 616      if ($dimension === false)
 617      {
 618          return false;
 619      }
 620  
 621      list($width, $height, $type, ) = $dimension;
 622  
 623      if (empty($width) || empty($height))
 624      {
 625          return false;
 626      }
 627  
 628      list($new_width, $new_height) = get_img_size_format($width, $height);
 629  
 630      // Do not create a thumbnail if the resulting width/height is bigger than the original one
 631      if ($new_width >= $width && $new_height >= $height)
 632      {
 633          return false;
 634      }
 635  
 636      $thumbnail_created = false;
 637  
 638      /**
 639       * Create thumbnail event to replace GD thumbnail creation with for example ImageMagick
 640       *
 641       * @event core.thumbnail_create_before
 642       * @var    string    source                Image source path
 643       * @var    string    destination            Thumbnail destination path
 644       * @var    string    mimetype            Image mime type
 645       * @var    float    new_width            Calculated thumbnail width
 646       * @var    float    new_height            Calculated thumbnail height
 647       * @var    bool    thumbnail_created    Set to true to skip default GD thumbnail creation
 648       * @since 3.2.4
 649       */
 650      $vars = array(
 651          'source',
 652          'destination',
 653          'mimetype',
 654          'new_width',
 655          'new_height',
 656          'thumbnail_created',
 657      );
 658      extract($phpbb_dispatcher->trigger_event('core.thumbnail_create_before', compact($vars)));
 659  
 660      if (!$thumbnail_created)
 661      {
 662          $type = get_supported_image_types($type);
 663  
 664          if ($type['gd'])
 665          {
 666              // If the type is not supported, we are not able to create a thumbnail
 667              if ($type['format'] === false)
 668              {
 669                  return false;
 670              }
 671  
 672              switch ($type['format'])
 673              {
 674                  case IMG_GIF:
 675                      $image = @imagecreatefromgif($source);
 676                  break;
 677  
 678                  case IMG_JPG:
 679                      @ini_set('gd.jpeg_ignore_warning', 1);
 680                      $image = @imagecreatefromjpeg($source);
 681                  break;
 682  
 683                  case IMG_PNG:
 684                      $image = @imagecreatefrompng($source);
 685                  break;
 686  
 687                  case IMG_WBMP:
 688                      $image = @imagecreatefromwbmp($source);
 689                  break;
 690              }
 691  
 692              if (empty($image))
 693              {
 694                  return false;
 695              }
 696  
 697              if ($type['version'] == 1)
 698              {
 699                  $new_image = imagecreate($new_width, $new_height);
 700  
 701                  if ($new_image === false)
 702                  {
 703                      return false;
 704                  }
 705  
 706                  imagecopyresized($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
 707              }
 708              else
 709              {
 710                  $new_image = imagecreatetruecolor($new_width, $new_height);
 711  
 712                  if ($new_image === false)
 713                  {
 714                      return false;
 715                  }
 716  
 717                  // Preserve alpha transparency (png for example)
 718                  @imagealphablending($new_image, false);
 719                  @imagesavealpha($new_image, true);
 720  
 721                  imagecopyresampled($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
 722              }
 723  
 724              // If we are in safe mode create the destination file prior to using the gd functions to circumvent a PHP bug
 725              if (@ini_get('safe_mode') || @strtolower(ini_get('safe_mode')) == 'on')
 726              {
 727                  @touch($destination);
 728              }
 729  
 730              switch ($type['format'])
 731              {
 732                  case IMG_GIF:
 733                      imagegif($new_image, $destination);
 734                  break;
 735  
 736                  case IMG_JPG:
 737                      imagejpeg($new_image, $destination, 90);
 738                  break;
 739  
 740                  case IMG_PNG:
 741                      imagepng($new_image, $destination);
 742                  break;
 743  
 744                  case IMG_WBMP:
 745                      imagewbmp($new_image, $destination);
 746                  break;
 747              }
 748  
 749              imagedestroy($new_image);
 750          }
 751          else
 752          {
 753              return false;
 754          }
 755      }
 756  
 757      if (!file_exists($destination))
 758      {
 759          return false;
 760      }
 761  
 762      try
 763      {
 764          $phpbb_filesystem->phpbb_chmod($destination, \phpbb\filesystem\filesystem_interface::CHMOD_READ | \phpbb\filesystem\filesystem_interface::CHMOD_WRITE);
 765      }
 766      catch (\phpbb\filesystem\exception\filesystem_exception $e)
 767      {
 768          // Do nothing
 769      }
 770  
 771      return true;
 772  }
 773  
 774  /**
 775  * Assign Inline attachments (build option fields)
 776  */
 777  function posting_gen_inline_attachments(&$attachment_data)
 778  {
 779      global $template;
 780  
 781      if (count($attachment_data))
 782      {
 783          $s_inline_attachment_options = '';
 784  
 785          foreach ($attachment_data as $i => $attachment)
 786          {
 787              $s_inline_attachment_options .= '<option value="' . $i . '">' . utf8_basename($attachment['real_filename']) . '</option>';
 788          }
 789  
 790          $template->assign_var('S_INLINE_ATTACHMENT_OPTIONS', $s_inline_attachment_options);
 791  
 792          return true;
 793      }
 794  
 795      return false;
 796  }
 797  
 798  /**
 799  * Generate inline attachment entry
 800  */
 801  function posting_gen_attachment_entry($attachment_data, &$filename_data, $show_attach_box = true)
 802  {
 803      global $template, $config, $phpbb_root_path, $phpEx, $user, $phpbb_dispatcher;
 804  
 805      // Some default template variables
 806      $template->assign_vars(array(
 807          'S_SHOW_ATTACH_BOX'    => $show_attach_box,
 808          'S_HAS_ATTACHMENTS'    => count($attachment_data),
 809          'FILESIZE'            => $config['max_filesize'],
 810          'FILE_COMMENT'        => (isset($filename_data['filecomment'])) ? $filename_data['filecomment'] : '',
 811      ));
 812  
 813      if (count($attachment_data))
 814      {
 815          // We display the posted attachments within the desired order.
 816          ($config['display_order']) ? krsort($attachment_data) : ksort($attachment_data);
 817  
 818          $attachrow_template_vars = [];
 819  
 820          foreach ($attachment_data as $count => $attach_row)
 821          {
 822              $hidden = '';
 823              $attach_row['real_filename'] = utf8_basename($attach_row['real_filename']);
 824  
 825              foreach ($attach_row as $key => $value)
 826              {
 827                  $hidden .= '<input type="hidden" name="attachment_data[' . $count . '][' . $key . ']" value="' . $value . '" />';
 828              }
 829  
 830              $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);
 831  
 832              $attachrow_template_vars[(int) $attach_row['attach_id']] = array(
 833                  'FILENAME'            => utf8_basename($attach_row['real_filename']),
 834                  'A_FILENAME'        => addslashes(utf8_basename($attach_row['real_filename'])),
 835                  'FILE_COMMENT'        => $attach_row['attach_comment'],
 836                  'ATTACH_ID'            => $attach_row['attach_id'],
 837                  'S_IS_ORPHAN'        => $attach_row['is_orphan'],
 838                  'ASSOC_INDEX'        => $count,
 839                  'FILESIZE'            => get_formatted_filesize($attach_row['filesize']),
 840  
 841                  'U_VIEW_ATTACHMENT'    => $download_link,
 842                  'S_HIDDEN'            => $hidden,
 843              );
 844          }
 845  
 846          /**
 847          * Modify inline attachments template vars
 848          *
 849          * @event core.modify_inline_attachments_template_vars
 850          * @var    array    attachment_data                Array containing attachments data
 851          * @var    array    attachrow_template_vars        Array containing attachments template vars
 852          * @since 3.2.2-RC1
 853          */
 854          $vars = array('attachment_data', 'attachrow_template_vars');
 855          extract($phpbb_dispatcher->trigger_event('core.modify_inline_attachments_template_vars', compact($vars)));
 856  
 857          $template->assign_block_vars_array('attach_row', $attachrow_template_vars);
 858      }
 859  
 860      return count($attachment_data);
 861  }
 862  
 863  //
 864  // General Post functions
 865  //
 866  
 867  /**
 868  * Load Drafts
 869  */
 870  function load_drafts($topic_id = 0, $forum_id = 0, $id = 0, $pm_action = '', $msg_id = 0)
 871  {
 872      global $user, $db, $template, $auth;
 873      global $phpbb_root_path, $phpbb_dispatcher, $phpEx;
 874  
 875      $topic_ids = $forum_ids = $draft_rows = array();
 876  
 877      // Load those drafts not connected to forums/topics
 878      // If forum_id == 0 AND topic_id == 0 then this is a PM draft
 879      if (!$topic_id && !$forum_id)
 880      {
 881          $sql_and = ' AND d.forum_id = 0 AND d.topic_id = 0';
 882      }
 883      else
 884      {
 885          $sql_and = '';
 886          $sql_and .= ($forum_id) ? ' AND d.forum_id = ' . (int) $forum_id : '';
 887          $sql_and .= ($topic_id) ? ' AND d.topic_id = ' . (int) $topic_id : '';
 888      }
 889  
 890      $sql = 'SELECT d.*, f.forum_id, f.forum_name
 891          FROM ' . DRAFTS_TABLE . ' d
 892          LEFT JOIN ' . FORUMS_TABLE . ' f ON (f.forum_id = d.forum_id)
 893              WHERE d.user_id = ' . $user->data['user_id'] . "
 894              $sql_and
 895          ORDER BY d.save_time DESC";
 896      $result = $db->sql_query($sql);
 897  
 898      while ($row = $db->sql_fetchrow($result))
 899      {
 900          if ($row['topic_id'])
 901          {
 902              $topic_ids[] = (int) $row['topic_id'];
 903          }
 904          $draft_rows[] = $row;
 905      }
 906      $db->sql_freeresult($result);
 907  
 908      if (!count($draft_rows))
 909      {
 910          return;
 911      }
 912  
 913      $topic_rows = array();
 914      if (count($topic_ids))
 915      {
 916          $sql = 'SELECT topic_id, forum_id, topic_title, topic_poster
 917              FROM ' . TOPICS_TABLE . '
 918              WHERE ' . $db->sql_in_set('topic_id', array_unique($topic_ids));
 919          $result = $db->sql_query($sql);
 920  
 921          while ($row = $db->sql_fetchrow($result))
 922          {
 923              $topic_rows[$row['topic_id']] = $row;
 924          }
 925          $db->sql_freeresult($result);
 926      }
 927  
 928      /**
 929      * Drafts found and their topics
 930      * Edit $draft_rows in order to add or remove drafts loaded
 931      *
 932      * @event core.load_drafts_draft_list_result
 933      * @var    array    draft_rows            The drafts query result. Includes its forum id and everything about the draft
 934      * @var    array    topic_ids            The list of topics got from the topics table
 935      * @var    array    topic_rows            The topics that draft_rows references
 936      * @since 3.1.0-RC3
 937      */
 938      $vars = array('draft_rows', 'topic_ids', 'topic_rows');
 939      extract($phpbb_dispatcher->trigger_event('core.load_drafts_draft_list_result', compact($vars)));
 940  
 941      unset($topic_ids);
 942  
 943      $template->assign_var('S_SHOW_DRAFTS', true);
 944  
 945      foreach ($draft_rows as $draft)
 946      {
 947          $link_topic = $link_forum = $link_pm = false;
 948          $view_url = $title = '';
 949  
 950          if (isset($topic_rows[$draft['topic_id']])
 951              && (
 952                  ($topic_rows[$draft['topic_id']]['forum_id'] && $auth->acl_get('f_read', $topic_rows[$draft['topic_id']]['forum_id']))
 953                  ||
 954                  (!$topic_rows[$draft['topic_id']]['forum_id'] && $auth->acl_getf_global('f_read'))
 955              ))
 956          {
 957              $topic_forum_id = ($topic_rows[$draft['topic_id']]['forum_id']) ? $topic_rows[$draft['topic_id']]['forum_id'] : $forum_id;
 958  
 959              $link_topic = true;
 960              $view_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $topic_forum_id . '&amp;t=' . $draft['topic_id']);
 961              $title = $topic_rows[$draft['topic_id']]['topic_title'];
 962  
 963              $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']);
 964          }
 965          else if ($draft['forum_id'] && $auth->acl_get('f_read', $draft['forum_id']))
 966          {
 967              $link_forum = true;
 968              $view_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $draft['forum_id']);
 969              $title = $draft['forum_name'];
 970  
 971              $insert_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'f=' . $draft['forum_id'] . '&amp;mode=post&amp;d=' . $draft['draft_id']);
 972          }
 973          else
 974          {
 975              // Either display as PM draft if forum_id and topic_id are empty or if access to the forums has been denied afterwards...
 976              $link_pm = true;
 977              $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" : ''));
 978          }
 979  
 980          $template->assign_block_vars('draftrow', array(
 981              'DRAFT_ID'        => $draft['draft_id'],
 982              'DATE'            => $user->format_date($draft['save_time']),
 983              'DRAFT_SUBJECT'    => $draft['draft_subject'],
 984  
 985              'TITLE'            => $title,
 986              'U_VIEW'        => $view_url,
 987              'U_INSERT'        => $insert_url,
 988  
 989              'S_LINK_PM'        => $link_pm,
 990              'S_LINK_TOPIC'    => $link_topic,
 991              'S_LINK_FORUM'    => $link_forum)
 992          );
 993      }
 994  }
 995  
 996  /**
 997  * Topic Review
 998  */
 999  function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id = 0, $show_quote_button = true)
1000  {
1001      global $user, $auth, $db, $template;
1002      global $config, $phpbb_root_path, $phpEx, $phpbb_container, $phpbb_dispatcher;
1003  
1004      /* @var $phpbb_content_visibility \phpbb\content_visibility */
1005      $phpbb_content_visibility = $phpbb_container->get('content.visibility');
1006      $sql_sort = ($mode == 'post_review') ? 'ASC' : 'DESC';
1007  
1008      // Go ahead and pull all data for this topic
1009      $sql = 'SELECT p.post_id
1010          FROM ' . POSTS_TABLE . ' p' . "
1011          WHERE p.topic_id = $topic_id
1012              AND " . $phpbb_content_visibility->get_visibility_sql('post', $forum_id, 'p.') . '
1013              ' . (($mode == 'post_review') ? " AND p.post_id > $cur_post_id" : '') . '
1014              ' . (($mode == 'post_review_edit') ? " AND p.post_id = $cur_post_id" : '') . '
1015          ORDER BY p.post_time ' . $sql_sort . ', p.post_id ' . $sql_sort;
1016      $result = $db->sql_query_limit($sql, $config['posts_per_page']);
1017  
1018      $post_list = array();
1019  
1020      while ($row = $db->sql_fetchrow($result))
1021      {
1022          $post_list[] = $row['post_id'];
1023      }
1024  
1025      $db->sql_freeresult($result);
1026  
1027      if (!count($post_list))
1028      {
1029          return false;
1030      }
1031  
1032      // Handle 'post_review_edit' like 'post_review' from now on
1033      if ($mode == 'post_review_edit')
1034      {
1035          $mode = 'post_review';
1036      }
1037  
1038      $sql_ary = array(
1039          'SELECT'    => 'u.username, u.user_id, u.user_colour, p.*, z.friend, z.foe, uu.username as post_delete_username, uu.user_colour as post_delete_user_colour',
1040  
1041          'FROM'        => array(
1042              USERS_TABLE        => 'u',
1043              POSTS_TABLE        => 'p',
1044          ),
1045  
1046          'LEFT_JOIN'    => array(
1047              array(
1048                  'FROM'    => array(ZEBRA_TABLE => 'z'),
1049                  'ON'    => 'z.user_id = ' . $user->data['user_id'] . ' AND z.zebra_id = p.poster_id',
1050              ),
1051              array(
1052                  'FROM'    => array(USERS_TABLE => 'uu'),
1053                  'ON'    => 'uu.user_id = p.post_delete_user',
1054              ),
1055          ),
1056  
1057          'WHERE'        => $db->sql_in_set('p.post_id', $post_list) . '
1058              AND u.user_id = p.poster_id',
1059      );
1060  
1061      /**
1062      * Event to modify the SQL query for topic reviews
1063      *
1064      * @event core.topic_review_modify_sql_ary
1065      * @var    int        topic_id            The topic ID that is being reviewed
1066      * @var    int        forum_id            The topic's forum ID
1067      * @var    string    mode                The topic review mode
1068      * @var    int        cur_post_id            Post offset ID
1069      * @var    bool    show_quote_button    Flag indicating if the quote button should be displayed
1070      * @var    array    post_list            Array with the post IDs
1071      * @var    array    sql_ary                Array with the SQL query
1072      * @since 3.2.8-RC1
1073      */
1074      $vars = array(
1075          'topic_id',
1076          'forum_id',
1077          'mode',
1078          'cur_post_id',
1079          'show_quote_button',
1080          'post_list',
1081          'sql_ary',
1082      );
1083      extract($phpbb_dispatcher->trigger_event('core.topic_review_modify_sql_ary', compact($vars)));
1084  
1085      $sql = $db->sql_build_query('SELECT', $sql_ary);
1086      $result = $db->sql_query($sql);
1087  
1088      $rowset = array();
1089      $has_attachments = false;
1090      while ($row = $db->sql_fetchrow($result))
1091      {
1092          $rowset[$row['post_id']] = $row;
1093  
1094          if ($row['post_attachment'])
1095          {
1096              $has_attachments = true;
1097          }
1098      }
1099      $db->sql_freeresult($result);
1100  
1101      // Grab extensions
1102      $attachments = array();
1103      if ($has_attachments && $auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id))
1104      {
1105          // Get attachments...
1106          $sql = 'SELECT *
1107              FROM ' . ATTACHMENTS_TABLE . '
1108              WHERE ' . $db->sql_in_set('post_msg_id', $post_list) . '
1109                  AND in_message = 0
1110              ORDER BY filetime DESC, post_msg_id ASC';
1111          $result = $db->sql_query($sql);
1112  
1113          while ($row = $db->sql_fetchrow($result))
1114          {
1115              $attachments[$row['post_msg_id']][] = $row;
1116          }
1117          $db->sql_freeresult($result);
1118      }
1119  
1120      /**
1121      * Event to modify the posts list for topic reviews
1122      *
1123      * @event core.topic_review_modify_post_list
1124      * @var    array    attachments            Array with the post attachments data
1125      * @var    int        cur_post_id            Post offset ID
1126      * @var    int        forum_id            The topic's forum ID
1127      * @var    string    mode                The topic review mode
1128      * @var    array    post_list            Array with the post IDs
1129      * @var    array    rowset                Array with the posts data
1130      * @var    bool    show_quote_button    Flag indicating if the quote button should be displayed
1131      * @var    int        topic_id            The topic ID that is being reviewed
1132      * @since 3.1.9-RC1
1133      */
1134      $vars = array(
1135          'attachments',
1136          'cur_post_id',
1137          'forum_id',
1138          'mode',
1139          'post_list',
1140          'rowset',
1141          'show_quote_button',
1142          'topic_id',
1143      );
1144      extract($phpbb_dispatcher->trigger_event('core.topic_review_modify_post_list', compact($vars)));
1145  
1146      for ($i = 0, $end = count($post_list); $i < $end; ++$i)
1147      {
1148          // A non-existing rowset only happens if there was no user present for the entered poster_id
1149          // This could be a broken posts table.
1150          if (!isset($rowset[$post_list[$i]]))
1151          {
1152              continue;
1153          }
1154  
1155          $row = $rowset[$post_list[$i]];
1156  
1157          $poster_id        = $row['user_id'];
1158          $post_subject    = $row['post_subject'];
1159  
1160          $decoded_message = false;
1161  
1162          if ($show_quote_button && $auth->acl_get('f_reply', $forum_id))
1163          {
1164              $decoded_message = censor_text($row['post_text']);
1165              decode_message($decoded_message, $row['bbcode_uid']);
1166  
1167              $decoded_message = bbcode_nl2br($decoded_message);
1168          }
1169  
1170          $parse_flags = ($row['bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0);
1171          $parse_flags |= ($row['enable_smilies'] ? OPTION_FLAG_SMILIES : 0);
1172          $message = generate_text_for_display($row['post_text'], $row['bbcode_uid'], $row['bbcode_bitfield'], $parse_flags, true);
1173  
1174          if (!empty($attachments[$row['post_id']]))
1175          {
1176              $update_count = array();
1177              parse_attachments($forum_id, $message, $attachments[$row['post_id']], $update_count);
1178          }
1179  
1180          $post_subject = censor_text($post_subject);
1181  
1182          $post_anchor = ($mode == 'post_review') ? 'ppr' . $row['post_id'] : 'pr' . $row['post_id'];
1183          $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']}");
1184  
1185          $l_deleted_message = '';
1186          if ($row['post_visibility'] == ITEM_DELETED)
1187          {
1188              $display_postername = get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']);
1189  
1190              // User having deleted the post also being the post author?
1191              if (!$row['post_delete_user'] || $row['post_delete_user'] == $poster_id)
1192              {
1193                  $display_username = $display_postername;
1194              }
1195              else
1196              {
1197                  $display_username = get_username_string('full', $row['post_delete_user'], $row['post_delete_username'], $row['post_delete_user_colour']);
1198              }
1199  
1200              if ($row['post_delete_reason'])
1201              {
1202                  $l_deleted_message = $user->lang('POST_DELETED_BY_REASON', $display_postername, $display_username, $user->format_date($row['post_delete_time'], false, true), $row['post_delete_reason']);
1203              }
1204              else
1205              {
1206                  $l_deleted_message = $user->lang('POST_DELETED_BY', $display_postername, $display_username, $user->format_date($row['post_delete_time'], false, true));
1207              }
1208          }
1209  
1210          $post_row = array(
1211              'POST_AUTHOR_FULL'        => get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
1212              'POST_AUTHOR_COLOUR'    => get_username_string('colour', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
1213              'POST_AUTHOR'            => get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
1214              'U_POST_AUTHOR'            => get_username_string('profile', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
1215  
1216              'S_HAS_ATTACHMENTS'    => (!empty($attachments[$row['post_id']])) ? true : false,
1217              'S_FRIEND'            => ($row['friend']) ? true : false,
1218              'S_IGNORE_POST'        => ($row['foe']) ? true : false,
1219              '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>') : '',
1220              'S_POST_DELETED'    => ($row['post_visibility'] == ITEM_DELETED) ? true : false,
1221              'L_DELETE_POST'        => $l_deleted_message,
1222  
1223              'POST_SUBJECT'        => $post_subject,
1224              'MINI_POST_IMG'        => $user->img('icon_post_target', $user->lang['POST']),
1225              'POST_DATE'            => $user->format_date($row['post_time']),
1226              'MESSAGE'            => $message,
1227              'DECODED_MESSAGE'    => $decoded_message,
1228              'POST_ID'            => $row['post_id'],
1229              'POST_TIME'            => $row['post_time'],
1230              'USER_ID'            => $row['user_id'],
1231              'U_MINI_POST'        => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'p=' . $row['post_id']) . '#p' . $row['post_id'],
1232              '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) : '',
1233              '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'])) : '',
1234          );
1235  
1236          $current_row_number = $i;
1237  
1238          /**
1239          * Event to modify the template data block for topic reviews
1240          *
1241          * @event core.topic_review_modify_row
1242          * @var    string    mode                The review mode
1243          * @var    int        topic_id            The topic that is being reviewed
1244          * @var    int        forum_id            The topic's forum
1245          * @var    int        cur_post_id            Post offset id
1246          * @var    int        current_row_number    Number of the current row being iterated
1247          * @var    array    post_row            Template block array of the current post
1248          * @var    array    row                    Array with original post and user data
1249          * @since 3.1.4-RC1
1250          */
1251          $vars = array(
1252              'mode',
1253              'topic_id',
1254              'forum_id',
1255              'cur_post_id',
1256              'current_row_number',
1257              'post_row',
1258              'row',
1259          );
1260          extract($phpbb_dispatcher->trigger_event('core.topic_review_modify_row', compact($vars)));
1261  
1262          $template->assign_block_vars($mode . '_row', $post_row);
1263  
1264          // Display not already displayed Attachments for this post, we already parsed them. ;)
1265          if (!empty($attachments[$row['post_id']]))
1266          {
1267              foreach ($attachments[$row['post_id']] as $attachment)
1268              {
1269                  $template->assign_block_vars($mode . '_row.attachment', array(
1270                      'DISPLAY_ATTACHMENT'    => $attachment)
1271                  );
1272              }
1273          }
1274  
1275          unset($rowset[$post_list[$i]]);
1276      }
1277  
1278      if ($mode == 'topic_review')
1279      {
1280          $template->assign_var('QUOTE_IMG', $user->img('icon_post_quote', $user->lang['REPLY_WITH_QUOTE']));
1281      }
1282  
1283      return true;
1284  }
1285  
1286  //
1287  // Post handling functions
1288  //
1289  
1290  /**
1291  * Delete Post
1292  */
1293  function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $softdelete_reason = '')
1294  {
1295      global $db, $user, $phpbb_container, $phpbb_dispatcher;
1296      global $config, $phpEx, $phpbb_root_path;
1297  
1298      // Specify our post mode
1299      $post_mode = 'delete';
1300      if (($data['topic_first_post_id'] === $data['topic_last_post_id']) && ($data['topic_posts_approved'] + $data['topic_posts_unapproved'] + $data['topic_posts_softdeleted'] == 1))
1301      {
1302          $post_mode = 'delete_topic';
1303      }
1304      else if ($data['topic_first_post_id'] == $post_id)
1305      {
1306          $post_mode = 'delete_first_post';
1307      }
1308      else if ($data['topic_last_post_id'] == $post_id)
1309      {
1310          $post_mode = 'delete_last_post';
1311      }
1312      $sql_data = array();
1313      $next_post_id = false;
1314  
1315      include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
1316  
1317      $db->sql_transaction('begin');
1318  
1319      // we must make sure to update forums that contain the shadow'd topic
1320      if ($post_mode == 'delete_topic')
1321      {
1322          $shadow_forum_ids = array();
1323  
1324          $sql = 'SELECT forum_id
1325              FROM ' . TOPICS_TABLE . '
1326              WHERE ' . $db->sql_in_set('topic_moved_id', $topic_id);
1327          $result = $db->sql_query($sql);
1328          while ($row = $db->sql_fetchrow($result))
1329          {
1330              if (!isset($shadow_forum_ids[(int) $row['forum_id']]))
1331              {
1332                  $shadow_forum_ids[(int) $row['forum_id']] = 1;
1333              }
1334              else
1335              {
1336                  $shadow_forum_ids[(int) $row['forum_id']]++;
1337              }
1338          }
1339          $db->sql_freeresult($result);
1340      }
1341  
1342      /* @var $phpbb_content_visibility \phpbb\content_visibility */
1343      $phpbb_content_visibility = $phpbb_container->get('content.visibility');
1344  
1345      // (Soft) delete the post
1346      if ($is_soft && ($post_mode != 'delete_topic'))
1347      {
1348          $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));
1349      }
1350      else if (!$is_soft)
1351      {
1352          if (!delete_posts('post_id', array($post_id), false, false, false))
1353          {
1354              // Try to delete topic, we may had an previous error causing inconsistency
1355              if ($post_mode == 'delete_topic')
1356              {
1357                  delete_topics('topic_id', array($topic_id), false);
1358              }
1359              trigger_error('ALREADY_DELETED');
1360          }
1361      }
1362  
1363      $db->sql_transaction('commit');
1364  
1365      // Collect the necessary information for updating the tables
1366      $sql_data[FORUMS_TABLE] = $sql_data[TOPICS_TABLE] = '';
1367      switch ($post_mode)
1368      {
1369          case 'delete_topic':
1370  
1371              foreach ($shadow_forum_ids as $updated_forum => $topic_count)
1372              {
1373                  // counting is fun! we only have to do count($forum_ids) number of queries,
1374                  // even if the topic is moved back to where its shadow lives (we count how many times it is in a forum)
1375                  $sql = 'UPDATE ' . FORUMS_TABLE . '
1376                      SET forum_topics_approved = forum_topics_approved - ' . $topic_count . '
1377                      WHERE forum_id = ' . $updated_forum;
1378                  $db->sql_query($sql);
1379                  update_post_information('forum', $updated_forum);
1380              }
1381  
1382              if ($is_soft)
1383              {
1384                  $phpbb_content_visibility->set_topic_visibility(ITEM_DELETED, $topic_id, $forum_id, $user->data['user_id'], time(), $softdelete_reason);
1385              }
1386              else
1387              {
1388                  delete_topics('topic_id', array($topic_id), false);
1389  
1390                  $phpbb_content_visibility->remove_topic_from_statistic($data, $sql_data);
1391                  $config->increment('num_posts', -1, false);
1392  
1393                  $update_sql = update_post_information('forum', $forum_id, true);
1394                  if (count($update_sql))
1395                  {
1396                      $sql_data[FORUMS_TABLE] .= ($sql_data[FORUMS_TABLE]) ? ', ' : '';
1397                      $sql_data[FORUMS_TABLE] .= implode(', ', $update_sql[$forum_id]);
1398                  }
1399              }
1400  
1401          break;
1402  
1403          case 'delete_first_post':
1404              $sql = 'SELECT p.post_id, p.poster_id, p.post_time, p.post_username, u.username, u.user_colour
1405                  FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u
1406                  WHERE p.topic_id = $topic_id
1407                      AND p.poster_id = u.user_id
1408                      AND p.post_visibility = " . ITEM_APPROVED . '
1409                  ORDER BY p.post_time ASC, p.post_id ASC';
1410              $result = $db->sql_query_limit($sql, 1);
1411              $row = $db->sql_fetchrow($result);
1412              $db->sql_freeresult($result);
1413  
1414              if (!$row)
1415              {
1416                  // No approved post, so the first is a not-approved post (unapproved or soft deleted)
1417                  $sql = 'SELECT p.post_id, p.poster_id, p.post_time, p.post_username, u.username, u.user_colour
1418                      FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u
1419                      WHERE p.topic_id = $topic_id
1420                          AND p.poster_id = u.user_id
1421                      ORDER BY p.post_time ASC, p.post_id ASC";
1422                  $result = $db->sql_query_limit($sql, 1);
1423                  $row = $db->sql_fetchrow($result);
1424                  $db->sql_freeresult($result);
1425              }
1426  
1427              $next_post_id = (int) $row['post_id'];
1428  
1429              $sql_data[TOPICS_TABLE] = $db->sql_build_array('UPDATE', array(
1430                  'topic_poster'                => (int) $row['poster_id'],
1431                  'topic_first_post_id'        => (int) $row['post_id'],
1432                  'topic_first_poster_colour'    => $row['user_colour'],
1433                  'topic_first_poster_name'    => ($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username'],
1434                  'topic_time'                => (int) $row['post_time'],
1435              ));
1436          break;
1437  
1438          case 'delete_last_post':
1439              if (!$is_soft)
1440              {
1441                  // Update last post information when hard deleting. Soft delete already did that by itself.
1442                  $update_sql = update_post_information('forum', $forum_id, true);
1443                  if (count($update_sql))
1444                  {
1445                      $sql_data[FORUMS_TABLE] = (($sql_data[FORUMS_TABLE]) ? $sql_data[FORUMS_TABLE] . ', ' : '') . implode(', ', $update_sql[$forum_id]);
1446                  }
1447  
1448                  $sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_bumped = 0, topic_bumper = 0';
1449  
1450                  $update_sql = update_post_information('topic', $topic_id, true);
1451                  if (!empty($update_sql))
1452                  {
1453                      $sql_data[TOPICS_TABLE] .= ', ' . implode(', ', $update_sql[$topic_id]);
1454                      $next_post_id = (int) str_replace('topic_last_post_id = ', '', $update_sql[$topic_id][0]);
1455                  }
1456              }
1457  
1458              if (!$next_post_id)
1459              {
1460                  $sql = 'SELECT MAX(post_id) as last_post_id
1461                      FROM ' . POSTS_TABLE . "
1462                      WHERE topic_id = $topic_id
1463                          AND " . $phpbb_content_visibility->get_visibility_sql('post', $forum_id);
1464                  $result = $db->sql_query($sql);
1465                  $next_post_id = (int) $db->sql_fetchfield('last_post_id');
1466                  $db->sql_freeresult($result);
1467              }
1468          break;
1469  
1470          case 'delete':
1471              $sql = 'SELECT post_id
1472                  FROM ' . POSTS_TABLE . "
1473                  WHERE topic_id = $topic_id
1474                      AND " . $phpbb_content_visibility->get_visibility_sql('post', $forum_id) . '
1475                      AND post_time > ' . $data['post_time'] . '
1476                  ORDER BY post_time ASC, post_id ASC';
1477              $result = $db->sql_query_limit($sql, 1);
1478              $next_post_id = (int) $db->sql_fetchfield('post_id');
1479              $db->sql_freeresult($result);
1480          break;
1481      }
1482  
1483      if (($post_mode == 'delete') || ($post_mode == 'delete_last_post') || ($post_mode == 'delete_first_post'))
1484      {
1485          if (!$is_soft)
1486          {
1487              $phpbb_content_visibility->remove_post_from_statistic($data, $sql_data);
1488          }
1489  
1490          $sql = 'SELECT 1 AS has_attachments
1491              FROM ' . ATTACHMENTS_TABLE . '
1492              WHERE topic_id = ' . $topic_id;
1493          $result = $db->sql_query_limit($sql, 1);
1494          $has_attachments = (int) $db->sql_fetchfield('has_attachments');
1495          $db->sql_freeresult($result);
1496  
1497          if (!$has_attachments)
1498          {
1499              $sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_attachment = 0';
1500          }
1501      }
1502  
1503      $db->sql_transaction('begin');
1504  
1505      $where_sql = array(
1506          FORUMS_TABLE    => "forum_id = $forum_id",
1507          TOPICS_TABLE    => "topic_id = $topic_id",
1508          USERS_TABLE        => 'user_id = ' . $data['poster_id'],
1509      );
1510  
1511      foreach ($sql_data as $table => $update_sql)
1512      {
1513          if ($update_sql)
1514          {
1515              $db->sql_query("UPDATE $table SET $update_sql WHERE " . $where_sql[$table]);
1516          }
1517      }
1518  
1519      // Adjust posted info for this user by looking for a post by him/her within this topic...
1520      if ($post_mode != 'delete_topic' && $config['load_db_track'] && $data['poster_id'] != ANONYMOUS)
1521      {
1522          $sql = 'SELECT poster_id
1523              FROM ' . POSTS_TABLE . '
1524              WHERE topic_id = ' . $topic_id . '
1525                  AND poster_id = ' . $data['poster_id'];
1526          $result = $db->sql_query_limit($sql, 1);
1527          $poster_id = (int) $db->sql_fetchfield('poster_id');
1528          $db->sql_freeresult($result);
1529  
1530          // The user is not having any more posts within this topic
1531          if (!$poster_id)
1532          {
1533              $sql = 'DELETE FROM ' . TOPICS_POSTED_TABLE . '
1534                  WHERE topic_id = ' . $topic_id . '
1535                      AND user_id = ' . $data['poster_id'];
1536              $db->sql_query($sql);
1537          }
1538      }
1539  
1540      $db->sql_transaction('commit');
1541  
1542      if ($data['post_reported'] && ($post_mode != 'delete_topic'))
1543      {
1544          sync('topic_reported', 'topic_id', array($topic_id));
1545      }
1546  
1547      /**
1548      * This event is used for performing actions directly after a post or topic
1549      * has been deleted.
1550      *
1551      * @event core.delete_post_after
1552      * @var    int        forum_id            Post forum ID
1553      * @var    int        topic_id            Post topic ID
1554      * @var    int        post_id                Post ID
1555      * @var    array    data                Post data
1556      * @var    bool    is_soft                Soft delete flag
1557      * @var    string    softdelete_reason    Soft delete reason
1558      * @var    string    post_mode            delete_topic, delete_first_post, delete_last_post or delete
1559      * @var    mixed    next_post_id        Next post ID in the topic (post ID or false)
1560      *
1561      * @since 3.1.11-RC1
1562      */
1563      $vars = array(
1564          'forum_id',
1565          'topic_id',
1566          'post_id',
1567          'data',
1568          'is_soft',
1569          'softdelete_reason',
1570          'post_mode',
1571          'next_post_id',
1572      );
1573      extract($phpbb_dispatcher->trigger_event('core.delete_post_after', compact($vars)));
1574  
1575      return $next_post_id;
1576  }
1577  
1578  /**
1579  * Submit Post
1580  * @todo Split up and create lightweight, simple API for this.
1581  */
1582  function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data_ary, $update_message = true, $update_search_index = true)
1583  {
1584      global $db, $auth, $user, $config, $phpEx, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher, $phpbb_log, $request;
1585  
1586      $poll = $poll_ary;
1587      $data = $data_ary;
1588      /**
1589      * Modify the data for post submitting
1590      *
1591      * @event core.modify_submit_post_data
1592      * @var    string    mode                Variable containing posting mode value
1593      * @var    string    subject                Variable containing post subject value
1594      * @var    string    username            Variable containing post author name
1595      * @var    int        topic_type            Variable containing topic type value
1596      * @var    array    poll                Array with the poll data for the post
1597      * @var    array    data                Array with the data for the post
1598      * @var    bool    update_message        Flag indicating if the post will be updated
1599      * @var    bool    update_search_index    Flag indicating if the search index will be updated
1600      * @since 3.1.0-a4
1601      */
1602      $vars = array(
1603          'mode',
1604          'subject',
1605          'username',
1606          'topic_type',
1607          'poll',
1608          'data',
1609          'update_message',
1610          'update_search_index',
1611      );
1612      extract($phpbb_dispatcher->trigger_event('core.modify_submit_post_data', compact($vars)));
1613      $poll_ary = $poll;
1614      $data_ary = $data;
1615      unset($poll);
1616      unset($data);
1617  
1618      // We do not handle erasing posts here
1619      if ($mode == 'delete')
1620      {
1621          return false;
1622      }
1623  
1624      if (!empty($data_ary['post_time']))
1625      {
1626          $current_time = $data_ary['post_time'];
1627      }
1628      else
1629      {
1630          $current_time = time();
1631      }
1632  
1633      if ($mode == 'post')
1634      {
1635          $post_mode = 'post';
1636          $update_message = true;
1637      }
1638      else if ($mode != 'edit')
1639      {
1640          $post_mode = 'reply';
1641          $update_message = true;
1642      }
1643      else if ($mode == 'edit')
1644      {
1645          $post_mode = ($data_ary['topic_posts_approved'] + $data_ary['topic_posts_unapproved'] + $data_ary['topic_posts_softdeleted'] == 1) ? 'edit_topic' : (($data_ary['topic_first_post_id'] == $data_ary['post_id']) ? 'edit_first_post' : (($data_ary['topic_last_post_id'] == $data_ary['post_id']) ? 'edit_last_post' : 'edit'));
1646      }
1647  
1648      // First of all make sure the subject and topic title are having the correct length.
1649      // To achieve this without cutting off between special chars we convert to an array and then count the elements.
1650      $subject = truncate_string($subject, 120);
1651      $data_ary['topic_title'] = truncate_string($data_ary['topic_title'], 120);
1652  
1653      // Collect some basic information about which tables and which rows to update/insert
1654      $sql_data = $topic_row = array();
1655      $poster_id = ($mode == 'edit') ? $data_ary['poster_id'] : (int) $user->data['user_id'];
1656  
1657      // Retrieve some additional information if not present
1658      if ($mode == 'edit' && (!isset($data_ary['post_visibility']) || !isset($data_ary['topic_visibility']) || $data_ary['post_visibility'] === false || $data_ary['topic_visibility'] === false))
1659      {
1660          $sql = 'SELECT p.post_visibility, t.topic_type, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, t.topic_visibility
1661              FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p
1662              WHERE t.topic_id = p.topic_id
1663                  AND p.post_id = ' . $data_ary['post_id'];
1664          $result = $db->sql_query($sql);
1665          $topic_row = $db->sql_fetchrow($result);
1666          $db->sql_freeresult($result);
1667  
1668          $data_ary['topic_visibility'] = $topic_row['topic_visibility'];
1669          $data_ary['post_visibility'] = $topic_row['post_visibility'];
1670      }
1671  
1672      // This variable indicates if the user is able to post or put into the queue
1673      $post_visibility = ITEM_APPROVED;
1674  
1675      // Check the permissions for post approval.
1676      // Moderators must go through post approval like ordinary users.
1677      if (!$auth->acl_get('f_noapprove', $data_ary['forum_id']))
1678      {
1679          // Post not approved, but in queue
1680          $post_visibility = ITEM_UNAPPROVED;
1681          switch ($post_mode)
1682          {
1683              case 'edit_first_post':
1684              case 'edit':
1685              case 'edit_last_post':
1686              case 'edit_topic':
1687                  $post_visibility = ITEM_REAPPROVE;
1688              break;
1689          }
1690      }
1691      else if (isset($data_ary['post_visibility']) && $data_ary['post_visibility'] !== false)
1692      {
1693          $post_visibility = $data_ary['post_visibility'];
1694      }
1695  
1696      // MODs/Extensions are able to force any visibility on posts
1697      if (isset($data_ary['force_approved_state']))
1698      {
1699          $post_visibility = (in_array((int) $data_ary['force_approved_state'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE))) ? (int) $data_ary['force_approved_state'] : $post_visibility;
1700      }
1701      if (isset($data_ary['force_visibility']))
1702      {
1703          $post_visibility = (in_array((int) $data_ary['force_visibility'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE))) ? (int) $data_ary['force_visibility'] : $post_visibility;
1704      }
1705  
1706      // Start the transaction here
1707      $db->sql_transaction('begin');
1708  
1709      // Collect Information
1710      switch ($post_mode)
1711      {
1712          case 'post':
1713          case 'reply':
1714              $sql_data[POSTS_TABLE]['sql'] = array(
1715                  'forum_id'            => $data_ary['forum_id'],
1716                  'poster_id'            => (int) $user->data['user_id'],
1717                  'icon_id'            => $data_ary['icon_id'],
1718                  'poster_ip'            => $user->ip,
1719                  'post_time'            => $current_time,
1720                  'post_visibility'    => $post_visibility,
1721                  'enable_bbcode'        => $data_ary['enable_bbcode'],
1722                  'enable_smilies'    => $data_ary['enable_smilies'],
1723                  'enable_magic_url'    => $data_ary['enable_urls'],
1724                  'enable_sig'        => $data_ary['enable_sig'],
1725                  'post_username'        => (!$user->data['is_registered']) ? $username : '',
1726                  'post_subject'        => $subject,
1727                  'post_text'            => $data_ary['message'],
1728                  'post_checksum'        => $data_ary['message_md5'],
1729                  'post_attachment'    => (!empty($data_ary['attachment_data'])) ? 1 : 0,
1730                  'bbcode_bitfield'    => $data_ary['bbcode_bitfield'],
1731                  'bbcode_uid'        => $data_ary['bbcode_uid'],
1732                  'post_postcount'    => ($auth->acl_get('f_postcount', $data_ary['forum_id'])) ? 1 : 0,
1733                  'post_edit_locked'    => $data_ary['post_edit_locked']
1734              );
1735          break;
1736  
1737          case 'edit_first_post':
1738          case 'edit':
1739  
1740          case 'edit_last_post':
1741          case 'edit_topic':
1742  
1743              // If edit reason is given always display edit info
1744  
1745              // If editing last post then display no edit info
1746              // If m_edit permission then display no edit info
1747              // If normal edit display edit info
1748  
1749              // Display edit info if edit reason given or user is editing his post, which is not the last within the topic.
1750              if ($data_ary['post_edit_reason'] || (!$auth->acl_get('m_edit', $data_ary['forum_id']) && ($post_mode == 'edit' || $post_mode == 'edit_first_post')))
1751              {
1752                  $data_ary['post_edit_reason']        = truncate_string($data_ary['post_edit_reason'], 255, 255, false);
1753  
1754                  $sql_data[POSTS_TABLE]['sql']    = array(
1755                      'post_edit_time'    => $current_time,
1756                      'post_edit_reason'    => $data_ary['post_edit_reason'],
1757                      'post_edit_user'    => (int) $data_ary['post_edit_user'],
1758                  );
1759  
1760                  $sql_data[POSTS_TABLE]['stat'][] = 'post_edit_count = post_edit_count + 1';
1761              }
1762              else if (!$data_ary['post_edit_reason'] && $mode == 'edit' && $auth->acl_get('m_edit', $data_ary['forum_id']))
1763              {
1764                  $sql_data[POSTS_TABLE]['sql'] = array(
1765                      'post_edit_reason'    => '',
1766                  );
1767              }
1768  
1769              // If the person editing this post is different to the one having posted then we will add a log entry stating the edit
1770              // Could be simplified by only adding to the log if the edit is not tracked - but this may confuse admins/mods
1771              if ($user->data['user_id'] != $poster_id)
1772              {
1773                  $log_subject = ($subject) ? $subject : $data_ary['topic_title'];
1774                  $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_POST_EDITED', false, array(
1775                      'forum_id' => $data_ary['forum_id'],
1776                      'topic_id' => $data_ary['topic_id'],
1777                      'post_id'  => $data_ary['post_id'],
1778                      $log_subject,
1779                      (!empty($username)) ? $username : $user->lang['GUEST'],
1780                      $data_ary['post_edit_reason']
1781                  ));
1782              }
1783  
1784              if (!isset($sql_data[POSTS_TABLE]['sql']))
1785              {
1786                  $sql_data[POSTS_TABLE]['sql'] = array();
1787              }
1788  
1789              $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array(
1790                  'forum_id'            => $data_ary['forum_id'],
1791                  'poster_id'            => $data_ary['poster_id'],
1792                  'icon_id'            => $data_ary['icon_id'],
1793                  // We will change the visibility later
1794                  //'post_visibility'    => $post_visibility,
1795                  'enable_bbcode'        => $data_ary['enable_bbcode'],
1796                  'enable_smilies'    => $data_ary['enable_smilies'],
1797                  'enable_magic_url'    => $data_ary['enable_urls'],
1798                  'enable_sig'        => $data_ary['enable_sig'],
1799                  'post_username'        => ($username && $data_ary['poster_id'] == ANONYMOUS) ? $username : '',
1800                  'post_subject'        => $subject,
1801                  'post_checksum'        => $data_ary['message_md5'],
1802                  'post_attachment'    => (!empty($data_ary['attachment_data'])) ? 1 : 0,
1803                  'bbcode_bitfield'    => $data_ary['bbcode_bitfield'],
1804                  'bbcode_uid'        => $data_ary['bbcode_uid'],
1805                  'post_edit_locked'    => $data_ary['post_edit_locked'])
1806              );
1807  
1808              if ($update_message)
1809              {
1810                  $sql_data[POSTS_TABLE]['sql']['post_text'] = $data_ary['message'];
1811              }
1812  
1813          break;
1814      }
1815  
1816      // And the topic ladies and gentlemen
1817      switch ($post_mode)
1818      {
1819          case 'post':
1820              $sql_data[TOPICS_TABLE]['sql'] = array(
1821                  'topic_poster'                => (int) $user->data['user_id'],
1822                  'topic_time'                => $current_time,
1823                  'topic_last_view_time'        => $current_time,
1824                  'forum_id'                    => $data_ary['forum_id'],
1825                  'icon_id'                    => $data_ary['icon_id'],
1826                  'topic_posts_approved'        => ($post_visibility == ITEM_APPROVED) ? 1 : 0,
1827                  'topic_posts_softdeleted'    => ($post_visibility == ITEM_DELETED) ? 1 : 0,
1828                  'topic_posts_unapproved'    => ($post_visibility == ITEM_UNAPPROVED) ? 1 : 0,
1829                  'topic_visibility'            => $post_visibility,
1830                  'topic_delete_user'            => ($post_visibility != ITEM_APPROVED) ? (int) $user->data['user_id'] : 0,
1831                  'topic_title'                => $subject,
1832                  'topic_first_poster_name'    => (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : ''),
1833                  'topic_first_poster_colour'    => $user->data['user_colour'],
1834                  'topic_type'                => $topic_type,
1835                  'topic_time_limit'            => $topic_type != POST_NORMAL ? ($data_ary['topic_time_limit'] * 86400) : 0,
1836                  'topic_attachment'            => (!empty($data_ary['attachment_data'])) ? 1 : 0,
1837                  'topic_status'                => (isset($data_ary['topic_status'])) ? $data_ary['topic_status'] : ITEM_UNLOCKED,
1838              );
1839  
1840              if (isset($poll_ary['poll_options']) && !empty($poll_ary['poll_options']))
1841              {
1842                  $poll_start = ($poll_ary['poll_start']) ? $poll_ary['poll_start'] : $current_time;
1843                  $poll_length = $poll_ary['poll_length'] * 86400;
1844                  if ($poll_length < 0)
1845                  {
1846                      $poll_start = $poll_start + $poll_length;
1847                      if ($poll_start < 0)
1848                      {
1849                          $poll_start = 0;
1850                      }
1851                      $poll_length = 1;
1852                  }
1853  
1854                  $sql_data[TOPICS_TABLE]['sql'] = array_merge($sql_data[TOPICS_TABLE]['sql'], array(
1855                      'poll_title'        => $poll_ary['poll_title'],
1856                      'poll_start'        => $poll_start,
1857                      'poll_max_options'    => $poll_ary['poll_max_options'],
1858                      'poll_length'        => $poll_length,
1859                      'poll_vote_change'    => $poll_ary['poll_vote_change'])
1860                  );
1861              }
1862  
1863              $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data_ary['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : '');
1864  
1865              if ($post_visibility == ITEM_APPROVED)
1866              {
1867                  $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_approved = forum_topics_approved + 1';
1868                  $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_approved = forum_posts_approved + 1';
1869              }
1870              else if ($post_visibility == ITEM_UNAPPROVED)
1871              {
1872                  $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_unapproved = forum_topics_unapproved + 1';
1873                  $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_unapproved = forum_posts_unapproved + 1';
1874              }
1875              else if ($post_visibility == ITEM_DELETED)
1876              {
1877                  $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_softdeleted = forum_topics_softdeleted + 1';
1878                  $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_softdeleted = forum_posts_softdeleted + 1';
1879              }
1880          break;
1881  
1882          case 'reply':
1883              $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_view_time = ' . $current_time . ',
1884                  topic_bumped = 0,
1885                  topic_bumper = 0' .
1886                  (($post_visibility == ITEM_APPROVED) ? ', topic_posts_approved = topic_posts_approved + 1' : '') .
1887                  (($post_visibility == ITEM_UNAPPROVED) ? ', topic_posts_unapproved = topic_posts_unapproved + 1' : '') .
1888                  (($post_visibility == ITEM_DELETED) ? ', topic_posts_softdeleted = topic_posts_softdeleted + 1' : '') .
1889                  ((!empty($data_ary['attachment_data']) || (isset($data_ary['topic_attachment']) && $data_ary['topic_attachment'])) ? ', topic_attachment = 1' : '');
1890  
1891              $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data_ary['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : '');
1892  
1893              if ($post_visibility == ITEM_APPROVED)
1894              {
1895                  $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_approved = forum_posts_approved + 1';
1896              }
1897              else if ($post_visibility == ITEM_UNAPPROVED)
1898              {
1899                  $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_unapproved = forum_posts_unapproved + 1';
1900              }
1901              else if ($post_visibility == ITEM_DELETED)
1902              {
1903                  $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_softdeleted = forum_posts_softdeleted + 1';
1904              }
1905          break;
1906  
1907          case 'edit_topic':
1908          case 'edit_first_post':
1909              if (isset($poll_ary['poll_options']))
1910              {
1911                  $poll_start = ($poll_ary['poll_start'] || empty($poll_ary['poll_options'])) ? $poll_ary['poll_start'] : $current_time;
1912                  $poll_length = $poll_ary['poll_length'] * 86400;
1913                  if ($poll_length < 0)
1914                  {
1915                      $poll_start = $poll_start + $poll_length;
1916                      if ($poll_start < 0)
1917                      {
1918                          $poll_start = 0;
1919                      }
1920                      $poll_length = 1;
1921                  }
1922              }
1923  
1924              $sql_data[TOPICS_TABLE]['sql'] = array(
1925                  'forum_id'                    => $data_ary['forum_id'],
1926                  'icon_id'                    => $data_ary['icon_id'],
1927                  'topic_title'                => $subject,
1928                  'topic_first_poster_name'    => $username,
1929                  'topic_type'                => $topic_type,
1930                  'topic_time_limit'            => $topic_type != POST_NORMAL ? ($data_ary['topic_time_limit'] * 86400) : 0,
1931                  'poll_title'                => (isset($poll_ary['poll_options'])) ? $poll_ary['poll_title'] : '',
1932                  'poll_start'                => (isset($poll_ary['poll_options'])) ? $poll_start : 0,
1933                  'poll_max_options'            => (isset($poll_ary['poll_options'])) ? $poll_ary['poll_max_options'] : 1,
1934                  'poll_length'                => (isset($poll_ary['poll_options'])) ? $poll_length : 0,
1935                  'poll_vote_change'            => (isset($poll_ary['poll_vote_change'])) ? $poll_ary['poll_vote_change'] : 0,
1936                  'topic_last_view_time'        => $current_time,
1937  
1938                  'topic_attachment'            => (!empty($data_ary['attachment_data'])) ? 1 : (isset($data_ary['topic_attachment']) ? $data_ary['topic_attachment'] : 0),
1939              );
1940  
1941          break;
1942      }
1943  
1944      $poll = $poll_ary;
1945      $data = $data_ary;
1946      /**
1947      * Modify sql query data for post submitting
1948      *
1949      * @event core.submit_post_modify_sql_data
1950      * @var    array    data                Array with the data for the post
1951      * @var    array    poll                Array with the poll data for the post
1952      * @var    string    post_mode            Variable containing posting mode value
1953      * @var    bool    sql_data            Array with the data for the posting SQL query
1954      * @var    string    subject                Variable containing post subject value
1955      * @var    int        topic_type            Variable containing topic type value
1956      * @var    string    username            Variable containing post author name
1957      * @since 3.1.3-RC1
1958      */
1959      $vars = array(
1960          'data',
1961          'poll',
1962          'post_mode',
1963          'sql_data',
1964          'subject',
1965          'topic_type',
1966          'username',
1967      );
1968      extract($phpbb_dispatcher->trigger_event('core.submit_post_modify_sql_data', compact($vars)));
1969      $poll_ary = $poll;
1970      $data_ary = $data;
1971      unset($poll);
1972      unset($data);
1973  
1974      // Submit new topic
1975      if ($post_mode == 'post')
1976      {
1977          $sql = 'INSERT INTO ' . TOPICS_TABLE . ' ' .
1978              $db->sql_build_array('INSERT', $sql_data[TOPICS_TABLE]['sql']);
1979          $db->sql_query($sql);
1980  
1981          $data_ary['topic_id'] = $db->sql_nextid();
1982  
1983          $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array(
1984              'topic_id' => $data_ary['topic_id'])
1985          );
1986          unset($sql_data[TOPICS_TABLE]['sql']);
1987      }
1988  
1989      // Submit new post
1990      if ($post_mode == 'post' || $post_mode == 'reply')
1991      {
1992          if ($post_mode == 'reply')
1993          {
1994              $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array(
1995                  'topic_id' => $data_ary['topic_id'],
1996              ));
1997          }
1998  
1999          $sql = 'INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data[POSTS_TABLE]['sql']);
2000          $db->sql_query($sql);
2001          $data_ary['post_id'] = $db->sql_nextid();
2002  
2003          if ($post_mode == 'post' || $post_visibility == ITEM_APPROVED)
2004          {
2005              $sql_data[TOPICS_TABLE]['sql'] = array(
2006                  'topic_last_post_id'        => $data_ary['post_id'],
2007                  'topic_last_post_time'        => $current_time,
2008                  'topic_last_poster_id'        => $sql_data[POSTS_TABLE]['sql']['poster_id'],
2009                  'topic_last_poster_name'    => ($user->data['user_id'] == ANONYMOUS) ? $sql_data[POSTS_TABLE]['sql']['post_username'] : $user->data['username'],
2010                  'topic_last_poster_colour'    => $user->data['user_colour'],
2011                  'topic_last_post_subject'    => (string) $subject,
2012              );
2013          }
2014  
2015          if ($post_mode == 'post')
2016          {
2017              $sql_data[TOPICS_TABLE]['sql']['topic_first_post_id'] = $data_ary['post_id'];
2018          }
2019  
2020          // Update total post count and forum information
2021          if ($post_visibility == ITEM_APPROVED)
2022          {
2023              if ($post_mode == 'post')
2024              {
2025                  $config->increment('num_topics', 1, false);
2026              }
2027              $config->increment('num_posts', 1, false);
2028  
2029              $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . $data_ary['post_id'];
2030              $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'";
2031              $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . $current_time;
2032              $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $user->data['user_id'];
2033              $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'] : '')) . "'";
2034              $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($user->data['user_colour']) . "'";
2035          }
2036  
2037          unset($sql_data[POSTS_TABLE]['sql']);
2038      }
2039  
2040      // Update the topics table
2041      if (isset($sql_data[TOPICS_TABLE]['sql']))
2042      {
2043          $sql = 'UPDATE ' . TOPICS_TABLE . '
2044              SET ' . $db->sql_build_array('UPDATE', $sql_data[TOPICS_TABLE]['sql']) . '
2045              WHERE topic_id = ' . $data_ary['topic_id'];
2046          $db->sql_query($sql);
2047  
2048          unset($sql_data[TOPICS_TABLE]['sql']);
2049      }
2050  
2051      // Update the posts table
2052      if (isset($sql_data[POSTS_TABLE]['sql']))
2053      {
2054          $sql = 'UPDATE ' . POSTS_TABLE . '
2055              SET ' . $db->sql_build_array('UPDATE', $sql_data[POSTS_TABLE]['sql']) . '
2056              WHERE post_id = ' . $data_ary['post_id'];
2057          $db->sql_query($sql);
2058  
2059          unset($sql_data[POSTS_TABLE]['sql']);
2060      }
2061  
2062      // Update Poll Tables
2063      if (isset($poll_ary['poll_options']))
2064      {
2065          $cur_poll_options = array();
2066  
2067          if ($mode == 'edit')
2068          {
2069              $sql = 'SELECT *
2070                  FROM ' . POLL_OPTIONS_TABLE . '
2071                  WHERE topic_id = ' . $data_ary['topic_id'] . '
2072                  ORDER BY poll_option_id';
2073              $result = $db->sql_query($sql);
2074  
2075              $cur_poll_options = array();
2076              while ($row = $db->sql_fetchrow($result))
2077              {
2078                  $cur_poll_options[] = $row;
2079              }
2080              $db->sql_freeresult($result);
2081          }
2082  
2083          $sql_insert_ary = array();
2084  
2085          for ($i = 0, $size = count($poll_ary['poll_options']); $i < $size; $i++)
2086          {
2087              if (strlen(trim($poll_ary['poll_options'][$i])))
2088              {
2089                  if (empty($cur_poll_options[$i]))
2090                  {
2091                      // If we add options we need to put them to the end to be able to preserve votes...
2092                      $sql_insert_ary[] = array(
2093                          'poll_option_id'    => (int) count($cur_poll_options) + 1 + count($sql_insert_ary),
2094                          'topic_id'            => (int) $data_ary['topic_id'],
2095                          'poll_option_text'    => (string) $poll_ary['poll_options'][$i]
2096                      );
2097                  }
2098                  else if ($poll_ary['poll_options'][$i] != $cur_poll_options[$i])
2099                  {
2100                      $sql = 'UPDATE ' . POLL_OPTIONS_TABLE . "
2101                          SET poll_option_text = '" . $db->sql_escape($poll_ary['poll_options'][$i]) . "'
2102                          WHERE poll_option_id = " . $cur_poll_options[$i]['poll_option_id'] . '
2103                              AND topic_id = ' . $data_ary['topic_id'];
2104                      $db->sql_query($sql);
2105                  }
2106              }
2107          }
2108  
2109          $db->sql_multi_insert(POLL_OPTIONS_TABLE, $sql_insert_ary);
2110  
2111          if (count($poll_ary['poll_options']) < count($cur_poll_options))
2112          {
2113              $sql = 'DELETE FROM ' . POLL_OPTIONS_TABLE . '
2114                  WHERE poll_option_id > ' . count($poll_ary['poll_options']) . '
2115                      AND topic_id = ' . $data_ary['topic_id'];
2116              $db->sql_query($sql);
2117          }
2118  
2119          // 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
2120          if ($mode == 'edit' && count($poll_ary['poll_options']) != count($cur_poll_options))
2121          {
2122              $db->sql_query('DELETE FROM ' . POLL_VOTES_TABLE . ' WHERE topic_id = ' . $data_ary['topic_id']);
2123              $db->sql_query('UPDATE ' . POLL_OPTIONS_TABLE . ' SET poll_option_total = 0 WHERE topic_id = ' . $data_ary['topic_id']);
2124          }
2125      }
2126  
2127      // Submit Attachments
2128      if (!empty($data_ary['attachment_data']) && $data_ary['post_id'] && in_array($mode, array('post', 'reply', 'quote', 'edit')))
2129      {
2130          $space_taken = $files_added = 0;
2131          $orphan_rows = array();
2132  
2133          foreach ($data_ary['attachment_data'] as $pos => $attach_row)
2134          {
2135              $orphan_rows[(int) $attach_row['attach_id']] = array();
2136          }
2137  
2138          if (count($orphan_rows))
2139          {
2140              $sql = 'SELECT attach_id, filesize, physical_filename
2141                  FROM ' . ATTACHMENTS_TABLE . '
2142                  WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . '
2143                      AND is_orphan = 1
2144                      AND poster_id = ' . $user->data['user_id'];
2145              $result = $db->sql_query($sql);
2146  
2147              $orphan_rows = array();
2148              while ($row = $db->sql_fetchrow($result))
2149              {
2150                  $orphan_rows[$row['attach_id']] = $row;
2151              }
2152              $db->sql_freeresult($result);
2153          }
2154  
2155          foreach ($data_ary['attachment_data'] as $pos => $attach_row)
2156          {
2157              if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']]))
2158              {
2159                  continue;
2160              }
2161  
2162              if (preg_match('/[\x{10000}-\x{10FFFF}]/u', $attach_row['attach_comment']))
2163              {
2164                  trigger_error('ATTACH_COMMENT_NO_EMOJIS');
2165              }
2166  
2167              if (!$attach_row['is_orphan'])
2168              {
2169                  // update entry in db if attachment already stored in db and filespace
2170                  $sql = 'UPDATE ' . ATTACHMENTS_TABLE . "
2171                      SET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "'
2172                      WHERE attach_id = " . (int) $attach_row['attach_id'] . '
2173                          AND is_orphan = 0';
2174                  $db->sql_query($sql);
2175              }
2176              else
2177              {
2178                  // insert attachment into db
2179                  if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($orphan_rows[$attach_row['attach_id']]['physical_filename'])))
2180                  {
2181                      continue;
2182                  }
2183  
2184                  $space_taken += $orphan_rows[$attach_row['attach_id']]['filesize'];
2185                  $files_added++;
2186  
2187                  $attach_sql = array(
2188                      'post_msg_id'        => $data_ary['post_id'],
2189                      'topic_id'            => $data_ary['topic_id'],
2190                      'is_orphan'            => 0,
2191                      'poster_id'            => $poster_id,
2192                      'attach_comment'    => $attach_row['attach_comment'],
2193                  );
2194  
2195                  $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . '
2196                      WHERE attach_id = ' . $attach_row['attach_id'] . '
2197                          AND is_orphan = 1
2198                          AND poster_id = ' . $user->data['user_id'];
2199                  $db->sql_query($sql);
2200              }
2201          }
2202  
2203          if ($space_taken && $files_added)
2204          {
2205              $config->increment('upload_dir_size', $space_taken, false);
2206              $config->increment('num_files', $files_added, false);
2207          }
2208      }
2209  
2210      $first_post_has_topic_info = ($post_mode == 'edit_first_post' &&
2211              (($post_visibility == ITEM_DELETED && $data_ary['topic_posts_softdeleted'] == 1) ||
2212              ($post_visibility == ITEM_UNAPPROVED && $data_ary['topic_posts_unapproved'] == 1) ||
2213              ($post_visibility == ITEM_REAPPROVE && $data_ary['topic_posts_unapproved'] == 1) ||
2214              ($post_visibility == ITEM_APPROVED && $data_ary['topic_posts_approved'] == 1)));
2215      // Fix the post's and topic's visibility and first/last post information, when the post is edited
2216      if (($post_mode != 'post' && $post_mode != 'reply') && $data_ary['post_visibility'] != $post_visibility)
2217      {
2218          // If the post was not approved, it could also be the starter,
2219          // so we sync the starter after approving/restoring, to ensure that the stats are correct
2220          // Same applies for the last post
2221          $is_starter = ($post_mode == 'edit_first_post' || $post_mode == 'edit_topic' || $data_ary['post_visibility'] != ITEM_APPROVED);
2222          $is_latest = ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $data_ary['post_visibility'] != ITEM_APPROVED);
2223  
2224          /* @var $phpbb_content_visibility \phpbb\content_visibility */
2225          $phpbb_content_visibility = $phpbb_container->get('content.visibility');
2226          $phpbb_content_visibility->set_post_visibility($post_visibility, $data_ary['post_id'], $data_ary['topic_id'], $data_ary['forum_id'], $user->data['user_id'], time(), '', $is_starter, $is_latest);
2227      }
2228      else if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $first_post_has_topic_info)
2229      {
2230          if ($post_visibility == ITEM_APPROVED || $data_ary['topic_visibility'] == $post_visibility)
2231          {
2232              // only the subject can be changed from edit
2233              $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($subject) . "'";
2234  
2235              // Maybe not only the subject, but also changing anonymous usernames. ;)
2236              if ($data_ary['poster_id'] == ANONYMOUS)
2237              {
2238                  $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape($username) . "'";
2239              }
2240  
2241              if ($post_visibility == ITEM_APPROVED)
2242              {
2243                  // this does not _necessarily_ mean that we must update the info again,
2244                  // it just means that we might have to
2245                  $sql = 'SELECT forum_last_post_id, forum_last_post_subject
2246                      FROM ' . FORUMS_TABLE . '
2247                      WHERE forum_id = ' . (int) $data_ary['forum_id'];
2248                  $result = $db->sql_query($sql);
2249                  $row = $db->sql_fetchrow($result);
2250                  $db->sql_freeresult($result);
2251  
2252                  // this post is the latest post in the forum, better update
2253                  if ($row['forum_last_post_id'] == $data_ary['post_id'] && ($row['forum_last_post_subject'] !== $subject || $data_ary['poster_id'] == ANONYMOUS))
2254                  {
2255                      // the post's subject changed
2256                      if ($row['forum_last_post_subject'] !== $subject)
2257                      {
2258                          $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'";
2259                      }
2260  
2261                      // Update the user name if poster is anonymous... just in case a moderator changed it
2262                      if ($data_ary['poster_id'] == ANONYMOUS)
2263                      {
2264                          $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($username) . "'";
2265                      }
2266                  }
2267              }
2268          }
2269      }
2270  
2271      // Update forum stats
2272      $where_sql = array(
2273          POSTS_TABLE        => 'post_id = ' . $data_ary['post_id'],
2274          TOPICS_TABLE    => 'topic_id = ' . $data_ary['topic_id'],
2275          FORUMS_TABLE    => 'forum_id = ' . $data_ary['forum_id'],
2276          USERS_TABLE        => 'user_id = ' . $poster_id
2277      );
2278  
2279      foreach ($sql_data as $table => $update_ary)
2280      {
2281          if (isset($update_ary['stat']) && implode('', $update_ary['stat']))
2282          {
2283              $sql = "UPDATE $table SET " . implode(', ', $update_ary['stat']) . ' WHERE ' . $where_sql[$table];
2284              $db->sql_query($sql);
2285          }
2286      }
2287  
2288      // Delete topic shadows (if any exist). We do not need a shadow topic for an global announcement
2289      if ($topic_type == POST_GLOBAL)
2290      {
2291          $sql = 'DELETE FROM ' . TOPICS_TABLE . '
2292              WHERE topic_moved_id = ' . $data_ary['topic_id'];
2293          $db->sql_query($sql);
2294      }
2295  
2296      // Committing the transaction before updating search index
2297      $db->sql_transaction('commit');
2298  
2299      // Delete draft if post was loaded...
2300      $draft_id = $request->variable('draft_loaded', 0);
2301      if ($draft_id)
2302      {
2303          $sql = 'DELETE FROM ' . DRAFTS_TABLE . "
2304              WHERE draft_id = $draft_id
2305                  AND user_id = {$user->data['user_id']}";
2306          $db->sql_query($sql);
2307      }
2308  
2309      // Index message contents
2310      if ($update_search_index && $data_ary['enable_indexing'])
2311      {
2312          // Select the search method and do some additional checks to ensure it can actually be utilised
2313          $search_type = $config['search_type'];
2314  
2315          if (!class_exists($search_type))
2316          {
2317              trigger_error('NO_SUCH_SEARCH_MODULE');
2318          }
2319  
2320          $error = false;
2321          $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher);
2322  
2323          if ($error)
2324          {
2325              trigger_error($error);
2326          }
2327  
2328          $search->index($mode, $data_ary['post_id'], $data_ary['message'], $subject, $poster_id, $data_ary['forum_id']);
2329      }
2330  
2331      // Topic Notification, do not change if moderator is changing other users posts...
2332      if ($user->data['user_id'] == $poster_id)
2333      {
2334          if (!$data_ary['notify_set'] && $data_ary['notify'])
2335          {
2336              $sql = 'INSERT INTO ' . TOPICS_WATCH_TABLE . ' (user_id, topic_id)
2337                  VALUES (' . $user->data['user_id'] . ', ' . $data_ary['topic_id'] . ')';
2338              $db->sql_query($sql);
2339          }
2340          else if (($config['email_enable'] || $config['jab_enable']) && $data_ary['notify_set'] && !$data_ary['notify'])
2341          {
2342              $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . '
2343                  WHERE user_id = ' . $user->data['user_id'] . '
2344                      AND topic_id = ' . $data_ary['topic_id'];
2345              $db->sql_query($sql);
2346          }
2347      }
2348  
2349      if ($mode == 'post' || $mode == 'reply' || $mode == 'quote')
2350      {
2351          // Mark this topic as posted to
2352          markread('post', $data_ary['forum_id'], $data_ary['topic_id']);
2353      }
2354  
2355      // Mark this topic as read
2356      // We do not use post_time here, this is intended (post_time can have a date in the past if editing a message)
2357      markread('topic', $data_ary['forum_id'], $data_ary['topic_id'], time());
2358  
2359      //
2360      if ($config['load_db_lastread'] && $user->data['is_registered'])
2361      {
2362          $sql = 'SELECT mark_time
2363              FROM ' . FORUMS_TRACK_TABLE . '
2364              WHERE user_id = ' . $user->data['user_id'] . '
2365                  AND forum_id = ' . $data_ary['forum_id'];
2366          $result = $db->sql_query($sql);
2367          $f_mark_time = (int) $db->sql_fetchfield('mark_time');
2368          $db->sql_freeresult($result);
2369      }
2370      else if ($config['load_anon_lastread'] || $user->data['is_registered'])
2371      {
2372          $f_mark_time = false;
2373      }
2374  
2375      if (($config['load_db_lastread'] && $user->data['is_registered']) || $config['load_anon_lastread'] || $user->data['is_registered'])
2376      {
2377          // Update forum info
2378          $sql = 'SELECT forum_last_post_time
2379              FROM ' . FORUMS_TABLE . '
2380              WHERE forum_id = ' . $data_ary['forum_id'];
2381          $result = $db->sql_query($sql);
2382          $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time');
2383          $db->sql_freeresult($result);
2384  
2385          update_forum_tracking_info($data_ary['forum_id'], $forum_last_post_time, $f_mark_time, false);
2386      }
2387  
2388      // If a username was supplied or the poster is a guest, we will use the supplied username.
2389      // Doing it this way we can use "...post by guest-username..." in notifications when
2390      // "guest-username" is supplied or ommit the username if it is not.
2391      $username = ($username !== '' || !$user->data['is_registered']) ? $username : $user->data['username'];
2392  
2393      // Send Notifications
2394      $notification_data = array_merge($data_ary, array(
2395          'topic_title'        => (isset($data_ary['topic_title'])) ? $data_ary['topic_title'] : $subject,
2396          'post_username'        => $username,
2397          'poster_id'            => $poster_id,
2398          'post_text'            => $data_ary['message'],
2399          'post_time'            => $current_time,
2400          'post_subject'        => $subject,
2401      ));
2402  
2403      /**
2404      * This event allows you to modify the notification data upon submission
2405      *
2406      * @event core.modify_submit_notification_data
2407      * @var    array    notification_data    The notification data to be inserted in to the database
2408      * @var    array    data_ary            The data array with a lot of the post submission data
2409      * @var     string    mode                The posting mode
2410      * @var    int        poster_id            The poster id
2411      * @since 3.2.4-RC1
2412      */
2413      $vars = array('notification_data', 'data_ary', 'mode', 'poster_id');
2414      extract($phpbb_dispatcher->trigger_event('core.modify_submit_notification_data', compact($vars)));
2415  
2416      /* @var $phpbb_notifications \phpbb\notification\manager */
2417      $phpbb_notifications = $phpbb_container->get('notification_manager');
2418  
2419      if ($post_visibility == ITEM_APPROVED)
2420      {
2421          switch ($mode)
2422          {
2423              case 'post':
2424                  $phpbb_notifications->add_notifications(array(
2425                      'notification.type.quote',
2426                      'notification.type.topic',
2427                  ), $notification_data);
2428              break;
2429  
2430              case 'reply':
2431              case 'quote':
2432                  $phpbb_notifications->add_notifications(array(
2433                      'notification.type.quote',
2434                      'notification.type.bookmark',
2435                      'notification.type.post',
2436                  ), $notification_data);
2437              break;
2438  
2439              case 'edit_topic':
2440              case 'edit_first_post':
2441              case 'edit':
2442              case 'edit_last_post':
2443                  if ($user->data['user_id'] == $poster_id)
2444                  {
2445                      $phpbb_notifications->update_notifications(array(
2446                          'notification.type.quote',
2447                      ), $notification_data);
2448                  }
2449  
2450                  $phpbb_notifications->update_notifications(array(
2451                      'notification.type.bookmark',
2452                      'notification.type.topic',
2453                      'notification.type.post',
2454                  ), $notification_data);
2455              break;
2456          }
2457      }
2458      else if ($post_visibility == ITEM_UNAPPROVED)
2459      {
2460          switch ($mode)
2461          {
2462              case 'post':
2463                  $phpbb_notifications->add_notifications('notification.type.topic_in_queue', $notification_data);
2464              break;
2465  
2466              case 'reply':
2467              case 'quote':
2468                  $phpbb_notifications->add_notifications('notification.type.post_in_queue', $notification_data);
2469              break;
2470  
2471              case 'edit_topic':
2472              case 'edit_first_post':
2473              case 'edit':
2474              case 'edit_last_post':
2475                  // Nothing to do here
2476              break;
2477          }
2478      }
2479      else if ($post_visibility == ITEM_REAPPROVE)
2480      {
2481          switch ($mode)
2482          {
2483              case 'edit_topic':
2484              case 'edit_first_post':
2485                  $phpbb_notifications->add_notifications('notification.type.topic_in_queue', $notification_data);
2486  
2487                  // Delete the approve_post notification so we can notify the user again,
2488                  // when his post got reapproved
2489                  $phpbb_notifications->delete_notifications('notification.type.approve_post', $notification_data['post_id']);
2490              break;
2491  
2492              case 'edit':
2493              case 'edit_last_post':
2494                  $phpbb_notifications->add_notifications('notification.type.post_in_queue', $notification_data);
2495  
2496                  // Delete the approve_post notification so we can notify the user again,
2497                  // when his post got reapproved
2498                  $phpbb_notifications->delete_notifications('notification.type.approve_post', $notification_data['post_id']);
2499              break;
2500  
2501              case 'post':
2502              case 'reply':
2503              case 'quote':
2504                  // Nothing to do here
2505              break;
2506          }
2507      }
2508      else if ($post_visibility == ITEM_DELETED)
2509      {
2510          switch ($mode)
2511          {
2512              case 'post':
2513              case 'reply':
2514              case 'quote':
2515              case 'edit_topic':
2516              case 'edit_first_post':
2517              case 'edit':
2518              case 'edit_last_post':
2519                  // Nothing to do here
2520              break;
2521          }
2522      }
2523  
2524      $params = $add_anchor = '';
2525  
2526      if ($post_visibility == ITEM_APPROVED ||
2527          ($auth->acl_get('m_softdelete', $data_ary['forum_id']) && $post_visibility == ITEM_DELETED) ||
2528          ($auth->acl_get('m_approve', $data_ary['forum_id']) && in_array($post_visibility, array(ITEM_UNAPPROVED, ITEM_REAPPROVE))))
2529      {
2530          $params .= '&amp;t=' . $data_ary['topic_id'];
2531  
2532          if ($mode != 'post')
2533          {
2534              $params .= '&amp;p=' . $data_ary['post_id'];
2535              $add_anchor = '#p' . $data_ary['post_id'];
2536          }
2537      }
2538      else if ($mode != 'post' && $post_mode != 'edit_first_post' && $post_mode != 'edit_topic')
2539      {
2540          $params .= '&amp;t=' . $data_ary['topic_id'];
2541      }
2542  
2543      $url = (!$params) ? "{$phpbb_root_path}viewforum.$phpEx" : "{$phpbb_root_path}viewtopic.$phpEx";
2544      $url = append_sid($url, 'f=' . $data_ary['forum_id'] . $params) . $add_anchor;
2545  
2546      $poll = $poll_ary;
2547      $data = $data_ary;
2548      /**
2549      * This event is used for performing actions directly after a post or topic
2550      * has been submitted. When a new topic is posted, the topic ID is
2551      * available in the $data array.
2552      *
2553      * The only action that can be done by altering data made available to this
2554      * event is to modify the return URL ($url).
2555      *
2556      * @event core.submit_post_end
2557      * @var    string    mode                Variable containing posting mode value
2558      * @var    string    subject                Variable containing post subject value
2559      * @var    string    username            Variable containing post author name
2560      * @var    int        topic_type            Variable containing topic type value
2561      * @var    array    poll                Array with the poll data for the post
2562      * @var    array    data                Array with the data for the post
2563      * @var    int        post_visibility        Variable containing up to date post visibility
2564      * @var    bool    update_message        Flag indicating if the post will be updated
2565      * @var    bool    update_search_index    Flag indicating if the search index will be updated
2566      * @var    string    url                    The "Return to topic" URL
2567      *
2568      * @since 3.1.0-a3
2569      * @changed 3.1.0-RC3 Added vars mode, subject, username, topic_type,
2570      *        poll, update_message, update_search_index
2571      */
2572      $vars = array(
2573          'mode',
2574          'subject',
2575          'username',
2576          'topic_type',
2577          'poll',
2578          'data',
2579          'post_visibility',
2580          'update_message',
2581          'update_search_index',
2582          'url',
2583      );
2584      extract($phpbb_dispatcher->trigger_event('core.submit_post_end', compact($vars)));
2585      $data_ary = $data;
2586      $poll_ary = $poll;
2587      unset($data);
2588      unset($poll);
2589  
2590      return $url;
2591  }
2592  
2593  /**
2594  * Handle topic bumping
2595  * @param int $forum_id The ID of the forum the topic is being bumped belongs to
2596  * @param int $topic_id The ID of the topic is being bumping
2597  * @param array $post_data Passes some topic parameters:
2598  *                - 'topic_title'
2599  *                - 'topic_last_post_id'
2600  *                - 'topic_last_poster_id'
2601  *                - 'topic_last_post_subject'
2602  *                - 'topic_last_poster_name'
2603  *                - 'topic_last_poster_colour'
2604  * @param int $bump_time The time at which topic was bumped, usually it is a current time as obtained via time().
2605  * @return string An URL to the bumped topic, example: ./viewtopic.php?forum_id=1&amptopic_id=2&ampp=3#p3
2606  */
2607  function phpbb_bump_topic($forum_id, $topic_id, $post_data, $bump_time = false)
2608  {
2609      global $config, $db, $user, $phpEx, $phpbb_root_path, $phpbb_log;
2610  
2611      if ($bump_time === false)
2612      {
2613          $bump_time = time();
2614      }
2615  
2616      // Begin bumping
2617      $db->sql_transaction('begin');
2618  
2619      // Update the topic's last post post_time
2620      $sql = 'UPDATE ' . POSTS_TABLE . "
2621          SET post_time = $bump_time
2622          WHERE post_id = {$post_data['topic_last_post_id']}
2623              AND topic_id = $topic_id";
2624      $db->sql_query($sql);
2625  
2626      // Sync the topic's last post time, the rest of the topic's last post data isn't changed
2627      $sql = 'UPDATE ' . TOPICS_TABLE . "
2628          SET topic_last_post_time = $bump_time,
2629              topic_bumped = 1,
2630              topic_bumper = " . $user->data['user_id'] . "
2631          WHERE topic_id = $topic_id";
2632      $db->sql_query($sql);
2633  
2634      // Update the forum's last post info
2635      $sql = 'UPDATE ' . FORUMS_TABLE . "
2636          SET forum_last_post_id = " . $post_data['topic_last_post_id'] . ",
2637              forum_last_poster_id = " . $post_data['topic_last_poster_id'] . ",
2638              forum_last_post_subject = '" . $db->sql_escape($post_data['topic_last_post_subject']) . "',
2639              forum_last_post_time = $bump_time,
2640              forum_last_poster_name = '" . $db->sql_escape($post_data['topic_last_poster_name']) . "',
2641              forum_last_poster_colour = '" . $db->sql_escape($post_data['topic_last_poster_colour']) . "'
2642          WHERE forum_id = $forum_id";
2643      $db->sql_query($sql);
2644  
2645      // Update bumper's time of the last posting to prevent flood
2646      $sql = 'UPDATE ' . USERS_TABLE . "
2647          SET user_lastpost_time = $bump_time
2648          WHERE user_id = " . $user->data['user_id'];
2649      $db->sql_query($sql);
2650  
2651      $db->sql_transaction('commit');
2652  
2653      // Mark this topic as posted to
2654      markread('post', $forum_id, $topic_id, $bump_time);
2655  
2656      // Mark this topic as read
2657      markread('topic', $forum_id, $topic_id, $bump_time);
2658  
2659      // Update forum tracking info
2660      if ($config['load_db_lastread'] && $user->data['is_registered'])
2661      {
2662          $sql = 'SELECT mark_time
2663              FROM ' . FORUMS_TRACK_TABLE . '
2664              WHERE user_id = ' . $user->data['user_id'] . '
2665                  AND forum_id = ' . $forum_id;
2666          $result = $db->sql_query($sql);
2667          $f_mark_time = (int) $db->sql_fetchfield('mark_time');
2668          $db->sql_freeresult($result);
2669      }
2670      else if ($config['load_anon_lastread'] || $user->data['is_registered'])
2671      {
2672          $f_mark_time = false;
2673      }
2674  
2675      if (($config['load_db_lastread'] && $user->data['is_registered']) || $config['load_anon_lastread'] || $user->data['is_registered'])
2676      {
2677          // Update forum info
2678          $sql = 'SELECT forum_last_post_time
2679              FROM ' . FORUMS_TABLE . '
2680              WHERE forum_id = ' . $forum_id;
2681          $result = $db->sql_query($sql);
2682          $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time');
2683          $db->sql_freeresult($result);
2684  
2685          update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_time, false);
2686      }
2687  
2688      $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_BUMP_TOPIC', false, array(
2689          'forum_id' => $forum_id,
2690          'topic_id' => $topic_id,
2691          $post_data['topic_title']
2692      ));
2693  
2694      $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']}";
2695  
2696      return $url;
2697  }
2698  
2699  /**
2700  * Show upload popup (progress bar)
2701  */
2702  function phpbb_upload_popup($forum_style = 0)
2703  {
2704      global $template, $user;
2705  
2706      ($forum_style) ? $user->setup('posting', $forum_style) : $user->setup('posting');
2707  
2708      page_header($user->lang['PROGRESS_BAR']);
2709  
2710      $template->set_filenames(array(
2711              'popup'    => 'posting_progress_bar.html')
2712      );
2713  
2714      $template->assign_vars(array(
2715              'PROGRESS_BAR'    => $user->img('upload_bar', $user->lang['UPLOAD_IN_PROGRESS']))
2716      );
2717  
2718      $template->display('popup');
2719  
2720      garbage_collection();
2721      exit_handler();
2722  }
2723  
2724  /**
2725  * Do the various checks required for removing posts as well as removing it
2726  *
2727  * @param int        $forum_id        The id of the forum
2728  * @param int        $topic_id        The id of the topic
2729  * @param int        $post_id        The id of the post
2730  * @param array        $post_data        Array with the post data
2731  * @param bool        $is_soft        The flag indicating whether it is the soft delete mode
2732  * @param string        $delete_reason    Description for the post deletion reason
2733  *
2734  * @return null
2735  */
2736  function phpbb_handle_post_delete($forum_id, $topic_id, $post_id, &$post_data, $is_soft = false, $delete_reason = '')
2737  {
2738      global $user, $auth, $config, $request;
2739      global $phpbb_root_path, $phpEx, $phpbb_log, $phpbb_dispatcher;
2740  
2741      $force_delete_allowed = $force_softdelete_allowed = false;
2742      $perm_check = ($is_soft) ? 'softdelete' : 'delete';
2743  
2744      /**
2745      * This event allows to modify the conditions for the post deletion
2746      *
2747      * @event core.handle_post_delete_conditions
2748      * @var    int        forum_id        The id of the forum
2749      * @var    int        topic_id        The id of the topic
2750      * @var    int        post_id            The id of the post
2751      * @var    array    post_data        Array with the post data
2752      * @var    bool    is_soft            The flag indicating whether it is the soft delete mode
2753      * @var    string    delete_reason    Description for the post deletion reason
2754      * @var    bool    force_delete_allowed        Allow the user to delete the post (all permissions and conditions are ignored)
2755      * @var    bool    force_softdelete_allowed    Allow the user to softdelete the post (all permissions and conditions are ignored)
2756      * @var    string    perm_check        The deletion mode softdelete|delete
2757      * @since 3.1.11-RC1
2758      */
2759      $vars = array(
2760          'forum_id',
2761          'topic_id',
2762          'post_id',
2763          'post_data',
2764          'is_soft',
2765          'delete_reason',
2766          'force_delete_allowed',
2767          'force_softdelete_allowed',
2768          'perm_check',
2769      );
2770      extract($phpbb_dispatcher->trigger_event('core.handle_post_delete_conditions', compact($vars)));
2771  
2772      // If moderator removing post or user itself removing post, present a confirmation screen
2773      if ($force_delete_allowed || ($is_soft && $force_softdelete_allowed) || $auth->acl_get("m_$perm_check", $forum_id) || ($post_data['poster_id'] == $user->data['user_id'] && $user->data['is_registered'] && $auth->acl_get("f_$perm_check", $forum_id) && $post_id == $post_data['topic_last_post_id'] && !$post_data['post_edit_locked'] && ($post_data['post_time'] > time() - ($config['delete_time'] * 60) || !$config['delete_time'])))
2774      {
2775          $s_hidden_fields = array(
2776              'p'        => $post_id,
2777              'f'        => $forum_id,
2778              'mode'    => ($is_soft) ? 'soft_delete' : 'delete',
2779          );
2780  
2781          if (confirm_box(true))
2782          {
2783              $data = array(
2784                  'topic_first_post_id'    => $post_data['topic_first_post_id'],
2785                  'topic_last_post_id'    => $post_data['topic_last_post_id'],
2786                  'topic_posts_approved'        => $post_data['topic_posts_approved'],
2787                  'topic_posts_unapproved'    => $post_data['topic_posts_unapproved'],
2788                  'topic_posts_softdeleted'    => $post_data['topic_posts_softdeleted'],
2789                  'topic_visibility'        => $post_data['topic_visibility'],
2790                  'topic_type'            => $post_data['topic_type'],
2791                  'post_visibility'        => $post_data['post_visibility'],
2792                  'post_reported'            => $post_data['post_reported'],
2793                  'post_time'                => $post_data['post_time'],
2794                  'poster_id'                => $post_data['poster_id'],
2795                  'post_postcount'        => $post_data['post_postcount'],
2796              );
2797  
2798              $next_post_id = delete_post($forum_id, $topic_id, $post_id, $data, $is_soft, $delete_reason);
2799              $post_username = ($post_data['poster_id'] == ANONYMOUS && !empty($post_data['post_username'])) ? $post_data['post_username'] : $post_data['username'];
2800  
2801              if ($next_post_id === false)
2802              {
2803                  $phpbb_log->add('mod', $user->data['user_id'], $user->ip, (($is_soft) ? 'LOG_SOFTDELETE_TOPIC' : 'LOG_DELETE_TOPIC'), false, array(
2804                      'forum_id' => $forum_id,
2805                      'topic_id' => $topic_id,
2806                      $post_data['topic_title'],
2807                      $post_username,
2808                      $delete_reason
2809                  ));
2810  
2811                  $meta_info = append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id");
2812                  $message = $user->lang['POST_DELETED'];
2813              }
2814              else
2815              {
2816                  $phpbb_log->add('mod', $user->data['user_id'], $user->ip, (($is_soft) ? 'LOG_SOFTDELETE_POST' : 'LOG_DELETE_POST'), false, array(
2817                      'forum_id' => $forum_id,
2818                      'topic_id' => $topic_id,
2819                      'post_id'  => $post_id,
2820                      $post_data['post_subject'],
2821                      $post_username,
2822                      $delete_reason
2823                  ));
2824  
2825                  $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";
2826                  $message = $user->lang['POST_DELETED'];
2827  
2828                  if (!$request->is_ajax())
2829                  {
2830                      $message .= '<br /><br />' . $user->lang('RETURN_TOPIC', '<a href="' . $meta_info . '">', '</a>');
2831                  }
2832              }
2833  
2834              meta_refresh(3, $meta_info);
2835              if (!$request->is_ajax())
2836              {
2837                  $message .= '<br /><br />' . $user->lang('RETURN_FORUM', '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id) . '">', '</a>');
2838              }
2839              trigger_error($message);
2840          }
2841          else
2842          {
2843              global $template;
2844  
2845              $can_delete = $force_delete_allowed || ($auth->acl_get('m_delete', $forum_id) || ($post_data['poster_id'] == $user->data['user_id'] && $user->data['is_registered'] && $auth->acl_get('f_delete', $forum_id)));
2846              $can_softdelete = $force_softdelete_allowed || ($auth->acl_get('m_softdelete', $forum_id) || ($post_data['poster_id'] == $user->data['user_id'] && $user->data['is_registered'] && $auth->acl_get('f_softdelete', $forum_id)));
2847  
2848              $template->assign_vars(array(
2849                  'S_SOFTDELETED'            => $post_data['post_visibility'] == ITEM_DELETED,
2850                  'S_CHECKED_PERMANENT'    => $request->is_set_post('delete_permanent') ? ' checked="checked"' : '',
2851                  'S_ALLOWED_DELETE'        => $can_delete,
2852                  'S_ALLOWED_SOFTDELETE'    => $can_softdelete,
2853              ));
2854  
2855              $l_confirm = 'DELETE_POST';
2856              if ($post_data['post_visibility'] == ITEM_DELETED)
2857              {
2858                  $l_confirm .= '_PERMANENTLY';
2859                  $s_hidden_fields['delete_permanent'] = '1';
2860              }
2861              else if (!$can_softdelete)
2862              {
2863                  $s_hidden_fields['delete_permanent'] = '1';
2864              }
2865  
2866              confirm_box(false, [$l_confirm, 1], build_hidden_fields($s_hidden_fields), 'confirm_delete_body.html');
2867          }
2868      }
2869  
2870      // If we are here the user is not able to delete - present the correct error message
2871      if ($post_data['poster_id'] != $user->data['user_id'] && $auth->acl_get('f_delete', $forum_id))
2872      {
2873          trigger_error('DELETE_OWN_POSTS');
2874      }
2875  
2876      if ($post_data['poster_id'] == $user->data['user_id'] && $auth->acl_get('f_delete', $forum_id) && $post_id != $post_data['topic_last_post_id'])
2877      {
2878          trigger_error('CANNOT_DELETE_REPLIED');
2879      }
2880  
2881      trigger_error('USER_CANNOT_DELETE');
2882  }


Generated: Wed Nov 11 20:33:01 2020 Cross-referenced by PHPXref 0.7.1