[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/includes/ -> functions_posting.php (source)

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


Generated: Wed Oct 2 15:03:47 2013 Cross-referenced by PHPXref 0.7.1