1<?php
2/**
3 * Provides various mass-moderation tools to moderators.
4 *
5 * @copyright (C) 2008-2012 PunBB, partially based on code (C) 2008-2009 FluxBB.org
6 * @license http://www.gnu.org/licenses/gpl.html GPL version 2 or higher
7 * @package PunBB
8 */
9
10
11if (!defined('FORUM_ROOT'))
12	define('FORUM_ROOT', './');
13require FORUM_ROOT.'include/common.php';
14
15($hook = get_hook('mr_start')) ? eval($hook) : null;
16
17// Load the misc.php language file
18require FORUM_ROOT.'lang/'.$forum_user['language'].'/misc.php';
19
20
21// This particular function doesn't require forum-based moderator access. It can be used
22// by all moderators and admins.
23if (isset($_GET['get_host']))
24{
25	if (!$forum_user['is_admmod'])
26		message($lang_common['No permission']);
27
28	$_get_host = $_GET['get_host'];
29	if (!is_string($_get_host))
30		message($lang_common['Bad request']);
31
32	($hook = get_hook('mr_view_ip_selected')) ? eval($hook) : null;
33
34	// Is get_host an IP address or a post ID?
35	if (preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $_get_host) || preg_match('/^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/', $_get_host))
36		$ip = $_get_host;
37	else
38	{
39		$get_host = intval($_get_host);
40		if ($get_host < 1)
41			message($lang_common['Bad request']);
42
43		$query = array(
44			'SELECT'	=> 'p.poster_ip',
45			'FROM'		=> 'posts AS p',
46			'WHERE'		=> 'p.id='.$get_host
47		);
48
49		($hook = get_hook('mr_view_ip_qr_get_poster_ip')) ? eval($hook) : null;
50		$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
51		$ip = $forum_db->result($result);
52
53		if (!$ip)
54			message($lang_common['Bad request']);
55	}
56
57	($hook = get_hook('mr_view_ip_pre_output')) ? eval($hook) : null;
58
59	message(sprintf($lang_misc['Hostname lookup'], $ip, @gethostbyaddr($ip), '<a href="'.forum_link($forum_url['admin_users']).'?show_users='.$ip.'">'.$lang_misc['Show more users'].'</a>'));
60}
61
62
63// All other functions require moderator/admin access
64$fid = isset($_GET['fid']) ? intval($_GET['fid']) : 0;
65if ($fid < 1)
66	message($lang_common['Bad request']);
67
68// Get some info about the forum we're moderating
69$query = array(
70	'SELECT'	=> 'f.forum_name, f.redirect_url, f.num_topics, f.moderators, f.sort_by',
71	'FROM'		=> 'forums AS f',
72	'JOINS'		=> array(
73		array(
74			'LEFT JOIN'		=> 'forum_perms AS fp',
75			'ON'			=> '(fp.forum_id=f.id AND fp.group_id='.$forum_user['g_id'].')'
76		)
77	),
78	'WHERE'		=> '(fp.read_forum IS NULL OR fp.read_forum=1) AND f.id='.$fid
79);
80
81($hook = get_hook('mr_qr_get_forum_data')) ? eval($hook) : null;
82$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
83$cur_forum = $forum_db->fetch_assoc($result);
84
85if (!$cur_forum)
86	message($lang_common['Bad request']);
87
88// Make sure we're not trying to moderate a redirect forum
89if ($cur_forum['redirect_url'] != '')
90	message($lang_common['Bad request']);
91
92// Setup the array of moderators
93$mods_array = ($cur_forum['moderators'] != '') ? unserialize($cur_forum['moderators']) : array();
94
95($hook = get_hook('mr_pre_permission_check')) ? eval($hook) : null;
96
97if ($forum_user['g_id'] != FORUM_ADMIN && ($forum_user['g_moderator'] != '1' || !array_key_exists($forum_user['username'], $mods_array)))
98	message($lang_common['No permission']);
99
100// Get topic/forum tracking data
101if (!$forum_user['is_guest'])
102	$tracked_topics = get_tracked_topics();
103
104
105// Did someone click a cancel button?
106if (isset($_POST['cancel']))
107	redirect(forum_link($forum_url['forum'], array($fid, sef_friendly($cur_forum['forum_name']))), $lang_common['Cancel redirect']);
108
109// All topic moderation features require a topic id in GET
110if (isset($_GET['tid']))
111{
112	($hook = get_hook('mr_post_actions_selected')) ? eval($hook) : null;
113
114	$tid = intval($_GET['tid']);
115	if ($tid < 1)
116		message($lang_common['Bad request']);
117
118	// Fetch some info about the topic
119	$query = array(
120		'SELECT'	=> 't.subject, t.poster, t.first_post_id, t.posted, t.num_replies',
121		'FROM'		=> 'topics AS t',
122		'WHERE'		=> 't.id='.$tid.' AND t.moved_to IS NULL'
123	);
124
125	($hook = get_hook('mr_post_actions_qr_get_topic_info')) ? eval($hook) : null;
126	$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
127	$cur_topic = $forum_db->fetch_assoc($result);
128
129	if (!$cur_topic)
130		message($lang_common['Bad request']);
131
132	// User pressed the cancel button
133	if (isset($_POST['delete_posts_cancel']))
134		redirect(forum_link($forum_url['topic'], array($tid, sef_friendly($cur_topic['subject']))), $lang_common['Cancel redirect']);
135
136	// Delete one or more posts
137	if (isset($_POST['delete_posts']) || isset($_POST['delete_posts_comply']))
138	{
139		($hook = get_hook('mr_delete_posts_form_submitted')) ? eval($hook) : null;
140
141		$posts = isset($_POST['posts']) && !empty($_POST['posts']) ? $_POST['posts'] : array();
142		$posts = array_map('intval', (is_array($posts) ? $posts : explode(',', $posts)));
143
144		if (empty($posts))
145			message($lang_misc['No posts selected']);
146
147		if (isset($_POST['delete_posts_comply']))
148		{
149			if (!isset($_POST['req_confirm']))
150				redirect(forum_link($forum_url['topic'], array($tid, sef_friendly($cur_topic['subject']))), $lang_common['No confirm redirect']);
151
152			($hook = get_hook('mr_confirm_delete_posts_form_submitted')) ? eval($hook) : null;
153
154			// Verify that the post IDs are valid
155			$query = array(
156				'SELECT'	=> 'COUNT(p.id)',
157				'FROM'		=> 'posts AS p',
158				'WHERE'		=> 'p.id IN('.implode(',', $posts).') AND p.id!='.$cur_topic['first_post_id'].' AND p.topic_id='.$tid
159			);
160
161			($hook = get_hook('mr_confirm_delete_posts_qr_verify_post_ids')) ? eval($hook) : null;
162			$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
163			if ($forum_db->result($result) != count($posts))
164				message($lang_common['Bad request']);
165
166			// Delete the posts
167			$query = array(
168				'DELETE'	=> 'posts',
169				'WHERE'		=> 'id IN('.implode(',', $posts).')'
170			);
171
172			($hook = get_hook('mr_confirm_delete_posts_qr_delete_posts')) ? eval($hook) : null;
173			$forum_db->query_build($query) or error(__FILE__, __LINE__);
174
175			if (!defined('FORUM_SEARCH_IDX_FUNCTIONS_LOADED'))
176				require FORUM_ROOT.'include/search_idx.php';
177
178			strip_search_index($posts);
179
180			sync_topic($tid);
181			sync_forum($fid);
182
183			$forum_flash->add_info($lang_misc['Delete posts redirect']);
184
185			($hook = get_hook('mr_confirm_delete_posts_pre_redirect')) ? eval($hook) : null;
186
187			redirect(forum_link($forum_url['topic'], array($tid, sef_friendly($cur_topic['subject']))), $lang_misc['Delete posts redirect']);
188		}
189
190		// Setup form
191		$forum_page['group_count'] = $forum_page['item_count'] = $forum_page['fld_count'] = 0;
192		$forum_page['form_action'] = forum_link($forum_url['moderate_topic'], array($fid, $tid));
193
194		$forum_page['hidden_fields'] = array(
195			'csrf_token'	=> '<input type="hidden" name="csrf_token" value="'.generate_form_token($forum_page['form_action']).'" />',
196			'posts'			=> '<input type="hidden" name="posts" value="'.implode(',', $posts).'" />'
197		);
198
199		// Setup breadcrumbs
200		$forum_page['crumbs'] = array(
201			array($forum_config['o_board_title'], forum_link($forum_url['index'])),
202			array($cur_forum['forum_name'], forum_link($forum_url['forum'], array($fid, sef_friendly($cur_forum['forum_name'])))),
203			array($cur_topic['subject'], forum_link($forum_url['topic'], array($tid, sef_friendly($cur_topic['subject'])))),
204			$lang_misc['Delete posts']
205		);
206
207		($hook = get_hook('mr_confirm_delete_posts_pre_header_load')) ? eval($hook) : null;
208
209		define('FORUM_PAGE', 'dialogue');
210		require FORUM_ROOT.'header.php';
211
212		// START SUBST - <!-- forum_main -->
213		ob_start();
214
215		($hook = get_hook('mr_confirm_delete_posts_output_start')) ? eval($hook) : null;
216
217?>
218	<div class="main-head">
219		<h2 class="hn"><span><?php echo $lang_misc['Confirm post delete'] ?></span></h2>
220	</div>
221	<div class="main-content main-frm">
222		<form class="frm-form" method="post" accept-charset="utf-8" action="<?php echo $forum_page['form_action'] ?>">
223			<div class="hidden">
224				<?php echo implode("\n\t\t\t\t", $forum_page['hidden_fields'])."\n" ?>
225			</div>
226<?php ($hook = get_hook('mr_confirm_delete_posts_pre_fieldset')) ? eval($hook) : null; ?>
227			<fieldset class="frm-group group<?php echo ++$forum_page['group_count'] ?>">
228				<legend class="group-legend"><strong><?php echo $lang_misc['Delete posts'] ?></strong></legend>
229<?php ($hook = get_hook('mr_confirm_delete_posts_pre_confirm_checkbox')) ? eval($hook) : null; ?>
230				<div class="sf-set set<?php echo ++$forum_page['item_count'] ?>">
231					<div class="sf-box checkbox">
232						<span class="fld-input"><input type="checkbox" id="fld<?php echo ++$forum_page['fld_count'] ?>" name="req_confirm" value="1" checked="checked" /></span>
233						<label for="fld<?php echo $forum_page['fld_count'] ?>"><span><?php echo $lang_common['Please confirm'] ?></span> <?php echo $lang_misc['Confirm post delete'] ?>.</label>
234					</div>
235				</div>
236<?php ($hook = get_hook('mr_confirm_delete_posts_pre_fieldset_end')) ? eval($hook) : null; ?>
237			</fieldset>
238<?php ($hook = get_hook('mr_confirm_delete_posts_fieldset_end')) ? eval($hook) : null; ?>
239			<div class="frm-buttons">
240				<span class="submit primary caution"><input type="submit" name="delete_posts_comply" value="<?php echo $lang_common['Delete'] ?>" /></span>
241				<span class="cancel"><input type="submit" name="cancel" value="<?php echo $lang_common['Cancel'] ?>" formnovalidate /></span>
242			</div>
243		</form>
244	</div>
245<?php
246
247		$forum_id = $fid;
248
249		($hook = get_hook('mr_confirm_delete_posts_end')) ? eval($hook) : null;
250
251		$tpl_temp = forum_trim(ob_get_contents());
252		$tpl_main = str_replace('<!-- forum_main -->', $tpl_temp, $tpl_main);
253		ob_end_clean();
254		// END SUBST - <!-- forum_main -->
255
256		require FORUM_ROOT.'footer.php';
257	}
258	else if (isset($_POST['split_posts']) || isset($_POST['split_posts_comply']))
259	{
260		($hook = get_hook('mr_split_posts_form_submitted')) ? eval($hook) : null;
261
262		$posts = isset($_POST['posts']) && !empty($_POST['posts']) ? $_POST['posts'] : array();
263		$posts = array_map('intval', (is_array($posts) ? $posts : explode(',', $posts)));
264
265		if (empty($posts))
266			message($lang_misc['No posts selected']);
267
268		if (isset($_POST['split_posts_comply']))
269		{
270			if (!isset($_POST['req_confirm']))
271				redirect(forum_link($forum_url['topic'], array($tid, sef_friendly($cur_topic['subject']))), $lang_common['No confirm redirect']);
272
273			// Load the post.php language file
274			require FORUM_ROOT.'lang/'.$forum_user['language'].'/post.php';
275
276			($hook = get_hook('mr_confirm_split_posts_form_submitted')) ? eval($hook) : null;
277
278			// Verify that the post IDs are valid
279			$query = array(
280				'SELECT'	=> 'COUNT(p.id)',
281				'FROM'		=> 'posts AS p',
282				'WHERE'		=> 'p.id IN('.implode(',', $posts).') AND p.id!='.$cur_topic['first_post_id'].' AND p.topic_id='.$tid
283			);
284
285			($hook = get_hook('mr_confirm_split_posts_qr_verify_post_ids')) ? eval($hook) : null;
286			$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
287			if ($forum_db->result($result) != count($posts))
288				message($lang_common['Bad request']);
289
290			$new_subject = isset($_POST['new_subject']) ? forum_trim($_POST['new_subject']) : '';
291
292			if ($new_subject == '')
293				message($lang_post['No subject']);
294			else if (utf8_strlen($new_subject) > FORUM_SUBJECT_MAXIMUM_LENGTH)
295				message(sprintf($lang_post['Too long subject'], FORUM_SUBJECT_MAXIMUM_LENGTH));
296
297			// Get data from the new first post
298			$query = array(
299				'SELECT'	=> 'p.id, p.poster, p.posted',
300				'FROM'		=> 'posts AS p',
301				'WHERE'		=> 'p.id = '.min($posts)
302			);
303
304			($hook = get_hook('mr_confirm_split_posts_qr_get_first_post_data')) ? eval($hook) : null;
305			$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
306			$first_post_data = $forum_db->fetch_assoc($result);
307
308			// Create the new topic
309			$query = array(
310				'INSERT'	=> 'poster, subject, posted, first_post_id, forum_id',
311				'INTO'		=> 'topics',
312				'VALUES'	=> '\''.$forum_db->escape($first_post_data['poster']).'\', \''.$forum_db->escape($new_subject).'\', '.$first_post_data['posted'].', '.$first_post_data['id'].', '.$fid
313			);
314
315			($hook = get_hook('mr_confirm_split_posts_qr_add_topic')) ? eval($hook) : null;
316			$forum_db->query_build($query) or error(__FILE__, __LINE__);
317			$new_tid = $forum_db->insert_id();
318
319			// Move the posts to the new topic
320			$query = array(
321				'UPDATE'	=> 'posts',
322				'SET'		=> 'topic_id='.$new_tid,
323				'WHERE'		=> 'id IN('.implode(',', $posts).')'
324			);
325
326			($hook = get_hook('mr_confirm_split_posts_qr_move_posts')) ? eval($hook) : null;
327			$forum_db->query_build($query) or error(__FILE__, __LINE__);
328
329			// Sync last post data for the old topic, the new topic, and the forum itself
330			sync_topic($new_tid);
331			sync_topic($tid);
332			sync_forum($fid);
333
334			$forum_flash->add_info($lang_misc['Split posts redirect']);
335
336			($hook = get_hook('mr_confirm_split_posts_pre_redirect')) ? eval($hook) : null;
337
338			redirect(forum_link($forum_url['topic'], array($new_tid, sef_friendly($new_subject))), $lang_misc['Split posts redirect']);
339		}
340
341		// Setup form
342		$forum_page['group_count'] = $forum_page['item_count'] = $forum_page['fld_count'] = 0;
343		$forum_page['form_action'] = forum_link($forum_url['moderate_topic'], array($fid, $tid));
344
345		$forum_page['hidden_fields'] = array(
346			'csrf_token'	=> '<input type="hidden" name="csrf_token" value="'.generate_form_token($forum_page['form_action']).'" />',
347			'posts'			=> '<input type="hidden" name="posts" value="'.implode(',', $posts).'" />'
348		);
349
350		// Setup breadcrumbs
351		$forum_page['crumbs'] = array(
352			array($forum_config['o_board_title'], forum_link($forum_url['index'])),
353			array($cur_forum['forum_name'], forum_link($forum_url['forum'], array($fid, sef_friendly($cur_forum['forum_name'])))),
354			array($cur_topic['subject'], forum_link($forum_url['topic'], array($tid, sef_friendly($cur_topic['subject'])))),
355			$lang_misc['Split posts']
356		);
357
358		($hook = get_hook('mr_confirm_split_posts_pre_header_load')) ? eval($hook) : null;
359
360		define('FORUM_PAGE', 'dialogue');
361		require FORUM_ROOT.'header.php';
362
363		// START SUBST - <!-- forum_main -->
364		ob_start();
365
366		($hook = get_hook('mr_confirm_split_posts_output_start')) ? eval($hook) : null;
367
368?>
369	<div class="main-head">
370		<h2 class="hn"><span><?php echo $lang_misc['Confirm post split'] ?></span></h2>
371	</div>
372	<div class="main-content main-frm">
373		<form class="frm-form" method="post" accept-charset="utf-8" action="<?php echo $forum_page['form_action'] ?>">
374			<div class="hidden">
375				<?php echo implode("\n\t\t\t\t", $forum_page['hidden_fields'])."\n" ?>
376			</div>
377<?php ($hook = get_hook('mr_confirm_split_posts_pre_fieldset')) ? eval($hook) : null; ?>
378			<fieldset class="frm-group group<?php echo ++$forum_page['group_count'] ?>">
379				<legend class="group-legend"><strong><?php echo $lang_misc['Split posts'] ?></strong></legend>
380				<div class="sf-set set<?php echo ++$forum_page['item_count'] ?>">
381<?php ($hook = get_hook('mr_confirm_split_posts_pre_subject')) ? eval($hook) : null; ?>
382					<div class="sf-box text required">
383						<label for="fld<?php echo ++$forum_page['fld_count'] ?>"><span><?php echo $lang_misc['New subject'] ?></span></label><br />
384						<span class="fld-input"><input type="text" id="fld<?php echo $forum_page['fld_count'] ?>" name="new_subject" size="<?php echo FORUM_SUBJECT_MAXIMUM_LENGTH ?>" maxlength="<?php echo FORUM_SUBJECT_MAXIMUM_LENGTH ?>" required /></span>
385					</div>
386<?php ($hook = get_hook('mr_confirm_split_posts_pre_confirm_checkbox')) ? eval($hook) : null; ?>
387					<div class="sf-box checkbox">
388						<span class="fld-input"><input type="checkbox" id="fld<?php echo ++$forum_page['fld_count'] ?>" name="req_confirm" value="1" checked="checked" /></span>
389						<label for="fld<?php echo ++$forum_page['fld_count'] ?>"><span><?php echo $lang_common['Please confirm'] ?></span> <?php echo $lang_misc['Confirm topic split'] ?>.</label>
390					</div>
391				</div>
392<?php ($hook = get_hook('mr_confirm_split_posts_pre_fieldset_end')) ? eval($hook) : null; ?>
393			</fieldset>
394<?php ($hook = get_hook('mr_confirm_split_posts_fieldset_end')) ? eval($hook) : null; ?>
395			<div class="frm-buttons">
396				<span class="submit primary"><input type="submit" name="split_posts_comply" value="<?php echo $lang_common['Split'] ?>" /></span>
397				<span class="cancel"><input type="submit" name="cancel" value="<?php echo $lang_common['Cancel'] ?>" formnovalidate /></span>
398			</div>
399		</form>
400	</div>
401<?php
402
403		$forum_id = $fid;
404
405		($hook = get_hook('mr_confirm_split_posts_end')) ? eval($hook) : null;
406
407		$tpl_temp = forum_trim(ob_get_contents());
408		$tpl_main = str_replace('<!-- forum_main -->', $tpl_temp, $tpl_main);
409		ob_end_clean();
410		// END SUBST - <!-- forum_main -->
411
412		require FORUM_ROOT.'footer.php';
413	}
414
415
416	// Show the moderate topic view
417
418	// Load the viewtopic.php language file
419	require FORUM_ROOT.'lang/'.$forum_user['language'].'/topic.php';
420
421	// Used to disable the Split and Delete buttons if there are no replies to this topic
422	$forum_page['button_status'] = ($cur_topic['num_replies'] == 0) ? ' disabled="disabled"' : '';
423
424
425	// Determine the post offset (based on $_GET['p'])
426	$forum_page['num_pages'] = ceil(($cur_topic['num_replies'] + 1) / $forum_user['disp_posts']);
427	$forum_page['page'] = (!isset($_GET['p']) || !is_numeric($_GET['p']) || $_GET['p'] <= 1 || $_GET['p'] > $forum_page['num_pages']) ? 1 : intval($_GET['p']);
428	$forum_page['start_from'] = $forum_user['disp_posts'] * ($forum_page['page'] - 1);
429	$forum_page['finish_at'] = min(($forum_page['start_from'] + $forum_user['disp_posts']), ($cur_topic['num_replies'] + 1));
430	$forum_page['items_info'] = generate_items_info($lang_misc['Posts'], ($forum_page['start_from'] + 1), ($cur_topic['num_replies'] + 1));
431
432	// Generate paging links
433	$forum_page['page_post']['paging'] = '<p class="paging"><span class="pages">'.$lang_common['Pages'].'</span> '.paginate($forum_page['num_pages'], $forum_page['page'], $forum_url['moderate_topic'], $lang_common['Paging separator'], array($fid, $tid)).'</p>';
434
435	// Navigation links for header and page numbering for title/meta description
436	if ($forum_page['page'] < $forum_page['num_pages'])
437	{
438		$forum_page['nav']['last'] = '<link rel="last" href="'.forum_sublink($forum_url['moderate_topic'], $forum_url['page'], $forum_page['num_pages'], array($fid, $tid)).'" title="'.$lang_common['Page'].' '.$forum_page['num_pages'].'" />';
439		$forum_page['nav']['next'] = '<link rel="next" href="'.forum_sublink($forum_url['moderate_topic'], $forum_url['page'], ($forum_page['page'] + 1), array($fid, $tid)).'" title="'.$lang_common['Page'].' '.($forum_page['page'] + 1).'" />';
440	}
441	if ($forum_page['page'] > 1)
442	{
443		$forum_page['nav']['prev'] = '<link rel="prev" href="'.forum_sublink($forum_url['moderate_topic'], $forum_url['page'], ($forum_page['page'] - 1), array($fid, $tid)).'" title="'.$lang_common['Page'].' '.($forum_page['page'] - 1).'" />';
444		$forum_page['nav']['first'] = '<link rel="first" href="'.forum_link($forum_url['moderate_topic'], array($fid, $tid)).'" title="'.$lang_common['Page'].' 1" />';
445	}
446
447	if ($forum_config['o_censoring'] == '1')
448		$cur_topic['subject'] = censor_words($cur_topic['subject']);
449
450	// Setup form
451	$forum_page['form_action'] = forum_link($forum_url['moderate_topic'], array($fid, $tid));
452
453	// Setup breadcrumbs
454	$forum_page['crumbs'] = array(
455		array($forum_config['o_board_title'], forum_link($forum_url['index'])),
456		array($cur_forum['forum_name'], forum_link($forum_url['forum'], array($fid, sef_friendly($cur_forum['forum_name'])))),
457		array($cur_topic['subject'], forum_link($forum_url['topic'], array($tid, sef_friendly($cur_topic['subject'])))),
458		$lang_topic['Moderate topic']
459	);
460
461	// Setup main heading
462	$forum_page['main_title'] = sprintf($lang_misc['Moderate topic head'], forum_htmlencode($cur_topic['subject']));
463
464	$forum_page['main_head_options']['select_all'] = '<span '.(empty($forum_page['main_head_options']) ? ' class="first-item"' : '').'><span class="select-all js_link" data-check-form="mr-post-actions-form">'.$lang_misc['Select all'].'</span></span>';
465	$forum_page['main_foot_options']['select_all'] = '<span '.(empty($forum_page['main_foot_options']) ? ' class="first-item"' : '').'><span class="select-all js_link" data-check-form="mr-post-actions-form">'.$lang_misc['Select all'].'</span></span>';
466
467	if ($forum_page['num_pages'] > 1)
468		$forum_page['main_head_pages'] = sprintf($lang_common['Page info'], $forum_page['page'], $forum_page['num_pages']);
469
470	($hook = get_hook('mr_post_actions_pre_header_load')) ? eval($hook) : null;
471
472	define('FORUM_PAGE', 'modtopic');
473	require FORUM_ROOT.'header.php';
474
475	// START SUBST - <!-- forum_main -->
476	ob_start();
477
478	($hook = get_hook('mr_post_actions_output_start')) ? eval($hook) : null;
479
480?>
481	<div class="main-head">
482<?php
483
484	if (!empty($forum_page['main_head_options']))
485		echo "\n\t\t".'<p class="options">'.implode(' ', $forum_page['main_head_options']).'</p>';
486
487?>
488		<h2 class="hn"><span><?php echo $forum_page['items_info'] ?></span></h2>
489	</div>
490	<form id="mr-post-actions-form" class="newform" method="post" accept-charset="utf-8" action="<?php echo $forum_page['form_action'] ?>">
491	<div class="main-content main-topic">
492		<div class="hidden">
493			<input type="hidden" name="csrf_token" value="<?php echo generate_form_token($forum_page['form_action']) ?>" />
494		</div>
495
496<?php
497
498	if (!defined('FORUM_PARSER_LOADED'))
499		require FORUM_ROOT.'include/parser.php';
500
501	$forum_page['item_count'] = 0;	// Keep track of post numbers
502
503	// Retrieve the posts (and their respective poster)
504	$query = array(
505		'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',
506		'FROM'		=> 'posts AS p',
507		'JOINS'		=> array(
508			array(
509				'INNER JOIN'	=> 'users AS u',
510				'ON'			=> 'u.id=p.poster_id'
511			),
512			array(
513				'INNER JOIN'	=> 'groups AS g',
514				'ON'			=> 'g.g_id=u.group_id'
515			)
516		),
517		'WHERE'		=> 'p.topic_id='.$tid,
518		'ORDER BY'	=> 'p.id',
519		'LIMIT'		=> $forum_page['start_from'].','.$forum_user['disp_posts']
520	);
521
522	($hook = get_hook('mr_post_actions_qr_get_posts')) ? eval($hook) : null;
523	$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
524	while ($cur_post = $forum_db->fetch_assoc($result))
525	{
526		($hook = get_hook('mr_post_actions_loop_start')) ? eval($hook) : null;
527
528		++$forum_page['item_count'];
529
530		$forum_page['post_ident'] = array();
531		$forum_page['message'] = array();
532		$forum_page['user_ident'] = array();
533		$cur_post['username'] = $cur_post['poster'];
534
535		// Generate the post heading
536		$forum_page['post_ident']['num'] = '<span class="post-num">'.forum_number_format($forum_page['start_from'] + $forum_page['item_count']).'</span>';
537
538		if ($cur_post['poster_id'] > 1)
539			$forum_page['post_ident']['byline'] = '<span class="post-byline">'.sprintf((($cur_post['id'] == $cur_topic['first_post_id']) ? $lang_topic['Topic byline'] : $lang_topic['Reply byline']), (($forum_user['g_view_users'] == '1') ? '<a title="'.sprintf($lang_topic['Go to profile'], forum_htmlencode($cur_post['username'])).'" href="'.forum_link($forum_url['user'], $cur_post['poster_id']).'">'.forum_htmlencode($cur_post['username']).'</a>' : '<strong>'.forum_htmlencode($cur_post['username']).'</strong>')).'</span>';
540		else
541			$forum_page['post_ident']['byline'] = '<span class="post-byline">'.sprintf((($cur_post['id'] == $cur_topic['first_post_id']) ? $lang_topic['Topic byline'] : $lang_topic['Reply byline']), '<strong>'.forum_htmlencode($cur_post['username']).'</strong>').'</span>';
542
543		$forum_page['post_ident']['link'] = '<span class="post-link"><a class="permalink" rel="bookmark" title="'.$lang_topic['Permalink post'].'" href="'.forum_link($forum_url['post'], $cur_post['id']).'">'.format_time($cur_post['posted']).'</a></span>';
544
545		if ($cur_post['edited'] != '')
546			$forum_page['post_ident']['edited'] = '<span class="post-edit">'.sprintf($lang_topic['Last edited'], forum_htmlencode($cur_post['edited_by']), format_time($cur_post['edited'])).'</span>';
547
548		($hook = get_hook('mr_row_pre_item_ident_merge')) ? eval($hook) : null;
549
550		// Generate the checkbox field
551		if ($cur_post['id'] != $cur_topic['first_post_id'])
552			$forum_page['item_select'] = '<p class="item-select"><input type="checkbox" id="fld'.$cur_post['id'].'" name="posts[]" value="'.$cur_post['id'].'" /> <label for="fld'.$cur_post['id'].'">'.$lang_misc['Select post'].' '.forum_number_format($forum_page['start_from'] + $forum_page['item_count']).'</label></p>';
553
554		// Generate author identification
555		$forum_page['author_ident']['username'] = '<li class="username">'.(($cur_post['poster_id'] > '1') ? '<a title="'.sprintf($lang_topic['Go to profile'], forum_htmlencode($cur_post['username'])).'" href="'.forum_link($forum_url['user'], $cur_post['poster_id']).'">'.forum_htmlencode($cur_post['username']).'</a>' : '<strong>'.forum_htmlencode($cur_post['username']).'</strong>').'</li>';
556		$forum_page['author_ident']['usertitle'] = '<li class="usertitle"><span>'.get_title($cur_post).'</span></li>';
557
558		// Give the post some class
559		$forum_page['item_status'] = array(
560			'post',
561			($forum_page['item_count'] % 2 != 0) ? 'odd' : 'even'
562		);
563
564		if ($forum_page['item_count'] == 1)
565			$forum_page['item_status']['firstpost'] = 'firstpost';
566
567		if (($forum_page['start_from'] + $forum_page['item_count']) == $forum_page['finish_at'])
568			$forum_page['item_status']['lastpost'] = 'lastpost';
569
570		if ($cur_post['id'] == $cur_topic['first_post_id'])
571			$forum_page['item_status']['topicpost'] = 'topicpost';
572		else
573			$forum_page['item_status']['replypost'] = 'replypost';
574
575		// Generate the post title
576		if ($cur_post['id'] == $cur_topic['first_post_id'])
577			$forum_page['item_subject'] = sprintf($lang_topic['Topic title'], $cur_topic['subject']);
578		else
579			$forum_page['item_subject'] = sprintf($lang_topic['Reply title'], $cur_topic['subject']);
580
581		$forum_page['item_subject'] = forum_htmlencode($forum_page['item_subject']);
582
583		// Perform the main parsing of the message (BBCode, smilies, censor words etc)
584		$forum_page['message']['message'] = parse_message($cur_post['message'], $cur_post['hide_smilies']);
585
586		($hook = get_hook('mr_post_actions_row_pre_display')) ? eval($hook) : null;
587
588?>
589			<div class="<?php echo implode(' ', $forum_page['item_status']) ?>">
590				<div id="p<?php echo $cur_post['id'] ?>" class="posthead">
591					<h3 class="hn post-ident"><?php echo implode(' ', $forum_page['post_ident']) ?></h3>
592<?php ($hook = get_hook('mr_post_actions_pre_item_select')) ? eval($hook) : null; ?>
593<?php if (isset($forum_page['item_select'])) echo "\t\t\t\t".$forum_page['item_select']."\n" ?>
594<?php ($hook = get_hook('mr_post_actions_new_post_head_option')) ? eval($hook) : null; ?>
595				</div>
596				<div class="postbody">
597					<div class="post-author">
598						<ul class="author-ident">
599							<?php echo implode("\n\t\t\t\t\t\t", $forum_page['author_ident'])."\n" ?>
600						</ul>
601<?php ($hook = get_hook('mr_post_actions_new_user_ident_data')) ? eval($hook) : null; ?>
602					</div>
603					<div class="post-entry">
604						<h4 class="entry-title"><?php echo $forum_page['item_subject'] ?></h4>
605						<div class="entry-content">
606							<?php echo implode("\n\t\t\t\t\t\t\t", $forum_page['message'])."\n" ?>
607						</div>
608<?php ($hook = get_hook('mr_post_actions_new_post_entry_data')) ? eval($hook) : null; ?>
609					</div>
610				</div>
611			</div>
612<?php
613
614	}
615
616?>
617	</div>
618<?php
619
620$forum_page['mod_options'] = array(
621	'del_posts'		=> '<span class="submit first-item"><input type="submit" name="delete_posts" value="'.$lang_misc['Delete posts'].'" /></span>',
622	'split_posts'	=> '<span class="submit"><input type="submit" name="split_posts" value="'.$lang_misc['Split posts'].'" /></span>',
623	'del_topic'		=> '<span><a href="'.forum_link($forum_url['delete'], $cur_topic['first_post_id']).'">'.$lang_misc['Delete whole topic'].'</a></span>'
624);
625
626($hook = get_hook('mr_post_actions_pre_mod_options')) ? eval($hook) : null;
627
628?>
629
630	<div class="main-options mod-options gen-content">
631		<p class="options"><?php echo implode(' ', $forum_page['mod_options']) ?></p>
632	</div>
633	</form>
634	<div class="main-foot">
635<?php
636
637	if (!empty($forum_page['main_foot_options']))
638		echo "\n\t\t".'<p class="options">'.implode(' ', $forum_page['main_foot_options']).'</p>';
639
640?>
641		<h2 class="hn"><span><?php echo $forum_page['items_info'] ?></span></h2>
642	</div>
643<?php
644
645	$forum_id = $fid;
646
647	// Init JS helper for select-all
648	$forum_loader->add_js('PUNBB.common.addDOMReadyEvent(PUNBB.common.initToggleCheckboxes);', array('type' => 'inline'));
649
650	($hook = get_hook('mr_post_actions_end')) ? eval($hook) : null;
651
652	$tpl_temp = forum_trim(ob_get_contents());
653	$tpl_main = str_replace('<!-- forum_main -->', $tpl_temp, $tpl_main);
654	ob_end_clean();
655	// END SUBST - <!-- forum_main -->
656
657	require FORUM_ROOT.'footer.php';
658}
659
660
661// Move one or more topics
662if (isset($_REQUEST['move_topics']) || isset($_POST['move_topics_to']))
663{
664	if (isset($_POST['move_topics_to']))
665	{
666		($hook = get_hook('mr_confirm_move_topics_form_submitted')) ? eval($hook) : null;
667
668		$topics = isset($_POST['topics']) && !empty($_POST['topics']) ? explode(',', $_POST['topics']) : array();
669		$topics = array_map('intval', $topics);
670
671		$move_to_forum = isset($_POST['move_to_forum']) ? intval($_POST['move_to_forum']) : 0;
672		if (empty($topics) || $move_to_forum < 1)
673			message($lang_common['Bad request']);
674
675		// Fetch the forum name for the forum we're moving to
676		$query = array(
677			'SELECT'	=> 'f.forum_name',
678			'FROM'		=> 'forums AS f',
679			'WHERE'		=> 'f.id='.$move_to_forum
680		);
681
682		($hook = get_hook('mr_confirm_move_topics_qr_get_move_to_forum_name')) ? eval($hook) : null;
683		$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
684
685		$move_to_forum_name = $forum_db->result($result);
686
687		if (!$move_to_forum_name)
688			message($lang_common['Bad request']);
689
690		// Verify that the topic IDs are valid
691		$query = array(
692			'SELECT'	=> 'COUNT(t.id)',
693			'FROM'		=> 'topics AS t',
694			'WHERE'		=> 't.id IN('.implode(',', $topics).') AND t.forum_id='.$fid
695		);
696
697		($hook = get_hook('mr_confirm_move_topics_qr_verify_topic_ids')) ? eval($hook) : null;
698		$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
699		if ($forum_db->result($result) != count($topics))
700			message($lang_common['Bad request']);
701
702		// 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)
703		$query = array(
704			'DELETE'	=> 'topics',
705			'WHERE'		=> 'forum_id='.$move_to_forum.' AND moved_to IN('.implode(',', $topics).')'
706		);
707
708		($hook = get_hook('mr_confirm_move_topics_qr_delete_redirect_topics')) ? eval($hook) : null;
709		$forum_db->query_build($query) or error(__FILE__, __LINE__);
710
711		// Move the topic(s)
712		$query = array(
713			'UPDATE'	=> 'topics',
714			'SET'		=> 'forum_id='.$move_to_forum,
715			'WHERE'		=> 'id IN('.implode(',', $topics).')'
716		);
717
718		($hook = get_hook('mr_confirm_move_topics_qr_move_topics')) ? eval($hook) : null;
719		$forum_db->query_build($query) or error(__FILE__, __LINE__);
720
721		// Should we create redirect topics?
722		if (isset($_POST['with_redirect']))
723		{
724			foreach ($topics as $cur_topic)
725			{
726				// Fetch info for the redirect topic
727				$query = array(
728					'SELECT'	=> 't.poster, t.subject, t.posted, t.last_post',
729					'FROM'		=> 'topics AS t',
730					'WHERE'		=> 't.id='.$cur_topic
731				);
732
733				($hook = get_hook('mr_confirm_move_topics_qr_get_redirect_topic_data')) ? eval($hook) : null;
734				$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
735				$moved_to = $forum_db->fetch_assoc($result);
736
737				// Create the redirect topic
738				$query = array(
739					'INSERT'	=> 'poster, subject, posted, last_post, moved_to, forum_id',
740					'INTO'		=> 'topics',
741					'VALUES'	=> '\''.$forum_db->escape($moved_to['poster']).'\', \''.$forum_db->escape($moved_to['subject']).'\', '.$moved_to['posted'].', '.$moved_to['last_post'].', '.$cur_topic.', '.$fid
742				);
743
744				($hook = get_hook('mr_confirm_move_topics_qr_add_redirect_topic')) ? eval($hook) : null;
745				$forum_db->query_build($query) or error(__FILE__, __LINE__);
746			}
747		}
748
749		sync_forum($fid);			// Synchronize the forum FROM which the topic was moved
750		sync_forum($move_to_forum);	// Synchronize the forum TO which the topic was moved
751
752		$forum_page['redirect_msg'] = (count($topics) > 1) ? $lang_misc['Move topics redirect'] : $lang_misc['Move topic redirect'];
753
754		$forum_flash->add_info($forum_page['redirect_msg']);
755
756		($hook = get_hook('mr_confirm_move_topics_pre_redirect')) ? eval($hook) : null;
757
758		redirect(forum_link($forum_url['forum'], array($move_to_forum, sef_friendly($move_to_forum_name))), $forum_page['redirect_msg']);
759	}
760
761	if (isset($_POST['move_topics']))
762	{
763		$topics = isset($_POST['topics']) && is_array($_POST['topics']) ? $_POST['topics'] : array();
764		$topics = array_map('intval', $topics);
765
766		if (empty($topics))
767			message($lang_misc['No topics selected']);
768
769		if (count($topics) == 1)
770		{
771			$topics = $topics[0];
772			$action = 'single';
773		}
774		else
775			$action = 'multiple';
776	}
777	else
778	{
779		$topics = intval($_GET['move_topics']);
780		if ($topics < 1)
781			message($lang_common['Bad request']);
782
783		$action = 'single';
784	}
785	if ($action == 'single')
786	{
787		// Fetch the topic subject
788		$query = array(
789			'SELECT'	=> 't.subject',
790			'FROM'		=> 'topics AS t',
791			'WHERE'		=> 't.id='.$topics
792		);
793
794		($hook = get_hook('mr_move_topics_qr_get_topic_to_move_subject')) ? eval($hook) : null;
795		$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
796		$subject = $forum_db->result($result);
797
798		if (!$subject)
799		{
800			message($lang_common['Bad request']);
801		}
802	}
803
804	// Get forums we can move the post into
805	$query = array(
806		'SELECT'	=> 'c.id AS cid, c.cat_name, f.id AS fid, f.forum_name',
807		'FROM'		=> 'categories AS c',
808		'JOINS'		=> array(
809			array(
810				'INNER JOIN'	=> 'forums AS f',
811				'ON'			=> 'c.id=f.cat_id'
812			),
813			array(
814				'LEFT JOIN'		=> 'forum_perms AS fp',
815				'ON'			=> '(fp.forum_id=f.id AND fp.group_id='.$forum_user['g_id'].')'
816			)
817		),
818		'WHERE'		=> '(fp.read_forum IS NULL OR fp.read_forum=1) AND f.redirect_url IS NULL AND f.id!='.$fid,
819		'ORDER BY'	=> 'c.disp_position, c.id, f.disp_position'
820	);
821
822	($hook = get_hook('mr_move_topics_qr_get_target_forums')) ? eval($hook) : null;
823	$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
824
825	$forum_list = array();
826	while ($cur_sel_forum = $forum_db->fetch_assoc($result))
827	{
828		$forum_list[] = $cur_sel_forum;
829	}
830
831	if (empty($forum_list))
832	{
833		message($lang_misc['Nowhere to move']);
834	}
835
836
837	// Setup form
838	$forum_page['group_count'] = $forum_page['item_count'] = $forum_page['fld_count'] = 0;
839	$forum_page['form_action'] = forum_link($forum_url['moderate_forum'], $fid);
840
841	$forum_page['hidden_fields'] = array(
842		'csrf_token'	=> '<input type="hidden" name="csrf_token" value="'.generate_form_token($forum_page['form_action']).'" />',
843		'topics'		=> '<input type="hidden" name="topics" value="'.($action == 'single' ? $topics : implode(',', $topics)).'" />'
844	);
845
846	// Setup breadcrumbs
847	$forum_page['crumbs'][] = array($forum_config['o_board_title'], forum_link($forum_url['index']));
848	$forum_page['crumbs'][] = array($cur_forum['forum_name'], forum_link($forum_url['forum'], array($fid, sef_friendly($cur_forum['forum_name']))));
849	if ($action == 'single')
850		$forum_page['crumbs'][] = array($subject, forum_link($forum_url['topic'], array($topics, sef_friendly($subject))));
851	else
852		$forum_page['crumbs'][] = array($lang_misc['Moderate forum'], forum_link($forum_url['moderate_forum'], $fid));
853	$forum_page['crumbs'][] = ($action == 'single') ? $lang_misc['Move topic'] : $lang_misc['Move topics'];
854
855	//Setup main heading
856	$forum_page['main_title'] = end($forum_page['crumbs']).' '.$lang_misc['To new forum'];
857
858	($hook = get_hook('mr_move_topics_pre_header_load')) ? eval($hook) : null;
859
860	define('FORUM_PAGE', 'dialogue');
861	require FORUM_ROOT.'header.php';
862
863	// START SUBST - <!-- forum_main -->
864	ob_start();
865
866	($hook = get_hook('mr_move_topics_output_start')) ? eval($hook) : null;
867
868?>
869	<div class="main-head">
870		<h2 class="hn"><span><?php echo end($forum_page['crumbs']).' '.$lang_misc['To new forum'] ?></span></h2>
871	</div>
872	<div class="main-content main-frm">
873		<form class="frm-form" method="post" accept-charset="utf-8" action="<?php echo $forum_page['form_action'] ?>">
874			<div class="hidden">
875				<?php echo implode("\n\t\t\t\t", $forum_page['hidden_fields'])."\n" ?>
876			</div>
877<?php ($hook = get_hook('mr_move_topics_pre_fieldset')) ? eval($hook) : null; ?>
878			<fieldset class="frm-group group<?php echo ++$forum_page['group_count'] ?>">
879				<legend class="group-legend"><strong><?php echo $lang_misc['Move topic'] ?></strong></legend>
880<?php ($hook = get_hook('mr_move_topics_pre_move_to_forum')) ? eval($hook) : null; ?>
881				<div class="sf-set set<?php echo ++$forum_page['item_count'] ?>">
882					<div class="sf-box select">
883						<label for="fld<?php echo ++$forum_page['fld_count'] ?>"><span><?php echo $lang_misc['Move to'] ?></span></label><br />
884						<span class="fld-input"><select id="fld<?php echo $forum_page['fld_count'] ?>" name="move_to_forum">
885<?php
886
887	$forum_page['cur_category'] = 0;
888	foreach ($forum_list as $cur_forum)
889	{
890		($hook = get_hook('mr_move_topics_forum_loop_start')) ? eval($hook) : null;
891
892		if ($cur_forum['cid'] != $forum_page['cur_category'])	// A new category since last iteration?
893		{
894			if ($forum_page['cur_category'])
895				echo "\t\t\t\t".'</optgroup>'."\n";
896
897			echo "\t\t\t\t".'<optgroup label="'.forum_htmlencode($cur_forum['cat_name']).'">'."\n";
898			$forum_page['cur_category'] = $cur_forum['cid'];
899		}
900
901		if ($cur_forum['fid'] != $fid)
902			echo "\t\t\t\t".'<option value="'.$cur_forum['fid'].'">'.forum_htmlencode($cur_forum['forum_name']).'</option>'."\n";
903
904		($hook = get_hook('mr_move_topics_forum_loop_end')) ? eval($hook) : null;
905	}
906
907?>
908						</optgroup>
909						</select></span>
910					</div>
911				</div>
912<?php ($hook = get_hook('mr_move_topics_pre_redirect_checkbox')) ? eval($hook) : null; ?>
913				<div class="sf-set set<?php echo ++$forum_page['item_count'] ?>">
914					<div class="sf-box checkbox">
915						<span class="fld-input"><input type="checkbox" id="fld<?php echo (++$forum_page['fld_count']) ?>" name="with_redirect" value="1"<?php if ($action == 'single') echo ' checked="checked"' ?> /></span>
916						<label for="fld<?php echo $forum_page['fld_count'] ?>"><?php echo ($action == 'single') ? $lang_misc['Leave redirect'] : $lang_misc['Leave redirects'] ?></label>
917					</div>
918				</div>
919<?php ($hook = get_hook('mr_move_topics_pre_fieldset_end')) ? eval($hook) : null; ?>
920			</fieldset>
921<?php ($hook = get_hook('mr_move_topics_fieldset_end')) ? eval($hook) : null; ?>
922			<div class="frm-buttons">
923				<span class="submit primary"><input type="submit" name="move_topics_to" value="<?php echo $lang_misc['Move'] ?>" /></span>
924				<span class="cancel"><input type="submit" name="cancel" value="<?php echo $lang_common['Cancel'] ?>" formnovalidate /></span>
925			</div>
926		</form>
927	</div>
928<?php
929
930	$forum_id = $fid;
931
932	($hook = get_hook('mr_move_topics_end')) ? eval($hook) : null;
933
934	$tpl_temp = forum_trim(ob_get_contents());
935	$tpl_main = str_replace('<!-- forum_main -->', $tpl_temp, $tpl_main);
936	ob_end_clean();
937	// END SUBST - <!-- forum_main -->
938
939	require FORUM_ROOT.'footer.php';
940}
941
942
943// Merge topics
944else if (isset($_POST['merge_topics']) || isset($_POST['merge_topics_comply']))
945{
946	$topics = isset($_POST['topics']) && !empty($_POST['topics']) ? $_POST['topics'] : array();
947	$topics = array_map('intval', (is_array($topics) ? $topics : explode(',', $topics)));
948
949	if (empty($topics))
950		message($lang_misc['No topics selected']);
951
952	if (count($topics) == 1)
953		message($lang_misc['Merge error']);
954
955	if (isset($_POST['merge_topics_comply']))
956	{
957		($hook = get_hook('mr_confirm_merge_topics_form_submitted')) ? eval($hook) : null;
958
959		// Verify that the topic IDs are valid
960		$query = array(
961			'SELECT'	=> 'COUNT(t.id), MIN(t.id)',
962			'FROM'		=> 'topics AS t',
963			'WHERE'		=> 't.id IN('.implode(',', $topics).') AND t.moved_to IS NULL AND t.forum_id='.$fid
964		);
965
966		($hook = get_hook('mr_confirm_merge_topics_qr_verify_topic_ids')) ? eval($hook) : null;
967		$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
968		list($num_topics, $merge_to_tid) = $forum_db->fetch_row($result);
969		if ($num_topics != count($topics))
970			message($lang_common['Bad request']);
971
972		// Make any redirect topics point to our new, merged topic
973		$query = array(
974			'UPDATE'	=> 'topics',
975			'SET'		=> 'moved_to='.$merge_to_tid,
976			'WHERE'		=> 'moved_to IN('.implode(',', $topics).')'
977		);
978
979		// Should we create redirect topics?
980		if (isset($_POST['with_redirect']))
981			$query['WHERE'] .= ' OR (id IN('.implode(',', $topics).') AND id != '.$merge_to_tid.')';
982
983		($hook = get_hook('mr_confirm_merge_topics_qr_fix_redirect_topics')) ? eval($hook) : null;
984		$forum_db->query_build($query) or error(__FILE__, __LINE__);
985
986		// Merge the posts into the topic
987		$query = array(
988			'UPDATE'	=> 'posts',
989			'SET'		=> 'topic_id='.$merge_to_tid,
990			'WHERE'		=> 'topic_id IN('.implode(',', $topics).')'
991		);
992
993		($hook = get_hook('mr_confirm_merge_topics_qr_merge_posts')) ? eval($hook) : null;
994		$forum_db->query_build($query) or error(__FILE__, __LINE__);
995
996		// Delete any subscriptions
997		$query = array(
998			'DELETE'	=> 'subscriptions',
999			'WHERE'		=> 'topic_id IN('.implode(',', $topics).') AND topic_id != '.$merge_to_tid
1000		);
1001
1002		($hook = get_hook('mr_confirm_merge_topics_qr_delete_subscriptions')) ? eval($hook) : null;
1003		$forum_db->query_build($query) or error(__FILE__, __LINE__);
1004
1005		if (!isset($_POST['with_redirect']))
1006		{
1007			// Delete the topics that have been merged
1008			$query = array(
1009				'DELETE'	=> 'topics',
1010				'WHERE'		=> 'id IN('.implode(',', $topics).') AND id != '.$merge_to_tid
1011			);
1012
1013			($hook = get_hook('mr_confirm_merge_topics_qr_delete_merged_topics')) ? eval($hook) : null;
1014			$forum_db->query_build($query) or error(__FILE__, __LINE__);
1015		}
1016
1017		// Synchronize the topic we merged to and the forum where the topics were merged
1018		sync_topic($merge_to_tid);
1019		sync_forum($fid);
1020
1021		$forum_flash->add_info($lang_misc['Merge topics redirect']);
1022
1023		($hook = get_hook('mr_confirm_merge_topics_pre_redirect')) ? eval($hook) : null;
1024
1025		redirect(forum_link($forum_url['forum'], array($fid, sef_friendly($cur_forum['forum_name']))), $lang_misc['Merge topics redirect']);
1026	}
1027
1028	// Setup form
1029	$forum_page['group_count'] = $forum_page['item_count'] = $forum_page['fld_count'] = 0;
1030	$forum_page['form_action'] = forum_link($forum_url['moderate_forum'], $fid);
1031
1032	$forum_page['hidden_fields'] = array(
1033		'csrf_token'	=> '<input type="hidden" name="csrf_token" value="'.generate_form_token($forum_page['form_action']).'" />',
1034		'topics'		=> '<input type="hidden" name="topics" value="'.implode(',', $topics).'" />'
1035	);
1036
1037	// Setup breadcrumbs
1038	$forum_page['crumbs'] = array(
1039		array($forum_config['o_board_title'], forum_link($forum_url['index'])),
1040		array($cur_forum['forum_name'], forum_link($forum_url['forum'], array($fid, sef_friendly($cur_forum['forum_name'])))),
1041		array($lang_misc['Moderate forum'], forum_link($forum_url['moderate_forum'], $fid)),
1042		$lang_misc['Merge topics']
1043	);
1044
1045	($hook = get_hook('mr_merge_topics_pre_header_load')) ? eval($hook) : null;
1046
1047	define('FORUM_PAGE', 'dialogue');
1048	require FORUM_ROOT.'header.php';
1049
1050	// START SUBST - <!-- forum_main -->
1051	ob_start();
1052
1053	($hook = get_hook('mr_merge_topics_output_start')) ? eval($hook) : null;
1054
1055?>
1056	<div class="main-head">
1057		<h2 class="hn"><span><?php echo $lang_misc['Confirm topic merge'] ?></span></h2>
1058	</div>
1059	<div class="main-content main-frm">
1060		<form class="frm-form" method="post" accept-charset="utf-8" action="<?php echo $forum_page['form_action'] ?>">
1061			<div class="hidden">
1062				<?php echo implode("\n\t\t\t\t", $forum_page['hidden_fields'])."\n" ?>
1063			</div>
1064<?php ($hook = get_hook('mr_merge_topics_pre_fieldset')) ? eval($hook) : null; ?>
1065			<fieldset class="frm-group group<?php echo ++$forum_page['group_count'] ?>">
1066				<legend class="group-legend"><strong><?php echo $lang_misc['Merge topics'] ?></strong></legend>
1067<?php ($hook = get_hook('mr_merge_topics_pre_redirect_checkbox')) ? eval($hook) : null; ?>
1068				<div class="sf-set set<?php echo ++$forum_page['item_count'] ?>">
1069					<div class="sf-box checkbox">
1070						<span class="fld-input"><input type="checkbox" id="fld<?php echo (++$forum_page['fld_count']) ?>" name="with_redirect" value="1" /></span>
1071						<label for="fld<?php echo $forum_page['fld_count'] ?>"><?php echo $lang_misc['Leave merge redirects'] ?></label>
1072					</div>
1073				</div>
1074<?php ($hook = get_hook('mr_merge_topics_pre_fieldset_end')) ? eval($hook) : null; ?>
1075			</fieldset>
1076<?php ($hook = get_hook('mr_merge_topics_fieldset_end')) ? eval($hook) : null; ?>
1077			<div class="frm-buttons">
1078				<span class="submit primary"><input type="submit" name="merge_topics_comply" value="<?php echo $lang_misc['Merge'] ?>" /></span>
1079				<span class="cancel"><input type="submit" name="cancel" value="<?php echo $lang_common['Cancel'] ?>" formnovalidate /></span>
1080			</div>
1081		</form>
1082	</div>
1083<?php
1084
1085	$forum_id = $fid;
1086
1087	($hook = get_hook('mr_merge_topics_end')) ? eval($hook) : null;
1088
1089	$tpl_temp = forum_trim(ob_get_contents());
1090	$tpl_main = str_replace('<!-- forum_main -->', $tpl_temp, $tpl_main);
1091	ob_end_clean();
1092	// END SUBST - <!-- forum_main -->
1093
1094	require FORUM_ROOT.'footer.php';
1095}
1096
1097
1098// Delete one or more topics
1099else if (isset($_REQUEST['delete_topics']) || isset($_POST['delete_topics_comply']))
1100{
1101	$topics = isset($_POST['topics']) && !empty($_POST['topics']) ? $_POST['topics'] : array();
1102	$topics = array_map('intval', (is_array($topics) ? $topics : explode(',', $topics)));
1103
1104	if (empty($topics))
1105		message($lang_misc['No topics selected']);
1106
1107	$multi = count($topics) > 1;
1108	if (isset($_POST['delete_topics_comply']))
1109	{
1110		if (!isset($_POST['req_confirm']))
1111			redirect(forum_link($forum_url['forum'], array($fid, sef_friendly($cur_forum['forum_name']))), $lang_common['Cancel redirect']);
1112
1113		($hook = get_hook('mr_confirm_delete_topics_form_submitted')) ? eval($hook) : null;
1114
1115		// Verify that the topic IDs are valid
1116		$query = array(
1117			'SELECT'	=> 'COUNT(t.id)',
1118			'FROM'		=> 'topics AS t',
1119			'WHERE'		=> 't.id IN('.implode(',', $topics).') AND t.forum_id='.$fid
1120		);
1121
1122		($hook = get_hook('mr_confirm_delete_topics_qr_verify_topic_ids')) ? eval($hook) : null;
1123		$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
1124		if ($forum_db->result($result) != count($topics))
1125			message($lang_common['Bad request']);
1126
1127		// Create an array of forum IDs that need to be synced
1128		$forum_ids = array($fid);
1129		$query = array(
1130			'SELECT'	=> 't.forum_id',
1131			'FROM'		=> 'topics AS t',
1132			'WHERE'		=> 't.moved_to IN('.implode(',', $topics).')'
1133		);
1134
1135		($hook = get_hook('mr_confirm_delete_topics_qr_get_forums_to_sync')) ? eval($hook) : null;
1136		$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
1137		while ($row = $forum_db->fetch_row($result))
1138			$forum_ids[] = $row[0];
1139
1140		// Delete the topics and any redirect topics
1141		$query = array(
1142			'DELETE'	=> 'topics',
1143			'WHERE'		=> 'id IN('.implode(',', $topics).') OR moved_to IN('.implode(',', $topics).')'
1144		);
1145
1146		($hook = get_hook('mr_confirm_delete_topics_qr_delete_topics')) ? eval($hook) : null;
1147		$forum_db->query_build($query) or error(__FILE__, __LINE__);
1148
1149		// Delete any subscriptions
1150		$query = array(
1151			'DELETE'	=> 'subscriptions',
1152			'WHERE'		=> 'topic_id IN('.implode(',', $topics).')'
1153		);
1154
1155		($hook = get_hook('mr_confirm_delete_topics_qr_delete_subscriptions')) ? eval($hook) : null;
1156		$forum_db->query_build($query) or error(__FILE__, __LINE__);
1157
1158		// Create a list of the post ID's in the deleted topic and strip the search index
1159		$query = array(
1160			'SELECT'	=> 'p.id',
1161			'FROM'		=> 'posts AS p',
1162			'WHERE'		=> 'p.topic_id IN('.implode(',', $topics).')'
1163		);
1164
1165		($hook = get_hook('mr_confirm_delete_topics_qr_get_deleted_posts')) ? eval($hook) : null;
1166		$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
1167
1168		$post_ids = array();
1169		while ($row = $forum_db->fetch_row($result))
1170			$post_ids[] = $row[0];
1171
1172		// Strip the search index provided we're not just deleting redirect topics
1173		if (!empty($post_ids))
1174		{
1175			if (!defined('FORUM_SEARCH_IDX_FUNCTIONS_LOADED'))
1176				require FORUM_ROOT.'include/search_idx.php';
1177
1178			strip_search_index($post_ids);
1179		}
1180
1181		// Delete posts
1182		$query = array(
1183			'DELETE'	=> 'posts',
1184			'WHERE'		=> 'topic_id IN('.implode(',', $topics).')'
1185		);
1186
1187		($hook = get_hook('mr_confirm_delete_topics_qr_delete_topic_posts')) ? eval($hook) : null;
1188		$forum_db->query_build($query) or error(__FILE__, __LINE__);
1189
1190		foreach ($forum_ids as $cur_forum_id)
1191			sync_forum($cur_forum_id);
1192
1193		$forum_flash->add_info($multi ? $lang_misc['Delete topics redirect'] : $lang_misc['Delete topic redirect']);
1194
1195		($hook = get_hook('mr_confirm_delete_topics_pre_redirect')) ? eval($hook) : null;
1196
1197		redirect(forum_link($forum_url['forum'], array($fid, sef_friendly($cur_forum['forum_name']))), $multi ? $lang_misc['Delete topics redirect'] : $lang_misc['Delete topic redirect']);
1198	}
1199
1200
1201	// Setup form
1202	$forum_page['group_count'] = $forum_page['item_count'] = $forum_page['fld_count'] =0;
1203	$forum_page['form_action'] = forum_link($forum_url['moderate_forum'], $fid);
1204
1205	$forum_page['hidden_fields'] = array(
1206		'csrf_token'	=> '<input type="hidden" name="csrf_token" value="'.generate_form_token($forum_page['form_action']).'" />',
1207		'topics'		=> '<input type="hidden" name="topics" value="'.implode(',', $topics).'" />'
1208	);
1209
1210	// Setup breadcrumbs
1211	$forum_page['crumbs'] = array(
1212		array($forum_config['o_board_title'], forum_link($forum_url['index'])),
1213		array($cur_forum['forum_name'], forum_link($forum_url['forum'], array($fid, sef_friendly($cur_forum['forum_name'])))),
1214		array($lang_misc['Moderate forum'], forum_link($forum_url['moderate_forum'], $fid)),
1215		$multi ? $lang_misc['Delete topics'] : $lang_misc['Delete topic']
1216	);
1217
1218	($hook = get_hook('mr_delete_topics_pre_header_load')) ? eval($hook) : null;
1219
1220	define('FORUM_PAGE', 'dialogue');
1221	require FORUM_ROOT.'header.php';
1222
1223	// START SUBST - <!-- forum_main -->
1224	ob_start();
1225
1226	($hook = get_hook('mr_delete_topics_output_start')) ? eval($hook) : null;
1227
1228?>
1229	<div class="main-head">
1230		<h2 class="hn"><span><?php echo $lang_misc['Confirm topic delete'] ?></span></h2>
1231	</div>
1232	<div class="main-content main-frm">
1233		<form class="frm-form" method="post" accept-charset="utf-8" action="<?php echo $forum_page['form_action'] ?>">
1234			<div class="hidden">
1235				<?php echo implode("\n\t\t\t\t", $forum_page['hidden_fields'])."\n" ?>
1236			</div>
1237<?php ($hook = get_hook('mr_delete_topics_pre_fieldset')) ? eval($hook) : null; ?>
1238			<fieldset class="frm-group group<?php echo ++$forum_page['group_count'] ?>">
1239				<legend class="group-legend"><strong><?php echo $multi ? $lang_misc['Delete topics'] : $lang_misc['Delete topics'] ?></strong></legend>
1240<?php ($hook = get_hook('mr_delete_topics_pre_confirm_checkbox')) ? eval($hook) : null; ?>
1241				<div class="sf-set set<?php echo ++$forum_page['item_count'] ?>">
1242					<div class="sf-box checkbox">
1243						<span class="fld-input"><input type="checkbox" id="fld<?php echo ++$forum_page['fld_count'] ?>" name="req_confirm" value="1" checked="checked" /></span>
1244						<label for="fld<?php echo $forum_page['fld_count'] ?>"><span><?php echo $lang_common['Please confirm'] ?></span> <?php echo $multi ? $lang_misc['Delete topics comply'] : $lang_misc['Delete topic comply'] ?></label>
1245					</div>
1246				</div>
1247<?php ($hook = get_hook('mr_delete_topics_pre_fieldset_end')) ? eval($hook) : null; ?>
1248			</fieldset>
1249<?php ($hook = get_hook('mr_delete_topics_fieldset_end')) ? eval($hook) : null; ?>
1250			<div class="frm-buttons">
1251				<span class="submit primary caution"><input type="submit" name="delete_topics_comply" value="<?php echo $lang_common['Delete'] ?>" /></span>
1252				<span class="cancel"><input type="submit" name="cancel" value="<?php echo $lang_common['Cancel'] ?>" formnovalidate /></span>
1253			</div>
1254		</form>
1255	</div>
1256<?php
1257
1258	$forum_id = $fid;
1259
1260	($hook = get_hook('mr_delete_topics_end')) ? eval($hook) : null;
1261
1262	$tpl_temp = forum_trim(ob_get_contents());
1263	$tpl_main = str_replace('<!-- forum_main -->', $tpl_temp, $tpl_main);
1264	ob_end_clean();
1265	// END SUBST - <!-- forum_main -->
1266
1267	require FORUM_ROOT.'footer.php';
1268}
1269
1270
1271// Open or close one or more topics
1272else if (isset($_REQUEST['open']) || isset($_REQUEST['close']))
1273{
1274	$action = (isset($_REQUEST['open'])) ? 0 : 1;
1275
1276	($hook = get_hook('mr_open_close_topic_selected')) ? eval($hook) : null;
1277
1278	// There could be an array of topic ID's in $_POST
1279	if (isset($_POST['open']) || isset($_POST['close']))
1280	{
1281		$topics = isset($_POST['topics']) && is_array($_POST['topics']) ? $_POST['topics'] : array();
1282		$topics = array_map('intval', $topics);
1283
1284		if (empty($topics))
1285			message($lang_misc['No topics selected']);
1286
1287		$query = array(
1288			'UPDATE'	=> 'topics',
1289			'SET'		=> 'closed='.$action,
1290			'WHERE'		=> 'id IN('.implode(',', $topics).') AND forum_id='.$fid
1291		);
1292
1293		($hook = get_hook('mr_open_close_multi_topics_qr_open_close_topics')) ? eval($hook) : null;
1294		$forum_db->query_build($query) or error(__FILE__, __LINE__);
1295
1296		if (count($topics) == 1)
1297			$forum_page['redirect_msg'] = ($action) ? $lang_misc['Close topic redirect'] : $lang_misc['Open topic redirect'];
1298		else
1299			$forum_page['redirect_msg'] = ($action) ? $lang_misc['Close topics redirect'] : $lang_misc['Open topics redirect'];
1300
1301		$forum_flash->add_info($forum_page['redirect_msg']);
1302
1303		($hook = get_hook('mr_open_close_multi_topics_pre_redirect')) ? eval($hook) : null;
1304
1305		redirect(forum_link($forum_url['moderate_forum'], $fid), $forum_page['redirect_msg']);
1306	}
1307	// Or just one in $_GET
1308	else
1309	{
1310		$topic_id = ($action) ? intval($_GET['close']) : intval($_GET['open']);
1311		if ($topic_id < 1)
1312			message($lang_common['Bad request']);
1313
1314		// We validate the CSRF token. If it's set in POST and we're at this point, the token is valid.
1315		// If it's in GET, we need to make sure it's valid.
1316		if (!isset($_POST['csrf_token']) && (!isset($_GET['csrf_token']) || $_GET['csrf_token'] !== generate_form_token(($action ? 'close' : 'open').$topic_id)))
1317			csrf_confirm_form();
1318
1319		// Get the topic subject
1320		$query = array(
1321			'SELECT'	=> 't.subject',
1322			'FROM'		=> 'topics AS t',
1323			'WHERE'		=> 't.id='.$topic_id.' AND forum_id='.$fid
1324		);
1325
1326		($hook = get_hook('mr_open_close_single_topic_qr_get_subject')) ? eval($hook) : null;
1327		$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
1328
1329		$subject = $forum_db->result($result);
1330
1331		if (!$subject)
1332		{
1333			message($lang_common['Bad request']);
1334		}
1335
1336		$query = array(
1337			'UPDATE'	=> 'topics',
1338			'SET'		=> 'closed='.$action,
1339			'WHERE'		=> 'id='.$topic_id.' AND forum_id='.$fid
1340		);
1341
1342		($hook = get_hook('mr_open_close_single_topic_qr_open_close_topic')) ? eval($hook) : null;
1343		$forum_db->query_build($query) or error(__FILE__, __LINE__);
1344
1345		$forum_page['redirect_msg'] = ($action) ? $lang_misc['Close topic redirect'] : $lang_misc['Open topic redirect'];
1346
1347		$forum_flash->add_info($forum_page['redirect_msg']);
1348
1349		($hook = get_hook('mr_open_close_single_topic_pre_redirect')) ? eval($hook) : null;
1350
1351		redirect(forum_link($forum_url['topic'], array($topic_id, sef_friendly($subject))), $forum_page['redirect_msg']);
1352	}
1353}
1354
1355
1356// Stick a topic
1357else if (isset($_GET['stick']))
1358{
1359	$stick = intval($_GET['stick']);
1360	if ($stick < 1)
1361		message($lang_common['Bad request']);
1362
1363	// We validate the CSRF token. If it's set in POST and we're at this point, the token is valid.
1364	// If it's in GET, we need to make sure it's valid.
1365	if (!isset($_POST['csrf_token']) && (!isset($_GET['csrf_token']) || $_GET['csrf_token'] !== generate_form_token('stick'.$stick)))
1366		csrf_confirm_form();
1367
1368	($hook = get_hook('mr_stick_topic_selected')) ? eval($hook) : null;
1369
1370	// Get the topic subject
1371	$query = array(
1372		'SELECT'	=> 't.subject',
1373		'FROM'		=> 'topics AS t',
1374		'WHERE'		=> 't.id='.$stick.' AND forum_id='.$fid
1375	);
1376
1377	($hook = get_hook('mr_stick_topic_qr_get_subject')) ? eval($hook) : null;
1378	$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
1379	$subject = $forum_db->result($result);
1380
1381	if (!$subject)
1382	{
1383		message($lang_common['Bad request']);
1384	}
1385
1386	$query = array(
1387		'UPDATE'	=> 'topics',
1388		'SET'		=> 'sticky=1',
1389		'WHERE'		=> 'id='.$stick.' AND forum_id='.$fid
1390	);
1391
1392	($hook = get_hook('mr_stick_topic_qr_stick_topic')) ? eval($hook) : null;
1393	$forum_db->query_build($query) or error(__FILE__, __LINE__);
1394
1395	$forum_flash->add_info($lang_misc['Stick topic redirect']);
1396
1397	($hook = get_hook('mr_stick_topic_pre_redirect')) ? eval($hook) : null;
1398
1399	redirect(forum_link($forum_url['topic'], array($stick, sef_friendly($subject))), $lang_misc['Stick topic redirect']);
1400}
1401
1402
1403// Unstick a topic
1404else if (isset($_GET['unstick']))
1405{
1406	$unstick = intval($_GET['unstick']);
1407	if ($unstick < 1)
1408		message($lang_common['Bad request']);
1409
1410	// We validate the CSRF token. If it's set in POST and we're at this point, the token is valid.
1411	// If it's in GET, we need to make sure it's valid.
1412	if (!isset($_POST['csrf_token']) && (!isset($_GET['csrf_token']) || $_GET['csrf_token'] !== generate_form_token('unstick'.$unstick)))
1413		csrf_confirm_form();
1414
1415	($hook = get_hook('mr_unstick_topic_selected')) ? eval($hook) : null;
1416
1417	// Get the topic subject
1418	$query = array(
1419		'SELECT'	=> 't.subject',
1420		'FROM'		=> 'topics AS t',
1421		'WHERE'		=> 't.id='.$unstick.' AND forum_id='.$fid
1422	);
1423
1424	($hook = get_hook('mr_unstick_topic_qr_get_subject')) ? eval($hook) : null;
1425	$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
1426	$subject = $forum_db->result($result);
1427
1428	if (!$subject)
1429	{
1430		message($lang_common['Bad request']);
1431	}
1432
1433	$query = array(
1434		'UPDATE'	=> 'topics',
1435		'SET'		=> 'sticky=0',
1436		'WHERE'		=> 'id='.$unstick.' AND forum_id='.$fid
1437	);
1438
1439	($hook = get_hook('mr_unstick_topic_qr_unstick_topic')) ? eval($hook) : null;
1440	$forum_db->query_build($query) or error(__FILE__, __LINE__);
1441
1442	$forum_flash->add_info($lang_misc['Unstick topic redirect']);
1443
1444	($hook = get_hook('mr_unstick_topic_pre_redirect')) ? eval($hook) : null;
1445
1446	redirect(forum_link($forum_url['topic'], array($unstick, sef_friendly($subject))), $lang_misc['Unstick topic redirect']);
1447}
1448
1449
1450($hook = get_hook('mr_new_action')) ? eval($hook) : null;
1451
1452
1453// No specific forum moderation action was specified in the query string, so we'll display the moderate forum view
1454
1455// If forum is empty
1456if ($cur_forum['num_topics'] == 0)
1457	message($lang_common['Bad request']);
1458
1459// Load the viewforum.php language file
1460require FORUM_ROOT.'lang/'.$forum_user['language'].'/forum.php';
1461
1462// Determine the topic offset (based on $_GET['p'])
1463$forum_page['num_pages'] = ceil($cur_forum['num_topics'] / $forum_user['disp_topics']);
1464
1465$forum_page['page'] = (!isset($_GET['p']) || !is_numeric($_GET['p']) || $_GET['p'] <= 1 || $_GET['p'] > $forum_page['num_pages']) ? 1 : $_GET['p'];
1466$forum_page['start_from'] = $forum_user['disp_topics'] * ($forum_page['page'] - 1);
1467$forum_page['finish_at'] = min(($forum_page['start_from'] + $forum_user['disp_topics']), ($cur_forum['num_topics']));
1468$forum_page['items_info'] = generate_items_info($lang_misc['Topics'], ($forum_page['start_from'] + 1), $cur_forum['num_topics']);
1469
1470// Select topics
1471$query = array(
1472	'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',
1473	'FROM'		=> 'topics AS t',
1474	'WHERE'		=> 'forum_id='.$fid,
1475	'ORDER BY'	=> 't.sticky DESC, '.(($cur_forum['sort_by'] == '1') ? 't.posted' : 't.last_post').' DESC',
1476	'LIMIT'		=>	$forum_page['start_from'].', '.$forum_user['disp_topics']
1477);
1478
1479// With "has posted" indication
1480if (!$forum_user['is_guest'] && $forum_config['o_show_dot'] == '1')
1481{
1482	$query['SELECT'] .= ', p.poster_id AS has_posted';
1483	$query['JOINS'][]	= array(
1484		'LEFT JOIN'		=> 'posts AS p',
1485		'ON'			=> '(p.poster_id='.$forum_user['id'].' AND p.topic_id=t.id)'
1486	);
1487
1488	// Must have same columns as in prev SELECT
1489	$query['GROUP BY'] = '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, p.poster_id';
1490
1491	($hook = get_hook('mr_qr_get_has_posted')) ? eval($hook) : null;
1492}
1493
1494($hook = get_hook('mr_qr_get_topics')) ? eval($hook) : null;
1495$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
1496
1497// Generate paging links
1498$forum_page['page_post']['paging'] = '<p class="paging"><span class="pages">'.$lang_common['Pages'].'</span> '.paginate($forum_page['num_pages'], $forum_page['page'], $forum_url['moderate_forum'], $lang_common['Paging separator'], $fid).'</p>';
1499
1500// Navigation links for header and page numbering for title/meta description
1501if ($forum_page['page'] < $forum_page['num_pages'])
1502{
1503	$forum_page['nav']['last'] = '<link rel="last" href="'.forum_sublink($forum_url['moderate_forum'], $forum_url['page'], $forum_page['num_pages'], $fid).'" title="'.$lang_common['Page'].' '.$forum_page['num_pages'].'" />';
1504	$forum_page['nav']['next'] = '<link rel="next" href="'.forum_sublink($forum_url['moderate_forum'], $forum_url['page'], ($forum_page['page'] + 1), $fid).'" title="'.$lang_common['Page'].' '.($forum_page['page'] + 1).'" />';
1505}
1506if ($forum_page['page'] > 1)
1507{
1508	$forum_page['nav']['prev'] = '<link rel="prev" href="'.forum_sublink($forum_url['moderate_forum'], $forum_url['page'], ($forum_page['page'] - 1), $fid).'" title="'.$lang_common['Page'].' '.($forum_page['page'] - 1).'" />';
1509	$forum_page['nav']['first'] = '<link rel="first" href="'.forum_link($forum_url['moderate_forum'], $fid).'" title="'.$lang_common['Page'].' 1" />';
1510}
1511
1512// Setup form
1513$forum_page['fld_count'] = 0;
1514$forum_page['form_action'] = forum_link($forum_url['moderate_forum'], $fid);
1515
1516// Setup breadcrumbs
1517$forum_page['crumbs'] = array(
1518	array($forum_config['o_board_title'], forum_link($forum_url['index'])),
1519	array($cur_forum['forum_name'], forum_link($forum_url['forum'], array($fid, sef_friendly($cur_forum['forum_name'])))),
1520	sprintf($lang_misc['Moderate forum head'], forum_htmlencode($cur_forum['forum_name']))
1521);
1522
1523// Setup main heading
1524if ($forum_page['num_pages'] > 1)
1525	$forum_page['main_head_pages'] = sprintf($lang_common['Page info'], $forum_page['page'], $forum_page['num_pages']);
1526
1527$forum_page['main_head_options']['select_all'] = '<span '.(empty($forum_page['main_head_options']) ? ' class="first-item"' : '').'><span class="select-all js_link" data-check-form="mr-topic-actions-form">'.$lang_misc['Select all'].'</span></span>';
1528$forum_page['main_foot_options']['select_all'] = '<span '.(empty($forum_page['main_foot_options']) ? ' class="first-item"' : '').'><span class="select-all js_link" data-check-form="mr-topic-actions-form">'.$lang_misc['Select all'].'</span></span>';
1529
1530($hook = get_hook('mr_topic_actions_pre_header_load')) ? eval($hook) : null;
1531
1532define('FORUM_PAGE', 'modforum');
1533require FORUM_ROOT.'header.php';
1534
1535// START SUBST - <!-- forum_main -->
1536ob_start();
1537
1538$forum_page['item_header'] = array();
1539$forum_page['item_header']['subject']['title'] = '<strong class="subject-title">'.$lang_forum['Topics'].'</strong>';
1540
1541if ($forum_config['o_topic_views'] == '1')
1542	$forum_page['item_header']['info']['views'] = '<strong class="info-views">'.$lang_forum['views'].'</strong>';
1543
1544$forum_page['item_header']['info']['replies'] = '<strong class="info-replies">'.$lang_forum['replies'].'</strong>';
1545$forum_page['item_header']['info']['lastpost'] = '<strong class="info-lastpost">'.$lang_forum['last post'].'</strong>';
1546
1547($hook = get_hook('mr_topic_actions_output_start')) ? eval($hook) : null;
1548
1549?>
1550	<div class="main-head">
1551<?php
1552
1553	if (!empty($forum_page['main_head_options']))
1554		echo "\n\t\t".'<p class="options">'.implode(' ', $forum_page['main_head_options']).'</p>';
1555
1556?>
1557		<h2 class="hn"><span><?php echo $forum_page['items_info'] ?></span></h2>
1558	</div>
1559	<form id="mr-topic-actions-form" method="post" accept-charset="utf-8" action="<?php echo $forum_page['form_action'] ?>">
1560	<div class="main-subhead">
1561		<p class="item-summary<?php echo ($forum_config['o_topic_views'] == '1') ? ' forum-views' : ' forum-noview' ?>"><span><?php printf($lang_forum['Forum subtitle'], implode(' ', $forum_page['item_header']['subject']), implode(', ', $forum_page['item_header']['info'])) ?></span></p>
1562	</div>
1563	<div id="forum<?php echo $fid ?>" class="main-content main-forum<?php echo ($forum_config['o_topic_views'] == '1') ? ' forum-views' : ' forum-noview' ?>">
1564		<div class="hidden">
1565			<input type="hidden" name="csrf_token" value="<?php echo generate_form_token($forum_page['form_action']) ?>" />
1566		</div>
1567<?php
1568
1569	$forum_page['item_count'] = 0;
1570
1571	while ($cur_topic = $forum_db->fetch_assoc($result))
1572	{
1573		($hook = get_hook('mr_topic_actions_row_loop_start')) ? eval($hook) : null;
1574
1575		++$forum_page['item_count'];
1576
1577		// Start from scratch
1578		$forum_page['item_subject'] = $forum_page['item_body'] = $forum_page['item_status'] = $forum_page['item_nav'] = $forum_page['item_title'] = $forum_page['item_title_status'] = array();
1579
1580		if ($forum_config['o_censoring'] == '1')
1581			$cur_topic['subject'] = censor_words($cur_topic['subject']);
1582
1583		$forum_page['item_subject']['starter'] = '<span class="item-starter">'.sprintf($lang_forum['Topic starter'], forum_htmlencode($cur_topic['poster'])).'</span>';
1584
1585		if ($cur_topic['moved_to'] != null)
1586		{
1587			$forum_page['item_status']['moved'] = 'moved';
1588			$forum_page['item_title']['link'] = '<span class="item-status"><em class="moved">'.sprintf($lang_forum['Item status'], $lang_forum['Moved']).'</em></span> <a href="'.forum_link($forum_url['topic'], array($cur_topic['moved_to'], sef_friendly($cur_topic['subject']))).'">'.forum_htmlencode($cur_topic['subject']).'</a>';
1589
1590			// Combine everything to produce the Topic heading
1591			$forum_page['item_body']['subject']['title'] = '<h3 class="hn"><span class="item-num">'.forum_number_format($forum_page['start_from'] + $forum_page['item_count']).'</span> <strong>'.$forum_page['item_title']['link'].'</strong></h3>';
1592
1593			($hook = get_hook('mr_topic_actions_moved_row_pre_item_subject_merge')) ? eval($hook) : null;
1594
1595			if ($forum_config['o_topic_views'] == '1')
1596				$forum_page['item_body']['info']['views'] = '<li class="info-views"><span class="label">'.$lang_forum['No views info'].'</span></li>';
1597
1598			$forum_page['item_body']['info']['replies'] = '<li class="info-replies"><span class="label">'.$lang_forum['No replies info'].'</span></li>';
1599			$forum_page['item_body']['info']['lastpost'] = '<li class="info-lastpost"><span class="label">'.$lang_forum['No lastpost info'].'</span></li>';
1600			$forum_page['item_body']['info']['select'] = '<li class="info-select"><input id="fld'.++$forum_page['fld_count'].'" type="checkbox" name="topics[]" value="'.$cur_topic['id'].'" /> <label for="fld'.$forum_page['fld_count'].'">'.sprintf($lang_forum['Select topic'], forum_htmlencode($cur_topic['subject'])).'</label></li>';
1601
1602			($hook = get_hook('mr_topic_actions_moved_row_pre_output')) ? eval($hook) : null;
1603		}
1604		else
1605		{
1606			$forum_page['ghost_topic'] = false;
1607
1608			// First assemble the Topic heading
1609
1610			// Should we display the dot or not? :)
1611			if (!$forum_user['is_guest'] && $forum_config['o_show_dot'] == '1' && $cur_topic['has_posted'] == $forum_user['id'])
1612			{
1613				$forum_page['item_title']['posted'] = '<span class="posted-mark">'.$lang_forum['You posted indicator'].'</span>';
1614				$forum_page['item_status']['posted'] = 'posted';
1615			}
1616
1617			if ($cur_topic['sticky'] == '1')
1618			{
1619				$forum_page['item_title_status']['sticky'] = '<em class="sticky">'.$lang_forum['Sticky'].'</em>';
1620				$forum_page['item_status']['sticky'] = 'sticky';
1621			}
1622
1623			if ($cur_topic['closed'] == '1')
1624			{
1625				$forum_page['item_title_status']['closed'] = '<em class="closed">'.$lang_forum['Closed'].'</em>';
1626				$forum_page['item_status']['closed'] = 'closed';
1627			}
1628
1629			($hook = get_hook('mr_topic_loop_normal_topic_pre_item_title_status_merge')) ? eval($hook) : null;
1630
1631			if (!empty($forum_page['item_title_status']))
1632				$forum_page['item_title']['status'] = '<span class="item-status">'.sprintf($lang_forum['Item status'], implode(', ', $forum_page['item_title_status'])).'</span>';
1633
1634			$forum_page['item_title']['link'] = '<a href="'.forum_link($forum_url['topic'], array($cur_topic['id'], sef_friendly($cur_topic['subject']))).'">'.forum_htmlencode($cur_topic['subject']).'</a>';
1635
1636			($hook = get_hook('mr_topic_loop_normal_topic_pre_item_title_merge')) ? eval($hook) : null;
1637
1638			$forum_page['item_body']['subject']['title'] = '<h3 class="hn"><span class="item-num">'.forum_number_format($forum_page['start_from'] + $forum_page['item_count']).'</span> '.implode(' ', $forum_page['item_title']).'</h3>';
1639
1640
1641			if (empty($forum_page['item_status']))
1642				$forum_page['item_status']['normal'] = 'normal';
1643
1644			$forum_page['item_pages'] = ceil(($cur_topic['num_replies'] + 1) / $forum_user['disp_posts']);
1645
1646			if ($forum_page['item_pages'] > 1)
1647				$forum_page['item_nav']['pages'] = '<span>'.$lang_forum['Pages'].'&#160;</span>'.paginate($forum_page['item_pages'], -1, $forum_url['topic'], $lang_common['Page separator'], array($cur_topic['id'], sef_friendly($cur_topic['subject'])));
1648
1649			// Does this topic contain posts we haven't read? If so, tag it accordingly.
1650			if (!$forum_user['is_guest'] && $cur_topic['last_post'] > $forum_user['last_visit'] && (!isset($tracked_topics['topics'][$cur_topic['id']]) || $tracked_topics['topics'][$cur_topic['id']] < $cur_topic['last_post']) && (!isset($tracked_topics['forums'][$fid]) || $tracked_topics['forums'][$fid] < $cur_topic['last_post']))
1651			{
1652				$forum_page['item_nav']['new'] = '<em class="item-newposts"><a href="'.forum_link($forum_url['topic_new_posts'], array($cur_topic['id'], sef_friendly($cur_topic['subject']))).'">'.$lang_forum['New posts'].'</a></em>';
1653				$forum_page['item_status']['new'] = 'new';
1654			}
1655
1656			($hook = get_hook('mr_topic_loop_normal_topic_pre_item_nav_merge')) ? eval($hook) : null;
1657
1658			if (!empty($forum_page['item_nav']))
1659				$forum_page['item_subject']['nav'] = '<span class="item-nav">'.sprintf($lang_forum['Topic navigation'], implode('&#160;&#160;', $forum_page['item_nav'])).'</span>';
1660
1661			// Assemble the Topic subject
1662
1663			$forum_page['item_body']['info']['replies'] = '<li class="info-replies"><strong>'.forum_number_format($cur_topic['num_replies']).'</strong> <span class="label">'.(($cur_topic['num_replies'] == 1) ? $lang_forum['Reply'] : $lang_forum['Replies']).'</span></li>';
1664
1665			if ($forum_config['o_topic_views'] == '1')
1666				$forum_page['item_body']['info']['views'] = '<li class="info-views"><strong>'.forum_number_format($cur_topic['num_views']).'</strong> <span class="label">'.(($cur_topic['num_views'] == 1) ? $lang_forum['View'] : $lang_forum['Views']).'</span></li>';
1667
1668			$forum_page['item_body']['info']['lastpost'] = '<li class="info-lastpost"><span class="label">'.$lang_forum['Last post'].'</span> <strong><a href="'.forum_link($forum_url['post'], $cur_topic['last_post_id']).'">'.format_time($cur_topic['last_post']).'</a></strong> <cite>'.sprintf($lang_forum['by poster'], forum_htmlencode($cur_topic['last_poster'])).'</cite></li>';
1669			$forum_page['item_body']['info']['select'] = '<li class="info-select"><input id="fld'.++$forum_page['fld_count'].'" type="checkbox" name="topics[]" value="'.$cur_topic['id'].'" /> <label for="fld'.$forum_page['fld_count'].'">'.sprintf($lang_forum['Select topic'], forum_htmlencode($cur_topic['subject'])).'</label></li>';
1670
1671			($hook = get_hook('mr_topic_actions_normal_row_pre_output')) ? eval($hook) : null;
1672		}
1673
1674		$forum_page['item_body']['subject']['desc'] = '<p>'.implode(' ', $forum_page['item_subject']).'</p>';
1675
1676		($hook = get_hook('mr_topic_actions_row_pre_item_status_merge')) ? eval($hook) : null;
1677
1678		$forum_page['item_style'] = (($forum_page['item_count'] % 2 != 0) ? ' odd' : ' even').(($forum_page['item_count'] == 1) ? ' main-first-item' : '').((!empty($forum_page['item_status'])) ? ' '.implode(' ', $forum_page['item_status']) : '');
1679
1680		($hook = get_hook('mr_topic_actions_row_pre_display')) ? eval($hook) : null;
1681
1682?>
1683			<div id="topic<?php echo $cur_topic['id'] ?>" class="main-item<?php echo $forum_page['item_style'] ?>">
1684				<span class="icon <?php echo implode(' ', $forum_page['item_status']) ?>"><!-- --></span>
1685				<div class="item-subject">
1686					<?php echo implode("\n\t\t\t\t\t", $forum_page['item_body']['subject'])."\n" ?>
1687				</div>
1688				<ul class="item-info">
1689					<?php echo implode("\n\t\t\t\t\t", $forum_page['item_body']['info'])."\n" ?>
1690				</ul>
1691			</div>
1692<?php
1693
1694	}
1695
1696?>
1697	</div>
1698<?php
1699
1700	($hook = get_hook('mr_topic_actions_post_topic_list')) ? eval($hook) : null;
1701
1702	// Setup moderator control buttons
1703	$forum_page['mod_options'] = array(
1704		'mod_move'		=> '<span class="submit first-item"><input type="submit" name="move_topics" value="'.$lang_misc['Move'].'" /></span>',
1705		'mod_delete'	=> '<span class="submit"><input type="submit" name="delete_topics" value="'.$lang_common['Delete'].'" /></span>',
1706		'mod_merge'		=> '<span class="submit"><input type="submit" name="merge_topics" value="'.$lang_misc['Merge'].'" /></span>',
1707		'mod_open'		=> '<span class="submit"><input type="submit" name="open" value="'.$lang_misc['Open'].'" /></span>',
1708		'mod_close'		=> '<span class="submit"><input type="submit" name="close" value="'.$lang_misc['Close'].'" /></span>'
1709	);
1710
1711	($hook = get_hook('mr_topic_actions_pre_mod_option_output')) ? eval($hook) : null;
1712
1713?>
1714	<div class="main-options mod-options gen-content">
1715		<p class="options"><?php echo implode(' ', $forum_page['mod_options']) ?></p>
1716	</div>
1717	</form>
1718	<div class="main-foot">
1719<?php
1720
1721	if (!empty($forum_page['main_foot_options']))
1722		echo "\n\t\t".'<p class="options">'.implode(' ', $forum_page['main_foot_options']).'</p>';
1723
1724?>
1725		<h2 class="hn"><span><?php echo $forum_page['items_info'] ?></span></h2>
1726	</div>
1727
1728<?php
1729
1730$forum_id = $fid;
1731
1732// Init JS helper for select-all
1733$forum_loader->add_js('PUNBB.common.addDOMReadyEvent(PUNBB.common.initToggleCheckboxes);', array('type' => 'inline'));
1734
1735($hook = get_hook('mr_end')) ? eval($hook) : null;
1736
1737$tpl_temp = forum_trim(ob_get_contents());
1738$tpl_main = str_replace('<!-- forum_main -->', $tpl_temp, $tpl_main);
1739ob_end_clean();
1740// END SUBST - <!-- forum_main -->
1741
1742require FORUM_ROOT.'footer.php';
1743