punbb/moderate.php
changeset 7 98bbc533541c
equal deleted inserted replaced
6:5e1f1e916419 7:98bbc533541c
       
     1 <?php
       
     2 /***********************************************************************
       
     3 
       
     4   Copyright (C) 2002-2008  PunBB.org
       
     5 
       
     6   This file is part of PunBB.
       
     7 
       
     8   PunBB is free software; you can redistribute it and/or modify it
       
     9   under the terms of the GNU General Public License as published
       
    10   by the Free Software Foundation; either version 2 of the License,
       
    11   or (at your option) any later version.
       
    12 
       
    13   PunBB is distributed in the hope that it will be useful, but
       
    14   WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    16   GNU General Public License for more details.
       
    17 
       
    18   You should have received a copy of the GNU General Public License
       
    19   along with this program; if not, write to the Free Software
       
    20   Foundation, Inc., 59 Temple Place, Suite 330, Boston,
       
    21   MA  02111-1307  USA
       
    22 
       
    23 ************************************************************************/
       
    24 
       
    25 
       
    26 // if (!defined('PUN_ROOT'))
       
    27 // 	define('PUN_ROOT', './');
       
    28 // require PUN_ROOT.'include/common.php';
       
    29 
       
    30 // import globals (I really hope this isn't dangerous)
       
    31 foreach ( $GLOBALS as $key => $_ )
       
    32 {
       
    33   $$key =& $GLOBALS[$key];
       
    34 }
       
    35 
       
    36 ($hook = get_hook('mr_start')) ? eval($hook) : null;
       
    37 
       
    38 
       
    39 // This particular function doesn't require forum-based moderator access. It can be used
       
    40 // by all moderators and admins.
       
    41 if (isset($_GET['get_host']))
       
    42 {
       
    43 	if (!$pun_user['is_admmod'])
       
    44 		message($lang_common['No permission']);
       
    45 
       
    46 	($hook = get_hook('mr_view_ip_selected')) ? eval($hook) : null;
       
    47 
       
    48 	// Is get_host an IP address or a post ID?
       
    49 	if (@preg_match('/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/', $_GET['get_host']))
       
    50 		$ip = $_GET['get_host'];
       
    51 	else
       
    52 	{
       
    53 		$get_host = intval($_GET['get_host']);
       
    54 		if ($get_host < 1)
       
    55 			message($lang_common['Bad request']);
       
    56 
       
    57 		$query = array(
       
    58 			'SELECT'	=> 'p.poster_ip',
       
    59 			'FROM'		=> 'posts AS p',
       
    60 			'WHERE'		=> 'p.id='.$get_host
       
    61 		);
       
    62 
       
    63 		($hook = get_hook('mr_qr_get_poster_ip')) ? eval($hook) : null;
       
    64 		$result = $pun_db->query_build($query) or error(__FILE__, __LINE__);
       
    65 		if (!$pun_db->num_rows($result))
       
    66 			message($lang_common['Bad request']);
       
    67 
       
    68 		$ip = $pun_db->result($result);
       
    69 	}
       
    70 
       
    71 	message('The IP address is: '.$ip.'<br />The host name is: '.@gethostbyaddr($ip).'<br /><br /><a href="'.pun_link($pun_url['admin_users']).'&show_users='.$ip.'">Show more users for this IP</a>');
       
    72 }
       
    73 
       
    74 
       
    75 // All other functions require moderator/admin access
       
    76 $fid = isset($_GET['fid']) ? intval($_GET['fid']) : 0;
       
    77 if ($fid < 1)
       
    78 	message($lang_common['Bad request']);
       
    79 
       
    80 // Get some info about the forum we're moderating
       
    81 $query = array(
       
    82 	'SELECT'	=> 'f.forum_name, f.redirect_url, f.num_topics, f.moderators',
       
    83 	'FROM'		=> 'forums AS f',
       
    84 	'JOINS'		=> array(
       
    85 		array(
       
    86 			'LEFT JOIN'		=> 'forum_perms AS fp',
       
    87 			'ON'			=> '(fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].')'
       
    88 		)
       
    89 	),
       
    90 	'WHERE'		=> '(fp.read_forum IS NULL OR fp.read_forum=1) AND f.id='.$fid
       
    91 );
       
    92 
       
    93 ($hook = get_hook('mr_qr_get_forum_data')) ? eval($hook) : null;
       
    94 $result = $pun_db->query_build($query) or error(__FILE__, __LINE__);
       
    95 if (!$pun_db->num_rows($result))
       
    96 	message($lang_common['Bad request']);
       
    97 
       
    98 $cur_forum = $pun_db->fetch_assoc($result);
       
    99 
       
   100 // Make sure we're not trying to moderate a redirect forum
       
   101 if ($cur_forum['redirect_url'] != '')
       
   102 	message($lang_common['Bad request']);
       
   103 
       
   104 // Setup the array of moderators
       
   105 $mods_array = ($cur_forum['moderators'] != '') ? unserialize($cur_forum['moderators']) : array();
       
   106 
       
   107 if ($pun_user['g_id'] != PUN_ADMIN && ($pun_user['g_moderator'] != '1' || !array_key_exists($pun_user['username'], $mods_array)))
       
   108 	message($lang_common['No permission']);
       
   109 
       
   110 // Get topic/forum tracking data
       
   111 if (!$pun_user['is_guest'])
       
   112 	$tracked_topics = get_tracked_topics();
       
   113 
       
   114 // Load the misc.php language file
       
   115 require PUN_ROOT.'lang/'.$pun_user['language'].'/misc.php';
       
   116 
       
   117 
       
   118 // Did someone click a cancel button?
       
   119 if (isset($_POST['cancel']))
       
   120 	pun_redirect(pun_link($pun_url['forum'], $fid), $lang_common['Cancel redirect']);
       
   121 
       
   122 
       
   123 // All other topic moderation features require a topic id in GET
       
   124 if (isset($_GET['tid']))
       
   125 {
       
   126 	($hook = get_hook('mr_post_actions_selected')) ? eval($hook) : null;
       
   127 
       
   128 	$tid = intval($_GET['tid']);
       
   129 	if ($tid < 1)
       
   130 		message($lang_common['Bad request']);
       
   131 
       
   132 	// User pressed the cancel button
       
   133 	if (isset($_POST['delete_posts_cancel']))
       
   134 		pun_redirect(pun_link($pun_url['topic'], $tid), $lang_common['Cancel redirect']);
       
   135 
       
   136 	// Fetch some info about the topic
       
   137 	$query = array(
       
   138 		'SELECT'	=> 't.subject, t.poster, t.first_post_id, t.posted, t.num_replies',
       
   139 		'FROM'		=> 'topics AS t',
       
   140 		'WHERE'		=> 't.id='.$tid.' AND t.moved_to IS NULL'
       
   141 	);
       
   142 
       
   143 	($hook = get_hook('mr_qr_get_topic_info')) ? eval($hook) : null;
       
   144 	$result = $pun_db->query_build($query) or error(__FILE__, __LINE__);
       
   145 	if (!$pun_db->num_rows($result))
       
   146 		message($lang_common['Bad request']);
       
   147 
       
   148 	$cur_topic = $pun_db->fetch_assoc($result);
       
   149 
       
   150 	// Delete one or more posts
       
   151 	if (isset($_POST['delete_posts']) || isset($_POST['delete_posts_comply']))
       
   152 	{
       
   153 		($hook = get_hook('mr_delete_posts_form_submitted')) ? eval($hook) : null;
       
   154 
       
   155 		$posts = $_POST['posts'];
       
   156 		if (empty($posts))
       
   157 			message($lang_misc['No posts selected']);
       
   158 
       
   159 		if (isset($_POST['delete_posts_comply']))
       
   160 		{
       
   161 			if (!isset($_POST['req_confirm']))
       
   162 				pun_redirect(pun_link($pun_url['topic'], $tid), $lang_common['No confirm redirect']);
       
   163 
       
   164 			($hook = get_hook('mr_confirm_delete_posts_form_submitted')) ? eval($hook) : null;
       
   165 
       
   166 			if (@preg_match('/[^0-9,]/', $posts))
       
   167 				message($lang_common['Bad request']);
       
   168 
       
   169 			// Verify that the post IDs are valid
       
   170 			$query = array(
       
   171 				'SELECT'	=> '1',
       
   172 				'FROM'		=> 'posts AS p',
       
   173 				'WHERE'		=> 'p.id IN('.$posts.') AND p.id!='.$cur_topic['first_post_id'].' AND p.topic_id='.$tid
       
   174 			);
       
   175 
       
   176 			($hook = get_hook('mr_qr_verify_post_ids')) ? eval($hook) : null;
       
   177 			$result = $pun_db->query_build($query) or error(__FILE__, __LINE__);
       
   178 			if ($pun_db->num_rows($result) != substr_count($posts, ',') + 1)
       
   179 				message($lang_common['Bad request']);
       
   180 
       
   181 			// Delete the posts
       
   182 			$query = array(
       
   183 				'DELETE'	=> 'posts',
       
   184 				'WHERE'		=> 'id IN('.$posts.')'
       
   185 			);
       
   186 
       
   187 			($hook = get_hook('mr_qr_delete_topics')) ? eval($hook) : null;
       
   188 			$pun_db->query_build($query) or error(__FILE__, __LINE__);
       
   189 
       
   190 			if ($db_type != 'mysql' && $db_type != 'mysqli')
       
   191 			{
       
   192 				require PUN_ROOT.'include/search_idx.php';
       
   193 				strip_search_index($posts);
       
   194 			}
       
   195 
       
   196 			// Get last_post, last_post_id, and last_poster for the topic after deletion
       
   197 			$query = array(
       
   198 				'SELECT'	=> 'p.id, p.poster, p.posted',
       
   199 				'FROM'		=> 'posts AS p',
       
   200 				'WHERE'		=> 'p.topic_id='.$tid,
       
   201 				'ORDER BY'	=> 'p.id',
       
   202 				'LIMIT'		=> '1'
       
   203 			);
       
   204 
       
   205 			($hook = get_hook('mr_qr_get_topic_last_post_data')) ? eval($hook) : null;
       
   206 			$result = $pun_db->query_build($query) or error(__FILE__, __LINE__);
       
   207 			$last_post = $pun_db->fetch_assoc($result);
       
   208 
       
   209 			// How many posts did we just delete?
       
   210 			$num_posts_deleted = substr_count($posts, ',') + 1;
       
   211 
       
   212 			// Update the topic
       
   213 			$query = array(
       
   214 				'UPDATE'	=> 'topics',
       
   215 				'SET'		=> 'last_post='.$last_post['posted'].', last_post_id='.$last_post['id'].', last_poster=\''.$pun_db->escape($last_post['poster']).'\', num_replies=num_replies-'.$num_posts_deleted,
       
   216 				'WHERE'		=> 'id='.$tid
       
   217 			);
       
   218 
       
   219 			($hook = get_hook('mr_qr_update_topic')) ? eval($hook) : null;
       
   220 			$pun_db->query_build($query) or error(__FILE__, __LINE__);
       
   221 
       
   222 			sync_forum($fid);
       
   223 
       
   224 			pun_redirect(pun_link($pun_url['topic'], $tid), $lang_misc['Delete posts redirect']);
       
   225 		}
       
   226 
       
   227 		// Setup form
       
   228 		$pun_page['set_count'] = $pun_page['fld_count'] = 0;
       
   229 		$pun_page['form_action'] = pun_link($pun_url['delete_multiple'], array($fid, $tid));
       
   230 
       
   231 		$pun_page['hidden_fields'] = array(
       
   232 			'<input type="hidden" name="csrf_token" value="'.generate_form_token($pun_page['form_action']).'" />',
       
   233 			'<input type="hidden" name="posts" value="'.implode(',', array_keys($posts)).'" />'
       
   234 		);
       
   235 
       
   236 		// Setup breadcrumbs
       
   237 		$pun_page['crumbs'] = array(
       
   238 			array($pun_config['o_board_title'], pun_link($pun_url['index'])),
       
   239 			array($cur_forum['forum_name'], pun_link($pun_url['forum'], $fid)),
       
   240 			array($cur_topic['subject'], pun_link($pun_url['topic'], $tid)),
       
   241 			$lang_misc['Delete posts']
       
   242 		);
       
   243 
       
   244 		($hook = get_hook('mr_confirm_delete_posts_pre_header_load')) ? eval($hook) : null;
       
   245 
       
   246 		define('PUN_PAGE', 'dialogue');
       
   247 		require PUN_ROOT.'header.php';
       
   248 
       
   249 ?>
       
   250 <div id="pun-main" class="main">
       
   251 
       
   252 	<h1><span><?php echo end($pun_page['crumbs']) ?></span></h1>
       
   253 
       
   254 	<div class="main-head">
       
   255 		<h2><span><?php echo $lang_misc['Confirm post delete'] ?></span></h2>
       
   256 	</div>
       
   257 
       
   258 	<div class="main-content frm">
       
   259 		<form class="frm-form" method="post" accept-charset="utf-8" action="<?php echo $pun_page['form_action'] ?>">
       
   260 			<div class="hidden">
       
   261 				<?php echo implode("\n\t\t\t\t", $pun_page['hidden_fields'])."\n" ?>
       
   262 			</div>
       
   263 			<fieldset class="frm-set set<?php echo ++$pun_page['set_count'] ?>">
       
   264 				<legend class="frm-legend"><strong><?php echo $lang_misc['Delete posts'] ?></strong></legend>
       
   265 				<div class="checkbox radbox">
       
   266 					<label for="fld<?php echo ++$pun_page['fld_count'] ?>"><span class="fld-label"><?php echo $lang_common['Please confirm'] ?></span><br /><input type="checkbox" id="fld<?php echo $pun_page['fld_count'] ?>" name="req_confirm" value="1" checked="checked" /> <?php echo $lang_misc['Confirm post delete'] ?>.</label>
       
   267 				</div>
       
   268 			</fieldset>
       
   269 			<div class="frm-buttons">
       
   270 				<span class="submit"><input type="submit" name="delete_posts_comply" value="<?php echo $lang_common['Delete'] ?>" /></span>
       
   271 				<span class="cancel"><input type="submit" name="cancel" value="<?php echo $lang_common['Cancel'] ?>" /></span>
       
   272 			</div>
       
   273 		</form>
       
   274 	</div>
       
   275 
       
   276 </div>
       
   277 <?php
       
   278 
       
   279 		require PUN_ROOT.'footer.php';
       
   280 	}
       
   281 
       
   282 
       
   283 	// Show the delete multiple posts view
       
   284 
       
   285 	// Load the viewtopic.php language file
       
   286 	require PUN_ROOT.'lang/'.$pun_user['language'].'/topic.php';
       
   287 
       
   288 	// Used to disable the Move and Delete buttons if there are no replies to this topic
       
   289 	$pun_page['button_status'] = ($cur_topic['num_replies'] == 0) ? ' disabled="disabled"' : '';
       
   290 
       
   291 
       
   292 	// Determine the post offset (based on $_GET['p'])
       
   293 	$pun_page['num_pages'] = ceil(($cur_topic['num_replies'] + 1) / $pun_user['disp_posts']);
       
   294 	$pun_page['page'] = (!isset($_GET['p']) || $_GET['p'] <= 1 || $_GET['p'] > $pun_page['num_pages']) ? 1 : $_GET['p'];
       
   295 	$pun_page['start_from'] = $pun_user['disp_posts'] * ($pun_page['page'] - 1);
       
   296 	$pun_page['finish_at'] = min(($pun_page['start_from'] + $pun_user['disp_posts']), ($cur_topic['num_replies'] + 1));
       
   297 
       
   298 	// Generate paging links
       
   299 	$pun_page['page_post'] = '<p class="paging"><strong>'.$lang_common['Pages'].'</strong> '.pun_paginate($pun_page['num_pages'], $pun_page['page'], $pun_url['delete_multiple'], array($fid, $tid)).'</p>';
       
   300 
       
   301 	// Navigation links for header and page numbering for title/meta description
       
   302 	if ($pun_page['page'] < $pun_page['num_pages'])
       
   303 	{
       
   304 		$pun_page['nav'][] = '<link rel="last" href="'.pun_sublink($pun_url['delete_multiple'], $pun_url['page'], $pun_page['num_pages'], array($fid, $tid)).'" title="'.$lang_common['Page'].' '.$pun_page['num_pages'].'" />';
       
   305 		$pun_page['nav'][] = '<link rel="next" href="'.pun_sublink($pun_url['delete_multiple'], $pun_url['page'], ($pun_page['page'] + 1), array($fid, $tid)).'" title="'.$lang_common['Page'].' '.($pun_page['page'] + 1).'" />';
       
   306 	}
       
   307 	if ($pun_page['page'] > 1)
       
   308 	{
       
   309 		$pun_page['nav'][] = '<link rel="prev" href="'.pun_sublink($pun_url['delete_multiple'], $pun_url['page'], ($pun_page['page'] - 1), array($fid, $tid)).'" title="'.$lang_common['Page'].' '.($pun_page['page'] - 1).'" />';
       
   310 		$pun_page['nav'][] = '<link rel="first" href="'.pun_link($pun_url['delete_multiple'], array($fid, $tid)).'" title="'.$lang_common['Page'].' 1" />';
       
   311 	}
       
   312 
       
   313 	// Generate page information
       
   314 	if ($pun_page['num_pages'] > 1)
       
   315 		$pun_page['main_info'] = '<span>'.sprintf($lang_common['Page number'], $pun_page['page'], $pun_page['num_pages']).' </span>'.sprintf($lang_common['Paged info'], $lang_common['Posts'], $pun_page['start_from'] + 1, $pun_page['finish_at'], $cur_topic['num_replies'] + 1);
       
   316 	else
       
   317 		$pun_page['main_info'] = sprintf($lang_common['Page info'], $lang_common['Posts'], ($cur_topic['num_replies'] + 1));
       
   318 
       
   319 	if ($pun_config['o_censoring'] == '1')
       
   320 		$cur_topic['subject'] = censor_words($cur_topic['subject']);
       
   321 
       
   322 	// Setup form
       
   323 	$pun_page['form_action'] = pun_link($pun_url['delete_multiple'], array($fid, $tid));
       
   324 
       
   325 	// Setup breadcrumbs
       
   326 	$pun_page['crumbs'] = array(
       
   327 		array($pun_config['o_board_title'], pun_link($pun_url['index'])),
       
   328 		array($cur_forum['forum_name'], pun_link($pun_url['forum'], $fid)),
       
   329 		array($cur_topic['subject'], pun_link($pun_url['topic'], $tid)),
       
   330 		$lang_topic['Delete posts']
       
   331 	);
       
   332 
       
   333 	($hook = get_hook('mr_post_actions_pre_header_load')) ? eval($hook) : null;
       
   334 
       
   335 	define('PUN_PAGE', 'modtopic');
       
   336 	require PUN_ROOT.'header.php';
       
   337 
       
   338 ?>
       
   339 <div id="pun-main" class="main paged">
       
   340 
       
   341 	<h1><span><?php echo end($pun_page['crumbs']) ?></span></h1>
       
   342 
       
   343 	<form method="post" accept-charset="utf-8" action="<?php echo $pun_page['form_action'] ?>">
       
   344 
       
   345 	<div class="hidden">
       
   346 		<input type="hidden" name="csrf_token" value="<?php echo generate_form_token($pun_page['form_action']) ?>" />
       
   347 	</div>
       
   348 
       
   349 	<div class="paged-head">
       
   350 		<?php echo $pun_page['page_post']."\n" ?>
       
   351 	</div>
       
   352 
       
   353 	<div class="main-head">
       
   354 		<h2><span><?php echo $pun_page['main_info'] ?></span></h2>
       
   355 		<p class="main-options"><?php echo $lang_misc['Select posts'] ?></p>
       
   356 	</div>
       
   357 
       
   358 	<div class="main-content topic">
       
   359 <?php
       
   360 
       
   361 	require PUN_ROOT.'include/parser.php';
       
   362 
       
   363 	$pun_page['item_count'] = 0;	// Keep track of post numbers
       
   364 
       
   365 	// Retrieve the posts (and their respective poster)
       
   366 	$query = array(
       
   367 		'SELECT'	=> 'u.title, u.num_posts, g.g_id, g.g_user_title, p.id, p.poster, p.poster_id, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by',
       
   368 		'FROM'		=> 'posts AS p',
       
   369 		'JOINS'		=> array(
       
   370 			array(
       
   371 				'INNER JOIN'	=> 'users AS u',
       
   372 				'ON'			=> 'u.id=p.poster_id'
       
   373 			),
       
   374 			array(
       
   375 				'INNER JOIN'	=> 'groups AS g',
       
   376 				'ON'			=> 'g.g_id=u.group_id'
       
   377 			)
       
   378 		),
       
   379 		'WHERE'		=> 'p.topic_id='.$tid,
       
   380 		'ORDER BY'	=> 'p.id',
       
   381 		'LIMIT'		=> $pun_page['start_from'].','.$pun_user['disp_posts']
       
   382 	);
       
   383 
       
   384 	($hook = get_hook('mr_qr_get_topic_info')) ? eval($hook) : null;
       
   385 	$result = $pun_db->query_build($query, true) or error(__FILE__, __LINE__);
       
   386 	while ($cur_post = $pun_db->fetch_assoc($result))
       
   387 	{
       
   388 		++$pun_page['item_count'];
       
   389 
       
   390 		$pun_page['post_options'] = $pun_page['message'] = array();
       
   391 		$pun_page['user_ident'] = '';
       
   392 		$pun_page['user_info'] = '';
       
   393 		$cur_post['username'] = $cur_post['poster'];
       
   394 
       
   395 		// Generate the post heading
       
   396 		$pun_page['item_ident'] = array(
       
   397 			'num'	=> '<strong>'.($pun_page['start_from'] + $pun_page['item_count']).'</strong>',
       
   398 			'user'	=> '<cite>'.($cur_topic['posted'] == $cur_post['posted'] ? sprintf($lang_topic['Topic by'], htmlspecialchars($cur_post['username'])) : sprintf($lang_topic['Reply by'], htmlspecialchars($cur_post['username']))).'</cite>',
       
   399 			'date'	=> '<span>'.format_time($cur_post['posted']).'</span>'
       
   400 		);
       
   401 
       
   402 		$pun_page['item_head'] = '<a class="permalink" rel="bookmark" title="'.$lang_topic['Permalink post'].'" href="'.pun_link($pun_url['post'], $cur_post['id']).'">'.implode(' ', $pun_page['item_ident']).'</a>';
       
   403 
       
   404 		// Generate the checkbox field
       
   405 		if ($cur_post['id'] != $cur_topic['first_post_id'])
       
   406 			$pun_page['item_select'] = '<div class="checkbox radbox item-select"><label for="fld'.$cur_post['id'].'"><span class="fld-label">'.$lang_misc['Select post'].'</span> <input type="checkbox" id="fld'.$cur_post['id'].'" name="posts['.$cur_post['id'].']" value="1" /> '.$pun_page['item_ident']['num'].'</label></div>';
       
   407 
       
   408 		// Generate author identification
       
   409 		$pun_page['user_ident'] = (($cur_post['poster_id'] > 1) ? '<strong class="username"><a title="'.sprintf($lang_topic['Go to profile'], htmlspecialchars($cur_post['username'])).'" href="'.pun_link($pun_url['user'], $cur_post['poster_id']).'">'.htmlspecialchars($cur_post['username']).'</a></strong>' : '<strong class="username">'.htmlspecialchars($cur_post['username']).'</strong>');
       
   410 		$pun_page['user_info'] = '<li class="title"><span><strong>'.$lang_topic['Title'].'</strong> '.get_title($cur_post).'</span></li>';
       
   411 
       
   412 		// Give the post some class
       
   413 		$pun_page['item_status'] = array(
       
   414 			'post',
       
   415 			($pun_page['item_count'] % 2 == 0) ? 'odd' : 'even'
       
   416 		);
       
   417 
       
   418 		if ($pun_page['item_count'] == 1)
       
   419 			$pun_page['item_status'][] = 'firstpost';
       
   420 
       
   421 		if (($pun_page['start_from'] + $pun_page['item_count']) == $pun_page['finish_at'])
       
   422 			$pun_page['item_status'][] = 'lastpost';
       
   423 
       
   424 		if ($cur_post['id'] == $cur_topic['first_post_id'])
       
   425 			$pun_page['item_status'][] = 'topicpost';
       
   426 
       
   427 		if ($cur_post['id'] == $cur_topic['first_post_id'])
       
   428 			$pun_page['item_subject'] = $lang_common['Topic'].': '.$cur_topic['subject'];
       
   429 		else
       
   430 			$pun_page['item_subject'] = $lang_common['Re'].' '.$cur_topic['subject'];
       
   431 
       
   432 		// Perform the main parsing of the message (BBCode, smilies, censor words etc)
       
   433 		$pun_page['message'][] = parse_message($cur_post['message'], $cur_post['hide_smilies']);
       
   434 
       
   435 		if ($cur_post['edited'] != '')
       
   436 			$pun_page['message'][] = '<p class="lastedit"><em>'.sprintf($lang_topic['Last edited'], htmlspecialchars($cur_post['edited_by']), format_time($cur_post['edited'])).'</em></p>';
       
   437 
       
   438 		($hook = get_hook('mr_post_actions_row_pre_display')) ? eval($hook) : null;
       
   439 
       
   440 ?>
       
   441 		<div class="<?php echo implode(' ', $pun_page['item_status']) ?>">
       
   442 			<div class="postmain">
       
   443 				<div id="p<?php echo $cur_post['id'] ?>" class="posthead">
       
   444 					<h3><?php echo $pun_page['item_head'] ?></h3>
       
   445 				</div>
       
   446 				<?php if (isset($pun_page['item_select'])) echo $pun_page['item_select']."\n" ?>
       
   447 				<div class="postbody">
       
   448 					<div class="user">
       
   449 						<h4 class="user-ident"><?php echo $pun_page['user_ident'] ?></h4>
       
   450 						<ul class="user-info">
       
   451 							<?php echo $pun_page['user_info']."\n" ?>
       
   452 						</ul>
       
   453 					</div>
       
   454 					<div class="post-entry">
       
   455 						<h4 class="entry-title"><?php echo $pun_page['item_subject'] ?></h4>
       
   456 						<div class="entry-content">
       
   457 							<?php echo implode("\n\t\t\t\t\t\t\t", $pun_page['message'])."\n" ?>
       
   458 						</div>
       
   459 					</div>
       
   460 				</div>
       
   461 			</div>
       
   462 		</div>
       
   463 <?php
       
   464 
       
   465 	}
       
   466 
       
   467 ?>
       
   468 	</div>
       
   469 
       
   470 	<div class="main-foot">
       
   471 		<p class="h2"><strong><?php echo $pun_page['main_info'] ?></strong></p>
       
   472 	</div>
       
   473 
       
   474 	<div class="paged-foot">
       
   475 		<p class="submitting"><span class="submit"><input type="submit" name="delete_posts" value="<?php echo $lang_misc['Delete posts'] ?>"<?php echo $pun_page['button_status'] ?> /></span></p>
       
   476 		<?php echo $pun_page['page_post']."\n" ?>
       
   477 	</div>
       
   478 
       
   479 	</form>
       
   480 
       
   481 </div>
       
   482 
       
   483 <div id="pun-crumbs-foot">
       
   484 	<p class="crumbs"><?php echo generate_crumbs(false) ?></p>
       
   485 </div>
       
   486 
       
   487 <?php
       
   488 
       
   489 	require PUN_ROOT.'footer.php';
       
   490 }
       
   491 
       
   492 
       
   493 // Move one or more topics
       
   494 if (isset($_REQUEST['move_topics']) || isset($_POST['move_topics_to']))
       
   495 {
       
   496 	if (isset($_POST['move_topics_to']))
       
   497 	{
       
   498 		($hook = get_hook('mr_confirm_move_topics_form_submitted')) ? eval($hook) : null;
       
   499 
       
   500 		if (@preg_match('/[^0-9,]/', $_POST['topics']))
       
   501 			message($lang_common['Bad request']);
       
   502 
       
   503 		$topics = explode(',', $_POST['topics']);
       
   504 		$move_to_forum = isset($_POST['move_to_forum']) ? intval($_POST['move_to_forum']) : 0;
       
   505 		if (empty($topics) || $move_to_forum < 1)
       
   506 			message($lang_common['Bad request']);
       
   507 
       
   508 		// Verify that the topic IDs are valid
       
   509 		$query = array(
       
   510 			'SELECT'	=> '1',
       
   511 			'FROM'		=> 'topics AS t',
       
   512 			'WHERE'		=> 't.id IN('.implode(',', $topics).') AND t.forum_id='.$fid
       
   513 		);
       
   514 
       
   515 		($hook = get_hook('mr_qr_verify_topic_ids')) ? eval($hook) : null;
       
   516 		$result = $pun_db->query_build($query) or error(__FILE__, __LINE__);
       
   517 		if ($pun_db->num_rows($result) != count($topics))
       
   518 			message($lang_common['Bad request']);
       
   519 
       
   520 		// Delete any redirect topics if there are any (only if we moved/copied the topic back to where it where it was once moved from)
       
   521 		$query = array(
       
   522 			'DELETE'	=> 'topics',
       
   523 			'WHERE'		=> 'forum_id='.$move_to_forum.' AND moved_to IN('.implode(',', $topics).')'
       
   524 		);
       
   525 
       
   526 		($hook = get_hook('mr_qr_delete_redirect_topics')) ? eval($hook) : null;
       
   527 		$pun_db->query_build($query) or error(__FILE__, __LINE__);
       
   528 
       
   529 		// Move the topic(s)
       
   530 		$query = array(
       
   531 			'UPDATE'	=> 'topics',
       
   532 			'SET'		=> 'forum_id='.$move_to_forum,
       
   533 			'WHERE'		=> 'id IN('.implode(',', $topics).')'
       
   534 		);
       
   535 
       
   536 		($hook = get_hook('mr_qr_move_topics')) ? eval($hook) : null;
       
   537 		$pun_db->query_build($query) or error(__FILE__, __LINE__);
       
   538 
       
   539 		// Should we create redirect topics?
       
   540 		if (isset($_POST['with_redirect']))
       
   541 		{
       
   542 			while (list(, $cur_topic) = @each($topics))
       
   543 			{
       
   544 				// Fetch info for the redirect topic
       
   545 				$query = array(
       
   546 					'SELECT'	=> 't.poster, t.subject, t.posted, t.last_post',
       
   547 					'FROM'		=> 'topics AS t',
       
   548 					'WHERE'		=> 't.id='.$cur_topic
       
   549 				);
       
   550 
       
   551 				($hook = get_hook('mr_qr_get_redirect_topic_data')) ? eval($hook) : null;
       
   552 				$result = $pun_db->query_build($query) or error(__FILE__, __LINE__);
       
   553 				$moved_to = $pun_db->fetch_assoc($result);
       
   554 
       
   555 				// Create the redirect topic
       
   556 				$query = array(
       
   557 					'INSERT'	=> 'poster, subject, posted, last_post, moved_to, forum_id',
       
   558 					'INTO'		=> 'topics',
       
   559 					'VALUES'	=> '\''.$pun_db->escape($moved_to['poster']).'\', \''.$pun_db->escape($moved_to['subject']).'\', '.$moved_to['posted'].', '.$moved_to['last_post'].', '.$cur_topic.', '.$fid
       
   560 				);
       
   561 
       
   562 				($hook = get_hook('mr_qr_add_redirect_topic')) ? eval($hook) : null;
       
   563 				$pun_db->query_build($query) or error(__FILE__, __LINE__);
       
   564 			}
       
   565 		}
       
   566 
       
   567 		sync_forum($fid);			// Synchronize the forum FROM which the topic was moved
       
   568 		sync_forum($move_to_forum);	// Synchronize the forum TO which the topic was moved
       
   569 
       
   570 		$pun_page['redirect_msg'] = (count($topics) > 1) ? $lang_misc['Move topics redirect'] : $lang_misc['Move topic redirect'];
       
   571 		pun_redirect(pun_link($pun_url['forum'], $move_to_forum), $pun_page['redirect_msg']);
       
   572 	}
       
   573 
       
   574 	if (isset($_POST['move_topics']))
       
   575 	{
       
   576 		$topics = isset($_POST['topics']) ? $_POST['topics'] : array();
       
   577 		if (empty($topics))
       
   578 			message($lang_misc['No topics selected']);
       
   579 
       
   580 		$topics = implode(',', array_keys($topics));
       
   581 		$action = 'multi';
       
   582 	}
       
   583 	else
       
   584 	{
       
   585 		$topics = intval($_GET['move_topics']);
       
   586 		if ($topics < 1)
       
   587 			message($lang_common['Bad request']);
       
   588 
       
   589 		$action = 'single';
       
   590 
       
   591 		// Fetch the topic subject
       
   592 		$query = array(
       
   593 			'SELECT'	=> 't.subject',
       
   594 			'FROM'		=> 'topics AS t',
       
   595 			'WHERE'		=> 't.id='.$topics
       
   596 		);
       
   597 
       
   598 		($hook = get_hook('mr_qr_get_topic_subject')) ? eval($hook) : null;
       
   599 		$result = $pun_db->query_build($query) or error(__FILE__, __LINE__);
       
   600 		$subject = $pun_db->result($result);
       
   601 	}
       
   602 
       
   603 	// Get forums we can move the post into
       
   604 	$query = array(
       
   605 		'SELECT'	=> 'c.id AS cid, c.cat_name, f.id AS fid, f.forum_name',
       
   606 		'FROM'		=> 'categories AS c',
       
   607 		'JOINS'		=> array(
       
   608 			array(
       
   609 				'INNER JOIN'	=> 'forums AS f',
       
   610 				'ON'			=> 'c.id=f.cat_id'
       
   611 			),
       
   612 			array(
       
   613 				'LEFT JOIN'		=> 'forum_perms AS fp',
       
   614 				'ON'			=> '(fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].')'
       
   615 			)
       
   616 		),
       
   617 		'WHERE'		=> '(fp.read_forum IS NULL OR fp.read_forum=1) AND f.redirect_url IS NULL AND f.id!='.$fid,
       
   618 		'ORDER BY'	=> 'c.disp_position, c.id, f.disp_position'
       
   619 	);
       
   620 
       
   621 	($hook = get_hook('mr_qr_get_target_forums')) ? eval($hook) : null;
       
   622 	$result = $pun_db->query_build($query) or error(__FILE__, __LINE__);
       
   623 	$num_forums = $pun_db->num_rows($result);
       
   624 
       
   625 	if (!$num_forums)
       
   626 		message($lang_misc['Nowhere to move']);
       
   627 
       
   628 	$forum_list = array();
       
   629 	for ($i = 0; $i < $num_forums; ++$i)
       
   630 		$forum_list[] = $pun_db->fetch_assoc($result);
       
   631 
       
   632 	// Setup form
       
   633 	$pun_page['fld_count'] = $pun_page['set_count'] = 0;
       
   634 	$pun_page['form_action'] = pun_link($pun_url['moderate_forum'], $fid);
       
   635 
       
   636 	$pun_page['hidden_fields'] = array(
       
   637 		'<input type="hidden" name="csrf_token" value="'.generate_form_token($pun_page['form_action']).'" />',
       
   638 		'<input type="hidden" name="topics" value="'.$topics.'" />'
       
   639 	);
       
   640 
       
   641 	// Setup breadcrumbs
       
   642 	$pun_page['crumbs'][] = array($pun_config['o_board_title'], pun_link($pun_url['index']));
       
   643 	$pun_page['crumbs'][] = array($cur_forum['forum_name'], pun_link($pun_url['forum'], $fid));
       
   644 	if ($action == 'single')
       
   645 		$pun_page['crumbs'][] = array($subject, pun_link($pun_url['topic'], $topics));
       
   646 	else
       
   647 		$pun_page['crumbs'][] = array($lang_misc['Moderate forum'], pun_link($pun_url['moderate_forum'], $fid));
       
   648 	$pun_page['crumbs'][] =	($action == 'single') ? $lang_misc['Move topic'] : $lang_misc['Move topics'];
       
   649 
       
   650 	($hook = get_hook('mr_move_topics_pre_header_load')) ? eval($hook) : null;
       
   651 
       
   652 	define('PUN_PAGE', 'dialogue');
       
   653 	require PUN_ROOT.'header.php';
       
   654 
       
   655 ?>
       
   656 <div id="pun-main" class="main">
       
   657 
       
   658 	<h1><span><?php echo end($pun_page['crumbs']) ?></span></h1>
       
   659 
       
   660 	<div class="main-head">
       
   661 		<h2><span><?php echo end($pun_page['crumbs']).' '.$lang_misc['To new forum'] ?></span></h2>
       
   662 	</div>
       
   663 
       
   664 	<div class="main-content frm">
       
   665 		<form class="frm-form" method="post" accept-charset="utf-8" action="<?php echo $pun_page['form_action'] ?>">
       
   666 			<div class="hidden">
       
   667 				<?php echo implode("\n\t\t\t\t", $pun_page['hidden_fields'])."\n" ?>
       
   668 			</div>
       
   669 			<fieldset class="frm-set set<?php echo ++$pun_page['set_count'] ?>">
       
   670 				<legend class="frm-legend"><strong><?php echo $lang_misc['Move topic'] ?></strong></legend>
       
   671 				<div class="frm-fld select">
       
   672 					<label for="fld<?php echo ++$pun_page['fld_count'] ?>">
       
   673 						<span class="fld-label"><?php echo $lang_misc['Move to'] ?></span><br />
       
   674 						<span class="fld-input"><select id="fld<?php echo $pun_page['fld_count'] ?>" name="move_to_forum">
       
   675 <?php
       
   676 
       
   677 	$pun_page['cur_category'] = 0;
       
   678 	foreach ($forum_list as $cur_forum)
       
   679 	{
       
   680 		if ($cur_forum['cid'] != $pun_page['cur_category'])	// A new category since last iteration?
       
   681 		{
       
   682 			if ($pun_page['cur_category'])
       
   683 				echo "\t\t\t\t\t\t".'</optgroup>'."\n";
       
   684 
       
   685 			echo "\t\t\t\t\t\t".'<optgroup label="'.htmlspecialchars($cur_forum['cat_name']).'">'."\n";
       
   686 			$pun_page['cur_category'] = $cur_forum['cid'];
       
   687 		}
       
   688 
       
   689 		if ($cur_forum['fid'] != $fid)
       
   690 			echo "\t\t\t\t\t\t".'<option value="'.$cur_forum['fid'].'">'.htmlspecialchars($cur_forum['forum_name']).'</option>'."\n";
       
   691 	}
       
   692 
       
   693 ?>
       
   694 						</optgroup>
       
   695 						</select></span>
       
   696 					</label>
       
   697 				</div>
       
   698 				<div class="checkbox radbox">
       
   699 					<label for="fld<?php echo ++$pun_page['fld_count'] ?>"><span class="fld-label"><?php echo $lang_misc['Redirect topic'] ?></span><br /><input type="checkbox" id="fld<?php echo $pun_page['fld_count'] ?>" name="with_redirect" value="1"<?php if ($action == 'single') echo ' checked="checked"' ?> /> <?php echo ($action == 'single') ? $lang_misc['Leave redirect'] : $lang_misc['Leave redirects'] ?></label>
       
   700 				</div>
       
   701 			</fieldset>
       
   702 			<div class="frm-buttons">
       
   703 				<span class="submit"><input type="submit" name="move_topics_to" value="<?php echo $lang_misc['Move'] ?>" /></span>
       
   704 				<span class="cancel"><input type="submit" name="cancel" value="<?php echo $lang_common['Cancel'] ?>" /></span>
       
   705 			</div>
       
   706 		</form>
       
   707 	</div>
       
   708 
       
   709 </div>
       
   710 <?php
       
   711 
       
   712 	require PUN_ROOT.'footer.php';
       
   713 }
       
   714 
       
   715 
       
   716 // Delete one or more topics
       
   717 else if (isset($_REQUEST['delete_topics']) || isset($_POST['delete_topics_comply']))
       
   718 {
       
   719 	$topics = isset($_POST['topics']) ? $_POST['topics'] : array();
       
   720 	if (empty($topics))
       
   721 		message($lang_misc['No topics selected']);
       
   722 
       
   723 	if (isset($_POST['delete_topics_comply']))
       
   724 	{
       
   725 		if (!isset($_POST['req_confirm']))
       
   726 			pun_redirect(pun_link($pun_url['forum'], $fid), $lang_common['Cancel redirect']);
       
   727 
       
   728 		($hook = get_hook('mr_confirm_delete_topics_form_submitted')) ? eval($hook) : null;
       
   729 
       
   730 		if (@preg_match('/[^0-9,]/', $topics))
       
   731 			message($lang_common['Bad request']);
       
   732 
       
   733 		// Verify that the topic IDs are valid
       
   734 		$query = array(
       
   735 			'SELECT'	=> '1',
       
   736 			'FROM'		=> 'topics AS t',
       
   737 			'WHERE'		=> 't.id IN('.implode(',', $topics).') AND t.forum_id='.$fid
       
   738 		);
       
   739 
       
   740 		($hook = get_hook('mr_qr_verify_topic_ids2')) ? eval($hook) : null;
       
   741 		$result = $pun_db->query_build($query) or error(__FILE__, __LINE__);
       
   742 		if ($pun_db->num_rows($result) != substr_count($topics, ',') + 1)
       
   743 			message($lang_common['Bad request']);
       
   744 
       
   745 		// Delete the topics and any redirect topics
       
   746 		$query = array(
       
   747 			'DELETE'	=> 'topics',
       
   748 			'WHERE'		=> 'id IN('.$topics.') OR moved_to IN('.$topics.')'
       
   749 		);
       
   750 
       
   751 		($hook = get_hook('mr_qr_delete_topics')) ? eval($hook) : null;
       
   752 		$pun_db->query_build($query) or error(__FILE__, __LINE__);
       
   753 
       
   754 		// Delete any subscriptions
       
   755 		$query = array(
       
   756 			'DELETE'	=> 'subscriptions',
       
   757 			'WHERE'		=> 'topic_id IN('.$topics.')'
       
   758 		);
       
   759 
       
   760 		($hook = get_hook('mr_qr_delete_subscriptions')) ? eval($hook) : null;
       
   761 		$pun_db->query_build($query) or error(__FILE__, __LINE__);
       
   762 
       
   763 		if ($db_type != 'mysql' && $db_type != 'mysqli')
       
   764 		{
       
   765 			// Create a list of the post ID's in the deleted topic and strip the search index
       
   766 			$query = array(
       
   767 				'SELECT'	=> 'p.id',
       
   768 				'FROM'		=> 'posts AS p',
       
   769 				'WHERE'		=> 'p.topic_id IN('.$topics.')'
       
   770 			);
       
   771 
       
   772 			($hook = get_hook('mr_qr_get_deleted_posts')) ? eval($hook) : null;
       
   773 			$result = $pun_db->query_build($query) or error(__FILE__, __LINE__);
       
   774 
       
   775 			$post_ids = '';
       
   776 			while ($row = $pun_db->fetch_row($result))
       
   777 				$post_ids .= ($post_ids != '') ? ','.$row[0] : $row[0];
       
   778 
       
   779 			// Strip the search index provided we're not just deleting redirect topics
       
   780 			if ($post_ids != '')
       
   781 			{
       
   782 				require PUN_ROOT.'include/search_idx.php';
       
   783 				strip_search_index($post_ids);
       
   784 			}
       
   785 		}
       
   786 
       
   787 		// Delete posts
       
   788 		$query = array(
       
   789 			'DELETE'	=> 'posts',
       
   790 			'WHERE'		=> 'topic_id IN('.$topics.')'
       
   791 		);
       
   792 
       
   793 		($hook = get_hook('mr_qr_delete_posts')) ? eval($hook) : null;
       
   794 		$pun_db->query_build($query) or error(__FILE__, __LINE__);
       
   795 
       
   796 		sync_forum($fid);
       
   797 
       
   798 		pun_redirect(pun_link($pun_url['forum'], $fid), $lang_misc['Delete topics redirect']);
       
   799 	}
       
   800 
       
   801 
       
   802 	// Setup form
       
   803 	$pun_page['fld_count'] = $pun_page['set_count'] = 0;
       
   804 	$pun_page['form_action'] = pun_link($pun_url['moderate_forum'], $fid);
       
   805 
       
   806 	$pun_page['hidden_fields'] = array(
       
   807 		'<input type="hidden" name="csrf_token" value="'.generate_form_token($pun_page['form_action']).'" />',
       
   808 		'<input type="hidden" name="topics" value="'.implode(',', array_keys($topics)).'" />'
       
   809 	);
       
   810 
       
   811 	// Setup breadcrumbs
       
   812 	$pun_page['crumbs'] = array(
       
   813 		array($pun_config['o_board_title'], pun_link($pun_url['index'])),
       
   814 		array($cur_forum['forum_name'], pun_link($pun_url['forum'], $fid)),
       
   815 		array($lang_misc['Moderate forum'], pun_link($pun_url['moderate_forum'], $fid)),
       
   816 		$lang_misc['Delete topics']
       
   817 	);
       
   818 
       
   819 	($hook = get_hook('mr_delete_topics_pre_header_load')) ? eval($hook) : null;
       
   820 
       
   821 	define('PUN_PAGE', 'dialogue');
       
   822 	require PUN_ROOT.'header.php';
       
   823 
       
   824 ?>
       
   825 <div id="pun-main" class="main">
       
   826 
       
   827 	<h1><span><?php echo end($pun_page['crumbs']) ?></span></h1>
       
   828 
       
   829 	<div class="main-head">
       
   830 		<h2><span><?php echo $lang_misc['Confirm topic delete'] ?></span></h2>
       
   831 	</div>
       
   832 
       
   833 	<div class="main-content frm">
       
   834 		<form class="frm-form" method="post" accept-charset="utf-8" action="<?php echo $pun_page['form_action'] ?>">
       
   835 			<div class="hidden">
       
   836 				<?php echo implode("\n\t\t\t\t", $pun_page['hidden_fields'])."\n" ?>
       
   837 			</div>
       
   838 			<fieldset class="frm-set set<?php echo ++$pun_page['set_count'] ?>">
       
   839 				<legend class="frm-legend"><strong><?php echo $lang_misc['Delete topics'] ?></strong></legend>
       
   840 				<div class="checkbox radbox">
       
   841 					<label for="fld<?php echo ++$pun_page['fld_count'] ?>"><span class="fld-label"><?php echo $lang_common['Please confirm'] ?></span><br /><input type="checkbox" id="fld<?php echo $pun_page['fld_count'] ?>" name="req_confirm" value="1" checked="checked" /> <?php echo $lang_misc['Delete topics comply'] ?></label>
       
   842 				</div>
       
   843 			</fieldset>
       
   844 			<div class="frm-buttons">
       
   845 				<span class="submit"><input type="submit" name="delete_topics_comply" value="<?php echo $lang_common['Delete'] ?>" /></span>
       
   846 				<span class="cancel"><input type="submit" name="cancel" value="<?php echo $lang_common['Cancel'] ?>" /></span>
       
   847 			</div>
       
   848 		</form>
       
   849 	</div>
       
   850 
       
   851 </div>
       
   852 <?php
       
   853 
       
   854 	require PUN_ROOT.'footer.php';
       
   855 }
       
   856 
       
   857 
       
   858 // Open or close one or more topics
       
   859 else if (isset($_REQUEST['open']) || isset($_REQUEST['close']))
       
   860 {
       
   861 	$action = (isset($_REQUEST['open'])) ? 0 : 1;
       
   862 
       
   863 	($hook = get_hook('mr_open_close_topic_selected')) ? eval($hook) : null;
       
   864 
       
   865 	// There could be an array of topic ID's in $_POST
       
   866 	if (isset($_POST['open']) || isset($_POST['close']))
       
   867 	{
       
   868 		$topics = isset($_POST['topics']) ? @array_map('intval', @array_keys($_POST['topics'])) : array();
       
   869 		if (empty($topics))
       
   870 			message($lang_misc['No topics selected']);
       
   871 
       
   872 		$query = array(
       
   873 			'UPDATE'	=> 'topics',
       
   874 			'SET'		=> 'closed='.$action,
       
   875 			'WHERE'		=> 'id IN('.implode(',', $topics).') AND forum_id='.$fid
       
   876 		);
       
   877 
       
   878 		($hook = get_hook('mr_qr_open_close_topics')) ? eval($hook) : null;
       
   879 		$pun_db->query_build($query) or error(__FILE__, __LINE__);
       
   880 
       
   881 		$pun_page['redirect_msg'] = ($action) ? $lang_misc['Close topics redirect'] : $lang_misc['Open topics redirect'];
       
   882 		pun_redirect(pun_link($pun_url['moderate_forum'], $fid), $pun_page['redirect_msg']);
       
   883 	}
       
   884 	// Or just one in $_GET
       
   885 	else
       
   886 	{
       
   887 		$topic_id = ($action) ? intval($_GET['close']) : intval($_GET['open']);
       
   888 		if ($topic_id < 1)
       
   889 			message($lang_common['Bad request']);
       
   890 
       
   891 		// We validate the CSRF token. If it's set in POST and we're at this point, the token is valid.
       
   892 		// If it's in GET, we need to make sure it's valid.
       
   893 		if (!isset($_POST['csrf_token']) && (!isset($_GET['csrf_token']) || $_GET['csrf_token'] !== generate_form_token(($action ? 'close' : 'open').$topic_id)))
       
   894 			csrf_confirm_form();
       
   895 
       
   896 		$query = array(
       
   897 			'UPDATE'	=> 'topics',
       
   898 			'SET'		=> 'closed='.$action,
       
   899 			'WHERE'		=> 'id='.$topic_id.' AND forum_id='.$fid
       
   900 		);
       
   901 
       
   902 		($hook = get_hook('mr_qr_open_close_topic')) ? eval($hook) : null;
       
   903 		$pun_db->query_build($query) or error(__FILE__, __LINE__);
       
   904 
       
   905 		$pun_page['redirect_msg'] = ($action) ? $lang_misc['Close topic redirect'] : $lang_misc['Open topic redirect'];
       
   906 		pun_redirect(pun_link($pun_url['topic'], $topic_id), $pun_page['redirect_msg']);
       
   907 	}
       
   908 }
       
   909 
       
   910 
       
   911 // Stick a topic
       
   912 else if (isset($_GET['stick']))
       
   913 {
       
   914 	$stick = intval($_GET['stick']);
       
   915 	if ($stick < 1)
       
   916 		message($lang_common['Bad request']);
       
   917 
       
   918 	// We validate the CSRF token. If it's set in POST and we're at this point, the token is valid.
       
   919 	// If it's in GET, we need to make sure it's valid.
       
   920 	if (!isset($_POST['csrf_token']) && (!isset($_GET['csrf_token']) || $_GET['csrf_token'] !== generate_form_token('stick'.$stick)))
       
   921 		csrf_confirm_form();
       
   922 
       
   923 	($hook = get_hook('mr_stick_topic_selected')) ? eval($hook) : null;
       
   924 
       
   925 	$query = array(
       
   926 		'UPDATE'	=> 'topics',
       
   927 		'SET'		=> 'sticky=1',
       
   928 		'WHERE'		=> 'id='.$stick.' AND forum_id='.$fid
       
   929 	);
       
   930 
       
   931 	($hook = get_hook('mr_qr_stick_topic')) ? eval($hook) : null;
       
   932 	$pun_db->query_build($query) or error(__FILE__, __LINE__);
       
   933 
       
   934 	pun_redirect(pun_link($pun_url['topic'], $stick), $lang_misc['Stick topic redirect']);
       
   935 }
       
   936 
       
   937 
       
   938 // Unstick a topic
       
   939 else if (isset($_GET['unstick']))
       
   940 {
       
   941 	$unstick = intval($_GET['unstick']);
       
   942 	if ($unstick < 1)
       
   943 		message($lang_common['Bad request']);
       
   944 
       
   945 	// We validate the CSRF token. If it's set in POST and we're at this point, the token is valid.
       
   946 	// If it's in GET, we need to make sure it's valid.
       
   947 	if (!isset($_POST['csrf_token']) && (!isset($_GET['csrf_token']) || $_GET['csrf_token'] !== generate_form_token('unstick'.$unstick)))
       
   948 		csrf_confirm_form();
       
   949 
       
   950 	($hook = get_hook('mr_unstick_topic_selected')) ? eval($hook) : null;
       
   951 
       
   952 	$query = array(
       
   953 		'UPDATE'	=> 'topics',
       
   954 		'SET'		=> 'sticky=0',
       
   955 		'WHERE'		=> 'id='.$unstick.' AND forum_id='.$fid
       
   956 	);
       
   957 
       
   958 	($hook = get_hook('mr_qr_unstick_topic')) ? eval($hook) : null;
       
   959 	$pun_db->query_build($query) or error(__FILE__, __LINE__);
       
   960 
       
   961 	pun_redirect(pun_link($pun_url['topic'], $unstick), $lang_misc['Unstick topic redirect']);
       
   962 }
       
   963 
       
   964 
       
   965 ($hook = get_hook('mr_new_action')) ? eval($hook) : null;
       
   966 
       
   967 
       
   968 // No specific forum moderation action was specified in the query string, so we'll display the moderate forum view
       
   969 
       
   970 // Load the viewforum.php language file
       
   971 require PUN_ROOT.'lang/'.$pun_user['language'].'/forum.php';
       
   972 
       
   973 // Determine the topic offset (based on $_GET['p'])
       
   974 $pun_page['num_pages'] = ceil($cur_forum['num_topics'] / $pun_user['disp_topics']);
       
   975 
       
   976 $pun_page['page'] = (!isset($_GET['p']) || $_GET['p'] <= 1 || $_GET['p'] > $pun_page['num_pages']) ? 1 : $_GET['p'];
       
   977 $pun_page['start_from'] = $pun_user['disp_topics'] * ($pun_page['page'] - 1);
       
   978 $pun_page['finish_at'] = min(($pun_page['start_from'] + $pun_user['disp_topics']), ($cur_forum['num_topics']));
       
   979 
       
   980 // Generate paging links
       
   981 $pun_page['page_post'] = '<p class="paging"><strong>'.$lang_common['Pages'].'</strong> '.pun_paginate($pun_page['num_pages'], $pun_page['page'], $pun_url['moderate_forum'], $fid).'</p>';
       
   982 
       
   983 // Navigation links for header and page numbering for title/meta description
       
   984 if ($pun_page['page'] < $pun_page['num_pages'])
       
   985 {
       
   986 	$pun_page['nav'][] = '<link rel="last" href="'.pun_sublink($pun_url['moderate_forum'], $pun_url['page'], $pun_page['num_pages'], $fid).'" title="'.$lang_common['Page'].' '.$pun_page['num_pages'].'" />';
       
   987 	$pun_page['nav'][] = '<link rel="next" href="'.pun_sublink($pun_url['moderate_forum'], $pun_url['page'], ($pun_page['page'] + 1), $fid).'" title="'.$lang_common['Page'].' '.($pun_page['page'] + 1).'" />';
       
   988 }
       
   989 if ($pun_page['page'] > 1)
       
   990 {
       
   991 	$pun_page['nav'][] = '<link rel="prev" href="'.pun_sublink($pun_url['moderate_forum'], $pun_url['page'], ($pun_page['page'] - 1), $fid).'" title="'.$lang_common['Page'].' '.($pun_page['page'] - 1).'" />';
       
   992 	$pun_page['nav'][] = '<link rel="first" href="'.pun_link($pun_url['moderate_forum'], $fid).'" title="'.$lang_common['Page'].' 1" />';
       
   993 }
       
   994 
       
   995 // Generate page information
       
   996 if ($pun_page['num_pages'] > 1)
       
   997 	$pun_page['main_info'] = '<span>'.sprintf($lang_common['Page number'], $pun_page['page'], $pun_page['num_pages']).' </span>'.sprintf($lang_common['Paged info'], $lang_common['Topics'], $pun_page['start_from'] + 1, $pun_page['finish_at'], $cur_forum['num_topics']);
       
   998 else
       
   999 	$pun_page['main_info'] = (($pun_db->num_rows($result)) ? sprintf($lang_common['Page info'], $lang_common['Topics'], $cur_forum['num_topics']) : $lang_forum['No topics']);
       
  1000 
       
  1001 // Setup form
       
  1002 $pun_page['fld_count'] = 0;
       
  1003 $pun_page['form_action'] = pun_link($pun_url['moderate_forum'], $fid);
       
  1004 
       
  1005 // Setup breadcrumbs
       
  1006 $pun_page['crumbs'] = array(
       
  1007 	array($pun_config['o_board_title'], pun_link($pun_url['index'])),
       
  1008 	array($cur_forum['forum_name'], pun_link($pun_url['forum'], $fid)),
       
  1009 	$lang_forum['Moderate forum']
       
  1010 );
       
  1011 
       
  1012 ($hook = get_hook('mr_topic_actions_pre_header_load')) ? eval($hook) : null;
       
  1013 
       
  1014 define('PUN_PAGE', 'modforum');
       
  1015 require PUN_ROOT.'header.php';
       
  1016 
       
  1017 ?>
       
  1018 <div id="pun-main" class="main paged">
       
  1019 
       
  1020 	<h1><span><?php echo end($pun_page['crumbs']) ?></span></h1>
       
  1021 
       
  1022 	<form method="post" accept-charset="utf-8" action="<?php echo $pun_page['form_action'] ?>">
       
  1023 
       
  1024 	<div class="paged-head">
       
  1025 		<?php echo $pun_page['page_post']."\n" ?>
       
  1026 	</div>
       
  1027 
       
  1028 	<div class="main-head">
       
  1029 		<h2><span><?php echo $pun_page['main_info'] ?></span></h2>
       
  1030 		<p class="main-options"><?php echo $lang_misc['Select topics'] ?></p>
       
  1031 	</div>
       
  1032 
       
  1033 	<div id="forum<?php echo $fid ?>" class="main-content forum">
       
  1034 		<div class="hidden">
       
  1035 			<input type="hidden" name="csrf_token" value="<?php echo generate_form_token($pun_page['form_action']) ?>" />
       
  1036 		</div>
       
  1037 		<table cellspacing="0" summary="<?php echo $lang_forum['Table summary mods'].htmlspecialchars($cur_forum['forum_name']) ?>">
       
  1038 			<thead>
       
  1039 				<tr>
       
  1040 					<th class="tcl" scope="col"><?php echo $lang_common['Topic'] ?></th>
       
  1041 					<th class="tc2" scope="col"><?php echo $lang_common['Replies'] ?></th>
       
  1042 <?php if ($pun_config['o_topic_views'] == '1'): ?>					<th class="tc3" scope="col"><?php echo $lang_forum['Views'] ?></th>
       
  1043 <?php endif; ?>					<th class="tcr" scope="col"><?php echo $lang_common['Last post'] ?></th>
       
  1044 					<th class="tcmod" scope="col"><?php echo $lang_misc['Select'] ?></th>
       
  1045 				</tr>
       
  1046 			</thead>
       
  1047 			<tbody class="statused">
       
  1048 <?php
       
  1049 
       
  1050 // Select topics
       
  1051 $query = array(
       
  1052 	'SELECT'	=> 't.id, t.poster, t.subject, t.posted, t.last_post, t.last_post_id, t.last_poster, t.num_views, t.num_replies, t.closed, t.sticky, t.moved_to',
       
  1053 	'FROM'		=> 'topics AS t',
       
  1054 	'WHERE'		=> 'forum_id='.$fid,
       
  1055 	'ORDER BY'	=> 't.sticky DESC, last_post DESC',
       
  1056 	'LIMIT'		=>	$pun_page['start_from'].', '.$pun_user['disp_topics']
       
  1057 );
       
  1058 
       
  1059 ($hook = get_hook('mr_qr_get_topics')) ? eval($hook) : null;
       
  1060 $result = $pun_db->query_build($query) or error(__FILE__, __LINE__);
       
  1061 
       
  1062 // If there are topics in this forum.
       
  1063 if ($pun_db->num_rows($result))
       
  1064 {
       
  1065 	$pun_page['button_status'] = '';
       
  1066 	$pun_page['item_count'] = 0;
       
  1067 
       
  1068 	while ($cur_topic = $pun_db->fetch_assoc($result))
       
  1069 	{
       
  1070 		++$pun_page['item_count'];
       
  1071 
       
  1072 		// Start from scratch
       
  1073 		$pun_page['item_subject'] = $pun_page['item_status'] = $pun_page['item_last_post'] = $pun_page['item_alt_message'] = $pun_page['item_nav'] = array();
       
  1074 		$pun_page['item_indicator'] = '';
       
  1075 		$pun_page['item_alt_message'][] = $lang_common['Topic'].' '.($pun_page['start_from'] + $pun_page['item_count']);
       
  1076 
       
  1077 		if ($pun_config['o_censoring'] == '1')
       
  1078 			$cur_topic['subject'] = censor_words($cur_topic['subject']);
       
  1079 
       
  1080 		if ($cur_topic['moved_to'] != null)
       
  1081 		{
       
  1082 			$pun_page['item_status'][] = 'moved';
       
  1083 			$pun_page['item_last_post'][] = $pun_page['item_alt_message'][] = $lang_forum['Moved'];
       
  1084 			$pun_page['item_subject'][] = '<a href="'.pun_link($pun_url['topic'], array($cur_topic['moved_to'], sef_friendly($cur_topic['subject']))).'">'.htmlspecialchars($cur_topic['subject']).'</a>';
       
  1085 			$pun_page['item_subject'][] = '<span class="byuser">'.sprintf($lang_common['By user'], htmlspecialchars($cur_topic['poster'])).'</span>';
       
  1086 			$cur_topic['num_replies'] = $cur_topic['num_views'] = ' - ';
       
  1087 			$pun_page['ghost_topic'] = true;
       
  1088 		}
       
  1089 		else
       
  1090 		{
       
  1091 			$pun_page['ghost_topic'] = false;
       
  1092 
       
  1093 			if ($cur_topic['sticky'] == '1')
       
  1094 			{
       
  1095 				$pun_page['item_subject'][] = $lang_forum['Sticky'];
       
  1096 				$pun_page['item_status'][] = 'sticky';
       
  1097 			}
       
  1098 
       
  1099 			if ($cur_topic['closed'] == '1')
       
  1100 			{
       
  1101 				$pun_page['item_subject'][] = $lang_common['Closed'];
       
  1102 				$pun_page['item_status'][] = 'closed';
       
  1103 			}
       
  1104 
       
  1105 			$pun_page['item_subject'][] = '<a href="'.pun_link($pun_url['topic'], $cur_topic['id']).'">'.htmlspecialchars($cur_topic['subject']).'</a>';
       
  1106 
       
  1107 			$pun_page['item_pages'] = ceil(($cur_topic['num_replies'] + 1) / $pun_user['disp_posts']);
       
  1108 
       
  1109 			if ($pun_page['item_pages'] > 1)
       
  1110 				$pun_page['item_nav'][] = pun_paginate($pun_page['item_pages'], -1, $pun_url['topic'], $cur_topic['id']);
       
  1111 
       
  1112 			// Does this topic contains posts we haven't read? If so, tag it accordingly.
       
  1113 			if ($cur_topic['last_post'] > $pun_user['last_visit'] && (!isset($tracked_topics['topics'][$cur_topic['id']]) || $tracked_topics['topics'][$cur_topic['id']] < $cur_topic['last_post']) && (!isset($tracked_topics['forums'][$pun_page['fid']]) || $tracked_topics['forums'][$pun_page['fid']] < $cur_topic['last_post']) && !$ghost_topic)
       
  1114 			{
       
  1115 				$pun_page['item_nav'][] = '<a href="'.pun_link($pun_url['topic_new_posts'], $cur_topic['id']).'" title="'.$lang_forum['New posts info'].'">'.$lang_common['New posts'].'</a>';
       
  1116 				$pun_page['item_status'][] = 'new';
       
  1117 			}
       
  1118 
       
  1119 			if (!empty($pun_page['item_nav']))
       
  1120 				$pun_page['item_subject'][] = '<span class="topic-nav">[&#160;'.implode('&#160;&#160;', $pun_page['item_nav']).'&#160;]</span>';
       
  1121 
       
  1122 			$pun_page['item_subject'][] = '<span class="byuser">'.sprintf($lang_common['By user'], htmlspecialchars($cur_topic['poster'])).'</span>';
       
  1123 			$pun_page['item_last_post'][] = '<a href="'.pun_link($pun_url['post'], $cur_topic['last_post_id']).'">'.format_time($cur_topic['last_post']).'</a>';
       
  1124 			$pun_page['item_last_post'][] = '<span class="byuser">'.sprintf($lang_common['By user'], htmlspecialchars($cur_topic['last_poster'])).'</span>';
       
  1125 
       
  1126 			if (empty($pun_page['item_status']))
       
  1127 				$pun_page['item_status'][] = 'normal';
       
  1128 
       
  1129 			$pun_page['subject_label'] = $cur_topic['subject'];
       
  1130 		}
       
  1131 
       
  1132 		$pun_page['item_style'] = (($pun_page['item_count'] % 2 != 0) ? 'odd' : 'even').' '.implode(' ', $pun_page['item_status']);
       
  1133 		$pun_page['item_indicator'] = '<span class="status '.implode(' ', $pun_page['item_status']).'" title="'.implode(' - ', $pun_page['item_alt_message']).'"><img src="'.$base_url.'/style/'.$pun_user['style'].'/status.png" alt="'.implode(' - ', $pun_page['item_alt_message']).'" />'.$pun_page['item_indicator'].'</span>';
       
  1134 
       
  1135 		($hook = get_hook('mr_topic_actions_row_pre_display')) ? eval($hook) : null;
       
  1136 
       
  1137 ?>
       
  1138 				<tr class="<?php echo $pun_page['item_style'] ?>">
       
  1139 					<td class="tcl"><?php echo $pun_page['item_indicator'].' '.implode(' ', $pun_page['item_subject']) ?></td>
       
  1140 					<td class="tc2"><?php echo (!$pun_page['ghost_topic']) ? $cur_topic['num_replies'] : ' - ' ?></td>
       
  1141 <?php if ($pun_config['o_topic_views'] == '1'): ?>					<td class="tc3"><?php echo (!$pun_page['ghost_topic']) ? $cur_topic['num_views'] : ' - ' ?></td>
       
  1142 <?php endif; ?>					<td class="tcr"><?php echo implode(' ', $pun_page['item_last_post']) ?></td>
       
  1143 					<td class="tcmod"><label for="fld<?php echo ++$pun_page['fld_count'] ?>"><input id="fld<?php echo $pun_page['fld_count'] ?>" type="checkbox" name="topics[<?php echo $cur_topic['id'] ?>]" value="1" /> <span><?php echo $pun_page['subject_label'] ?></span></label></td>
       
  1144 				</tr>
       
  1145 <?php
       
  1146 
       
  1147 	}
       
  1148 }
       
  1149 else
       
  1150 {
       
  1151 	$pun_page['button_status'] = ' disabled="disabled"';
       
  1152 	$pun_page['item_indicator'] = '<span class="status empty" title="'.$lang_forum['No topics'].'"><img src="'.$base_url.'/style/'.$pun_user['style'].'/status.png" alt="'.$lang_forum['No topics'].'" /></span>';
       
  1153 
       
  1154 	($hook = get_hook('mr_topic_actions_forum_empty')) ? eval($hook) : null;
       
  1155 
       
  1156 ?>
       
  1157 				<tr class="odd empty">
       
  1158 					<td class="tcl"><?php echo $pun_page['item_indicator'].' '.$lang_forum['First topic nag'] ?></td>
       
  1159 					<td class="tc2"> - </td>
       
  1160 <?php if ($pun_config['o_topic_views'] == '1'): ?>					<td class="tc3"> - </td>
       
  1161 <?php endif; ?>					<td class="tcr"><?php echo $lang_forum['Never'] ?></td>
       
  1162 					<td class="tcmod"> - </td>
       
  1163 				</tr>
       
  1164 <?php
       
  1165 
       
  1166 }
       
  1167 
       
  1168 ?>
       
  1169 			</tbody>
       
  1170 		</table>
       
  1171 <?php
       
  1172 
       
  1173 // Setup moderator control buttons
       
  1174 $pun_page['main_mod_submit'] = array(
       
  1175 	'<span class="submit"><input type="submit" name="move_topics" value="'.$lang_misc['Move'].'"'.$pun_page['button_status'].' /></span>',
       
  1176 	'<span class="submit"><input type="submit" name="delete_topics" value="'.$lang_common['Delete'].'"'.$pun_page['button_status'].' /></span>',
       
  1177 	'<span class="submit"><input type="submit" name="open" value="'.$lang_misc['Open'].'"'.$pun_page['button_status'].' /></span>',
       
  1178 	'<span class="submit"><input type="submit" name="close" value="'.$lang_misc['Close'].'"'.$pun_page['button_status'].' /></span>'
       
  1179 );
       
  1180 
       
  1181 ($hook = get_hook('mr_topic_actions_post_topic_list')) ? eval($hook) : null;
       
  1182 
       
  1183 ?>
       
  1184 	</div>
       
  1185 
       
  1186 	<div class="main-foot">
       
  1187 		<p class="h2"><strong><?php echo $pun_page['main_info'] ?></strong></p>
       
  1188 	</div>
       
  1189 
       
  1190 	<div class="paged-foot">
       
  1191 		<p class="submitting"><?php echo implode("\n\t\t\t", $pun_page['main_mod_submit'])."\n" ?></p>
       
  1192 		<?php echo $pun_page['page_post']."\n" ?>
       
  1193 	</div>
       
  1194 
       
  1195 	</form>
       
  1196 
       
  1197 </div>
       
  1198 
       
  1199 <div id="pun-crumbs-foot">
       
  1200 	<p class="crumbs"><?php echo generate_crumbs(false) ?></p>
       
  1201 </div>
       
  1202 <?php
       
  1203 
       
  1204 ($hook = get_hook('mr_end')) ? eval($hook) : null;
       
  1205 
       
  1206 require PUN_ROOT.'footer.php';