/** * Save a new draft, or update an existing draft. */ function saveDraft() { global $smcFunc, $topic, $board, $user_info, $options; if (!isset($_REQUEST['draft']) || $user_info['is_guest'] || empty($options['use_drafts'])) { return false; } $msgid = isset($_REQUEST['msg']) ? $_REQUEST['msg'] : 0; // Clean up what we may or may not have $subject = isset($_POST['subject']) ? $_POST['subject'] : ''; $message = isset($_POST['message']) ? $_POST['message'] : ''; $icon = isset($_POST['icon']) ? preg_replace('~[\\./\\\\*:"\'<>]~', '', $_POST['icon']) : 'xx'; // Sanitise what we do have $subject = commonAPI::htmltrim(commonAPI::htmlspecialchars($subject)); $message = commonAPI::htmlspecialchars($message, ENT_QUOTES); preparsecode($message); if (commonAPI::htmltrim(commonAPI::htmlspecialchars($subject)) === '' && commonAPI::htmltrim(commonAPI::htmlspecialchars($_POST['message']), ENT_QUOTES) === '') { fatal_lang_error('empty_draft', false); } // Hrm, so is this a new draft or not? if (isset($_REQUEST['draft_id']) && (int) $_REQUEST['draft_id'] > 0 || $msgid) { $_REQUEST['draft_id'] = (int) $_REQUEST['draft_id']; $id_cond = $msgid ? ' 1=1 ' : ' id_draft = {int:draft} '; $id_sel = $msgid ? ' AND id_msg = {int:message} ' : ' AND id_board = {int:board} AND id_topic = {int:topic} '; // Does this draft exist? smf_db_query(' UPDATE {db_prefix}drafts SET subject = {string:subject}, body = {string:body}, updated = {int:post_time}, icon = {string:post_icon}, smileys = {int:smileys_enabled}, is_locked = {int:locked}, is_sticky = {int:sticky} WHERE ' . $id_cond . ' AND id_member = {int:member} ' . $id_sel . ' LIMIT 1', array('draft' => $_REQUEST['draft_id'], 'board' => $board, 'topic' => $topic, 'message' => $msgid, 'member' => $user_info['id'], 'subject' => $subject, 'body' => $message, 'post_time' => time(), 'post_icon' => $icon, 'smileys_enabled' => !isset($_POST['ns']) ? 1 : 0, 'locked' => !empty($_POST['lock_draft']) ? 1 : 0, 'sticky' => isset($_POST['sticky']) ? 1 : 0)); if (smf_db_affected_rows() != 0) { return $_REQUEST['draft_id']; } } smf_db_insert('insert', '{db_prefix}drafts', array('id_board' => 'int', 'id_topic' => 'int', 'id_msg' => 'int', 'id_member' => 'int', 'subject' => 'string', 'body' => 'string', 'updated' => 'int', 'icon' => 'string', 'smileys' => 'int', 'is_locked' => 'int', 'is_sticky' => 'int'), array($board, $topic, $msgid, $user_info['id'], $subject, $message, time(), $icon, !isset($_POST['ns']) ? 1 : 0, !empty($_POST['lock_draft']) ? 1 : 0, isset($_POST['sticky']) ? 1 : 0), array('id_draft')); return smf_db_insert_id('{db_prefix}drafts'); }
function RegisterCheckUsername() { global $sourcedir, $context, $txt; // This is XML! loadTemplate('Xml'); $context['sub_template'] = 'check_username'; $context['checked_username'] = isset($_GET['username']) ? $_GET['username'] : ''; $context['valid_username'] = true; // Clean it up like mother would. $context['checked_username'] = preg_replace('~[\\t\\n\\r\\x0B\\0' . ($context['server']['complex_preg_chars'] ? '\\x{A0}' : "Â ") . ']+~u', ' ', $context['checked_username']); if (commonAPI::strlen($context['checked_username']) > 25) { $context['checked_username'] = commonAPI::htmltrim(commonAPI::substr($context['checked_username'], 0, 25)); } // Only these characters are permitted. if (preg_match('~[<>&"\'=\\\\]~', preg_replace('~&#(?:\\d{1,7}|x[0-9a-fA-F]{1,6});~', '', $context['checked_username'])) != 0 || $context['checked_username'] == '_' || $context['checked_username'] == '|' || strpos($context['checked_username'], '[code') !== false || strpos($context['checked_username'], '[/code') !== false) { $context['valid_username'] = false; } if (stristr($context['checked_username'], $txt['guest_title']) !== false) { $context['valid_username'] = false; } if (trim($context['checked_username']) == '') { $context['valid_username'] = false; } else { require_once $sourcedir . '/lib/Subs-Members.php'; $context['valid_username'] &= isReservedName($context['checked_username'], 0, false, false) ? 0 : 1; } }
function ReportToModerator2() { global $txt, $scripturl, $topic, $board, $user_info, $modSettings, $sourcedir, $language, $context, $smcFunc; // You must have the proper permissions! isAllowedTo('report_any'); // Make sure they aren't spamming. spamProtection('reporttm'); require_once $sourcedir . '/lib/Subs-Post.php'; // No errors, yet. $post_errors = array(); // Check their session. if (checkSession('post', '', false) != '') { $post_errors[] = 'session_timeout'; } // Make sure we have a comment and it's clean. if (!isset($_POST['comment']) || commonAPI::htmltrim($_POST['comment']) === '') { $post_errors[] = 'no_comment'; } $poster_comment = strtr(commonAPI::htmlspecialchars($_POST['comment']), array("\r" => '', "\n" => '', "\t" => '')); // Guests need to provide their address! if ($user_info['is_guest']) { $_POST['email'] = !isset($_POST['email']) ? '' : trim($_POST['email']); if ($_POST['email'] === '') { $post_errors[] = 'no_email'; } elseif (preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', $_POST['email']) == 0) { $post_errors[] = 'bad_email'; } isBannedEmail($_POST['email'], 'cannot_post', sprintf($txt['you_are_post_banned'], $txt['guest_title'])); $user_info['email'] = htmlspecialchars($_POST['email']); } // Could they get the right verification code? if ($user_info['is_guest'] && !empty($modSettings['guests_report_require_captcha'])) { require_once $sourcedir . '/lib/Subs-Editor.php'; $verificationOptions = array('id' => 'report'); $context['require_verification'] = create_control_verification($verificationOptions, true); if (is_array($context['require_verification'])) { $post_errors = array_merge($post_errors, $context['require_verification']); } } // Any errors? if (!empty($post_errors)) { loadLanguage('Errors'); $context['post_errors'] = array(); foreach ($post_errors as $post_error) { $context['post_errors'][] = $txt['error_' . $post_error]; } return ReportToModerator(); } // Get the basic topic information, and make sure they can see it. $_POST['msg'] = (int) $_POST['msg']; $request = smf_db_query(' SELECT m.id_topic, m.id_board, m.subject, m.body, m.id_member AS id_poster, m.poster_name, mem.real_name FROM {db_prefix}messages AS m LEFT JOIN {db_prefix}members AS mem ON (m.id_member = mem.id_member) WHERE m.id_msg = {int:id_msg} AND m.id_topic = {int:current_topic} LIMIT 1', array('current_topic' => $topic, 'id_msg' => $_POST['msg'])); if (mysql_num_rows($request) == 0) { fatal_lang_error('no_board', false); } $message = mysql_fetch_assoc($request); mysql_free_result($request); $poster_name = un_htmlspecialchars($message['real_name']) . ($message['real_name'] != $message['poster_name'] ? ' (' . $message['poster_name'] . ')' : ''); $reporterName = un_htmlspecialchars($user_info['name']) . ($user_info['name'] != $user_info['username'] && $user_info['username'] != '' ? ' (' . $user_info['username'] . ')' : ''); $subject = un_htmlspecialchars($message['subject']); // Get a list of members with the moderate_board permission. require_once $sourcedir . '/lib/Subs-Members.php'; $moderators = membersAllowedTo('moderate_board', $board); $request = smf_db_query(' SELECT id_member, email_address, lngfile, mod_prefs FROM {db_prefix}members WHERE id_member IN ({array_int:moderator_list}) AND notify_types != {int:notify_types} ORDER BY lngfile', array('moderator_list' => $moderators, 'notify_types' => 4)); // Check that moderators do exist! if (mysql_num_rows($request) == 0) { fatal_lang_error('no_mods', false); } // If we get here, I believe we should make a record of this, for historical significance, yabber. if (empty($modSettings['disable_log_report'])) { $request2 = smf_db_query(' SELECT id_report, ignore_all FROM {db_prefix}log_reported WHERE id_msg = {int:id_msg} AND (closed = {int:not_closed} OR ignore_all = {int:ignored}) ORDER BY ignore_all DESC', array('id_msg' => $_POST['msg'], 'not_closed' => 0, 'ignored' => 1)); if (mysql_num_rows($request2) != 0) { list($id_report, $ignore) = mysql_fetch_row($request2); } mysql_free_result($request2); // If we're just going to ignore these, then who gives a monkeys... if (!empty($ignore)) { redirectexit('topic=' . $topic . '.msg' . $_POST['msg'] . '#msg' . $_POST['msg']); } // Already reported? My god, we could be dealing with a real rogue here... if (!empty($id_report)) { smf_db_query(' UPDATE {db_prefix}log_reported SET num_reports = num_reports + 1, time_updated = {int:current_time} WHERE id_report = {int:id_report}', array('current_time' => time(), 'id_report' => $id_report)); } else { if (empty($message['real_name'])) { $message['real_name'] = $message['poster_name']; } smf_db_insert('', '{db_prefix}log_reported', array('id_msg' => 'int', 'id_topic' => 'int', 'id_board' => 'int', 'id_member' => 'int', 'membername' => 'string', 'subject' => 'string', 'body' => 'string', 'time_started' => 'int', 'time_updated' => 'int', 'num_reports' => 'int', 'closed' => 'int'), array($_POST['msg'], $message['id_topic'], $message['id_board'], $message['id_poster'], $message['real_name'], $message['subject'], $message['body'], time(), time(), 1, 0), array('id_report')); $id_report = smf_db_insert_id('{db_prefix}log_reported', 'id_report'); } // Now just add our report... if ($id_report) { smf_db_insert('', '{db_prefix}log_reported_comments', array('id_report' => 'int', 'id_member' => 'int', 'membername' => 'string', 'email_address' => 'string', 'member_ip' => 'string', 'comment' => 'string', 'time_sent' => 'int'), array($id_report, $user_info['id'], $user_info['name'], $user_info['email'], $user_info['ip'], $poster_comment, time()), array('id_comment')); } } // Find out who the real moderators are - for mod preferences. $request2 = smf_db_query(' SELECT id_member FROM {db_prefix}moderators WHERE id_board = {int:current_board}', array('current_board' => $board)); $real_mods = array(); while ($row = mysql_fetch_assoc($request2)) { $real_mods[] = $row['id_member']; } mysql_free_result($request2); // Send every moderator an email. while ($row = mysql_fetch_assoc($request)) { // Maybe they don't want to know?! if (!empty($row['mod_prefs'])) { list(, , $pref_binary) = explode('|', $row['mod_prefs']); if (!($pref_binary & 1) && (!($pref_binary & 2) || !in_array($row['id_member'], $real_mods))) { continue; } } $replacements = array('TOPICSUBJECT' => $subject, 'POSTERNAME' => $poster_name, 'REPORTERNAME' => $reporterName, 'TOPICLINK' => $scripturl . '?topic=' . $topic . '.msg' . $_POST['msg'] . '#msg' . $_POST['msg'], 'REPORTLINK' => !empty($id_report) ? $scripturl . '?action=moderate;area=reports;report=' . $id_report : '', 'COMMENT' => $_POST['comment']); $emaildata = loadEmailTemplate('report_to_moderator', $replacements, empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']); // Send it to the moderator. sendmail($row['email_address'], $emaildata['subject'], $emaildata['body'], $user_info['email'], null, false, 2); } mysql_free_result($request); // Keep track of when the mod reports get updated, that way we know when we need to look again. updateSettings(array('last_mod_report_action' => time())); // Back to the post we reported! redirectexit('reportsent;topic=' . $topic . '.msg' . $_POST['msg'] . '#msg' . $_POST['msg']); }
function JavaScriptModify() { global $sourcedir, $modSettings, $board, $topic, $txt; global $user_info, $context, $language; // We have to have a topic! if (empty($topic)) { obExit(false); } checkSession('get'); require_once $sourcedir . '/lib/Subs-Post.php'; // Assume the first message if no message ID was given. $request = smf_db_query(' SELECT t.locked, t.num_replies, t.id_member_started, t.id_first_msg, m.id_msg, m.id_member, m.poster_time, m.subject, m.smileys_enabled, m.body, m.icon, m.modified_time, m.modified_name, m.approved, ba.id_topic AS banned_from_topic FROM {db_prefix}messages AS m INNER JOIN {db_prefix}topics AS t ON (t.id_topic = {int:current_topic}) LEFT JOIN {db_prefix}topicbans AS ba ON (ba.id_topic = {int:current_topic} AND ba.id_member = {int:current_member}) WHERE m.id_msg = {raw:id_msg} AND m.id_topic = {int:current_topic}' . (allowedTo('approve_posts') ? '' : (!$modSettings['postmod_active'] ? ' AND (m.id_member != {int:guest_id} AND m.id_member = {int:current_member})' : ' AND (m.approved = {int:is_approved} OR (m.id_member != {int:guest_id} AND m.id_member = {int:current_member}))')), array('current_member' => $user_info['id'], 'current_topic' => $topic, 'id_msg' => empty($_REQUEST['msg']) ? 't.id_first_msg' : (int) $_REQUEST['msg'], 'is_approved' => 1, 'guest_id' => 0)); if (mysql_num_rows($request) == 0) { fatal_lang_error('no_board', false); } $row = mysql_fetch_assoc($request); mysql_free_result($request); // Change either body or subject requires permissions to modify messages. if (isset($_POST['message']) || isset($_POST['subject']) || isset($_REQUEST['icon'])) { if (!empty($row['locked'])) { isAllowedTo('moderate_board'); } 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 ($row['id_member_started'] == $user_info['id'] && !allowedTo('modify_own')) { isAllowedTo('modify_replies'); } else { isAllowedTo('modify_own'); } } elseif ($row['id_member_started'] == $user_info['id'] && !allowedTo('modify_any')) { isAllowedTo('modify_replies'); } else { isAllowedTo('modify_any'); } // check topic bans if ($row['banned_from_topic'] != 0 && !$user_info['is_admin'] && !allowedTo('moderate_board') && !allowedTo('moderate_forum')) { fatal_lang_error('banned_from_topic'); } // Only log this action if it wasn't your message. $moderationAction = $row['id_member'] != $user_info['id']; } $post_errors = array(); if (isset($_POST['subject']) && commonAPI::htmltrim(commonAPI::htmlspecialchars($_POST['subject'])) !== '') { $_POST['subject'] = strtr(commonAPI::htmlspecialchars($_POST['subject']), array("\r" => '', "\n" => '', "\t" => '')); // Maximum number of characters. if (commonAPI::strlen($_POST['subject']) > 100) { $_POST['subject'] = commonAPI::substr($_POST['subject'], 0, 100); } } elseif (isset($_POST['subject'])) { $post_errors[] = 'no_subject'; unset($_POST['subject']); } if (isset($_POST['message'])) { if (commonAPI::htmltrim(commonAPI::htmlspecialchars($_POST['message'])) === '') { $post_errors[] = 'no_message'; unset($_POST['message']); } elseif (!empty($modSettings['max_messageLength']) && commonAPI::strlen($_POST['message']) > $modSettings['max_messageLength']) { $post_errors[] = 'long_message'; unset($_POST['message']); } else { $_POST['message'] = commonAPI::htmlspecialchars($_POST['message'], ENT_QUOTES); preparsecode($_POST['message']); if (commonAPI::htmltrim(strip_tags(parse_bbc($_POST['message'], false), '<img>')) === '') { $post_errors[] = 'no_message'; unset($_POST['message']); } } } if (isset($_POST['lock'])) { if (!allowedTo(array('lock_any', 'lock_own')) || !allowedTo('lock_any') && $user_info['id'] != $row['id_member']) { unset($_POST['lock']); } elseif (!allowedTo('lock_any')) { if ($row['locked'] == 1) { unset($_POST['lock']); } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 2; } } elseif (!empty($row['locked']) && !empty($_POST['lock']) || $_POST['lock'] == $row['locked']) { unset($_POST['lock']); } else { $_POST['lock'] = empty($_POST['lock']) ? 0 : 1; } } if (isset($_POST['sticky']) && !allowedTo('make_sticky')) { unset($_POST['sticky']); } if (empty($post_errors)) { $msgOptions = array('id' => $row['id_msg'], 'subject' => isset($_POST['subject']) ? $_POST['subject'] : null, 'body' => isset($_POST['message']) ? $_POST['message'] : null, 'icon' => isset($_REQUEST['icon']) ? preg_replace('~[\\./\\\\*\':"<>]~', '', $_REQUEST['icon']) : null, 'id_owner' => $row['id_member']); $topicOptions = array('id' => $topic, 'board' => $board, '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); $posterOptions = array(); // Only consider marking as editing if they have edited the subject, message or icon. if (isset($_POST['subject']) && $_POST['subject'] != $row['subject'] || isset($_POST['message']) && $_POST['message'] != $row['body'] || isset($_REQUEST['icon']) && $_REQUEST['icon'] != $row['icon']) { // And even then only if the time has passed... 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']; } } else { $moderationAction = false; } modifyPost($msgOptions, $topicOptions, $posterOptions); // If we didn't change anything this time but had before put back the old info. if (!isset($msgOptions['modify_time']) && !empty($row['modified_time'])) { $msgOptions['modify_time'] = $row['modified_time']; $msgOptions['modify_name'] = $row['modified_name']; } // Changing the first subject updates other subjects to 'Re: new_subject'. if (isset($_POST['subject']) && isset($_REQUEST['change_all_subjects']) && $row['id_first_msg'] == $row['id_msg'] && !empty($row['num_replies']) && (allowedTo('modify_any') || $row['id_member_started'] == $user_info['id'] && allowedTo('modify_replies'))) { // Get the proper (default language) response prefix first. if (!isset($context['response_prefix']) && !($context['response_prefix'] = CacheAPI::getCache('response_prefix'))) { if ($language === $user_info['language']) { $context['response_prefix'] = $txt['response_prefix']; } else { loadLanguage('index', $language, false); $context['response_prefix'] = $txt['response_prefix']; loadLanguage('index'); } CacheAPI::putCache('response_prefix', $context['response_prefix'], 600); } smf_db_query(' UPDATE {db_prefix}messages SET subject = {string:subject} WHERE id_topic = {int:current_topic} AND id_msg != {int:id_first_msg}', array('current_topic' => $topic, 'id_first_msg' => $row['id_first_msg'], 'subject' => $context['response_prefix'] . $_POST['subject'])); } if (!empty($moderationAction)) { logAction('modify', array('topic' => $topic, 'message' => $row['id_msg'], 'member' => $row['id_member'], 'board' => $board)); } } if (isset($_REQUEST['xml'])) { $context['sub_template'] = 'modifydone'; if (empty($post_errors) && isset($msgOptions['subject']) && isset($msgOptions['body'])) { $context['message'] = array('id' => $row['id_msg'], 'modified' => array('time' => isset($msgOptions['modify_time']) ? timeformat($msgOptions['modify_time']) : '', 'timestamp' => isset($msgOptions['modify_time']) ? forum_time(true, $msgOptions['modify_time']) : 0, 'name' => isset($msgOptions['modify_time']) ? $msgOptions['modify_name'] : ''), 'subject' => $msgOptions['subject'], 'first_in_topic' => $row['id_msg'] == $row['id_first_msg'], 'body' => strtr($msgOptions['body'], array(']]>' => ']]]]><![CDATA[>'))); censorText($context['message']['subject']); censorText($context['message']['body']); $cache_key = isset($msgOptions['modify_time']) ? $row['id_msg'] . '|' . $msgOptions['modify_time'] : $row['id_msg']; $context['message']['body'] = parse_bbc($context['message']['body'], $row['smileys_enabled'], $cache_key); parse_bbc_stage2($context['message']['body']); } elseif (empty($post_errors)) { $context['sub_template'] = 'modifytopicdone'; $context['message'] = array('id' => $row['id_msg'], 'icon' => isset($_REQUEST['icon']) ? $_REQUEST['icon'] : '', 'modified' => array('time' => isset($msgOptions['modify_time']) ? timeformat($msgOptions['modify_time']) : '', 'timestamp' => isset($msgOptions['modify_time']) ? forum_time(true, $msgOptions['modify_time']) : 0, 'name' => isset($msgOptions['modify_time']) ? $msgOptions['modify_name'] : ''), 'subject' => isset($msgOptions['subject']) ? $msgOptions['subject'] : ''); censorText($context['message']['subject']); } else { $context['message'] = array('id' => $row['id_msg'], 'errors' => array(), 'error_in_subject' => in_array('no_subject', $post_errors), 'error_in_body' => in_array('no_message', $post_errors) || in_array('long_message', $post_errors)); loadLanguage('Errors'); foreach ($post_errors as $post_error) { if ($post_error == 'long_message') { $context['message']['errors'][] = sprintf($txt['error_' . $post_error], $modSettings['max_messageLength']); } else { $context['message']['errors'][] = $txt['error_' . $post_error]; } } } } else { obExit(false); } }
function MoveTopic2() { global $txt, $board, $topic, $scripturl, $sourcedir, $modSettings, $context; global $board, $language, $user_info, $smcFunc; if (empty($topic)) { fatal_lang_error('no_access', false); } // You can't choose to have a redirection topic and use an empty reason. if (isset($_POST['postRedirect']) && (!isset($_POST['reason']) || trim($_POST['reason']) == '')) { fatal_lang_error('movetopic_no_reason', false); } // Make sure this form hasn't been submitted before. checkSubmitOnce('check'); $request = smf_db_query(' SELECT id_member_started, id_first_msg, approved FROM {db_prefix}topics WHERE id_topic = {int:current_topic} LIMIT 1', array('current_topic' => $topic)); list($id_member_started, $id_first_msg, $context['is_approved']) = mysql_fetch_row($request); mysql_free_result($request); // Can they see it? if (!$context['is_approved']) { isAllowedTo('approve_posts'); } // Can they move topics on this board? if (!allowedTo('move_any')) { if ($id_member_started == $user_info['id']) { isAllowedTo('move_own'); $boards = array_merge(boardsAllowedTo('move_own'), boardsAllowedTo('move_any')); } else { isAllowedTo('move_any'); } } else { $boards = boardsAllowedTo('move_any'); } // If this topic isn't approved don't let them move it if they can't approve it! if ($modSettings['postmod_active'] && !$context['is_approved'] && !allowedTo('approve_posts')) { // Only allow them to move it to other boards they can't approve it in. $can_approve = boardsAllowedTo('approve_posts'); $boards = array_intersect($boards, $can_approve); } checkSession(); require_once $sourcedir . '/lib/Subs-Post.php'; // The destination board must be numeric. $_POST['toboard'] = (int) $_POST['toboard']; // Make sure they can see the board they are trying to move to (and get whether posts count in the target board). $request = smf_db_query(' SELECT b.count_posts, b.name, m.subject FROM {db_prefix}boards AS b INNER JOIN {db_prefix}topics AS t ON (t.id_topic = {int:current_topic}) INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg) WHERE {query_see_board} AND b.id_board = {int:to_board} AND b.redirect = {string:blank_redirect} LIMIT 1', array('current_topic' => $topic, 'to_board' => $_POST['toboard'], 'blank_redirect' => '')); if (mysql_num_rows($request) == 0) { fatal_lang_error('no_board'); } list($pcounter, $board_name, $subject) = mysql_fetch_row($request); mysql_free_result($request); // Remember this for later. $_SESSION['move_to_topic'] = $_POST['toboard']; // Rename the topic... if (isset($_POST['reset_subject'], $_POST['custom_subject']) && $_POST['custom_subject'] != '') { $_POST['custom_subject'] = strtr(commonAPI::htmltrim(commonAPI::htmlspecialchars($_POST['custom_subject'])), array("\r" => '', "\n" => '', "\t" => '')); // Keep checking the length. if (commonAPI::strlen($_POST['custom_subject']) > 100) { $_POST['custom_subject'] = commonAPI::substr($_POST['custom_subject'], 0, 100); } // If it's still valid move onwards and upwards. if ($_POST['custom_subject'] != '') { if (isset($_POST['enforce_subject'])) { // Get a response prefix, but in the forum's default language. if (!isset($context['response_prefix']) && !($context['response_prefix'] = CacheAPI::getCache('response_prefix'))) { if ($language === $user_info['language']) { $context['response_prefix'] = $txt['response_prefix']; } else { loadLanguage('index', $language, false); $context['response_prefix'] = $txt['response_prefix']; loadLanguage('index'); } CacheAPI::putCache('response_prefix', $context['response_prefix'], 600); } smf_db_query(' UPDATE {db_prefix}messages SET subject = {string:subject} WHERE id_topic = {int:current_topic}', array('current_topic' => $topic, 'subject' => $context['response_prefix'] . $_POST['custom_subject'])); } smf_db_query(' UPDATE {db_prefix}messages SET subject = {string:custom_subject} WHERE id_msg = {int:id_first_msg}', array('id_first_msg' => $id_first_msg, 'custom_subject' => $_POST['custom_subject'])); // Fix the subject cache. updateStats('subject', $topic, $_POST['custom_subject']); } } // Create a link to this in the old board. //!!! Does this make sense if the topic was unapproved before? I'd just about say so. if (isset($_POST['postRedirect'])) { // Should be in the boardwide language. if ($user_info['language'] != $language) { loadLanguage('index', $language); } $_POST['reason'] = commonAPI::htmlspecialchars($_POST['reason'], ENT_QUOTES); preparsecode($_POST['reason']); // Add a URL onto the message. $_POST['reason'] = strtr($_POST['reason'], array($txt['movetopic_auto_board'] => '[url=' . $scripturl . '?board=' . $_POST['toboard'] . '.0]' . $board_name . '[/url]', $txt['movetopic_auto_topic'] => '[iurl]' . $scripturl . '?topic=' . $topic . '.0[/iurl]')); $msgOptions = array('subject' => $txt['moved'] . ': ' . $subject, 'body' => $_POST['reason'], 'icon' => 'moved', 'smileys_enabled' => 1); $topicOptions = array('board' => $board, 'lock_mode' => 1, 'mark_as_read' => true, 'topic_prefix' => 0, 'topic_layout' => 0); $posterOptions = array('id' => $user_info['id'], 'update_post_count' => empty($pcounter)); createPost($msgOptions, $topicOptions, $posterOptions); } $request = smf_db_query(' SELECT count_posts FROM {db_prefix}boards WHERE id_board = {int:current_board} LIMIT 1', array('current_board' => $board)); list($pcounter_from) = mysql_fetch_row($request); mysql_free_result($request); if ($pcounter_from != $pcounter) { $request = smf_db_query(' SELECT id_member FROM {db_prefix}messages WHERE id_topic = {int:current_topic} AND approved = {int:is_approved}', array('current_topic' => $topic, 'is_approved' => 1)); $posters = array(); while ($row = mysql_fetch_assoc($request)) { if (!isset($posters[$row['id_member']])) { $posters[$row['id_member']] = 0; } $posters[$row['id_member']]++; } mysql_free_result($request); foreach ($posters as $id_member => $posts) { // The board we're moving from counted posts, but not to. if (empty($pcounter_from)) { updateMemberData($id_member, array('posts' => 'posts - ' . $posts)); } else { updateMemberData($id_member, array('posts' => 'posts + ' . $posts)); } } } // Do the move (includes statistics update needed for the redirect topic). moveTopics($topic, $_POST['toboard']); // Log that they moved this topic. if (!allowedTo('move_own') || $id_member_started != $user_info['id']) { logAction('move', array('topic' => $topic, 'board_from' => $board, 'board_to' => $_POST['toboard'])); } // Notify people that this topic has been moved? sendNotifications($topic, 'move'); // Why not go back to the original board in case they want to keep moving? if (!isset($_REQUEST['goback'])) { redirectexit('board=' . $board . '.0'); } else { redirectexit('topic=' . $topic . '.0'); } }
function htmltrim__recursive($var, $level = 0) { global $smcFunc; // Remove spaces (32), tabs (9), returns (13, 10, and 11), nulls (0), and hard spaces. (160) if (!is_array($var)) { return isset($smcFunc) ? commonAPI::htmltrim($var) : trim($var, ' ' . "\t\n\r\v" . '\\0' . "�"); } // Go through all the elements and remove the whitespace. foreach ($var as $k => $v) { $var[$k] = $level > 25 ? null : htmltrim__recursive($v, $level + 1); } return $var; }
function MergeExecute($topics = array()) { global $user_info, $txt, $context, $scripturl, $sourcedir; global $smcFunc, $language, $modSettings; // Check the session. checkSession('request'); // Handle URLs from MergeIndex. if (!empty($_GET['from']) && !empty($_GET['to'])) { $topics = array((int) $_GET['from'], (int) $_GET['to']); } // If we came from a form, the topic IDs came by post. if (!empty($_POST['topics']) && is_array($_POST['topics'])) { $topics = $_POST['topics']; } // There's nothing to merge with just one topic... if (empty($topics) || !is_array($topics) || count($topics) == 1) { fatal_lang_error('merge_need_more_topics'); } // Make sure every topic is numeric, or some nasty things could be done with the DB. foreach ($topics as $id => $topic) { $topics[$id] = (int) $topic; } // Joy of all joys, make sure they're not pi**ing about with unapproved topics they can't see :P if ($modSettings['postmod_active']) { $can_approve_boards = boardsAllowedTo('approve_posts'); } // Get info about the topics and polls that will be merged. $request = smf_db_query(' SELECT t.id_topic, t.id_board, t.id_poll, t.num_views, t.is_sticky, t.approved, t.num_replies, t.unapproved_posts, m1.subject, m1.poster_time AS time_started, IFNULL(mem1.id_member, 0) AS id_member_started, IFNULL(mem1.real_name, m1.poster_name) AS name_started, m2.poster_time AS time_updated, IFNULL(mem2.id_member, 0) AS id_member_updated, IFNULL(mem2.real_name, m2.poster_name) AS name_updated FROM {db_prefix}topics AS t INNER JOIN {db_prefix}messages AS m1 ON (m1.id_msg = t.id_first_msg) INNER JOIN {db_prefix}messages AS m2 ON (m2.id_msg = t.id_last_msg) LEFT JOIN {db_prefix}members AS mem1 ON (mem1.id_member = m1.id_member) LEFT JOIN {db_prefix}members AS mem2 ON (mem2.id_member = m2.id_member) WHERE t.id_topic IN ({array_int:topic_list}) ORDER BY t.id_first_msg LIMIT ' . count($topics), array('topic_list' => $topics)); if (mysql_num_rows($request) < 2) { fatal_lang_error('no_topic_id'); } $num_views = 0; $is_sticky = 0; $boardTotals = array(); $boards = array(); $polls = array(); while ($row = mysql_fetch_assoc($request)) { // Make a note for the board counts... if (!isset($boardTotals[$row['id_board']])) { $boardTotals[$row['id_board']] = array('posts' => 0, 'topics' => 0, 'unapproved_posts' => 0, 'unapproved_topics' => 0); } // We can't see unapproved topics here? if ($modSettings['postmod_active'] && !$row['approved'] && $can_approve_boards != array(0) && in_array($row['id_board'], $can_approve_boards)) { continue; } elseif (!$row['approved']) { $boardTotals[$row['id_board']]['unapproved_topics']++; } else { $boardTotals[$row['id_board']]['topics']++; } $boardTotals[$row['id_board']]['unapproved_posts'] += $row['unapproved_posts']; $boardTotals[$row['id_board']]['posts'] += $row['num_replies'] + ($row['approved'] ? 1 : 0); $topic_data[$row['id_topic']] = array('id' => $row['id_topic'], 'board' => $row['id_board'], 'poll' => $row['id_poll'], 'num_views' => $row['num_views'], 'subject' => $row['subject'], 'started' => array('time' => timeformat($row['time_started']), 'timestamp' => forum_time(true, $row['time_started']), 'href' => empty($row['id_member_started']) ? '' : $scripturl . '?action=profile;u=' . $row['id_member_started'], 'link' => empty($row['id_member_started']) ? $row['name_started'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member_started'] . '">' . $row['name_started'] . '</a>'), 'updated' => array('time' => timeformat($row['time_updated']), 'timestamp' => forum_time(true, $row['time_updated']), 'href' => empty($row['id_member_updated']) ? '' : $scripturl . '?action=profile;u=' . $row['id_member_updated'], 'link' => empty($row['id_member_updated']) ? $row['name_updated'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member_updated'] . '">' . $row['name_updated'] . '</a>')); $num_views += $row['num_views']; $boards[] = $row['id_board']; // If there's no poll, id_poll == 0... if ($row['id_poll'] > 0) { $polls[] = $row['id_poll']; } // Store the id_topic with the lowest id_first_msg. if (empty($firstTopic)) { $firstTopic = $row['id_topic']; } $is_sticky = max($is_sticky, $row['is_sticky']); } mysql_free_result($request); // If we didn't get any topics then they've been messing with unapproved stuff. if (empty($topic_data)) { fatal_lang_error('no_topic_id'); } $boards = array_values(array_unique($boards)); // The parameters of MergeExecute were set, so this must've been an internal call. if (!empty($topics)) { isAllowedTo('merge_any', $boards); loadTemplate('SplitTopics'); } // Get the boards a user is allowed to merge in. $merge_boards = boardsAllowedTo('merge_any'); if (empty($merge_boards)) { fatal_lang_error('cannot_merge_any', 'user'); } // Make sure they can see all boards.... $request = smf_db_query(' SELECT b.id_board FROM {db_prefix}boards AS b WHERE b.id_board IN ({array_int:boards}) AND {query_see_board}' . (!in_array(0, $merge_boards) ? ' AND b.id_board IN ({array_int:merge_boards})' : '') . ' LIMIT ' . count($boards), array('boards' => $boards, 'merge_boards' => $merge_boards)); // If the number of boards that's in the output isn't exactly the same as we've put in there, you're in trouble. if (mysql_num_rows($request) != count($boards)) { fatal_lang_error('no_board'); } mysql_free_result($request); if (empty($_REQUEST['sa']) || $_REQUEST['sa'] == 'options') { if (count($polls) > 1) { $request = smf_db_query(' SELECT t.id_topic, t.id_poll, m.subject, p.question FROM {db_prefix}polls AS p INNER JOIN {db_prefix}topics AS t ON (t.id_poll = p.id_poll) INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg) WHERE p.id_poll IN ({array_int:polls}) LIMIT ' . count($polls), array('polls' => $polls)); while ($row = mysql_fetch_assoc($request)) { $context['polls'][] = array('id' => $row['id_poll'], 'topic' => array('id' => $row['id_topic'], 'subject' => $row['subject']), 'question' => $row['question'], 'selected' => $row['id_topic'] == $firstTopic); } mysql_free_result($request); } if (count($boards) > 1) { $request = smf_db_query(' SELECT id_board, name FROM {db_prefix}boards WHERE id_board IN ({array_int:boards}) ORDER BY name LIMIT ' . count($boards), array('boards' => $boards)); while ($row = mysql_fetch_assoc($request)) { $context['boards'][] = array('id' => $row['id_board'], 'name' => $row['name'], 'selected' => $row['id_board'] == $topic_data[$firstTopic]['board']); } mysql_free_result($request); } $context['topics'] = $topic_data; foreach ($topic_data as $id => $topic) { $context['topics'][$id]['selected'] = $topic['id'] == $firstTopic; } $context['page_title'] = $txt['merge']; $context['sub_template'] = 'merge_extra_options'; return; } // Determine target board. $target_board = count($boards) > 1 ? (int) $_REQUEST['board'] : $boards[0]; if (!in_array($target_board, $boards)) { fatal_lang_error('no_board'); } // Determine which poll will survive and which polls won't. $target_poll = count($polls) > 1 ? (int) $_POST['poll'] : (count($polls) == 1 ? $polls[0] : 0); if ($target_poll > 0 && !in_array($target_poll, $polls)) { fatal_lang_error('no_access', false); } $deleted_polls = empty($target_poll) ? $polls : array_diff($polls, array($target_poll)); // Determine the subject of the newly merged topic - was a custom subject specified? if (empty($_POST['subject']) && isset($_POST['custom_subject']) && $_POST['custom_subject'] != '') { $target_subject = strtr(commonAPI::htmltrim(commonAPI::htmlspecialchars($_POST['custom_subject'])), array("\r" => '', "\n" => '', "\t" => '')); // Keep checking the length. if (commonAPI::strlen($target_subject) > 100) { $target_subject = commonAPI::substr($target_subject, 0, 100); } // Nothing left - odd but pick the first topics subject. if ($target_subject == '') { $target_subject = $topic_data[$firstTopic]['subject']; } } elseif (!empty($topic_data[(int) $_POST['subject']]['subject'])) { $target_subject = $topic_data[(int) $_POST['subject']]['subject']; } else { $target_subject = $topic_data[$firstTopic]['subject']; } // Get the first and last message and the number of messages.... $request = smf_db_query(' SELECT approved, MIN(id_msg) AS first_msg, MAX(id_msg) AS last_msg, COUNT(*) AS message_count FROM {db_prefix}messages WHERE id_topic IN ({array_int:topics}) GROUP BY approved ORDER BY approved DESC', array('topics' => $topics)); $topic_approved = 1; while ($row = mysql_fetch_assoc($request)) { // If this is approved, or is fully unapproved. if ($row['approved'] || !isset($first_msg)) { $first_msg = $row['first_msg']; $last_msg = $row['last_msg']; if ($row['approved']) { $num_replies = $row['message_count'] - 1; $num_unapproved = 0; } else { $topic_approved = 0; $num_replies = 0; $num_unapproved = $row['message_count']; } } else { // If this has a lower first_msg then the first post is not approved and hence the number of replies was wrong! if ($first_msg > $row['first_msg']) { $first_msg = $row['first_msg']; $num_replies++; $topic_approved = 0; } $num_unapproved = $row['message_count']; } } mysql_free_result($request); // Ensure we have a board stat for the target board. if (!isset($boardTotals[$target_board])) { $boardTotals[$target_board] = array('posts' => 0, 'topics' => 0, 'unapproved_posts' => 0, 'unapproved_topics' => 0); } // Fix the topic count stuff depending on what the new one counts as. if ($topic_approved) { $boardTotals[$target_board]['topics']--; } else { $boardTotals[$target_board]['unapproved_topics']--; } $boardTotals[$target_board]['unapproved_posts'] -= $num_unapproved; $boardTotals[$target_board]['posts'] -= $topic_approved ? $num_replies + 1 : $num_replies; // Get the member ID of the first and last message. $request = smf_db_query(' SELECT id_member FROM {db_prefix}messages WHERE id_msg IN ({int:first_msg}, {int:last_msg}) ORDER BY id_msg LIMIT 2', array('first_msg' => $first_msg, 'last_msg' => $last_msg)); list($member_started) = mysql_fetch_row($request); list($member_updated) = mysql_fetch_row($request); // First and last message are the same, so only row was returned. if ($member_updated === NULL) { $member_updated = $member_started; } mysql_free_result($request); // Assign the first topic ID to be the merged topic. $id_topic = min($topics); // Delete the remaining topics. $deleted_topics = array_diff($topics, array($id_topic)); smf_db_query(' DELETE FROM {db_prefix}topics WHERE id_topic IN ({array_int:deleted_topics})', array('deleted_topics' => $deleted_topics)); smf_db_query(' DELETE FROM {db_prefix}log_search_subjects WHERE id_topic IN ({array_int:deleted_topics})', array('deleted_topics' => $deleted_topics)); // Asssign the properties of the newly merged topic. smf_db_query(' UPDATE {db_prefix}topics SET id_board = {int:id_board}, id_member_started = {int:id_member_started}, id_member_updated = {int:id_member_updated}, id_first_msg = {int:id_first_msg}, id_last_msg = {int:id_last_msg}, id_poll = {int:id_poll}, num_replies = {int:num_replies}, unapproved_posts = {int:unapproved_posts}, num_views = {int:num_views}, is_sticky = {int:is_sticky}, approved = {int:approved} WHERE id_topic = {int:id_topic}', array('id_board' => $target_board, 'is_sticky' => $is_sticky, 'approved' => $topic_approved, 'id_topic' => $id_topic, 'id_member_started' => $member_started, 'id_member_updated' => $member_updated, 'id_first_msg' => $first_msg, 'id_last_msg' => $last_msg, 'id_poll' => $target_poll, 'num_replies' => $num_replies, 'unapproved_posts' => $num_unapproved, 'num_views' => $num_views)); // Grab the response prefix (like 'Re: ') in the default forum language. if (!isset($context['response_prefix']) && !($context['response_prefix'] = CacheAPI::getCache('response_prefix'))) { if ($language === $user_info['language']) { $context['response_prefix'] = $txt['response_prefix']; } else { loadLanguage('index', $language, false); $context['response_prefix'] = $txt['response_prefix']; loadLanguage('index'); } CacheAPI::putCache('response_prefix', $context['response_prefix'], 600); } // Change the topic IDs of all messages that will be merged. Also adjust subjects if 'enforce subject' was checked. smf_db_query(' UPDATE {db_prefix}messages SET id_topic = {int:id_topic}, id_board = {int:target_board}' . (empty($_POST['enforce_subject']) ? '' : ', subject = {string:subject}') . ' WHERE id_topic IN ({array_int:topic_list})', array('topic_list' => $topics, 'id_topic' => $id_topic, 'target_board' => $target_board, 'subject' => $context['response_prefix'] . $target_subject)); // Any reported posts should reflect the new board. smf_db_query(' UPDATE {db_prefix}log_reported SET id_topic = {int:id_topic}, id_board = {int:target_board} WHERE id_topic IN ({array_int:topics_list})', array('topics_list' => $topics, 'id_topic' => $id_topic, 'target_board' => $target_board)); // Change the subject of the first message... smf_db_query(' UPDATE {db_prefix}messages SET subject = {string:target_subject} WHERE id_msg = {int:first_msg}', array('first_msg' => $first_msg, 'target_subject' => $target_subject)); // Adjust all calendar events to point to the new topic. smf_db_query(' UPDATE {db_prefix}calendar SET id_topic = {int:id_topic}, id_board = {int:target_board} WHERE id_topic IN ({array_int:deleted_topics})', array('deleted_topics' => $deleted_topics, 'id_topic' => $id_topic, 'target_board' => $target_board)); // Merge log topic entries. $request = smf_db_query(' SELECT id_member, MIN(id_msg) AS new_id_msg FROM {db_prefix}log_topics WHERE id_topic IN ({array_int:topics}) GROUP BY id_member', array('topics' => $topics)); if (mysql_num_rows($request) > 0) { $replaceEntries = array(); while ($row = mysql_fetch_assoc($request)) { $replaceEntries[] = array($row['id_member'], $id_topic, $row['new_id_msg']); } smf_db_insert('replace', '{db_prefix}log_topics', array('id_member' => 'int', 'id_topic' => 'int', 'id_msg' => 'int'), $replaceEntries, array('id_member', 'id_topic')); unset($replaceEntries); // Get rid of the old log entries. smf_db_query(' DELETE FROM {db_prefix}log_topics WHERE id_topic IN ({array_int:deleted_topics})', array('deleted_topics' => $deleted_topics)); } mysql_free_result($request); // Merge topic notifications. $notifications = isset($_POST['notifications']) && is_array($_POST['notifications']) ? array_intersect($topics, $_POST['notifications']) : array(); if (!empty($notifications)) { $request = smf_db_query(' SELECT id_member, MAX(sent) AS sent FROM {db_prefix}log_notify WHERE id_topic IN ({array_int:topics_list}) GROUP BY id_member', array('topics_list' => $notifications)); if (mysql_num_rows($request) > 0) { $replaceEntries = array(); while ($row = mysql_fetch_assoc($request)) { $replaceEntries[] = array($row['id_member'], $id_topic, 0, $row['sent']); } smf_db_insert('replace', '{db_prefix}log_notify', array('id_member' => 'int', 'id_topic' => 'int', 'id_board' => 'int', 'sent' => 'int'), $replaceEntries, array('id_member', 'id_topic', 'id_board')); unset($replaceEntries); smf_db_query(' DELETE FROM {db_prefix}log_topics WHERE id_topic IN ({array_int:deleted_topics})', array('deleted_topics' => $deleted_topics)); } mysql_free_result($request); } // Get rid of the redundant polls. if (!empty($deleted_polls)) { smf_db_query(' DELETE FROM {db_prefix}polls WHERE id_poll IN ({array_int:deleted_polls})', array('deleted_polls' => $deleted_polls)); smf_db_query(' DELETE FROM {db_prefix}poll_choices WHERE id_poll IN ({array_int:deleted_polls})', array('deleted_polls' => $deleted_polls)); smf_db_query(' DELETE FROM {db_prefix}log_polls WHERE id_poll IN ({array_int:deleted_polls})', array('deleted_polls' => $deleted_polls)); } // Cycle through each board... foreach ($boardTotals as $id_board => $stats) { smf_db_query(' UPDATE {db_prefix}boards SET num_topics = CASE WHEN {int:topics} > num_topics THEN 0 ELSE num_topics - {int:topics} END, unapproved_topics = CASE WHEN {int:unapproved_topics} > unapproved_topics THEN 0 ELSE unapproved_topics - {int:unapproved_topics} END, num_posts = CASE WHEN {int:posts} > num_posts THEN 0 ELSE num_posts - {int:posts} END, unapproved_posts = CASE WHEN {int:unapproved_posts} > unapproved_posts THEN 0 ELSE unapproved_posts - {int:unapproved_posts} END WHERE id_board = {int:id_board}', array('id_board' => $id_board, 'topics' => $stats['topics'], 'unapproved_topics' => $stats['unapproved_topics'], 'posts' => $stats['posts'], 'unapproved_posts' => $stats['unapproved_posts'])); } // Determine the board the final topic resides in $request = smf_db_query(' SELECT id_board FROM {db_prefix}topics WHERE id_topic = {int:id_topic} LIMIT 1', array('id_topic' => $id_topic)); list($id_board) = mysql_fetch_row($request); mysql_free_result($request); require_once $sourcedir . '/lib/Subs-Post.php'; // Update all the statistics. updateStats('topic'); updateStats('subject', $id_topic, $target_subject); updateLastMessages($boards); logAction('merge', array('topic' => $id_topic, 'board' => $id_board)); // Notify people that these topics have been merged? sendNotifications($id_topic, 'merge'); // Send them to the all done page. redirectexit('action=mergetopics;sa=done;to=' . $id_topic . ';targetboard=' . $target_board); }
function MessagePost2() { global $txt, $context, $sourcedir; global $user_info, $modSettings, $scripturl, $smcFunc; isAllowedTo('pm_send'); require_once $sourcedir . '/lib/Subs-Auth.php'; loadLanguage('PersonalMessage', '', false); // Extract out the spam settings - it saves database space! list($modSettings['max_pm_recipients'], $modSettings['pm_posts_verification'], $modSettings['pm_posts_per_hour']) = explode(',', $modSettings['pm_spam_settings']); // Check whether we've gone over the limit of messages we can send per hour - fatal error if fails! if (!empty($modSettings['pm_posts_per_hour']) && !allowedTo(array('admin_forum', 'moderate_forum', 'send_mail')) && $user_info['mod_cache']['bq'] == '0=1' && $user_info['mod_cache']['gq'] == '0=1') { // How many have they sent this last hour? $request = smf_db_query(' SELECT COUNT(pr.id_pm) AS post_count FROM {db_prefix}personal_messages AS pm INNER JOIN {db_prefix}pm_recipients AS pr ON (pr.id_pm = pm.id_pm) WHERE pm.id_member_from = {int:current_member} AND pm.msgtime > {int:msgtime}', array('current_member' => $user_info['id'], 'msgtime' => time() - 3600)); list($postCount) = mysql_fetch_row($request); mysql_free_result($request); if (!empty($postCount) && $postCount >= $modSettings['pm_posts_per_hour']) { fatal_lang_error('pm_too_many_per_hour', true, array($modSettings['pm_posts_per_hour'])); } } // If we came from WYSIWYG then turn it back into BBC regardless. if (!empty($_POST['message_mode']) && isset($_POST['message'])) { require_once $sourcedir . '/lib/Subs-Editor.php'; $_POST['message'] = html_to_bbc($_POST['message']); // We need to unhtml it now as it gets done shortly. $_POST['message'] = un_htmlspecialchars($_POST['message']); // We need this in case of errors etc. $_REQUEST['message'] = $_POST['message']; } // Initialize the errors we're about to make. $post_errors = array(); // If your session timed out, show an error, but do allow to re-submit. if (checkSession('post', '', false) != '') { $post_errors[] = 'session_timeout'; } $_REQUEST['subject'] = isset($_REQUEST['subject']) ? trim($_REQUEST['subject']) : ''; $_REQUEST['to'] = empty($_POST['to']) ? empty($_GET['to']) ? '' : $_GET['to'] : $_POST['to']; $_REQUEST['bcc'] = empty($_POST['bcc']) ? empty($_GET['bcc']) ? '' : $_GET['bcc'] : $_POST['bcc']; // Route the input from the 'u' parameter to the 'to'-list. if (!empty($_POST['u'])) { $_POST['recipient_to'] = explode(',', $_POST['u']); } // Construct the list of recipients. $recipientList = array(); $namedRecipientList = array(); $namesNotFound = array(); foreach (array('to', 'bcc') as $recipientType) { // First, let's see if there's user ID's given. $recipientList[$recipientType] = array(); if (!empty($_POST['recipient_' . $recipientType]) && is_array($_POST['recipient_' . $recipientType])) { foreach ($_POST['recipient_' . $recipientType] as $recipient) { $recipientList[$recipientType][] = (int) $recipient; } } // Are there also literal names set? if (!empty($_REQUEST[$recipientType])) { // We're going to take out the "s anyway ;). $recipientString = strtr($_REQUEST[$recipientType], array('\\"' => '"')); preg_match_all('~"([^"]+)"~', $recipientString, $matches); $namedRecipientList[$recipientType] = array_unique(array_merge($matches[1], explode(',', preg_replace('~"[^"]+"~', '', $recipientString)))); foreach ($namedRecipientList[$recipientType] as $index => $recipient) { if (strlen(trim($recipient)) > 0) { $namedRecipientList[$recipientType][$index] = commonAPI::htmlspecialchars(commonAPI::strtolower(trim($recipient))); } else { unset($namedRecipientList[$recipientType][$index]); } } if (!empty($namedRecipientList[$recipientType])) { $foundMembers = findMembers($namedRecipientList[$recipientType]); // Assume all are not found, until proven otherwise. $namesNotFound[$recipientType] = $namedRecipientList[$recipientType]; foreach ($foundMembers as $member) { $testNames = array(commonAPI::strtolower($member['username']), commonAPI::strtolower($member['name']), commonAPI::strtolower($member['email'])); if (count(array_intersect($testNames, $namedRecipientList[$recipientType])) !== 0) { $recipientList[$recipientType][] = $member['id']; // Get rid of this username, since we found it. $namesNotFound[$recipientType] = array_diff($namesNotFound[$recipientType], $testNames); } } } } // Selected a recipient to be deleted? Remove them now. if (!empty($_POST['delete_recipient'])) { $recipientList[$recipientType] = array_diff($recipientList[$recipientType], array((int) $_POST['delete_recipient'])); } // Make sure we don't include the same name twice $recipientList[$recipientType] = array_unique($recipientList[$recipientType]); } // Are we changing the recipients some how? $is_recipient_change = !empty($_POST['delete_recipient']) || !empty($_POST['to_submit']) || !empty($_POST['bcc_submit']); // Check if there's at least one recipient. if (empty($recipientList['to']) && empty($recipientList['bcc'])) { $post_errors[] = 'no_to'; } // Make sure that we remove the members who did get it from the screen. if (!$is_recipient_change) { foreach ($recipientList as $recipientType => $dummy) { if (!empty($namesNotFound[$recipientType])) { $post_errors[] = 'bad_' . $recipientType; // Since we already have a post error, remove the previous one. $post_errors = array_diff($post_errors, array('no_to')); foreach ($namesNotFound[$recipientType] as $name) { $context['send_log']['failed'][] = sprintf($txt['pm_error_user_not_found'], $name); } } } } // Did they make any mistakes? if ($_REQUEST['subject'] == '') { $post_errors[] = 'no_subject'; } if (!isset($_REQUEST['message']) || $_REQUEST['message'] == '') { $post_errors[] = 'no_message'; } elseif (!empty($modSettings['max_messageLength']) && commonAPI::strlen($_REQUEST['message']) > $modSettings['max_messageLength']) { $post_errors[] = 'long_message'; } else { // Preparse the message. $message = $_REQUEST['message']; preparsecode($message); // Make sure there's still some content left without the tags. if (commonAPI::htmltrim(strip_tags(parse_bbc(commonAPI::htmlspecialchars($message, ENT_QUOTES), false), '<img>')) === '' && (!allowedTo('admin_forum') || strpos($message, '[html]') === false)) { $post_errors[] = 'no_message'; } } // Wrong verification code? if (!$user_info['is_admin'] && !empty($modSettings['pm_posts_verification']) && $user_info['posts'] < $modSettings['pm_posts_verification']) { require_once $sourcedir . '/lib/Subs-Editor.php'; $verificationOptions = array('id' => 'pm', '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']); } } // If they did, give a chance to make ammends. if (!empty($post_errors) && !$is_recipient_change && !isset($_REQUEST['preview'])) { return messagePostError($post_errors, $namedRecipientList, $recipientList); } // Want to take a second glance before you send? if (isset($_REQUEST['preview'])) { // Set everything up to be displayed. $context['preview_subject'] = commonAPI::htmlspecialchars($_REQUEST['subject']); $context['preview_message'] = commonAPI::htmlspecialchars($_REQUEST['message'], ENT_QUOTES); preparsecode($context['preview_message'], true); // Parse out the BBC if it is enabled. $context['preview_message'] = parse_bbc($context['preview_message']); // Censor, as always. censorText($context['preview_subject']); censorText($context['preview_message']); // Set a descriptive title. $context['page_title'] = $txt['preview'] . ' - ' . $context['preview_subject']; // Pretend they messed up but don't ignore if they really did :P. return messagePostError($post_errors, $namedRecipientList, $recipientList); } elseif ($is_recipient_change) { // Maybe we couldn't find one? foreach ($namesNotFound as $recipientType => $names) { $post_errors[] = 'bad_' . $recipientType; foreach ($names as $name) { $context['send_log']['failed'][] = sprintf($txt['pm_error_user_not_found'], $name); } } return messagePostError(array(), $namedRecipientList, $recipientList); } elseif (!empty($modSettings['max_pm_recipients']) && count($recipientList['to']) + count($recipientList['bcc']) > $modSettings['max_pm_recipients'] && !allowedTo(array('moderate_forum', 'send_mail', 'admin_forum'))) { $context['send_log'] = array('sent' => array(), 'failed' => array(sprintf($txt['pm_too_many_recipients'], $modSettings['max_pm_recipients']))); return messagePostError($post_errors, $namedRecipientList, $recipientList); } // Protect from message spamming. spamProtection('pm'); // Prevent double submission of this form. checkSubmitOnce('check'); // Do the actual sending of the PM. if (!empty($recipientList['to']) || !empty($recipientList['bcc'])) { $context['send_log'] = sendpm($recipientList, $_REQUEST['subject'], $_REQUEST['message'], !empty($_REQUEST['outbox']), null, !empty($_REQUEST['pm_head']) ? (int) $_REQUEST['pm_head'] : 0); } else { $context['send_log'] = array('sent' => array(), 'failed' => array()); } // Mark the message as "replied to". if (!empty($context['send_log']['sent']) && !empty($_REQUEST['replied_to']) && isset($_REQUEST['f']) && $_REQUEST['f'] == 'inbox') { smf_db_query(' UPDATE {db_prefix}pm_recipients SET is_read = is_read | 2 WHERE id_pm = {int:replied_to} AND id_member = {int:current_member}', array('current_member' => $user_info['id'], 'replied_to' => (int) $_REQUEST['replied_to'])); } // If one or more of the recipient were invalid, go back to the post screen with the failed usernames. if (!empty($context['send_log']['failed'])) { return messagePostError($post_errors, $namesNotFound, array('to' => array_intersect($recipientList['to'], $context['send_log']['failed']), 'bcc' => array_intersect($recipientList['bcc'], $context['send_log']['failed']))); } // Message sent successfully? if (!empty($context['send_log']) && empty($context['send_log']['failed'])) { $context['current_label_redirect'] = $context['current_label_redirect'] . ';done=sent'; } // Go back to the where they sent from, if possible... redirectexit($context['current_label_redirect']); }
function validateEventPost() { global $modSettings, $txt, $sourcedir, $smcFunc; if (!isset($_POST['deleteevent'])) { // No month? No year? if (!isset($_POST['month'])) { fatal_lang_error('event_month_missing', false); } if (!isset($_POST['year'])) { fatal_lang_error('event_year_missing', false); } // Check the month and year... if ($_POST['month'] < 1 || $_POST['month'] > 12) { fatal_lang_error('invalid_month', false); } if ($_POST['year'] < $modSettings['cal_minyear'] || $_POST['year'] > $modSettings['cal_maxyear']) { fatal_lang_error('invalid_year', false); } } // Make sure they're allowed to post... isAllowedTo('calendar_post'); if (isset($_POST['span'])) { // Make sure it's turned on and not some fool trying to trick it. if (empty($modSettings['cal_allowspan'])) { fatal_lang_error('no_span', false); } if ($_POST['span'] < 1 || $_POST['span'] > $modSettings['cal_maxspan']) { fatal_lang_error('invalid_days_numb', false); } } // There is no need to validate the following values if we are just deleting the event. if (!isset($_POST['deleteevent'])) { // No day? if (!isset($_POST['day'])) { fatal_lang_error('event_day_missing', false); } if (!isset($_POST['evtitle']) && !isset($_POST['subject'])) { fatal_lang_error('event_title_missing', false); } elseif (!isset($_POST['evtitle'])) { $_POST['evtitle'] = $_POST['subject']; } // Bad day? if (!checkdate($_POST['month'], $_POST['day'], $_POST['year'])) { fatal_lang_error('invalid_date', false); } // No title? if (commonAPI::htmltrim($_POST['evtitle']) === '') { fatal_lang_error('no_event_title', false); } if (commonAPI::strlen($_POST['evtitle']) > 30) { $_POST['evtitle'] = commonAPI::substr($_POST['evtitle'], 0, 30); } $_POST['evtitle'] = str_replace(';', '', $_POST['evtitle']); } }
function displayDrafts($memID) { global $txt, $user_info, $scripturl, $modSettings, $context; if (!empty($_GET['de2lete']) && isset($_GET['topic'])) { $draft_id = (int) $_GET['delete']; $topic_id = (int) $_GET['topic']; $msgid = isset($_GET['msg']) ? (int) $_GET['msg'] : 0; $start = isset($_GET['start']) ? (int) $_GET['start'] : 0; checkSession('get'); smf_db_query(' DELETE FROM {db_prefix}drafts WHERE id_topic = {int:topic} AND id_draft = {int:draft} AND id_member = {int:member} AND id_msg = {int:message} LIMIT 1', array('topic' => $topic_id, 'draft' => $draft_id, 'member' => $user_info['id'], 'message' => $msgid)); redirectexit('action=profile;u=' . $memID . ';area=drafts;start=' . $start); } if (empty($_REQUEST['viewscount']) || !is_numeric($_REQUEST['viewscount'])) { $_REQUEST['viewscount'] = '10'; } // Get the count of applicable drafts $request = smf_db_query(' SELECT COUNT(id_draft) FROM {db_prefix}drafts AS pd INNER JOIN {db_prefix}boards AS b ON (b.id_board = pd.id_board AND {query_see_board}) WHERE id_member = {int:member}', array('member' => $memID)); list($msgCount) = mysql_fetch_row($request); mysql_free_result($request); $reverse = false; $maxIndex = (int) $modSettings['defaultMaxMessages']; // Make sure the starting place makes sense and construct our friend the page index. $context['page_index'] = constructPageIndex($scripturl . '?action=profile;u=' . $memID . ';area=showposts;sa=drafts', $context['start'], $msgCount, $maxIndex); $context['current_page'] = $context['start'] / $maxIndex; // Reverse the query if we're past 50% of the pages for better performance. $start = $context['start']; $reverse = $_REQUEST['start'] > $msgCount / 2; if ($reverse) { $maxIndex = $msgCount < $context['start'] + $modSettings['defaultMaxMessages'] + 1 && $msgCount > $context['start'] ? $msgCount - $context['start'] : (int) $modSettings['defaultMaxMessages']; $start = $msgCount < $context['start'] + $modSettings['defaultMaxMessages'] + 1 || $msgCount < $context['start'] + $modSettings['defaultMaxMessages'] ? 0 : $msgCount - $context['start'] - $modSettings['defaultMaxMessages']; } // Find this user's drafts. $request = smf_db_query(' SELECT b.id_board, b.name AS bname, pd.id_member, pd.id_draft, pd.body, pd.smileys, pd.subject, pd.updated, pd.icon, pd.id_topic, pd.id_msg, pd.is_locked, pd.is_sticky FROM {db_prefix}drafts AS pd INNER JOIN {db_prefix}boards AS b ON (b.id_board = pd.id_board AND {query_see_board}) WHERE pd.id_member = {int:current_member} ORDER BY pd.id_draft ' . ($reverse ? 'ASC' : 'DESC') . ' LIMIT ' . $start . ', ' . $maxIndex, array('current_member' => $memID)); // Start counting at the number of the first message displayed. $counter = $reverse ? $context['start'] + $maxIndex + 1 : $context['start']; $context['posts'] = array(); while ($row = mysql_fetch_assoc($request)) { // Censor.... if (empty($row['body'])) { $row['body'] = ''; } $row['subject'] = commonAPI::htmltrim($row['subject']); if (empty($row['subject'])) { $row['subject'] = $txt['no_subject']; } censorText($row['body']); censorText($row['subject']); // Do the code. $row['body'] = parse_bbc($row['body'], $row['smileys'], 'draft' . $row['id_draft']); // And the array... $context['posts'][$counter += $reverse ? -1 : 1] = array('body' => $row['body'], 'counter' => $counter, 'alternate' => $counter % 2, 'board' => array('name' => $row['bname'], 'id' => $row['id_board']), 'topic' => array('id' => $row['id_topic'], 'link' => empty($row['id']) ? $row['subject'] : '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.0">' . $row['subject'] . '</a>'), 'message' => array('id' => $row['id_msg']), 'subject' => $row['subject'], 'time' => timeformat($row['updated']), 'timestamp' => forum_time(true, $row['updated']), 'icon' => $row['icon'], 'id' => $row['id_draft'], 'locked' => $row['is_locked'], 'sticky' => $row['is_sticky']); } mysql_free_result($request); // All posts were retrieved in reverse order, get them right again. if ($reverse) { $context['posts'] = array_reverse($context['posts'], true); } $context['sub_template'] = 'showDrafts'; }