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