[ Index ]

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


Generated: Thu Jan 11 00:25:41 2018 Cross-referenced by PHPXref 0.7.1