function EditPoll2() { global $txt, $topic, $board, $context; global $modSettings, $user_info, $smcFunc, $sourcedir; // Sneaking off, are we? if (empty($_POST)) { redirectexit('action=editpoll;topic=' . $topic . '.0'); } if (checkSession('post', '', false) != '') { $poll_errors[] = 'session_timeout'; } if (isset($_POST['preview'])) { return EditPoll(); } // HACKERS (!!) can't edit :P. if (empty($topic)) { fatal_lang_error('no_access', false); } // Is this a new poll, or editing an existing? $isEdit = isset($_REQUEST['add']) ? 0 : 1; // Get the starter and the poll's ID - if it's an edit. $request = smf_db_query(' SELECT t.id_member_started, t.id_poll, p.id_member AS poll_starter, p.expire_time FROM {db_prefix}topics AS t LEFT JOIN {db_prefix}polls AS p ON (p.id_poll = t.id_poll) WHERE t.id_topic = {int:current_topic} LIMIT 1', array('current_topic' => $topic)); if (mysql_num_rows($request) == 0) { fatal_lang_error('no_board'); } $bcinfo = mysql_fetch_assoc($request); mysql_free_result($request); // Check their adding/editing is valid. if (!$isEdit && !empty($bcinfo['id_poll'])) { fatal_lang_error('poll_already_exists'); } elseif ($isEdit && empty($bcinfo['id_poll'])) { fatal_lang_error('poll_not_found'); } // Check if they have the power to add or edit the poll. if ($isEdit && !allowedTo('poll_edit_any')) { isAllowedTo('poll_edit_' . ($user_info['id'] == $bcinfo['id_member_started'] || $bcinfo['poll_starter'] != 0 && $user_info['id'] == $bcinfo['poll_starter'] ? 'own' : 'any')); } elseif (!$isEdit && !allowedTo('poll_add_any')) { isAllowedTo('poll_add_' . ($user_info['id'] == $bcinfo['id_member_started'] ? 'own' : 'any')); } $optionCount = 0; // Ensure the user is leaving a valid amount of options - there must be at least two. foreach ($_POST['options'] as $k => $option) { if (trim($option) != '') { $optionCount++; } } if ($optionCount < 2) { $poll_errors[] = 'poll_few'; } // Also - ensure they are not removing the question. if (trim($_POST['question']) == '') { $poll_errors[] = 'no_question'; } // Got any errors to report? if (!empty($poll_errors)) { loadLanguage('Errors'); // Previewing. $_POST['preview'] = true; $context['poll_error'] = array('messages' => array()); foreach ($poll_errors as $poll_error) { $context['poll_error'][$poll_error] = true; $context['poll_error']['messages'][] = $txt['error_' . $poll_error]; } return EditPoll(); } // Prevent double submission of this form. checkSubmitOnce('check'); // Now we've done all our error checking, let's get the core poll information cleaned... question first. $_POST['question'] = commonAPI::htmlspecialchars($_POST['question']); $_POST['question'] = commonAPI::truncate($_POST['question'], 255); $_POST['poll_hide'] = (int) $_POST['poll_hide']; $_POST['poll_expire'] = isset($_POST['poll_expire']) ? (int) $_POST['poll_expire'] : 0; $_POST['poll_change_vote'] = isset($_POST['poll_change_vote']) ? 1 : 0; $_POST['poll_guest_vote'] = isset($_POST['poll_guest_vote']) ? 1 : 0; // Make sure guests are actually allowed to vote generally. if ($_POST['poll_guest_vote']) { require_once $sourcedir . '/lib/Subs-Members.php'; $allowedGroups = groupsAllowedTo('poll_vote', $board); if (!in_array(-1, $allowedGroups['allowed'])) { $_POST['poll_guest_vote'] = 0; } } // Ensure that the number options allowed makes sense, and the expiration date is valid. if (!$isEdit || allowedTo('moderate_board')) { $_POST['poll_expire'] = $_POST['poll_expire'] > 9999 ? 9999 : ($_POST['poll_expire'] < 0 ? 0 : $_POST['poll_expire']); if (empty($_POST['poll_expire']) && $_POST['poll_hide'] == 2) { $_POST['poll_hide'] = 1; } elseif (!$isEdit || $_POST['poll_expire'] != ceil($bcinfo['expire_time'] <= time() ? -1 : ($bcinfo['expire_time'] - time()) / (3600 * 24))) { $_POST['poll_expire'] = empty($_POST['poll_expire']) ? '0' : time() + $_POST['poll_expire'] * 3600 * 24; } else { $_POST['poll_expire'] = $bcinfo['expire_time']; } if (empty($_POST['poll_max_votes']) || $_POST['poll_max_votes'] <= 0) { $_POST['poll_max_votes'] = 1; } else { $_POST['poll_max_votes'] = (int) $_POST['poll_max_votes']; } } // If we're editing, let's commit the changes. if ($isEdit) { smf_db_query(' UPDATE {db_prefix}polls SET question = {string:question}, change_vote = {int:change_vote},' . (allowedTo('moderate_board') ? ' hide_results = {int:hide_results}, expire_time = {int:expire_time}, max_votes = {int:max_votes}, guest_vote = {int:guest_vote}' : ' hide_results = CASE WHEN expire_time = {int:expire_time_zero} AND {int:hide_results} = 2 THEN 1 ELSE {int:hide_results} END') . ' WHERE id_poll = {int:id_poll}', array('change_vote' => $_POST['poll_change_vote'], 'hide_results' => $_POST['poll_hide'], 'expire_time' => !empty($_POST['poll_expire']) ? $_POST['poll_expire'] : 0, 'max_votes' => !empty($_POST['poll_max_votes']) ? $_POST['poll_max_votes'] : 0, 'guest_vote' => $_POST['poll_guest_vote'], 'expire_time_zero' => 0, 'id_poll' => $bcinfo['id_poll'], 'question' => $_POST['question'])); } else { // Create the poll. smf_db_insert('', '{db_prefix}polls', array('question' => 'string-255', 'hide_results' => 'int', 'max_votes' => 'int', 'expire_time' => 'int', 'id_member' => 'int', 'poster_name' => 'string-255', 'change_vote' => 'int', 'guest_vote' => 'int'), array($_POST['question'], $_POST['poll_hide'], $_POST['poll_max_votes'], $_POST['poll_expire'], $user_info['id'], $user_info['username'], $_POST['poll_change_vote'], $_POST['poll_guest_vote']), array('id_poll')); // Set the poll ID. $bcinfo['id_poll'] = smf_db_insert_id('{db_prefix}polls', 'id_poll'); // Link the poll to the topic smf_db_query(' UPDATE {db_prefix}topics SET id_poll = {int:id_poll} WHERE id_topic = {int:current_topic}', array('current_topic' => $topic, 'id_poll' => $bcinfo['id_poll'])); } // Get all the choices. (no better way to remove all emptied and add previously non-existent ones.) $request = smf_db_query(' SELECT id_choice FROM {db_prefix}poll_choices WHERE id_poll = {int:id_poll}', array('id_poll' => $bcinfo['id_poll'])); $choices = array(); while ($row = mysql_fetch_assoc($request)) { $choices[] = $row['id_choice']; } mysql_free_result($request); $delete_options = array(); foreach ($_POST['options'] as $k => $option) { // Make sure the key is numeric for sanity's sake. $k = (int) $k; // They've cleared the box. Either they want it deleted, or it never existed. if (trim($option) == '') { // They want it deleted. Bye. if (in_array($k, $choices)) { $delete_options[] = $k; } // Skip the rest... continue; } // Dress the option up for its big date with the database. $option = commonAPI::htmlspecialchars($option); // If it's already there, update it. If it's not... add it. if (in_array($k, $choices)) { smf_db_query(' UPDATE {db_prefix}poll_choices SET label = {string:option_name} WHERE id_poll = {int:id_poll} AND id_choice = {int:id_choice}', array('id_poll' => $bcinfo['id_poll'], 'id_choice' => $k, 'option_name' => $option)); } else { smf_db_insert('', '{db_prefix}poll_choices', array('id_poll' => 'int', 'id_choice' => 'int', 'label' => 'string-255', 'votes' => 'int'), array($bcinfo['id_poll'], $k, $option, 0), array()); } } // I'm sorry, but... well, no one was choosing you. Poor options, I'll put you out of your misery. if (!empty($delete_options)) { smf_db_query(' DELETE FROM {db_prefix}log_polls WHERE id_poll = {int:id_poll} AND id_choice IN ({array_int:delete_options})', array('delete_options' => $delete_options, 'id_poll' => $bcinfo['id_poll'])); smf_db_query(' DELETE FROM {db_prefix}poll_choices WHERE id_poll = {int:id_poll} AND id_choice IN ({array_int:delete_options})', array('delete_options' => $delete_options, 'id_poll' => $bcinfo['id_poll'])); } // Shall I reset the vote count, sir? if (isset($_POST['resetVoteCount'])) { smf_db_query(' UPDATE {db_prefix}polls SET num_guest_voters = {int:no_votes}, reset_poll = {int:time} WHERE id_poll = {int:id_poll}', array('no_votes' => 0, 'id_poll' => $bcinfo['id_poll'], 'time' => time())); smf_db_query(' UPDATE {db_prefix}poll_choices SET votes = {int:no_votes} WHERE id_poll = {int:id_poll}', array('no_votes' => 0, 'id_poll' => $bcinfo['id_poll'])); smf_db_query(' DELETE FROM {db_prefix}log_polls WHERE id_poll = {int:id_poll}', array('id_poll' => $bcinfo['id_poll'])); } // Off we go. redirectexit('topic=' . $topic . '.' . $_REQUEST['start']); }
function Post2() { global $board, $topic, $txt, $modSettings, $sourcedir, $context; global $user_info, $board_info, $options, $backend_subdir; /* todo: drafts -> plugin if(in_array('dr', $context['admin_features'])) { require_once($sourcedir . '/lib/Subs-Drafts.php'); enqueueThemeScript('drafts', 'scripts/drafts.js', true); $context['have_drafts'] = true; } else*/ $context['have_drafts'] = false; $context['auto_preview'] = isset($_REQUEST['autopreview']) && $_REQUEST['autopreview'] ? 1 : 0; $context['need_synhlt'] = true; $context['no_astream'] = isset($_REQUEST['noactivity']) && (int) $_REQUEST['noactivity'] == 1; $context['can_tag_users'] = allowedTo('tag_users'); // Sneaking off, are we? if (empty($_POST) && empty($topic)) { redirectexit('action=post;board=' . $board . '.0'); } elseif (empty($_POST) && !empty($topic)) { redirectexit('action=post;topic=' . $topic . '.0'); } // No need! $context['robot_no_index'] = true; // If we came from WYSIWYG then turn it back into BBC regardless. if (!empty($_REQUEST['message_mode']) && isset($_REQUEST['message'])) { require_once $sourcedir . '/lib/Subs-Editor.php'; $_REQUEST['message'] = html_to_bbc($_REQUEST['message']); // We need to unhtml it now as it gets done shortly. $_REQUEST['message'] = un_htmlspecialchars($_REQUEST['message']); // We need this for everything else. $_POST['message'] = $_REQUEST['message']; } // Previewing? Go back to start. if (isset($_REQUEST['preview'])) { return Post(); } // Prevent double submission of this form. checkSubmitOnce('check'); // No errors as yet. $post_errors = array(); // If the session has timed out, let the user re-submit their form. if (checkSession('post', '', false) != '') { $post_errors[] = 'session_timeout'; } // Wrong verification code? 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)) { require_once $sourcedir . '/lib/Subs-Editor.php'; $verificationOptions = array('id' => 'post', 'skip_template' => true); $context['require_verification'] = create_control_verification($verificationOptions, true); if (is_array($context['require_verification'])) { $post_errors = array_merge($post_errors, $context['require_verification']); } } require_once $sourcedir . '/lib/Subs-Post.php'; loadLanguage('Post'); // If this isn't a new topic load the topic info that we need. if (!empty($topic)) { $request = smf_db_query(' SELECT t.locked, t.is_sticky, t.id_poll, t.approved, t.id_first_msg, t.id_last_msg, t.id_member_started, t.id_member_updated, t.id_board, t.id_prefix, t.id_layout, t.num_replies, b.automerge, ba.id_topic AS banned_from_topic FROM {db_prefix}topics AS t LEFT JOIN {db_prefix}boards AS b on b.id_board = t.id_board LEFT JOIN {db_prefix}topicbans AS ba ON (ba.id_topic = {int:current_topic} AND ba.id_member = {int:current_member}) WHERE t.id_topic = {int:current_topic} LIMIT 1', array('current_topic' => $topic, 'current_member' => $user_info['id'])); $topic_info = mysql_fetch_assoc($request); mysql_free_result($request); // Though the topic should be there, it might have vanished. if (!is_array($topic_info)) { fatal_lang_error('topic_doesnt_exist'); } // Did this topic suddenly move? Just checking... if ($topic_info['id_board'] != $board) { fatal_lang_error('not_a_topic'); } if ($topic_info['banned_from_topic'] != 0 && !$user_info['is_admin'] && !allowedTo('moderate_board') && !allowedTo('moderate_forum')) { fatal_lang_error('banned_from_topic'); } } // Replying to a topic? if (!empty($topic) && !isset($_REQUEST['msg'])) { // Don't allow a post if it's locked. if ($topic_info['locked'] != 0 && !allowedTo('moderate_board')) { fatal_lang_error('topic_locked', false); } // Sorry, multiple polls aren't allowed... yet. You should stop giving me ideas :P. if (isset($_REQUEST['poll']) && $topic_info['id_poll'] > 0) { unset($_REQUEST['poll']); } // Do the permissions and approval stuff... $becomesApproved = true; if ($topic_info['id_member_started'] != $user_info['id']) { if ($modSettings['postmod_active'] && allowedTo('post_unapproved_replies_any') && !allowedTo('post_reply_any')) { $becomesApproved = false; } else { isAllowedTo('post_reply_any'); } } elseif (!allowedTo('post_reply_any')) { if ($modSettings['postmod_active'] && allowedTo('post_unapproved_replies_own') && !allowedTo('post_reply_own')) { $becomesApproved = false; } else { isAllowedTo('post_reply_own'); } } if (isset($_POST['lock'])) { // Nothing is changed to the lock. if (empty($topic_info['locked']) && empty($_POST['lock']) || !empty($_POST['lock']) && !empty($topic_info['locked'])) { unset($_POST['lock']); } elseif (!allowedTo(array('lock_any', 'lock_own')) || !allowedTo('lock_any') && $user_info['id'] != $topic_info['id_member_started']) { unset($_POST['lock']); } elseif (!allowedTo('lock_any')) { // You cannot override a moderator lock. if ($topic_info['locked'] == 1) { unset($_POST['lock']); } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 2; } } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 1; } } // So you wanna (un)sticky this...let's see. if (isset($_POST['sticky']) && (empty($modSettings['enableStickyTopics']) || $_POST['sticky'] == $topic_info['is_sticky'] || !allowedTo('make_sticky'))) { unset($_POST['sticky']); } // If the number of replies has changed, if the setting is enabled, go back to Post() - which handles the error. if (empty($options['no_new_reply_warning']) && isset($_POST['last_msg']) && $topic_info['id_last_msg'] > $_POST['last_msg']) { $_REQUEST['preview'] = true; return Post(); } // drafts if (isset($_POST['lock'])) { $_POST['lock_draft'] = !empty($_POST['lock']) ? 1 : 0; } else { $_POST['lock_draft'] = !empty($topic_info['locked']) ? 1 : 0; } // it's not, grab from topic's current info if ($context['have_drafts']) { $draft = saveDraft(); if (!empty($draft) && !in_array('session_timeout', $post_errors)) { if (isset($_REQUEST['xml'])) { draftXmlReturn($draft); } EoS_Smarty::loadTemplate('post/draft_saved'); $context['page_title'] = $txt['draft_saved_short']; return; } } $posterIsGuest = $user_info['is_guest']; } elseif (empty($topic)) { // Now don't be silly, new topics will get their own id_msg soon enough. unset($_REQUEST['msg'], $_POST['msg'], $_GET['msg']); // Do like, the permissions, for safety and stuff... $becomesApproved = true; if ($modSettings['postmod_active'] && !allowedTo('post_new') && allowedTo('post_unapproved_topics')) { $becomesApproved = false; } else { isAllowedTo('post_new'); } if (isset($_POST['lock'])) { // New topics are by default not locked. if (empty($_POST['lock'])) { unset($_POST['lock']); } elseif (!allowedTo(array('lock_any', 'lock_own'))) { unset($_POST['lock']); } else { $_POST['lock'] = allowedTo('lock_any') ? 1 : 2; } } if (isset($_POST['sticky']) && (empty($modSettings['enableStickyTopics']) || empty($_POST['sticky']) || !allowedTo('make_sticky'))) { unset($_POST['sticky']); } $posterIsGuest = $user_info['is_guest']; // Are we saving a draft? If so, hand over control to the draft code -- except, in the case of a session failure $_POST['lock_draft'] = !empty($_POST['lock']) ? 1 : 0; if ($context['have_drafts']) { $draft = saveDraft(); if (!empty($draft) && !in_array('session_timeout', $post_errors)) { if (isset($_REQUEST['xml'])) { draftXmlReturn($draft); } EoS_Smarty::loadTemplate('post/draft_saved'); $context['page_title'] = $txt['draft_saved_short']; return; } } } elseif (isset($_REQUEST['msg']) && !empty($topic)) { $_REQUEST['msg'] = (int) $_REQUEST['msg']; $request = smf_db_query(' SELECT id_member, poster_name, poster_email, poster_time, approved, locked FROM {db_prefix}messages WHERE id_msg = {int:id_msg} LIMIT 1', array('id_msg' => $_REQUEST['msg'])); if (mysql_num_rows($request) == 0) { fatal_lang_error('cant_find_messages', false); } $row = mysql_fetch_assoc($request); $msg_owner = $row['id_member']; mysql_free_result($request); if (!empty($topic_info['locked']) && !allowedTo('moderate_board')) { fatal_lang_error('topic_locked', false); } if (isset($_POST['lock'])) { // Nothing changes to the lock status. if (empty($_POST['lock']) && empty($topic_info['locked']) || !empty($_POST['lock']) && !empty($topic_info['locked'])) { unset($_POST['lock']); } elseif (!allowedTo(array('lock_any', 'lock_own')) || !allowedTo('lock_any') && $user_info['id'] != $topic_info['id_member_started']) { unset($_POST['lock']); } elseif (!allowedTo('lock_any')) { // You're not allowed to break a moderator's lock. if ($topic_info['locked'] == 1) { unset($_POST['lock']); } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 2; } } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 1; } } // Change the sticky status of this topic? if (isset($_POST['sticky']) && (!allowedTo('make_sticky') || $_POST['sticky'] == $topic_info['is_sticky'])) { unset($_POST['sticky']); } if ($row['locked'] && !(allowedTo('moderate_board') || allowedTo('moderate_forum'))) { fatal_lang_error('modify_message_locked', false); } if ($row['id_member'] == $user_info['id'] && !allowedTo('modify_any')) { if ((!$modSettings['postmod_active'] || $row['approved']) && !empty($modSettings['edit_disable_time']) && $row['poster_time'] + ($modSettings['edit_disable_time'] + 5) * 60 < time()) { fatal_lang_error('modify_post_time_passed', false); } elseif ($topic_info['id_member_started'] == $user_info['id'] && !allowedTo('modify_own')) { isAllowedTo('modify_replies'); } else { isAllowedTo('modify_own'); } } elseif ($topic_info['id_member_started'] == $user_info['id'] && !allowedTo('modify_any')) { isAllowedTo('modify_replies'); // If you're modifying a reply, I say it better be logged... $moderationAction = true; } else { isAllowedTo('modify_any'); // Log it, assuming you're not modifying your own post. if ($row['id_member'] != $user_info['id']) { $moderationAction = true; } } $posterIsGuest = empty($row['id_member']); // Can they approve it? $can_approve = allowedTo('approve_posts'); $becomesApproved = $modSettings['postmod_active'] ? $can_approve && !$row['approved'] ? !empty($_REQUEST['approve']) ? 1 : 0 : $row['approved'] : 1; $approve_has_changed = $row['approved'] != $becomesApproved; if (!allowedTo('moderate_forum') || !$posterIsGuest) { $_POST['guestname'] = $row['poster_name']; $_POST['email'] = $row['poster_email']; } if ($context['have_drafts']) { $draft = saveDraft(); if (!empty($draft) && !in_array('session_timeout', $post_errors)) { if (isset($_REQUEST['xml'])) { draftXmlReturn($draft); } EoS_Smarty::loadTemplate('post/draft_saved'); $context['page_title'] = $txt['draft_saved_short']; return; } } } // If the poster is a guest evaluate the legality of name and email. if ($posterIsGuest) { $_POST['guestname'] = !isset($_POST['guestname']) ? '' : trim($_POST['guestname']); $_POST['email'] = !isset($_POST['email']) ? '' : trim($_POST['email']); if ($_POST['guestname'] == '' || $_POST['guestname'] == '_') { $post_errors[] = 'no_name'; } if (commonAPI::strlen($_POST['guestname']) > 25) { $post_errors[] = 'long_name'; } if (empty($modSettings['guest_post_no_email'])) { // Only check if they changed it! if (!isset($row) || $row['poster_email'] != $_POST['email']) { if (!allowedTo('moderate_forum') && (!isset($_POST['email']) || $_POST['email'] == '')) { $post_errors[] = 'no_email'; } if (!allowedTo('moderate_forum') && preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', $_POST['email']) == 0) { $post_errors[] = 'bad_email'; } } // Now make sure this email address is not banned from posting. isBannedEmail($_POST['email'], 'cannot_post', sprintf($txt['you_are_post_banned'], $txt['guest_title'])); } // In case they are making multiple posts this visit, help them along by storing their name. if (empty($post_errors)) { $_SESSION['guest_name'] = $_POST['guestname']; $_SESSION['guest_email'] = $_POST['email']; } } // Check the subject and message. if (!isset($_POST['subject']) || commonAPI::htmltrim(commonAPI::htmlspecialchars($_POST['subject'])) === '') { $post_errors[] = 'no_subject'; } if (!isset($_POST['message']) || commonAPI::htmltrim(commonAPI::htmlspecialchars($_POST['message']), ENT_QUOTES) === '') { $post_errors[] = 'no_message'; } elseif (!empty($modSettings['max_messageLength']) && commonAPI::strlen($_POST['message']) > $modSettings['max_messageLength']) { $post_errors[] = 'long_message'; } else { // Prepare the message a bit for some additional testing. $_POST['message'] = commonAPI::htmlspecialchars($_POST['message'], ENT_QUOTES); // Preparse code. (Zef) if ($user_info['is_guest']) { $user_info['name'] = $_POST['guestname']; } preparsecode($_POST['message']); // Let's see if there's still some content left without the tags. if (commonAPI::htmltrim(strip_tags(parse_bbc($_POST['message'], false), '<img>')) === '' && (!allowedTo('admin_forum') || strpos($_POST['message'], '[html]') === false)) { $post_errors[] = 'no_message'; } } if (isset($_POST['calendar']) && !isset($_REQUEST['deleteevent']) && commonAPI::htmltrim($_POST['evtitle']) === '') { $post_errors[] = 'no_event'; } // You are not! if (isset($_POST['message']) && strtolower($_POST['message']) == 'i am the administrator.' && !$user_info['is_admin']) { fatal_error('Knave! Masquerader! Charlatan!', false); } // Validate the poll... if (isset($_REQUEST['poll']) && $modSettings['pollMode'] == '1') { if (!empty($topic) && !isset($_REQUEST['msg'])) { fatal_lang_error('no_access', false); } // This is a new topic... so it's a new poll. if (empty($topic)) { isAllowedTo('poll_post'); } elseif ($user_info['id'] == $topic_info['id_member_started'] && !allowedTo('poll_add_any')) { isAllowedTo('poll_add_own'); } else { isAllowedTo('poll_add_any'); } if (!isset($_POST['question']) || trim($_POST['question']) == '') { $post_errors[] = 'no_question'; } $_POST['options'] = empty($_POST['options']) ? array() : htmltrim__recursive($_POST['options']); // Get rid of empty ones. foreach ($_POST['options'] as $k => $option) { if ($option == '') { unset($_POST['options'][$k], $_POST['options'][$k]); } } // What are you going to vote between with one choice?!? if (count($_POST['options']) < 2) { $post_errors[] = 'poll_few'; } } if ($posterIsGuest) { // If user is a guest, make sure the chosen name isn't taken. require_once $sourcedir . '/lib/Subs-Members.php'; if (isReservedName($_POST['guestname'], 0, true, false) && (!isset($row['poster_name']) || $_POST['guestname'] != $row['poster_name'])) { $post_errors[] = 'bad_name'; } } elseif (!isset($_REQUEST['msg'])) { $_POST['guestname'] = $user_info['username']; $_POST['email'] = $user_info['email']; } // Any mistakes? if (!empty($post_errors)) { loadLanguage('Errors'); // Previewing. $_REQUEST['preview'] = true; $context['post_error'] = array('messages' => array()); foreach ($post_errors as $post_error) { $context['post_error'][$post_error] = true; if ($post_error == 'long_message') { $txt['error_' . $post_error] = sprintf($txt['error_' . $post_error], $modSettings['max_messageLength']); } $context['post_error']['messages'][] = $txt['error_' . $post_error]; } return Post(); } // Make sure the user isn't spamming the board. if (!isset($_REQUEST['msg'])) { spamProtection('post'); } // At about this point, we're posting and that's that. ignore_user_abort(true); @set_time_limit(300); // Add special html entities to the subject, name, and email. $_POST['subject'] = strtr(commonAPI::htmlspecialchars($_POST['subject']), array("\r" => '', "\n" => '', "\t" => '')); $_POST['guestname'] = htmlspecialchars($_POST['guestname']); $_POST['email'] = htmlspecialchars($_POST['email']); // At this point, we want to make sure the subject isn't too long. if (commonAPI::strlen($_POST['subject']) > 100) { $_POST['subject'] = commonAPI::substr($_POST['subject'], 0, 100); } // Make the poll... if (isset($_REQUEST['poll'])) { // Make sure that the user has not entered a ridiculous number of options.. if (empty($_POST['poll_max_votes']) || $_POST['poll_max_votes'] <= 0) { $_POST['poll_max_votes'] = 1; } elseif ($_POST['poll_max_votes'] > count($_POST['options'])) { $_POST['poll_max_votes'] = count($_POST['options']); } else { $_POST['poll_max_votes'] = (int) $_POST['poll_max_votes']; } $_POST['poll_expire'] = (int) $_POST['poll_expire']; $_POST['poll_expire'] = $_POST['poll_expire'] > 9999 ? 9999 : ($_POST['poll_expire'] < 0 ? 0 : $_POST['poll_expire']); // Just set it to zero if it's not there.. if (!isset($_POST['poll_hide'])) { $_POST['poll_hide'] = 0; } else { $_POST['poll_hide'] = (int) $_POST['poll_hide']; } $_POST['poll_change_vote'] = isset($_POST['poll_change_vote']) ? 1 : 0; $_POST['poll_guest_vote'] = isset($_POST['poll_guest_vote']) ? 1 : 0; // Make sure guests are actually allowed to vote generally. if ($_POST['poll_guest_vote']) { require_once $sourcedir . '/lib/Subs-Members.php'; $allowedVoteGroups = groupsAllowedTo('poll_vote', $board); if (!in_array(-1, $allowedVoteGroups['allowed'])) { $_POST['poll_guest_vote'] = 0; } } // If the user tries to set the poll too far in advance, don't let them. if (!empty($_POST['poll_expire']) && $_POST['poll_expire'] < 1) { fatal_lang_error('poll_range_error', false); } elseif (empty($_POST['poll_expire']) && $_POST['poll_hide'] == 2) { $_POST['poll_hide'] = 1; } // Clean up the question and answers. $_POST['question'] = htmlspecialchars($_POST['question']); $_POST['question'] = commonAPI::truncate($_POST['question'], 255); $_POST['question'] = preg_replace('~&#(\\d{4,5}|[2-9]\\d{2,4}|1[2-9]\\d);~', '&#$1;', $_POST['question']); $_POST['options'] = htmlspecialchars__recursive($_POST['options']); } // Check if they are trying to delete any current attachments.... if (isset($_REQUEST['msg'], $_POST['attach_del']) && (allowedTo('post_attachment') || $modSettings['postmod_active'] && allowedTo('post_unapproved_attachments'))) { $del_temp = array(); foreach ($_POST['attach_del'] as $i => $dummy) { $del_temp[$i] = (int) $dummy; } require_once $sourcedir . '/lib/Subs-ManageAttachments.php'; $attachmentQuery = array('attachment_type' => 0, 'id_msg' => (int) $_REQUEST['msg'], 'not_id_attach' => $del_temp); removeAttachments($attachmentQuery); } // ...or attach a new file... if (isset($_FILES['attachment']['name']) || !empty($_SESSION['temp_attachments']) && empty($_POST['from_qr'])) { // Verify they can post them! if (!$modSettings['postmod_active'] || !allowedTo('post_unapproved_attachments')) { isAllowedTo('post_attachment'); } // Make sure we're uploading to the right place. if (!empty($modSettings['currentAttachmentUploadDir'])) { if (!is_array($modSettings['attachmentUploadDir'])) { $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']); } // The current directory, of course! $current_attach_dir = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']]; } else { $current_attach_dir = $modSettings['attachmentUploadDir']; } // If this isn't a new post, check the current attachments. if (isset($_REQUEST['msg'])) { $request = smf_db_query(' SELECT COUNT(*), SUM(size) FROM {db_prefix}attachments WHERE id_msg = {int:id_msg} AND attachment_type = {int:attachment_type}', array('id_msg' => (int) $_REQUEST['msg'], 'attachment_type' => 0)); list($quantity, $total_size) = mysql_fetch_row($request); mysql_free_result($request); } else { $quantity = 0; $total_size = 0; } if (!empty($_SESSION['temp_attachments'])) { foreach ($_SESSION['temp_attachments'] as $attachID => $name) { if (preg_match('~^post_tmp_' . $user_info['id'] . '_\\d+$~', $attachID) == 0) { continue; } if (!empty($_POST['attach_del']) && !in_array($attachID, $_POST['attach_del'])) { unset($_SESSION['temp_attachments'][$attachID]); @unlink($current_attach_dir . '/' . $attachID); continue; } $_FILES['attachment']['tmp_name'][] = $attachID; $_FILES['attachment']['name'][] = $name; $_FILES['attachment']['size'][] = filesize($current_attach_dir . '/' . $attachID); list($_FILES['attachment']['width'][], $_FILES['attachment']['height'][]) = @getimagesize($current_attach_dir . '/' . $attachID); unset($_SESSION['temp_attachments'][$attachID]); } } if (!isset($_FILES['attachment']['name'])) { $_FILES['attachment']['tmp_name'] = array(); } $attachIDs = array(); foreach ($_FILES['attachment']['tmp_name'] as $n => $dummy) { if ($_FILES['attachment']['name'][$n] == '') { continue; } // Have we reached the maximum number of files we are allowed? $quantity++; if (!empty($modSettings['attachmentNumPerPostLimit']) && $quantity > $modSettings['attachmentNumPerPostLimit']) { checkSubmitOnce('free'); fatal_lang_error('attachments_limit_per_post', false, array($modSettings['attachmentNumPerPostLimit'])); } // Check the total upload size for this post... $total_size += $_FILES['attachment']['size'][$n]; if (!empty($modSettings['attachmentPostLimit']) && $total_size > $modSettings['attachmentPostLimit'] * 1024) { checkSubmitOnce('free'); fatal_lang_error('file_too_big', false, array($modSettings['attachmentPostLimit'])); } $attachmentOptions = array('post' => isset($_REQUEST['msg']) ? $_REQUEST['msg'] : 0, 'poster' => $user_info['id'], 'name' => $_FILES['attachment']['name'][$n], 'tmp_name' => $_FILES['attachment']['tmp_name'][$n], 'size' => $_FILES['attachment']['size'][$n], 'approved' => !$modSettings['postmod_active'] || allowedTo('post_attachment')); if (createAttachment($attachmentOptions)) { $attachIDs[] = $attachmentOptions['id']; if (!empty($attachmentOptions['thumb'])) { $attachIDs[] = $attachmentOptions['thumb']; } } else { if (in_array('could_not_upload', $attachmentOptions['errors'])) { checkSubmitOnce('free'); fatal_lang_error('attach_timeout', 'critical'); } if (in_array('too_large', $attachmentOptions['errors'])) { checkSubmitOnce('free'); fatal_lang_error('file_too_big', false, array($modSettings['attachmentSizeLimit'])); } if (in_array('bad_extension', $attachmentOptions['errors'])) { checkSubmitOnce('free'); fatal_error($attachmentOptions['name'] . '.<br />' . $txt['cant_upload_type'] . ' ' . $modSettings['attachmentExtensions'] . '.', false); } if (in_array('directory_full', $attachmentOptions['errors'])) { checkSubmitOnce('free'); fatal_lang_error('ran_out_of_space', 'critical'); } if (in_array('bad_filename', $attachmentOptions['errors'])) { checkSubmitOnce('free'); fatal_error(basename($attachmentOptions['name']) . '.<br />' . $txt['restricted_filename'] . '.', 'critical'); } if (in_array('taken_filename', $attachmentOptions['errors'])) { checkSubmitOnce('free'); fatal_lang_error('filename_exists'); } if (in_array('bad_attachment', $attachmentOptions['errors'])) { checkSubmitOnce('free'); fatal_lang_error('bad_attachment'); } } } } // Make the poll... if (isset($_REQUEST['poll'])) { // Create the poll. smf_db_insert('', '{db_prefix}polls', array('question' => 'string-255', 'hide_results' => 'int', 'max_votes' => 'int', 'expire_time' => 'int', 'id_member' => 'int', 'poster_name' => 'string-255', 'change_vote' => 'int', 'guest_vote' => 'int'), array($_POST['question'], $_POST['poll_hide'], $_POST['poll_max_votes'], empty($_POST['poll_expire']) ? 0 : time() + $_POST['poll_expire'] * 3600 * 24, $user_info['id'], $_POST['guestname'], $_POST['poll_change_vote'], $_POST['poll_guest_vote']), array('id_poll')); $id_poll = smf_db_insert_id('{db_prefix}polls', 'id_poll'); // Create each answer choice. $i = 0; $pollOptions = array(); foreach ($_POST['options'] as $option) { $pollOptions[] = array($id_poll, $i, $option); $i++; } smf_db_insert('insert', '{db_prefix}poll_choices', array('id_poll' => 'int', 'id_choice' => 'int', 'label' => 'string-255'), $pollOptions, array('id_poll', 'id_choice')); } else { $id_poll = 0; } // Creating a new topic? $newTopic = empty($_REQUEST['msg']) && empty($topic); $_POST['icon'] = !empty($attachIDs) && $_POST['icon'] == 'xx' ? 'clip' : $_POST['icon']; if (empty($attachIDs) && $_POST['icon'] == 'clip') { $_POST['icon'] = 'xx'; } // Collect all parameters for the creation or modification of a post. $msgOptions = array('id' => empty($_REQUEST['msg']) ? 0 : (int) $_REQUEST['msg'], 'subject' => $_POST['subject'], 'body' => $_POST['message'], 'icon' => preg_replace('~[\\./\\\\*:"\'<>]~', '', $_POST['icon']), 'smileys_enabled' => !isset($_POST['ns']), 'attachments' => empty($attachIDs) ? array() : $attachIDs, 'approved' => $becomesApproved, 'id_owner' => isset($msg_owner) ? $msg_owner : 0, 'locked' => !empty($_POST['lock_message']) && (allowedTo('moderate_board') || allowedTo('moderate_forum'))); $topicOptions = array('id' => empty($topic) ? 0 : $topic, 'board' => $board, 'poll' => isset($_REQUEST['poll']) ? $id_poll : null, 'lock_mode' => isset($_POST['lock']) ? (int) $_POST['lock'] : null, 'sticky_mode' => isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics']) ? (int) $_POST['sticky'] : null, 'mark_as_read' => true, 'topic_prefix' => isset($_REQUEST['topic_prefix']) ? intval($_REQUEST['topic_prefix']) : null, 'topic_layout' => (isset($_REQUEST['stickfirst']) && $_REQUEST['stickfirst'] ? 0x80 : 0) | (isset($_REQUEST['firstlayout']) && $_REQUEST['firstlayout'] ? $_REQUEST['firstlayout'] : 0), 'automerge' => !empty($topic) ? $topic_info['automerge'] : 0, 'id_first_msg' => !empty($topic) ? $topic_info['id_first_msg'] : 0, 'id_last_msg' => !empty($topic) ? $topic_info['id_last_msg'] : 0, 'id_member_started' => !empty($topic) ? $topic_info['id_member_started'] : 0, 'id_member_updated' => !empty($topic) ? $topic_info['id_member_updated'] : 0, 'is_approved' => !$modSettings['postmod_active'] || empty($topic) || !empty($board_info['cur_topic_approved']), 'num_replies' => !empty($topic) ? $topic_info['num_replies'] : 0); $posterOptions = array('id' => $user_info['id'], 'name' => $_POST['guestname'], 'email' => $_POST['email'], 'update_post_count' => !$user_info['is_guest'] && !isset($_REQUEST['msg']) && $board_info['posts_count']); // This is an already existing message. Edit it. if (!empty($_REQUEST['msg'])) { // Have admins allowed people to hide their screwups? if (time() - $row['poster_time'] > $modSettings['edit_wait_time'] || $user_info['id'] != $row['id_member']) { $msgOptions['modify_time'] = time(); $msgOptions['modify_name'] = $user_info['name']; } // This will save some time... if (empty($approve_has_changed)) { unset($msgOptions['approved']); } modifyPost($msgOptions, $topicOptions, $posterOptions); } else { //handleUserTags($msgOptions['body']); createPost($msgOptions, $topicOptions, $posterOptions); if (isset($topicOptions['id'])) { $topic = $topicOptions['id']; } if (isset($_REQUEST['tags']) && !isset($_REQUEST['num_replies'])) { global $user_info; $result = smf_db_query(' SELECT COUNT(*) as total FROM {db_prefix}tags_log WHERE ID_TOPIC = {int:id_topic}', array('id_topic' => $topic)); $row = mysql_fetch_assoc($result); $nr_tags = $row['total']; mysql_free_result($result); // Check Tag restrictions $tags = explode(',', htmlspecialchars($_REQUEST['tags'], ENT_QUOTES)); if ($nr_tags < $modSettings['smftags_set_maxtags']) { $count = 0; foreach ($tags as $tag) { $tag = trim($tag); if (empty($tag)) { continue; } if ($count >= $modSettings['smftags_set_maxtags']) { continue; } if (strlen($tag) < $modSettings['smftags_set_mintaglength']) { continue; } if (strlen($tag) > $modSettings['smftags_set_maxtaglength']) { continue; } $result = smf_db_query(' SELECT ID_TAG FROM {db_prefix}tags WHERE tag = {string:tag}', array('tag' => $tag)); if (0 == smf_db_affected_rows()) { smf_db_query('INSERT INTO {db_prefix}tags (tag, approved) VALUES ({string:tag}, 1)', array('tag' => $tag)); $ID_TAG = smf_db_insert_id('{db_prefix}tags', 'ID_TAG'); smf_db_query('INSERT INTO {db_prefix}tags_log (ID_TAG, ID_TOPIC, ID_MEMBER) VALUES ({int:id_tag}, {int:topic}, {int:userid})', array('id_tag' => $ID_TAG, 'topic' => $topic, 'userid' => $user_info['id'])); $count++; } else { $row = mysql_fetch_assoc($result); $ID_TAG = $row['ID_TAG']; $result2 = smf_db_query(' SELECT ID FROM {db_prefix}tags_log WHERE ID_TAG = {int:id_tag} AND ID_TOPIC = {int:topic}', array('id_tag' => $ID_TAG, 'topic' => $topic)); if (smf_db_affected_rows() != 0) { continue; } mysql_free_result($result2); smf_db_query('INSERT INTO {db_prefix}tags_log (ID_TAG, ID_TOPIC, ID_MEMBER) VALUES ({int:id_tag}, {int:topic}, {int:userid})', array('id_tag' => $ID_TAG, 'topic' => $topic, 'userid' => $user_info['id'])); $count++; } mysql_free_result($result); } } } } // Editing or posting an event? if (isset($_POST['calendar']) && (!isset($_REQUEST['eventid']) || $_REQUEST['eventid'] == -1)) { require_once $sourcedir . '/lib/Subs-Calendar.php'; // Make sure they can link an event to this post. canLinkEvent(); // Insert the event. $eventOptions = array('board' => $board, 'topic' => $topic, 'title' => $_POST['evtitle'], 'member' => $user_info['id'], 'start_date' => sprintf('%04d-%02d-%02d', $_POST['year'], $_POST['month'], $_POST['day']), 'span' => isset($_POST['span']) && $_POST['span'] > 0 ? min((int) $modSettings['cal_maxspan'], (int) $_POST['span'] - 1) : 0); insertEvent($eventOptions); } elseif (isset($_POST['calendar'])) { $_REQUEST['eventid'] = (int) $_REQUEST['eventid']; // Validate the post... require_once $sourcedir . '/lib/Subs-Calendar.php'; validateEventPost(); // If you're not allowed to edit any events, you have to be the poster. if (!allowedTo('calendar_edit_any')) { // Get the event's poster. $request = smf_db_query(' SELECT id_member FROM {db_prefix}calendar WHERE id_event = {int:id_event}', array('id_event' => $_REQUEST['eventid'])); $row2 = mysql_fetch_assoc($request); mysql_free_result($request); // Silly hacker, Trix are for kids. ...probably trademarked somewhere, this is FAIR USE! (parody...) isAllowedTo('calendar_edit_' . ($row2['id_member'] == $user_info['id'] ? 'own' : 'any')); } // Delete it? if (isset($_REQUEST['deleteevent'])) { smf_db_query(' DELETE FROM {db_prefix}calendar WHERE id_event = {int:id_event}', array('id_event' => $_REQUEST['eventid'])); } else { $span = !empty($modSettings['cal_allowspan']) && !empty($_REQUEST['span']) ? min((int) $modSettings['cal_maxspan'], (int) $_REQUEST['span'] - 1) : 0; $start_time = mktime(0, 0, 0, (int) $_REQUEST['month'], (int) $_REQUEST['day'], (int) $_REQUEST['year']); smf_db_query(' UPDATE {db_prefix}calendar SET end_date = {date:end_date}, start_date = {date:start_date}, title = {string:title} WHERE id_event = {int:id_event}', array('end_date' => strftime('%Y-%m-%d', $start_time + $span * 86400), 'start_date' => strftime('%Y-%m-%d', $start_time), 'id_event' => $_REQUEST['eventid'], 'title' => commonAPI::htmlspecialchars($_REQUEST['evtitle'], ENT_QUOTES))); } updateSettings(array('calendar_updated' => time())); } // Marking read should be done even for editing messages.... // Mark all the parents read. (since you just posted and they will be unread.) if (!$user_info['is_guest'] && !empty($board_info['parent_boards'])) { smf_db_query(' UPDATE {db_prefix}log_boards SET id_msg = {int:id_msg} WHERE id_member = {int:current_member} AND id_board IN ({array_int:board_list})', array('current_member' => $user_info['id'], 'board_list' => array_keys($board_info['parent_boards']), 'id_msg' => $modSettings['maxMsgID'])); } // Turn notification on or off. (note this just blows smoke if it's already on or off.) if (!empty($_POST['notify']) && allowedTo('mark_any_notify')) { smf_db_insert('ignore', '{db_prefix}log_notify', array('id_member' => 'int', 'id_topic' => 'int', 'id_board' => 'int'), array($user_info['id'], $topic, 0), array('id_member', 'id_topic', 'id_board')); } elseif (!$newTopic) { smf_db_query(' DELETE FROM {db_prefix}log_notify WHERE id_member = {int:current_member} AND id_topic = {int:current_topic}', array('current_member' => $user_info['id'], 'current_topic' => $topic)); } // Log an act of moderation - modifying. if (!empty($moderationAction)) { logAction('modify', array('topic' => $topic, 'message' => (int) $_REQUEST['msg'], 'member' => $row['id_member'], 'board' => $board)); } if (isset($_POST['lock']) && $_POST['lock'] != 2) { logAction('lock', array('topic' => $topicOptions['id'], 'board' => $topicOptions['board'])); } if (isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics'])) { logAction('sticky', array('topic' => $topicOptions['id'], 'board' => $topicOptions['board'])); } // Notify any members who have notification turned on for this topic - only do this if it's going to be approved(!) if ($becomesApproved) { if ($newTopic) { $notifyData = array('body' => $_POST['message'], 'subject' => $_POST['subject'], 'name' => $user_info['name'], 'poster' => $user_info['id'], 'msg' => $msgOptions['id'], 'board' => $board, 'topic' => $topic); notifyMembersBoard($notifyData); } elseif (empty($_REQUEST['msg'])) { // Only send it to everyone if the topic is approved, otherwise just to the topic starter if they want it. if ($topic_info['approved']) { sendNotifications($topic, 'reply'); } else { sendNotifications($topic, 'reply', array(), $topic_info['id_member_started']); } } } // Returning to the topic? // Um, did this come from a draft? if (!empty($_POST['draft_id']) && !empty($user_info['id'])) { $_POST['draft_id'] = (int) $_POST['draft_id']; smf_db_query(' DELETE FROM {db_prefix}drafts WHERE id_draft = {int:draft} AND id_member = {int:member} LIMIT 1', array('draft' => $_POST['draft_id'], 'member' => $user_info['id'])); } if (!empty($_REQUEST['goback'])) { // Mark the board as read.... because it might get confusing otherwise. smf_db_query(' UPDATE {db_prefix}log_boards SET id_msg = {int:maxMsgID} WHERE id_member = {int:current_member} AND id_board = {int:current_board}', array('current_board' => $board, 'current_member' => $user_info['id'], 'maxMsgID' => $modSettings['maxMsgID'])); } if ($board_info['num_topics'] == 0) { CacheAPI::putCache('board-' . $board, null, 120); } if (!empty($_POST['announce_topic'])) { redirectexit('action=announce;sa=selectgroup;topic=' . $topic . (!empty($_POST['move']) && allowedTo('move_any') ? ';move' : '') . (empty($_REQUEST['goback']) ? '' : ';goback')); } if (!empty($_POST['move']) && allowedTo('move_any')) { redirectexit('action=movetopic;topic=' . $topic . '.0' . (empty($_REQUEST['goback']) ? '' : ';goback')); } // Return to post if the mod is on. if (isset($_REQUEST['msg']) && !empty($_REQUEST['goback'])) { redirectexit('topic=' . $topic . '.msg' . $_REQUEST['msg'] . '#msg' . $_REQUEST['msg'], $context['browser']['is_ie']); } elseif (!empty($_REQUEST['goback'])) { redirectexit('topic=' . $topic . '.new#new', $context['browser']['is_ie']); } else { redirectexit('board=' . $board . '.0'); } }