PageRenderTime 349ms CodeModel.GetById 161ms app.highlight 91ms RepoModel.GetById 60ms app.codeStats 2ms

/php/Sources/Post.php

https://github.com/dekoza/openshift-smf-2.0.7
PHP | 2894 lines | 2160 code | 381 blank | 353 comment | 656 complexity | 44f251ac3da3176cfb7752a5429b6936 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2
   3/**
   4 * Simple Machines Forum (SMF)
   5 *
   6 * @package SMF
   7 * @author Simple Machines http://www.simplemachines.org
   8 * @copyright 2011 Simple Machines
   9 * @license http://www.simplemachines.org/about/smf/license.php BSD
  10 *
  11 * @version 2.0.7
  12 */
  13
  14if (!defined('SMF'))
  15	die('Hacking attempt...');
  16
  17/*	The job of this file is to handle everything related to posting replies,
  18	new topics, quotes, and modifications to existing posts.  It also handles
  19	quoting posts by way of javascript.
  20
  21	void Post()
  22		- handles showing the post screen, loading the post to be modified, and
  23		  loading any post quoted.
  24		- additionally handles previews of posts.
  25		- uses the Post template and language file, main sub template.
  26		- allows wireless access using the protocol_post sub template.
  27		- requires different permissions depending on the actions, but most
  28		  notably post_new, post_reply_own, and post_reply_any.
  29		- shows options for the editing and posting of calendar events and
  30		  attachments, as well as the posting of polls.
  31		- accessed from ?action=post.
  32
  33	void Post2()
  34		- actually posts or saves the message composed with Post().
  35		- requires various permissions depending on the action.
  36		- handles attachment, post, and calendar saving.
  37		- sends off notifications, and allows for announcements and moderation.
  38		- accessed from ?action=post2.
  39
  40	void AnnounceTopic()
  41		- handle the announce topic function (action=announce).
  42		- checks the topic announcement permissions and loads the announcement
  43		  template.
  44		- requires the announce_topic permission.
  45		- uses the ManageMembers template and Post language file.
  46		- call the right function based on the sub-action.
  47
  48	void AnnouncementSelectMembergroup()
  49		- lets the user select the membergroups that will receive the topic
  50		  announcement.
  51
  52	void AnnouncementSend()
  53		- splits the members to be sent a topic announcement into chunks.
  54		- composes notification messages in all languages needed.
  55		- does the actual sending of the topic announcements in chunks.
  56		- calculates a rough estimate of the percentage items sent.
  57
  58	void notifyMembersBoard(notifyData)
  59		- notifies members who have requested notification for new topics
  60		  posted on a board of said posts.
  61		- receives data on the topics to send out notifications to by the passed in array.
  62		- only sends notifications to those who can *currently* see the topic
  63		  (it doesn't matter if they could when they requested notification.)
  64		- loads the Post language file multiple times for each language if the
  65		  userLanguage setting is set.
  66
  67	void getTopic()
  68		- gets a summary of the most recent posts in a topic.
  69		- depends on the topicSummaryPosts setting.
  70		- if you are editing a post, only shows posts previous to that post.
  71
  72	void QuoteFast()
  73		- loads a post an inserts it into the current editing text box.
  74		- uses the Post language file.
  75		- uses special (sadly browser dependent) javascript to parse entities
  76		  for internationalization reasons.
  77		- accessed with ?action=quotefast.
  78
  79	void JavaScriptModify()
  80		// !!!
  81*/
  82
  83function Post()
  84{
  85	global $txt, $scripturl, $topic, $modSettings, $board;
  86	global $user_info, $sc, $board_info, $context, $settings;
  87	global $sourcedir, $options, $smcFunc, $language;
  88
  89	loadLanguage('Post');
  90
  91	// You can't reply with a poll... hacker.
  92	if (isset($_REQUEST['poll']) && !empty($topic) && !isset($_REQUEST['msg']))
  93		unset($_REQUEST['poll']);
  94
  95	// Posting an event?
  96	$context['make_event'] = isset($_REQUEST['calendar']);
  97	$context['robot_no_index'] = true;
  98
  99	// You must be posting to *some* board.
 100	if (empty($board) && !$context['make_event'])
 101		fatal_lang_error('no_board', false);
 102
 103	require_once($sourcedir . '/Subs-Post.php');
 104
 105	if (isset($_REQUEST['xml']))
 106	{
 107		$context['sub_template'] = 'post';
 108
 109		// Just in case of an earlier error...
 110		$context['preview_message'] = '';
 111		$context['preview_subject'] = '';
 112	}
 113
 114	// No message is complete without a topic.
 115	if (empty($topic) && !empty($_REQUEST['msg']))
 116	{
 117		$request = $smcFunc['db_query']('', '
 118			SELECT id_topic
 119			FROM {db_prefix}messages
 120			WHERE id_msg = {int:msg}',
 121			array(
 122				'msg' => (int) $_REQUEST['msg'],
 123		));
 124		if ($smcFunc['db_num_rows']($request) != 1)
 125			unset($_REQUEST['msg'], $_POST['msg'], $_GET['msg']);
 126		else
 127			list ($topic) = $smcFunc['db_fetch_row']($request);
 128		$smcFunc['db_free_result']($request);
 129	}
 130
 131	// Check if it's locked.  It isn't locked if no topic is specified.
 132	if (!empty($topic))
 133	{
 134		$request = $smcFunc['db_query']('', '
 135			SELECT
 136				t.locked, IFNULL(ln.id_topic, 0) AS notify, t.is_sticky, t.id_poll, t.id_last_msg, mf.id_member,
 137				t.id_first_msg, mf.subject,
 138				CASE WHEN ml.poster_time > ml.modified_time THEN ml.poster_time ELSE ml.modified_time END AS last_post_time
 139			FROM {db_prefix}topics AS t
 140				LEFT JOIN {db_prefix}log_notify AS ln ON (ln.id_topic = t.id_topic AND ln.id_member = {int:current_member})
 141				LEFT JOIN {db_prefix}messages AS mf ON (mf.id_msg = t.id_first_msg)
 142				LEFT JOIN {db_prefix}messages AS ml ON (ml.id_msg = t.id_last_msg)
 143			WHERE t.id_topic = {int:current_topic}
 144			LIMIT 1',
 145			array(
 146				'current_member' => $user_info['id'],
 147				'current_topic' => $topic,
 148			)
 149		);
 150		list ($locked, $context['notify'], $sticky, $pollID, $context['topic_last_message'], $id_member_poster, $id_first_msg, $first_subject, $lastPostTime) = $smcFunc['db_fetch_row']($request);
 151		$smcFunc['db_free_result']($request);
 152
 153		// If this topic already has a poll, they sure can't add another.
 154		if (isset($_REQUEST['poll']) && $pollID > 0)
 155			unset($_REQUEST['poll']);
 156
 157		if (empty($_REQUEST['msg']))
 158		{
 159			if ($user_info['is_guest'] && !allowedTo('post_reply_any') && (!$modSettings['postmod_active'] || !allowedTo('post_unapproved_replies_any')))
 160				is_not_guest();
 161
 162			// By default the reply will be approved...
 163			$context['becomes_approved'] = true;
 164			if ($id_member_poster != $user_info['id'])
 165			{
 166				if ($modSettings['postmod_active'] && allowedTo('post_unapproved_replies_any') && !allowedTo('post_reply_any'))
 167					$context['becomes_approved'] = false;
 168				else
 169					isAllowedTo('post_reply_any');
 170			}
 171			elseif (!allowedTo('post_reply_any'))
 172			{
 173				if ($modSettings['postmod_active'] && allowedTo('post_unapproved_replies_own') && !allowedTo('post_reply_own'))
 174					$context['becomes_approved'] = false;
 175				else
 176					isAllowedTo('post_reply_own');
 177			}
 178		}
 179		else
 180			$context['becomes_approved'] = true;
 181
 182		$context['can_lock'] = allowedTo('lock_any') || ($user_info['id'] == $id_member_poster && allowedTo('lock_own'));
 183		$context['can_sticky'] = allowedTo('make_sticky') && !empty($modSettings['enableStickyTopics']);
 184
 185		$context['notify'] = !empty($context['notify']);
 186		$context['sticky'] = isset($_REQUEST['sticky']) ? !empty($_REQUEST['sticky']) : $sticky;
 187	}
 188	else
 189	{
 190		$context['becomes_approved'] = true;
 191		if ((!$context['make_event'] || !empty($board)))
 192		{
 193			if ($modSettings['postmod_active'] && !allowedTo('post_new') && allowedTo('post_unapproved_topics'))
 194				$context['becomes_approved'] = false;
 195			else
 196				isAllowedTo('post_new');
 197		}
 198
 199		$locked = 0;
 200		// !!! These won't work if you're making an event.
 201		$context['can_lock'] = allowedTo(array('lock_any', 'lock_own'));
 202		$context['can_sticky'] = allowedTo('make_sticky') && !empty($modSettings['enableStickyTopics']);
 203
 204		$context['notify'] = !empty($context['notify']);
 205		$context['sticky'] = !empty($_REQUEST['sticky']);
 206	}
 207
 208	// !!! These won't work if you're posting an event!
 209	$context['can_notify'] = allowedTo('mark_any_notify');
 210	$context['can_move'] = allowedTo('move_any');
 211	$context['move'] = !empty($_REQUEST['move']);
 212	$context['announce'] = !empty($_REQUEST['announce']);
 213	// You can only announce topics that will get approved...
 214	$context['can_announce'] = allowedTo('announce_topic') && $context['becomes_approved'];
 215	$context['locked'] = !empty($locked) || !empty($_REQUEST['lock']);
 216	$context['can_quote'] = empty($modSettings['disabledBBC']) || !in_array('quote', explode(',', $modSettings['disabledBBC']));
 217
 218	// Generally don't show the approval box... (Assume we want things approved)
 219	$context['show_approval'] = false;
 220
 221	// An array to hold all the attachments for this topic.
 222	$context['current_attachments'] = array();
 223
 224	// Don't allow a post if it's locked and you aren't all powerful.
 225	if ($locked && !allowedTo('moderate_board'))
 226		fatal_lang_error('topic_locked', false);
 227	// Check the users permissions - is the user allowed to add or post a poll?
 228	if (isset($_REQUEST['poll']) && $modSettings['pollMode'] == '1')
 229	{
 230		// New topic, new poll.
 231		if (empty($topic))
 232			isAllowedTo('poll_post');
 233		// This is an old topic - but it is yours!  Can you add to it?
 234		elseif ($user_info['id'] == $id_member_poster && !allowedTo('poll_add_any'))
 235			isAllowedTo('poll_add_own');
 236		// If you're not the owner, can you add to any poll?
 237		else
 238			isAllowedTo('poll_add_any');
 239
 240		require_once($sourcedir . '/Subs-Members.php');
 241		$allowedVoteGroups = groupsAllowedTo('poll_vote', $board);
 242
 243		// Set up the poll options.
 244		$context['poll_options'] = array(
 245			'max_votes' => empty($_POST['poll_max_votes']) ? '1' : max(1, $_POST['poll_max_votes']),
 246			'hide' => empty($_POST['poll_hide']) ? 0 : $_POST['poll_hide'],
 247			'expire' => !isset($_POST['poll_expire']) ? '' : $_POST['poll_expire'],
 248			'change_vote' => isset($_POST['poll_change_vote']),
 249			'guest_vote' => isset($_POST['poll_guest_vote']),
 250			'guest_vote_enabled' => in_array(-1, $allowedVoteGroups['allowed']),
 251		);
 252
 253		// Make all five poll choices empty.
 254		$context['choices'] = array(
 255			array('id' => 0, 'number' => 1, 'label' => '', 'is_last' => false),
 256			array('id' => 1, 'number' => 2, 'label' => '', 'is_last' => false),
 257			array('id' => 2, 'number' => 3, 'label' => '', 'is_last' => false),
 258			array('id' => 3, 'number' => 4, 'label' => '', 'is_last' => false),
 259			array('id' => 4, 'number' => 5, 'label' => '', 'is_last' => true)
 260		);
 261	}
 262
 263	if ($context['make_event'])
 264	{
 265		// They might want to pick a board.
 266		if (!isset($context['current_board']))
 267			$context['current_board'] = 0;
 268
 269		// Start loading up the event info.
 270		$context['event'] = array();
 271		$context['event']['title'] = isset($_REQUEST['evtitle']) ? htmlspecialchars(stripslashes($_REQUEST['evtitle'])) : '';
 272
 273		$context['event']['id'] = isset($_REQUEST['eventid']) ? (int) $_REQUEST['eventid'] : -1;
 274		$context['event']['new'] = $context['event']['id'] == -1;
 275
 276		// Permissions check!
 277		isAllowedTo('calendar_post');
 278
 279		// Editing an event?  (but NOT previewing!?)
 280		if (!$context['event']['new'] && !isset($_REQUEST['subject']))
 281		{
 282			// If the user doesn't have permission to edit the post in this topic, redirect them.
 283			if ((empty($id_member_poster) || $id_member_poster != $user_info['id'] || !allowedTo('modify_own')) && !allowedTo('modify_any'))
 284			{
 285				require_once($sourcedir . '/Calendar.php');
 286				return CalendarPost();
 287			}
 288
 289			// Get the current event information.
 290			$request = $smcFunc['db_query']('', '
 291				SELECT
 292					id_member, title, MONTH(start_date) AS month, DAYOFMONTH(start_date) AS day,
 293					YEAR(start_date) AS year, (TO_DAYS(end_date) - TO_DAYS(start_date)) AS span
 294				FROM {db_prefix}calendar
 295				WHERE id_event = {int:id_event}
 296				LIMIT 1',
 297				array(
 298					'id_event' => $context['event']['id'],
 299				)
 300			);
 301			$row = $smcFunc['db_fetch_assoc']($request);
 302			$smcFunc['db_free_result']($request);
 303
 304			// Make sure the user is allowed to edit this event.
 305			if ($row['id_member'] != $user_info['id'])
 306				isAllowedTo('calendar_edit_any');
 307			elseif (!allowedTo('calendar_edit_any'))
 308				isAllowedTo('calendar_edit_own');
 309
 310			$context['event']['month'] = $row['month'];
 311			$context['event']['day'] = $row['day'];
 312			$context['event']['year'] = $row['year'];
 313			$context['event']['title'] = $row['title'];
 314			$context['event']['span'] = $row['span'] + 1;
 315		}
 316		else
 317		{
 318			$today = getdate();
 319
 320			// You must have a month and year specified!
 321			if (!isset($_REQUEST['month']))
 322				$_REQUEST['month'] = $today['mon'];
 323			if (!isset($_REQUEST['year']))
 324				$_REQUEST['year'] = $today['year'];
 325
 326			$context['event']['month'] = (int) $_REQUEST['month'];
 327			$context['event']['year'] = (int) $_REQUEST['year'];
 328			$context['event']['day'] = isset($_REQUEST['day']) ? $_REQUEST['day'] : ($_REQUEST['month'] == $today['mon'] ? $today['mday'] : 0);
 329			$context['event']['span'] = isset($_REQUEST['span']) ? $_REQUEST['span'] : 1;
 330
 331			// Make sure the year and month are in the valid range.
 332			if ($context['event']['month'] < 1 || $context['event']['month'] > 12)
 333				fatal_lang_error('invalid_month', false);
 334			if ($context['event']['year'] < $modSettings['cal_minyear'] || $context['event']['year'] > $modSettings['cal_maxyear'])
 335				fatal_lang_error('invalid_year', false);
 336
 337			// Get a list of boards they can post in.
 338			$boards = boardsAllowedTo('post_new');
 339			if (empty($boards))
 340				fatal_lang_error('cannot_post_new', 'user');
 341
 342			// Load a list of boards for this event in the context.
 343			require_once($sourcedir . '/Subs-MessageIndex.php');
 344			$boardListOptions = array(
 345				'included_boards' => in_array(0, $boards) ? null : $boards,
 346				'not_redirection' => true,
 347				'use_permissions' => true,
 348				'selected_board' => empty($context['current_board']) ? $modSettings['cal_defaultboard'] : $context['current_board'],
 349			);
 350			$context['event']['categories'] = getBoardList($boardListOptions);
 351		}
 352
 353		// Find the last day of the month.
 354		$context['event']['last_day'] = (int) strftime('%d', mktime(0, 0, 0, $context['event']['month'] == 12 ? 1 : $context['event']['month'] + 1, 0, $context['event']['month'] == 12 ? $context['event']['year'] + 1 : $context['event']['year']));
 355
 356		$context['event']['board'] = !empty($board) ? $board : $modSettings['cal_defaultboard'];
 357	}
 358
 359	if (empty($context['post_errors']))
 360		$context['post_errors'] = array();
 361
 362	// See if any new replies have come along.
 363	if (empty($_REQUEST['msg']) && !empty($topic))
 364	{
 365		if (empty($options['no_new_reply_warning']) && isset($_REQUEST['last_msg']) && $context['topic_last_message'] > $_REQUEST['last_msg'])
 366		{
 367			$request = $smcFunc['db_query']('', '
 368				SELECT COUNT(*)
 369				FROM {db_prefix}messages
 370				WHERE id_topic = {int:current_topic}
 371					AND id_msg > {int:last_msg}' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : '
 372					AND approved = {int:approved}') . '
 373				LIMIT 1',
 374				array(
 375					'current_topic' => $topic,
 376					'last_msg' => (int) $_REQUEST['last_msg'],
 377					'approved' => 1,
 378				)
 379			);
 380			list ($context['new_replies']) = $smcFunc['db_fetch_row']($request);
 381			$smcFunc['db_free_result']($request);
 382
 383			if (!empty($context['new_replies']))
 384			{
 385				if ($context['new_replies'] == 1)
 386					$txt['error_new_reply'] = isset($_GET['last_msg']) ? $txt['error_new_reply_reading'] : $txt['error_new_reply'];
 387				else
 388					$txt['error_new_replies'] = sprintf(isset($_GET['last_msg']) ? $txt['error_new_replies_reading'] : $txt['error_new_replies'], $context['new_replies']);
 389
 390				// If they've come from the display page then we treat the error differently....
 391				if (isset($_GET['last_msg']))
 392					$newRepliesError = $context['new_replies'];
 393				else
 394					$context['post_error'][$context['new_replies'] == 1 ? 'new_reply' : 'new_replies'] = true;
 395
 396				$modSettings['topicSummaryPosts'] = $context['new_replies'] > $modSettings['topicSummaryPosts'] ? max($modSettings['topicSummaryPosts'], 5) : $modSettings['topicSummaryPosts'];
 397			}
 398		}
 399		// Check whether this is a really old post being bumped...
 400		if (!empty($modSettings['oldTopicDays']) && $lastPostTime + $modSettings['oldTopicDays'] * 86400 < time() && empty($sticky) && !isset($_REQUEST['subject']))
 401			$oldTopicError = true;
 402	}
 403
 404	// Get a response prefix (like 'Re:') in the default forum language.
 405	if (!isset($context['response_prefix']) && !($context['response_prefix'] = cache_get_data('response_prefix')))
 406	{
 407		if ($language === $user_info['language'])
 408			$context['response_prefix'] = $txt['response_prefix'];
 409		else
 410		{
 411			loadLanguage('index', $language, false);
 412			$context['response_prefix'] = $txt['response_prefix'];
 413			loadLanguage('index');
 414		}
 415		cache_put_data('response_prefix', $context['response_prefix'], 600);
 416	}
 417
 418	// Previewing, modifying, or posting?
 419	if (isset($_REQUEST['message']) || !empty($context['post_error']))
 420	{
 421		// Validate inputs.
 422		if (empty($context['post_error']))
 423		{
 424			if (htmltrim__recursive(htmlspecialchars__recursive($_REQUEST['subject'])) == '')
 425				$context['post_error']['no_subject'] = true;
 426			if (htmltrim__recursive(htmlspecialchars__recursive($_REQUEST['message'])) == '')
 427				$context['post_error']['no_message'] = true;
 428			if (!empty($modSettings['max_messageLength']) && $smcFunc['strlen']($_REQUEST['message']) > $modSettings['max_messageLength'])
 429				$context['post_error']['long_message'] = true;
 430
 431			// Are you... a guest?
 432			if ($user_info['is_guest'])
 433			{
 434				$_REQUEST['guestname'] = !isset($_REQUEST['guestname']) ? '' : trim($_REQUEST['guestname']);
 435				$_REQUEST['email'] = !isset($_REQUEST['email']) ? '' : trim($_REQUEST['email']);
 436
 437				// Validate the name and email.
 438				if (!isset($_REQUEST['guestname']) || trim(strtr($_REQUEST['guestname'], '_', ' ')) == '')
 439					$context['post_error']['no_name'] = true;
 440				elseif ($smcFunc['strlen']($_REQUEST['guestname']) > 25)
 441					$context['post_error']['long_name'] = true;
 442				else
 443				{
 444					require_once($sourcedir . '/Subs-Members.php');
 445					if (isReservedName(htmlspecialchars($_REQUEST['guestname']), 0, true, false))
 446						$context['post_error']['bad_name'] = true;
 447				}
 448
 449				if (empty($modSettings['guest_post_no_email']))
 450				{
 451					if (!isset($_REQUEST['email']) || $_REQUEST['email'] == '')
 452						$context['post_error']['no_email'] = true;
 453					elseif (preg_match('~^[0-9A-Za-z=_+\-/][0-9A-Za-z=_\'+\-/\.]*@[\w\-]+(\.[\w\-]+)*(\.[\w]{2,6})$~', $_REQUEST['email']) == 0)
 454						$context['post_error']['bad_email'] = true;
 455				}
 456			}
 457
 458			// This is self explanatory - got any questions?
 459			if (isset($_REQUEST['question']) && trim($_REQUEST['question']) == '')
 460				$context['post_error']['no_question'] = true;
 461
 462			// This means they didn't click Post and get an error.
 463			$really_previewing = true;
 464		}
 465		else
 466		{
 467			if (!isset($_REQUEST['subject']))
 468				$_REQUEST['subject'] = '';
 469			if (!isset($_REQUEST['message']))
 470				$_REQUEST['message'] = '';
 471			if (!isset($_REQUEST['icon']))
 472				$_REQUEST['icon'] = 'xx';
 473
 474			// They are previewing if they asked to preview (i.e. came from quick reply).
 475			$really_previewing = !empty($_POST['preview']);
 476		}
 477
 478		// In order to keep the approval status flowing through, we have to pass it through the form...
 479		$context['becomes_approved'] = empty($_REQUEST['not_approved']);
 480		$context['show_approval'] = isset($_REQUEST['approve']) ? ($_REQUEST['approve'] ? 2 : 1) : 0;
 481		$context['can_announce'] &= $context['becomes_approved'];
 482
 483		// Set up the inputs for the form.
 484		$form_subject = strtr($smcFunc['htmlspecialchars']($_REQUEST['subject']), array("\r" => '', "\n" => '', "\t" => ''));
 485		$form_message = $smcFunc['htmlspecialchars']($_REQUEST['message'], ENT_QUOTES);
 486
 487		// Make sure the subject isn't too long - taking into account special characters.
 488		if ($smcFunc['strlen']($form_subject) > 100)
 489			$form_subject = $smcFunc['substr']($form_subject, 0, 100);
 490
 491		// Have we inadvertently trimmed off the subject of useful information?
 492		if ($smcFunc['htmltrim']($form_subject) === '')
 493			$context['post_error']['no_subject'] = true;
 494
 495		// Any errors occurred?
 496		if (!empty($context['post_error']))
 497		{
 498			loadLanguage('Errors');
 499
 500			$context['error_type'] = 'minor';
 501
 502			$context['post_error']['messages'] = array();
 503			foreach ($context['post_error'] as $post_error => $dummy)
 504			{
 505				if ($post_error == 'messages')
 506					continue;
 507
 508				if ($post_error == 'long_message')
 509					$txt['error_' . $post_error] = sprintf($txt['error_' . $post_error], $modSettings['max_messageLength']);
 510
 511				$context['post_error']['messages'][] = $txt['error_' . $post_error];
 512
 513				// If it's not a minor error flag it as such.
 514				if (!in_array($post_error, array('new_reply', 'not_approved', 'new_replies', 'old_topic', 'need_qr_verification')))
 515					$context['error_type'] = 'serious';
 516			}
 517		}
 518
 519		if (isset($_REQUEST['poll']))
 520		{
 521			$context['question'] = isset($_REQUEST['question']) ? $smcFunc['htmlspecialchars'](trim($_REQUEST['question'])) : '';
 522
 523			$context['choices'] = array();
 524			$choice_id = 0;
 525
 526			$_POST['options'] = empty($_POST['options']) ? array() : htmlspecialchars__recursive($_POST['options']);
 527			foreach ($_POST['options'] as $option)
 528			{
 529				if (trim($option) == '')
 530					continue;
 531
 532				$context['choices'][] = array(
 533					'id' => $choice_id++,
 534					'number' => $choice_id,
 535					'label' => $option,
 536					'is_last' => false
 537				);
 538			}
 539
 540			if (count($context['choices']) < 2)
 541			{
 542				$context['choices'][] = array(
 543					'id' => $choice_id++,
 544					'number' => $choice_id,
 545					'label' => '',
 546					'is_last' => false
 547				);
 548				$context['choices'][] = array(
 549					'id' => $choice_id++,
 550					'number' => $choice_id,
 551					'label' => '',
 552					'is_last' => false
 553				);
 554			}
 555			$context['choices'][count($context['choices']) - 1]['is_last'] = true;
 556		}
 557
 558		// Are you... a guest?
 559		if ($user_info['is_guest'])
 560		{
 561			$_REQUEST['guestname'] = !isset($_REQUEST['guestname']) ? '' : trim($_REQUEST['guestname']);
 562			$_REQUEST['email'] = !isset($_REQUEST['email']) ? '' : trim($_REQUEST['email']);
 563
 564			$_REQUEST['guestname'] = htmlspecialchars($_REQUEST['guestname']);
 565			$context['name'] = $_REQUEST['guestname'];
 566			$_REQUEST['email'] = htmlspecialchars($_REQUEST['email']);
 567			$context['email'] = $_REQUEST['email'];
 568
 569			$user_info['name'] = $_REQUEST['guestname'];
 570		}
 571
 572		// Only show the preview stuff if they hit Preview.
 573		if ($really_previewing == true || isset($_REQUEST['xml']))
 574		{
 575			// Set up the preview message and subject and censor them...
 576			$context['preview_message'] = $form_message;
 577			preparsecode($form_message, true);
 578			preparsecode($context['preview_message']);
 579
 580			// Do all bulletin board code tags, with or without smileys.
 581			$context['preview_message'] = parse_bbc($context['preview_message'], isset($_REQUEST['ns']) ? 0 : 1);
 582
 583			if ($form_subject != '')
 584			{
 585				$context['preview_subject'] = $form_subject;
 586
 587				censorText($context['preview_subject']);
 588				censorText($context['preview_message']);
 589			}
 590			else
 591				$context['preview_subject'] = '<em>' . $txt['no_subject'] . '</em>';
 592
 593			// Protect any CDATA blocks.
 594			if (isset($_REQUEST['xml']))
 595				$context['preview_message'] = strtr($context['preview_message'], array(']]>' => ']]]]><![CDATA[>'));
 596		}
 597
 598		// Set up the checkboxes.
 599		$context['notify'] = !empty($_REQUEST['notify']);
 600		$context['use_smileys'] = !isset($_REQUEST['ns']);
 601
 602		$context['icon'] = isset($_REQUEST['icon']) ? preg_replace('~[\./\\\\*\':"<>]~', '', $_REQUEST['icon']) : 'xx';
 603
 604		// Set the destination action for submission.
 605		$context['destination'] = 'post2;start=' . $_REQUEST['start'] . (isset($_REQUEST['msg']) ? ';msg=' . $_REQUEST['msg'] . ';' . $context['session_var'] . '=' . $context['session_id'] : '') . (isset($_REQUEST['poll']) ? ';poll' : '');
 606		$context['submit_label'] = isset($_REQUEST['msg']) ? $txt['save'] : $txt['post'];
 607
 608		// Previewing an edit?
 609		if (isset($_REQUEST['msg']) && !empty($topic))
 610		{
 611			// Get the existing message.
 612			$request = $smcFunc['db_query']('', '
 613				SELECT
 614					m.id_member, m.modified_time, m.smileys_enabled, m.body,
 615					m.poster_name, m.poster_email, m.subject, m.icon, m.approved,
 616					IFNULL(a.size, -1) AS filesize, a.filename, a.id_attach,
 617					a.approved AS attachment_approved, t.id_member_started AS id_member_poster,
 618					m.poster_time
 619			FROM {db_prefix}messages AS m
 620					INNER JOIN {db_prefix}topics AS t ON (t.id_topic = {int:current_topic})
 621					LEFT JOIN {db_prefix}attachments AS a ON (a.id_msg = m.id_msg AND a.attachment_type = {int:attachment_type})
 622				WHERE m.id_msg = {int:id_msg}
 623					AND m.id_topic = {int:current_topic}',
 624				array(
 625					'current_topic' => $topic,
 626					'attachment_type' => 0,
 627					'id_msg' => $_REQUEST['msg'],
 628				)
 629			);
 630			// The message they were trying to edit was most likely deleted.
 631			// !!! Change this error message?
 632			if ($smcFunc['db_num_rows']($request) == 0)
 633				fatal_lang_error('no_board', false);
 634			$row = $smcFunc['db_fetch_assoc']($request);
 635
 636			$attachment_stuff = array($row);
 637			while ($row2 = $smcFunc['db_fetch_assoc']($request))
 638				$attachment_stuff[] = $row2;
 639			$smcFunc['db_free_result']($request);
 640
 641			if ($row['id_member'] == $user_info['id'] && !allowedTo('modify_any'))
 642			{
 643				// Give an extra five minutes over the disable time threshold, so they can type - assuming the post is public.
 644				if ($row['approved'] && !empty($modSettings['edit_disable_time']) && $row['poster_time'] + ($modSettings['edit_disable_time'] + 5) * 60 < time())
 645					fatal_lang_error('modify_post_time_passed', false);
 646				elseif ($row['id_member_poster'] == $user_info['id'] && !allowedTo('modify_own'))
 647					isAllowedTo('modify_replies');
 648				else
 649					isAllowedTo('modify_own');
 650			}
 651			elseif ($row['id_member_poster'] == $user_info['id'] && !allowedTo('modify_any'))
 652				isAllowedTo('modify_replies');
 653			else
 654				isAllowedTo('modify_any');
 655
 656			if (!empty($modSettings['attachmentEnable']))
 657			{
 658				$request = $smcFunc['db_query']('', '
 659					SELECT IFNULL(size, -1) AS filesize, filename, id_attach, approved
 660					FROM {db_prefix}attachments
 661					WHERE id_msg = {int:id_msg}
 662						AND attachment_type = {int:attachment_type}',
 663					array(
 664						'id_msg' => (int) $_REQUEST['msg'],
 665						'attachment_type' => 0,
 666					)
 667				);
 668				while ($row = $smcFunc['db_fetch_assoc']($request))
 669				{
 670					if ($row['filesize'] <= 0)
 671						continue;
 672					$context['current_attachments'][] = array(
 673						'name' => htmlspecialchars($row['filename']),
 674						'id' => $row['id_attach'],
 675						'approved' => $row['approved'],
 676					);
 677				}
 678				$smcFunc['db_free_result']($request);
 679			}
 680
 681			// Allow moderators to change names....
 682			if (allowedTo('moderate_forum') && !empty($topic))
 683			{
 684				$request = $smcFunc['db_query']('', '
 685					SELECT id_member, poster_name, poster_email
 686					FROM {db_prefix}messages
 687					WHERE id_msg = {int:id_msg}
 688						AND id_topic = {int:current_topic}
 689					LIMIT 1',
 690					array(
 691						'current_topic' => $topic,
 692						'id_msg' => (int) $_REQUEST['msg'],
 693					)
 694				);
 695				$row = $smcFunc['db_fetch_assoc']($request);
 696				$smcFunc['db_free_result']($request);
 697
 698				if (empty($row['id_member']))
 699				{
 700					$context['name'] = htmlspecialchars($row['poster_name']);
 701					$context['email'] = htmlspecialchars($row['poster_email']);
 702				}
 703			}
 704		}
 705
 706		// No check is needed, since nothing is really posted.
 707		checkSubmitOnce('free');
 708	}
 709	// Editing a message...
 710	elseif (isset($_REQUEST['msg']) && !empty($topic))
 711	{
 712		$_REQUEST['msg'] = (int) $_REQUEST['msg'];
 713
 714		// Get the existing message.
 715		$request = $smcFunc['db_query']('', '
 716			SELECT
 717				m.id_member, m.modified_time, m.smileys_enabled, m.body,
 718				m.poster_name, m.poster_email, m.subject, m.icon, m.approved,
 719				IFNULL(a.size, -1) AS filesize, a.filename, a.id_attach,
 720				a.approved AS attachment_approved, t.id_member_started AS id_member_poster,
 721				m.poster_time
 722			FROM {db_prefix}messages AS m
 723				INNER JOIN {db_prefix}topics AS t ON (t.id_topic = {int:current_topic})
 724				LEFT JOIN {db_prefix}attachments AS a ON (a.id_msg = m.id_msg AND a.attachment_type = {int:attachment_type})
 725			WHERE m.id_msg = {int:id_msg}
 726				AND m.id_topic = {int:current_topic}',
 727			array(
 728				'current_topic' => $topic,
 729				'attachment_type' => 0,
 730				'id_msg' => $_REQUEST['msg'],
 731			)
 732		);
 733		// The message they were trying to edit was most likely deleted.
 734		// !!! Change this error message?
 735		if ($smcFunc['db_num_rows']($request) == 0)
 736			fatal_lang_error('no_board', false);
 737		$row = $smcFunc['db_fetch_assoc']($request);
 738
 739		$attachment_stuff = array($row);
 740		while ($row2 = $smcFunc['db_fetch_assoc']($request))
 741			$attachment_stuff[] = $row2;
 742		$smcFunc['db_free_result']($request);
 743
 744		if ($row['id_member'] == $user_info['id'] && !allowedTo('modify_any'))
 745		{
 746			// Give an extra five minutes over the disable time threshold, so they can type - assuming the post is public.
 747			if ($row['approved'] && !empty($modSettings['edit_disable_time']) && $row['poster_time'] + ($modSettings['edit_disable_time'] + 5) * 60 < time())
 748				fatal_lang_error('modify_post_time_passed', false);
 749			elseif ($row['id_member_poster'] == $user_info['id'] && !allowedTo('modify_own'))
 750				isAllowedTo('modify_replies');
 751			else
 752				isAllowedTo('modify_own');
 753		}
 754		elseif ($row['id_member_poster'] == $user_info['id'] && !allowedTo('modify_any'))
 755			isAllowedTo('modify_replies');
 756		else
 757			isAllowedTo('modify_any');
 758
 759		// When was it last modified?
 760		if (!empty($row['modified_time']))
 761			$context['last_modified'] = timeformat($row['modified_time']);
 762
 763		// Get the stuff ready for the form.
 764		$form_subject = $row['subject'];
 765		$form_message = un_preparsecode($row['body']);
 766		censorText($form_message);
 767		censorText($form_subject);
 768
 769		// Check the boxes that should be checked.
 770		$context['use_smileys'] = !empty($row['smileys_enabled']);
 771		$context['icon'] = $row['icon'];
 772
 773		// Show an "approve" box if the user can approve it, and the message isn't approved.
 774		if (!$row['approved'] && !$context['show_approval'])
 775			$context['show_approval'] = allowedTo('approve_posts');
 776
 777		// Load up 'em attachments!
 778		foreach ($attachment_stuff as $attachment)
 779		{
 780			if ($attachment['filesize'] >= 0 && !empty($modSettings['attachmentEnable']))
 781				$context['current_attachments'][] = array(
 782					'name' => htmlspecialchars($attachment['filename']),
 783					'id' => $attachment['id_attach'],
 784					'approved' => $attachment['attachment_approved'],
 785				);
 786		}
 787
 788		// Allow moderators to change names....
 789		if (allowedTo('moderate_forum') && empty($row['id_member']))
 790		{
 791			$context['name'] = htmlspecialchars($row['poster_name']);
 792			$context['email'] = htmlspecialchars($row['poster_email']);
 793		}
 794
 795		// Set the destinaton.
 796		$context['destination'] = 'post2;start=' . $_REQUEST['start'] . ';msg=' . $_REQUEST['msg'] . ';' . $context['session_var'] . '=' . $context['session_id'] . (isset($_REQUEST['poll']) ? ';poll' : '');
 797		$context['submit_label'] = $txt['save'];
 798	}
 799	// Posting...
 800	else
 801	{
 802		// By default....
 803		$context['use_smileys'] = true;
 804		$context['icon'] = 'xx';
 805
 806		if ($user_info['is_guest'])
 807		{
 808			$context['name'] = isset($_SESSION['guest_name']) ? $_SESSION['guest_name'] : '';
 809			$context['email'] = isset($_SESSION['guest_email']) ? $_SESSION['guest_email'] : '';
 810		}
 811		$context['destination'] = 'post2;start=' . $_REQUEST['start'] . (isset($_REQUEST['poll']) ? ';poll' : '');
 812
 813		$context['submit_label'] = $txt['post'];
 814
 815		// Posting a quoted reply?
 816		if (!empty($topic) && !empty($_REQUEST['quote']))
 817		{
 818			// Make sure they _can_ quote this post, and if so get it.
 819			$request = $smcFunc['db_query']('', '
 820				SELECT m.subject, IFNULL(mem.real_name, m.poster_name) AS poster_name, m.poster_time, m.body
 821				FROM {db_prefix}messages AS m
 822					INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board AND {query_see_board})
 823					LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)
 824				WHERE m.id_msg = {int:id_msg}' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : '
 825					AND m.approved = {int:is_approved}') . '
 826				LIMIT 1',
 827				array(
 828					'id_msg' => (int) $_REQUEST['quote'],
 829					'is_approved' => 1,
 830				)
 831			);
 832			if ($smcFunc['db_num_rows']($request) == 0)
 833				fatal_lang_error('quoted_post_deleted', false);
 834			list ($form_subject, $mname, $mdate, $form_message) = $smcFunc['db_fetch_row']($request);
 835			$smcFunc['db_free_result']($request);
 836
 837			// Add 'Re: ' to the front of the quoted subject.
 838			if (trim($context['response_prefix']) != '' && $smcFunc['strpos']($form_subject, trim($context['response_prefix'])) !== 0)
 839				$form_subject = $context['response_prefix'] . $form_subject;
 840
 841			// Censor the message and subject.
 842			censorText($form_message);
 843			censorText($form_subject);
 844
 845			// But if it's in HTML world, turn them into htmlspecialchar's so they can be edited!
 846			if (strpos($form_message, '[html]') !== false)
 847			{
 848				$parts = preg_split('~(\[/code\]|\[code(?:=[^\]]+)?\])~i', $form_message, -1, PREG_SPLIT_DELIM_CAPTURE);
 849				for ($i = 0, $n = count($parts); $i < $n; $i++)
 850				{
 851					// It goes 0 = outside, 1 = begin tag, 2 = inside, 3 = close tag, repeat.
 852					if ($i % 4 == 0)
 853						$parts[$i] = preg_replace_callback('~\[html\](.+?)\[/html\]~is', create_function('$m', ' return \'[html]\' . preg_replace(\'~<br\s?/?' . '>~i\', \'&lt;br /&gt;<br />\', "$m[1]") . \'[/html]\';'), $parts[$i]);
 854				}
 855				$form_message = implode('', $parts);
 856			}
 857
 858			$form_message = preg_replace('~<br ?/?' . '>~i', "\n", $form_message);
 859
 860			// Remove any nested quotes, if necessary.
 861			if (!empty($modSettings['removeNestedQuotes']))
 862				$form_message = preg_replace(array('~\n?\[quote.*?\].+?\[/quote\]\n?~is', '~^\n~', '~\[/quote\]~'), '', $form_message);
 863
 864			// Add a quote string on the front and end.
 865			$form_message = '[quote author=' . $mname . ' link=topic=' . $topic . '.msg' . (int) $_REQUEST['quote'] . '#msg' . (int) $_REQUEST['quote'] . ' date=' . $mdate . ']' . "\n" . rtrim($form_message) . "\n" . '[/quote]';
 866		}
 867		// Posting a reply without a quote?
 868		elseif (!empty($topic) && empty($_REQUEST['quote']))
 869		{
 870			// Get the first message's subject.
 871			$form_subject = $first_subject;
 872
 873			// Add 'Re: ' to the front of the subject.
 874			if (trim($context['response_prefix']) != '' && $form_subject != '' && $smcFunc['strpos']($form_subject, trim($context['response_prefix'])) !== 0)
 875				$form_subject = $context['response_prefix'] . $form_subject;
 876
 877			// Censor the subject.
 878			censorText($form_subject);
 879
 880			$form_message = '';
 881		}
 882		else
 883		{
 884			$form_subject = isset($_GET['subject']) ? $_GET['subject'] : '';
 885			$form_message = '';
 886		}
 887	}
 888
 889	// !!! This won't work if you're posting an event.
 890	if (allowedTo('post_attachment') || allowedTo('post_unapproved_attachments'))
 891	{
 892		if (empty($_SESSION['temp_attachments']))
 893			$_SESSION['temp_attachments'] = array();
 894
 895		if (!empty($modSettings['currentAttachmentUploadDir']))
 896		{
 897			if (!is_array($modSettings['attachmentUploadDir']))
 898				$modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']);
 899
 900			// Just use the current path for temp files.
 901			$current_attach_dir = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']];
 902		}
 903		else
 904			$current_attach_dir = $modSettings['attachmentUploadDir'];
 905
 906		// If this isn't a new post, check the current attachments.
 907		if (isset($_REQUEST['msg']))
 908		{
 909			$request = $smcFunc['db_query']('', '
 910				SELECT COUNT(*), SUM(size)
 911				FROM {db_prefix}attachments
 912				WHERE id_msg = {int:id_msg}
 913					AND attachment_type = {int:attachment_type}',
 914				array(
 915					'id_msg' => (int) $_REQUEST['msg'],
 916					'attachment_type' => 0,
 917				)
 918			);
 919			list ($quantity, $total_size) = $smcFunc['db_fetch_row']($request);
 920			$smcFunc['db_free_result']($request);
 921		}
 922		else
 923		{
 924			$quantity = 0;
 925			$total_size = 0;
 926		}
 927
 928		$temp_start = 0;
 929
 930		if (!empty($_SESSION['temp_attachments']))
 931		{
 932			if ($context['current_action'] != 'post2' || !empty($_POST['from_qr']))
 933			{
 934				$context['post_error']['messages'][] = $txt['error_temp_attachments'];
 935				$context['error_type'] = 'minor';
 936			}
 937
 938			foreach ($_SESSION['temp_attachments'] as $attachID => $name)
 939			{
 940				$temp_start++;
 941
 942				if (preg_match('~^post_tmp_' . $user_info['id'] . '_\d+$~', $attachID) == 0)
 943				{
 944					unset($_SESSION['temp_attachments'][$attachID]);
 945					continue;
 946				}
 947
 948				if (!empty($_POST['attach_del']) && !in_array($attachID, $_POST['attach_del']))
 949				{
 950					$deleted_attachments = true;
 951					unset($_SESSION['temp_attachments'][$attachID]);
 952					@unlink($current_attach_dir . '/' . $attachID);
 953					continue;
 954				}
 955
 956				$quantity++;
 957				$total_size += filesize($current_attach_dir . '/' . $attachID);
 958
 959				$context['current_attachments'][] = array(
 960					'name' => htmlspecialchars($name),
 961					'id' => $attachID,
 962					'approved' => 1,
 963				);
 964			}
 965		}
 966
 967		if (!empty($_POST['attach_del']))
 968		{
 969			$del_temp = array();
 970			foreach ($_POST['attach_del'] as $i => $dummy)
 971				$del_temp[$i] = (int) $dummy;
 972
 973			foreach ($context['current_attachments'] as $k => $dummy)
 974				if (!in_array($dummy['id'], $del_temp))
 975				{
 976					$context['current_attachments'][$k]['unchecked'] = true;
 977					$deleted_attachments = !isset($deleted_attachments) || is_bool($deleted_attachments) ? 1 : $deleted_attachments + 1;
 978					$quantity--;
 979				}
 980		}
 981
 982		if (!empty($_FILES['attachment']))
 983			foreach ($_FILES['attachment']['tmp_name'] as $n => $dummy)
 984			{
 985				if ($_FILES['attachment']['name'][$n] == '')
 986					continue;
 987
 988				if (!is_uploaded_file($_FILES['attachment']['tmp_name'][$n]) || (@ini_get('open_basedir') == '' && !file_exists($_FILES['attachment']['tmp_name'][$n])))
 989					fatal_lang_error('attach_timeout', 'critical');
 990
 991				if (!empty($modSettings['attachmentSizeLimit']) && $_FILES['attachment']['size'][$n] > $modSettings['attachmentSizeLimit'] * 1024)
 992					fatal_lang_error('file_too_big', false, array($modSettings['attachmentSizeLimit']));
 993
 994				$quantity++;
 995				if (!empty($modSettings['attachmentNumPerPostLimit']) && $quantity > $modSettings['attachmentNumPerPostLimit'])
 996					fatal_lang_error('attachments_limit_per_post', false, array($modSettings['attachmentNumPerPostLimit']));
 997
 998				$total_size += $_FILES['attachment']['size'][$n];
 999				if (!empty($modSettings['attachmentPostLimit']) && $total_size > $modSettings['attachmentPostLimit'] * 1024)
1000					fatal_lang_error('file_too_big', false, array($modSettings['attachmentPostLimit']));
1001
1002				if (!empty($modSettings['attachmentCheckExtensions']))
1003				{
1004					if (!in_array(strtolower(substr(strrchr($_FILES['attachment']['name'][$n], '.'), 1)), explode(',', strtolower($modSettings['attachmentExtensions']))))
1005						fatal_error($_FILES['attachment']['name'][$n] . '.<br />' . $txt['cant_upload_type'] . ' ' . $modSettings['attachmentExtensions'] . '.', false);
1006				}
1007
1008				if (!empty($modSettings['attachmentDirSizeLimit']))
1009				{
1010					// Make sure the directory isn't full.
1011					$dirSize = 0;
1012					$dir = @opendir($current_attach_dir) or fatal_lang_error('cant_access_upload_path', 'critical');
1013					while ($file = readdir($dir))
1014					{
1015						if ($file == '.' || $file == '..')
1016							continue;
1017
1018						if (preg_match('~^post_tmp_\d+_\d+$~', $file) != 0)
1019						{
1020							// Temp file is more than 5 hours old!
1021							if (filemtime($current_attach_dir . '/' . $file) < time() - 18000)
1022								@unlink($current_attach_dir . '/' . $file);
1023							continue;
1024						}
1025
1026						$dirSize += filesize($current_attach_dir . '/' . $file);
1027					}
1028					closedir($dir);
1029
1030					// Too big!  Maybe you could zip it or something...
1031					if ($_FILES['attachment']['size'][$n] + $dirSize > $modSettings['attachmentDirSizeLimit'] * 1024)
1032						fatal_lang_error('ran_out_of_space');
1033				}
1034
1035				if (!is_writable($current_attach_dir))
1036					fatal_lang_error('attachments_no_write', 'critical');
1037
1038				$attachID = 'post_tmp_' . $user_info['id'] . '_' . $temp_start++;
1039				$_SESSION['temp_attachments'][$attachID] = basename($_FILES['attachment']['name'][$n]);
1040				$context['current_attachments'][] = array(
1041					'name' => htmlspecialchars(basename($_FILES['attachment']['name'][$n])),
1042					'id' => $attachID,
1043					'approved' => 1,
1044				);
1045
1046				$destName = $current_attach_dir . '/' . $attachID;
1047
1048				if (!move_uploaded_file($_FILES['attachment']['tmp_name'][$n], $destName))
1049					fatal_lang_error('attach_timeout', 'critical');
1050				@chmod($destName, 0644);
1051			}
1052	}
1053
1054	// If we are coming here to make a reply, and someone has already replied... make a special warning message.
1055	if (isset($newRepliesError))
1056	{
1057		$context['post_error']['messages'][] = $newRepliesError == 1 ? $txt['error_new_reply'] : $txt['error_new_replies'];
1058		$context['error_type'] = 'minor';
1059	}
1060
1061	if (isset($oldTopicError))
1062	{
1063		$context['post_error']['messages'][] = sprintf($txt['error_old_topic'], $modSettings['oldTopicDays']);
1064		$context['error_type'] = 'minor';
1065	}
1066
1067	// What are you doing?  Posting a poll, modifying, previewing, new post, or reply...
1068	if (isset($_REQUEST['poll']))
1069		$context['page_title'] = $txt['new_poll'];
1070	elseif ($context['make_event'])
1071		$context['page_title'] = $context['event']['id'] == -1 ? $txt['calendar_post_event'] : $txt['calendar_edit'];
1072	elseif (isset($_REQUEST['msg']))
1073		$context['page_title'] = $txt['modify_msg'];
1074	elseif (isset($_REQUEST['subject'], $context['preview_subject']))
1075		$context['page_title'] = $txt['preview'] . ' - ' . strip_tags($context['preview_subject']);
1076	elseif (empty($topic))
1077		$context['page_title'] = $txt['start_new_topic'];
1078	else
1079		$context['page_title'] = $txt['post_reply'];
1080
1081	// Build the link tree.
1082	if (empty($topic))
1083		$context['linktree'][] = array(
1084			'name' => '<em>' . $txt['start_new_topic'] . '</em>'
1085		);
1086	else
1087		$context['linktree'][] = array(
1088			'url' => $scripturl . '?topic=' . $topic . '.' . $_REQUEST['start'],
1089			'name' => $form_subject,
1090			'extra_before' => '<span' . ($settings['linktree_inline'] ? ' class="smalltext"' : '') . '><strong class="nav">' . $context['page_title'] . ' ( </strong></span>',
1091			'extra_after' => '<span' . ($settings['linktree_inline'] ? ' class="smalltext"' : '') . '><strong class="nav"> )</strong></span>'
1092		);
1093
1094	// Give wireless a linktree url to the post screen, so that they can switch to full version.
1095	if (WIRELESS)
1096		$context['linktree'][count($context['linktree']) - 1]['url'] = $scripturl . '?action=post;' . (!empty($topic) ? 'topic=' . $topic : 'board=' . $board) . '.' . $_REQUEST['start'] . (isset($_REQUEST['msg']) ? ';msg=' . (int) $_REQUEST['msg'] . ';' . $context['session_var'] . '=' . $context['session_id'] : '');
1097
1098	// If they've unchecked an attachment, they may still want to attach that many more files, but don't allow more than num_allowed_attachments.
1099	// !!! This won't work if you're posting an event.
1100	$context['num_allowed_attachments'] = empty($modSettings['attachmentNumPerPostLimit']) ? 50 : min($modSettings['attachmentNumPerPostLimit'] - count($context['current_attachments']) + (isset($deleted_attachments) ? $deleted_attachments : 0), $modSettings['attachmentNumPerPostLimit']);
1101	$context['can_post_attachment'] = !empty($modSettings['attachmentEnable']) && $modSettings['attachmentEnable'] == 1 && (allowedTo('post_attachment') || ($modSettings['postmod_active'] && allowedTo('post_unapproved_attachments'))) && $context['num_allowed_attachments'] > 0;
1102	$context['can_post_attachment_unapproved'] = allowedTo('post_attachment');
1103
1104	$context['subject'] = addcslashes($form_subject, '"');
1105	$context['message'] = str_replace(array('"', '<', '>', '&nbsp;'), array('&quot;', '&lt;', '&gt;', ' '), $form_message);
1106
1107	// Needed for the editor and message icons.
1108	require_once($sourcedir . '/Subs-Editor.php');
1109
1110	// Now create the editor.
1111	$editorOptions = array(
1112		'id' => 'message',
1113		'value' => $context['message'],
1114		'labels' => array(
1115			'post_button' => $context['submit_label'],
1116		),
1117		// add height and width for the editor
1118		'height' => '175px',
1119		'width' => '100%',
1120		// We do XML preview here.
1121		'preview_type' => 2,
1122	);
1123	create_control_richedit($editorOptions);
1124
1125	// Store the ID.
1126	$context['post_box_name'] = $editorOptions['id'];
1127
1128	$context['attached'] = '';
1129	$context['make_poll'] = isset($_REQUEST['poll']);
1130
1131	// Message icons - customized icons are off?
1132	$context['icons'] = getMessageIcons($board);
1133
1134	if (!empty($context['icons']))
1135		$context['icons'][count($context['icons']) - 1]['is_last'] = true;
1136
1137	$context['icon_url'] = '';
1138	for ($i = 0, $n = count($context['icons']); $i < $n; $i++)
1139	{
1140		$context['icons'][$i]['selected'] = $context['icon'] == $context['icons'][$i]['value'];
1141		if ($context['icons'][$i]['selected'])
1142			$context['icon_url'] = $context['icons'][$i]['url'];
1143	}
1144	if (empty($context['icon_url']))
1145	{
1146		$context['icon_url'] = $settings[file_exists($settings['theme_dir'] . '/images/post/' . $context['icon'] . '.gif') ? 'images_url' : 'default_images_url'] . '/post/' . $context['icon'] . '.gif';
1147		array_unshift($context['icons'], array(
1148			'value' => $context['icon'],
1149			'name' => $txt['current_icon'],
1150			'url' => $context['icon_url'],
1151			'is_last' => empty($context['icons']),
1152			'selected' => true,
1153		));
1154	}
1155
1156	if (!empty($topic) && !empty($modSettings['topicSummaryPosts']))
1157		getTopic();
1158
1159	// If the user can post attachments prepare the warning labels.
1160	if ($context['can_post_attachment'])
1161	{
1162		$context['allowed_extensions'] = strtr($modSettings['attachmentExtensions'], array(',' => ', '));
1163		$context['attachment_restrictions'] = array();
1164		$attachmentRestrictionTypes = array('attachmentNumPerPostLimit', 'attachmentPostLimit', 'attachmentSizeLimit');
1165		foreach ($attachmentRestrictionTypes as $type)
1166			if (!empty($modSettings[$type]))
1167				$context['attachment_restrictions'][] = sprintf($txt['attach_restrict_' . $type], $modSettings[$type]);
1168	}
1169
1170	$context['back_to_topic'] = isset($_REQUEST['goback']) || (isset($_REQUEST['msg']) && !isset($_REQUEST['subject']));
1171	$context['show_additional_options'] = !empty($_POST['additional_options']) || !empty($_SESSION['temp_attachments']) || !empty($deleted_attachments);
1172
1173	$context['is_new_topic'] = empty($topic);
1174	$context['is_new_post'] = !isset($_REQUEST['msg']);
1175	$context['is_first_post'] = $context['is_new_topic'] || (isset($_REQUEST['msg']) && $_REQUEST['msg'] == $id_first_msg);
1176
1177	// Do we need to show the visual verification image?
1178	$context['require_verification'] = !$user_info['is_mod'] && !$user_info['is_admin'] && !empty($modSettings['posts_require_captcha']) && ($user_info['posts'] < $modSettings['posts_require_captcha'] || ($user_info['is_guest'] && $modSettings['posts_require_captcha'] == -1));
1179	if ($context['require_verification'])
1180	{
1181		require_once($sourcedir . '/Subs-Editor.php');
1182		$verificationOptions = array(
1183			'id' => 'post',
1184		);
1185		$context['require_verification'] = create_control_verification($verificationOptions);
1186		$context['visual_verification_id'] = $verificationOptions['id'];
1187	}
1188
1189	// If they came from quick reply, and have to enter verification details, give them some notice.
1190	if (!empty($_REQUEST['from_qr']) && !empty($context['require_verification']))
1191	{
1192		$context['post_error']['messages'][] = $txt['enter_verification_details'];
1193		$context['error_type'] = 'minor';
1194	}
1195
1196	// WYSIWYG only works if BBC is enabled
1197	$modSettings['disable_wysiwyg'] = !empty($modSettings['disable_wysiwyg']) || empty($modSettings['enableBBC']);
1198
1199	// Register this form in the session variables.
1200	checkSubmitOnce('register');
1201
1202	// Finally, load the template.
1203	if (WIRELESS && WIRELESS_PROTOCOL != 'wap')
1204		$context['sub_template'] = WIRELESS_PROTOCOL . '_post';
1205	elseif (!isset($_REQUEST['xml']))
1206		loadTemplate('Post');
1207}
1208
1209function Post2()
1210{
1211	global $board, $topic, $txt, $modSettings, $sourcedir, $context;
1212	global $user_info, $board_info, $options, $smcFunc;
1213
1214	// Sneaking off, are we?
1215	if (empty($_POST) && empty($topic))
1216		redirectexit('action=post;board=' . $board . '.0');
1217	elseif (empty($_POST) && !empty($topic))
1218		redirectexit('action=post;topic=' . $topic . '.0');
1219
1220	// No need!
1221	$context['robot_no_index'] = true;
1222
1223	// If we came from WYSIWYG then turn it back into BBC regardless.
1224	if (!empty($_REQUEST['message_mode']) && isset($_REQUEST['message']))
1225	{
1226		require_once($sourcedir . '/Subs-Editor.php');
1227
1228		$_REQUEST['message'] = html_to_bbc($_REQUEST['message']);
1229
1230		// We need to unhtml it now as it gets done shortly.
1231		$_REQUEST['message'] = un_htmlspecialchars($_REQUEST['message']);
1232
1233		// We need this for everything else.
1234		$_POST['message'] = $_REQUEST['message'];
1235	}
1236
1237	// Previewing? Go back to start.
1238	if (isset($_REQUEST['preview']))
1239		return Post();
1240
1241	// Prevent double submission of this form.
1242	checkSubmitOnce('check');
1243
1244	// No errors as yet.
1245	$post_errors = array();
1246
1247	// If the session has timed out, let the user re-submit their form.
1248	if (checkSession('post', '', false) != '')
1249		$post_errors[] = 'session_timeout';
1250
1251	// Wrong verification code?
1252	if (!$user_info['is_admin'] && !$user_info['is_mod'] && !empty($modSettings['posts_require_captcha']) && ($user_info['posts'] < $modSettings['posts_require_captcha'] || ($user_info['is_guest'] && $modSettings['posts_require_captcha'] == -1)))
1253	{
1254		require_once($sourcedir . '/Subs-Editor.php');
1255		$verificationOptions = array(
1256			'id' => 'post',
1257		);
1258		$context['require_verification'] = create_control_verification($verificationOptions, true);
1259		if (is_array($context['require_verification']))
1260			$post_errors = array_merge($post_errors, $context['require_verification']);
1261	}
1262
1263	require_once($sourcedir . '/Subs-Post.php');
1264	loadLanguage('Post');
1265
1266	// If this isn't a new topic load the topic info that we need.
1267	if (!empty($topic))
1268	{
1269		$request = $smcFunc['db_query']('', '
1270			SELECT locked, is_sticky, id_poll, approved, id_first_msg, id_last_msg, id_member_started, id_board
1271			FROM {db_prefix}topics
1272			WHERE id_topic = {int:current_topic}
1273			LIMIT 1',
1274			array(
1275				'current_topic' => $topic,
1276			)
1277		);
1278		$topic_info = $smcFunc['db_fetch_assoc']($request);
1279		$smcFunc['db_free_result']($request);
1280
1281		// Though the topic should be there, it might have vanished.
1282		if (!is_array($topic_info))
1283			fatal_lang_error('topic_doesnt_exist');
1284
1285		// Did this topic suddenly move? Just checking...
1286		if ($topic_info['id_board'] != $board)
1287			fatal_lang_error('not_a_topic');
1288	}
1289
1290	// Replying to a topic?
1291	if (!empty($topic) && !isset($_REQUEST['msg']))
1292	{
1293		// Don't allow a post if it's locked.
1294		if ($topic_info['locked'] != 0 && !allowedTo('moderate_board'))
1295			fatal_lang_error('topic_locked', false);
1296
1297		// Sorry, multiple polls aren't allowed... yet.  You should stop giving me ideas :P.
1298		if (isset($_REQUEST['poll']) && $topic_info['id_poll'] > 0)
1299			unset($_REQUEST['poll']);
1300
1301		// Do the permissions and approval stuff...
1302		$…

Large files files are truncated, but you can click here to view the full file