function createPost(&$msgOptions, &$topicOptions, &$posterOptions) { global $user_info, $txt, $modSettings, $smcFunc, $context; // Set optional parameters to the default value. $msgOptions['icon'] = empty($msgOptions['icon']) ? 'xx' : $msgOptions['icon']; $msgOptions['smileys_enabled'] = !empty($msgOptions['smileys_enabled']); $msgOptions['attachments'] = empty($msgOptions['attachments']) ? array() : $msgOptions['attachments']; $msgOptions['approved'] = isset($msgOptions['approved']) ? (int) $msgOptions['approved'] : 1; $topicOptions['id'] = empty($topicOptions['id']) ? 0 : (int) $topicOptions['id']; $topicOptions['poll'] = isset($topicOptions['poll']) ? (int) $topicOptions['poll'] : null; $topicOptions['lock_mode'] = isset($topicOptions['lock_mode']) ? $topicOptions['lock_mode'] : null; $topicOptions['sticky_mode'] = isset($topicOptions['sticky_mode']) ? $topicOptions['sticky_mode'] : null; $posterOptions['id'] = empty($posterOptions['id']) ? 0 : (int) $posterOptions['id']; $posterOptions['ip'] = empty($posterOptions['ip']) ? $user_info['ip'] : $posterOptions['ip']; // We need to know if the topic is approved. If we're told that's great - if not find out. if (!$modSettings['postmod_active']) { $topicOptions['is_approved'] = true; } elseif (!empty($topicOptions['id']) && !isset($topicOptions['is_approved'])) { $request = $smcFunc['db_query']('', ' SELECT approved FROM {db_prefix}topics WHERE id_topic = {int:id_topic} LIMIT 1', array('id_topic' => $topicOptions['id'])); list($topicOptions['is_approved']) = $smcFunc['db_fetch_row']($request); $smcFunc['db_free_result']($request); } // If nothing was filled in as name/e-mail address, try the member table. if (!isset($posterOptions['name']) || $posterOptions['name'] == '' || empty($posterOptions['email']) && !empty($posterOptions['id'])) { if (empty($posterOptions['id'])) { $posterOptions['id'] = 0; $posterOptions['name'] = $txt['guest_title']; $posterOptions['email'] = ''; } elseif ($posterOptions['id'] != $user_info['id']) { $request = $smcFunc['db_query']('', ' SELECT member_name, email_address FROM {db_prefix}members WHERE id_member = {int:id_member} LIMIT 1', array('id_member' => $posterOptions['id'])); // Couldn't find the current poster? if ($smcFunc['db_num_rows']($request) == 0) { trigger_error('createPost(): Invalid member id ' . $posterOptions['id'], E_USER_NOTICE); $posterOptions['id'] = 0; $posterOptions['name'] = $txt['guest_title']; $posterOptions['email'] = ''; } else { list($posterOptions['name'], $posterOptions['email']) = $smcFunc['db_fetch_row']($request); } $smcFunc['db_free_result']($request); } else { $posterOptions['name'] = $user_info['name']; $posterOptions['email'] = $user_info['email']; } } // It's do or die time: forget any user aborts! $previous_ignore_user_abort = ignore_user_abort(true); $new_topic = empty($topicOptions['id']); // Insert the post. $smcFunc['db_insert']('', '{db_prefix}messages', array('id_board' => 'int', 'id_topic' => 'int', 'id_member' => 'int', 'subject' => 'string-255', 'body' => !empty($modSettings['max_messageLength']) && $modSettings['max_messageLength'] > 65534 ? 'string-' . $modSettings['max_messageLength'] : 'string-65534', 'poster_name' => 'string-255', 'poster_email' => 'string-255', 'poster_time' => 'int', 'poster_ip' => 'string-255', 'smileys_enabled' => 'int', 'modified_name' => 'string', 'icon' => 'string-16', 'approved' => 'int'), array($topicOptions['board'], $topicOptions['id'], $posterOptions['id'], $msgOptions['subject'], $msgOptions['body'], $posterOptions['name'], $posterOptions['email'], time(), $posterOptions['ip'], $msgOptions['smileys_enabled'] ? 1 : 0, '', $msgOptions['icon'], $msgOptions['approved']), array('id_msg')); $msgOptions['id'] = $smcFunc['db_insert_id']('{db_prefix}messages', 'id_msg'); // Something went wrong creating the message... if (empty($msgOptions['id'])) { return false; } // Fix the attachments. if (!empty($msgOptions['attachments'])) { $smcFunc['db_query']('', ' UPDATE {db_prefix}attachments SET id_msg = {int:id_msg} WHERE id_attach IN ({array_int:attachment_list})', array('attachment_list' => $msgOptions['attachments'], 'id_msg' => $msgOptions['id'])); } // Insert a new topic (if the topicID was left empty.) if ($new_topic) { $smcFunc['db_insert']('', '{db_prefix}topics', array('id_board' => 'int', 'id_member_started' => 'int', 'id_member_updated' => 'int', 'id_first_msg' => 'int', 'id_last_msg' => 'int', 'locked' => 'int', 'is_sticky' => 'int', 'num_views' => 'int', 'id_poll' => 'int', 'unapproved_posts' => 'int', 'approved' => 'int'), array($topicOptions['board'], $posterOptions['id'], $posterOptions['id'], $msgOptions['id'], $msgOptions['id'], $topicOptions['lock_mode'] === null ? 0 : $topicOptions['lock_mode'], $topicOptions['sticky_mode'] === null ? 0 : $topicOptions['sticky_mode'], 0, $topicOptions['poll'] === null ? 0 : $topicOptions['poll'], $msgOptions['approved'] ? 0 : 1, $msgOptions['approved']), array('id_topic')); $topicOptions['id'] = $smcFunc['db_insert_id']('{db_prefix}topics', 'id_topic'); // The topic couldn't be created for some reason. if (empty($topicOptions['id'])) { // We should delete the post that did work, though... $smcFunc['db_query']('', ' DELETE FROM {db_prefix}messages WHERE id_msg = {int:id_msg}', array('id_msg' => $msgOptions['id'])); return false; } // Fix the message with the topic. $smcFunc['db_query']('', ' UPDATE {db_prefix}messages SET id_topic = {int:id_topic} WHERE id_msg = {int:id_msg}', array('id_topic' => $topicOptions['id'], 'id_msg' => $msgOptions['id'])); // There's been a new topic AND a new post today. trackStats(array('topics' => '+', 'posts' => '+')); updateStats('topic', true); updateStats('subject', $topicOptions['id'], $msgOptions['subject']); // What if we want to export new topics out to a CMS? call_integration_hook('integrate_create_topic', array($msgOptions, $topicOptions, $posterOptions)); } else { $countChange = $msgOptions['approved'] ? 'num_replies = num_replies + 1' : 'unapproved_posts = unapproved_posts + 1'; // Update the number of replies and the lock/sticky status. $smcFunc['db_query']('', ' UPDATE {db_prefix}topics SET ' . ($msgOptions['approved'] ? 'id_member_updated = {int:poster_id}, id_last_msg = {int:id_msg},' : '') . ' ' . $countChange . ($topicOptions['lock_mode'] === null ? '' : ', locked = {int:locked}') . ($topicOptions['sticky_mode'] === null ? '' : ', is_sticky = {int:is_sticky}') . ' WHERE id_topic = {int:id_topic}', array('poster_id' => $posterOptions['id'], 'id_msg' => $msgOptions['id'], 'locked' => $topicOptions['lock_mode'], 'is_sticky' => $topicOptions['sticky_mode'], 'id_topic' => $topicOptions['id'])); // One new post has been added today. trackStats(array('posts' => '+')); } // Creating is modifying...in a way. //!!! Why not set id_msg_modified on the insert? $smcFunc['db_query']('', ' UPDATE {db_prefix}messages SET id_msg_modified = {int:id_msg} WHERE id_msg = {int:id_msg}', array('id_msg' => $msgOptions['id'])); // Increase the number of posts and topics on the board. if ($msgOptions['approved']) { $smcFunc['db_query']('', ' UPDATE {db_prefix}boards SET num_posts = num_posts + 1' . ($new_topic ? ', num_topics = num_topics + 1' : '') . ' WHERE id_board = {int:id_board}', array('id_board' => $topicOptions['board'])); } else { $smcFunc['db_query']('', ' UPDATE {db_prefix}boards SET unapproved_posts = unapproved_posts + 1' . ($new_topic ? ', unapproved_topics = unapproved_topics + 1' : '') . ' WHERE id_board = {int:id_board}', array('id_board' => $topicOptions['board'])); // Add to the approval queue too. $smcFunc['db_insert']('', '{db_prefix}approval_queue', array('id_msg' => 'int'), array($msgOptions['id']), array()); } // Mark inserted topic as read (only for the user calling this function). if (!empty($topicOptions['mark_as_read']) && !$user_info['is_guest']) { // Since it's likely they *read* it before replying, let's try an UPDATE first. if (!$new_topic) { $smcFunc['db_query']('', ' UPDATE {db_prefix}log_topics SET id_msg = {int:id_msg} WHERE id_member = {int:current_member} AND id_topic = {int:id_topic}', array('current_member' => $posterOptions['id'], 'id_msg' => $msgOptions['id'], 'id_topic' => $topicOptions['id'])); $flag = $smcFunc['db_affected_rows']() != 0; } if (empty($flag)) { $smcFunc['db_insert']('ignore', '{db_prefix}log_topics', array('id_topic' => 'int', 'id_member' => 'int', 'id_msg' => 'int'), array($topicOptions['id'], $posterOptions['id'], $msgOptions['id']), array('id_topic', 'id_member')); } } // If there's a custom search index, it needs updating... if (!empty($modSettings['search_custom_index_config'])) { $customIndexSettings = unserialize($modSettings['search_custom_index_config']); $inserts = array(); foreach (text2words($msgOptions['body'], $customIndexSettings['bytes_per_word'], true) as $word) { $inserts[] = array($word, $msgOptions['id']); } if (!empty($inserts)) { $smcFunc['db_insert']('ignore', '{db_prefix}log_search_words', array('id_word' => 'int', 'id_msg' => 'int'), $inserts, array('id_word', 'id_msg')); } } // Increase the post counter for the user that created the post. if (!empty($posterOptions['update_post_count']) && !empty($posterOptions['id']) && $msgOptions['approved']) { // Are you the one that happened to create this post? if ($user_info['id'] == $posterOptions['id']) { $user_info['posts']++; } updateMemberData($posterOptions['id'], array('posts' => '+')); } // They've posted, so they can make the view count go up one if they really want. (this is to keep views >= replies...) $_SESSION['last_read_topic'] = 0; // Better safe than sorry. if (isset($_SESSION['topicseen_cache'][$topicOptions['board']])) { $_SESSION['topicseen_cache'][$topicOptions['board']]--; } // Update all the stats so everyone knows about this new topic and message. updateStats('message', true, $msgOptions['id']); // Update the last message on the board assuming it's approved AND the topic is. if ($msgOptions['approved']) { updateLastMessages($topicOptions['board'], $new_topic || !empty($topicOptions['is_approved']) ? $msgOptions['id'] : 0); } // Alright, done now... we can abort now, I guess... at least this much is done. ignore_user_abort($previous_ignore_user_abort); // Success. return true; }
/** * The main dispatcher. * This delegates to each area. */ function elk_main() { global $modSettings, $user_info, $topic, $board_info, $context; // Special case: session keep-alive, output a transparent pixel. if (isset($_GET['action']) && $_GET['action'] == 'keepalive') { header('Content-Type: image/gif'); die("GIF89a€!ù,D;"); } // We should set our security headers now. frameOptionsHeader(); securityOptionsHeader(); // Load the user's cookie (or set as guest) and load their settings. loadUserSettings(); // Load the current board's information. loadBoard(); // Load the current user's permissions. loadPermissions(); // Load BadBehavior before we go much further loadBadBehavior(); // Attachments don't require the entire theme to be loaded. if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'dlattach' && (!empty($modSettings['allow_guestAccess']) && $user_info['is_guest'])) { detectBrowser(); } else { loadTheme(); } // Check if the user should be disallowed access. is_not_banned(); // If we are in a topic and don't have permission to approve it then duck out now. if (!empty($topic) && empty($board_info['cur_topic_approved']) && !allowedTo('approve_posts') && ($user_info['id'] != $board_info['cur_topic_starter'] || $user_info['is_guest'])) { fatal_lang_error('not_a_topic', false); } $no_stat_actions = array('dlattach', 'findmember', 'jsoption', 'requestmembers', 'jslocale', 'xmlpreview', 'suggest', '.xml', 'xmlhttp', 'verificationcode', 'viewquery', 'viewadminfile'); call_integration_hook('integrate_pre_log_stats', array(&$no_stat_actions)); // Do some logging, unless this is an attachment, avatar, toggle of editor buttons, theme option, XML feed etc. if (empty($_REQUEST['action']) || !in_array($_REQUEST['action'], $no_stat_actions)) { // I see you! writeLog(); // Track forum statistics and hits...? if (!empty($modSettings['hitStats'])) { trackStats(array('hits' => '+')); } } unset($no_stat_actions); // What shall we do? require_once SOURCEDIR . '/SiteDispatcher.class.php'; $dispatcher = new Site_Dispatcher(); // Show where we came from, and go $context['site_action'] = $dispatcher->site_action(); $context['site_action'] = !empty($context['site_action']) ? $context['site_action'] : (isset($_REQUEST['action']) ? $_REQUEST['action'] : ''); $dispatcher->dispatch(); }
/** * Sends a personal message from the specified person to the specified people * ($from defaults to the user) * * @package PersonalMessage * @param mixed[] $recipients - an array containing the arrays 'to' and 'bcc', both containing id_member's. * @param string $subject - should have no slashes and no html entities * @param string $message - should have no slashes and no html entities * @param bool $store_outbox * @param mixed[]|null $from - an array with the id, name, and username of the member. * @param int $pm_head - the ID of the chain being replied to - if any. * @return mixed[] an array with log entries telling how many recipients were successful and which recipients it failed to send to. */ function sendpm($recipients, $subject, $message, $store_outbox = true, $from = null, $pm_head = 0) { global $scripturl, $txt, $user_info, $language, $modSettings, $webmaster_email; $db = database(); // Make sure the PM language file is loaded, we might need something out of it. loadLanguage('PersonalMessage'); // Needed for our email and post functions require_once SUBSDIR . '/Mail.subs.php'; require_once SUBSDIR . '/Post.subs.php'; // Initialize log array. $log = array('failed' => array(), 'sent' => array()); if ($from === null) { $from = array('id' => $user_info['id'], 'name' => $user_info['name'], 'username' => $user_info['username']); } else { $user_info['name'] = $from['name']; } // This is the one that will go in their inbox. $htmlmessage = Util::htmlspecialchars($message, ENT_QUOTES, 'UTF-8', true); preparsecode($htmlmessage); $htmlsubject = strtr(Util::htmlspecialchars($subject), array("\r" => '', "\n" => '', "\t" => '')); if (Util::strlen($htmlsubject) > 100) { $htmlsubject = Util::substr($htmlsubject, 0, 100); } // Make sure is an array if (!is_array($recipients)) { $recipients = array($recipients); } // Integrated PMs call_integration_hook('integrate_personal_message', array(&$recipients, &$from, &$subject, &$message)); // Get a list of usernames and convert them to IDs. $usernames = array(); foreach ($recipients as $rec_type => $rec) { foreach ($rec as $id => $member) { if (!is_numeric($recipients[$rec_type][$id])) { $recipients[$rec_type][$id] = Util::strtolower(trim(preg_replace('/[<>&"\'=\\\\]/', '', $recipients[$rec_type][$id]))); $usernames[$recipients[$rec_type][$id]] = 0; } } } if (!empty($usernames)) { $request = $db->query('pm_find_username', ' SELECT id_member, member_name FROM {db_prefix}members WHERE ' . (defined('DB_CASE_SENSITIVE') ? 'LOWER(member_name)' : 'member_name') . ' IN ({array_string:usernames})', array('usernames' => array_keys($usernames))); while ($row = $db->fetch_assoc($request)) { if (isset($usernames[Util::strtolower($row['member_name'])])) { $usernames[Util::strtolower($row['member_name'])] = $row['id_member']; } } $db->free_result($request); // Replace the usernames with IDs. Drop usernames that couldn't be found. foreach ($recipients as $rec_type => $rec) { foreach ($rec as $id => $member) { if (is_numeric($recipients[$rec_type][$id])) { continue; } if (!empty($usernames[$member])) { $recipients[$rec_type][$id] = $usernames[$member]; } else { $log['failed'][$id] = sprintf($txt['pm_error_user_not_found'], $recipients[$rec_type][$id]); unset($recipients[$rec_type][$id]); } } } } // Make sure there are no duplicate 'to' members. $recipients['to'] = array_unique($recipients['to']); // Only 'bcc' members that aren't already in 'to'. $recipients['bcc'] = array_diff(array_unique($recipients['bcc']), $recipients['to']); // Combine 'to' and 'bcc' recipients. $all_to = array_merge($recipients['to'], $recipients['bcc']); // Check no-one will want it deleted right away! $request = $db->query('', ' SELECT id_member, criteria, is_or FROM {db_prefix}pm_rules WHERE id_member IN ({array_int:to_members}) AND delete_pm = {int:delete_pm}', array('to_members' => $all_to, 'delete_pm' => 1)); $deletes = array(); // Check whether we have to apply anything... while ($row = $db->fetch_assoc($request)) { $criteria = unserialize($row['criteria']); // Note we don't check the buddy status, cause deletion from buddy = madness! $delete = false; foreach ($criteria as $criterium) { if ($criterium['t'] == 'mid' && $criterium['v'] == $from['id'] || $criterium['t'] == 'gid' && in_array($criterium['v'], $user_info['groups']) || $criterium['t'] == 'sub' && strpos($subject, $criterium['v']) !== false || $criterium['t'] == 'msg' && strpos($message, $criterium['v']) !== false) { $delete = true; } elseif (!$row['is_or']) { $delete = false; break; } } if ($delete) { $deletes[$row['id_member']] = 1; } } $db->free_result($request); // Load the membergrounp message limits. static $message_limit_cache = array(); if (!allowedTo('moderate_forum') && empty($message_limit_cache)) { $request = $db->query('', ' SELECT id_group, max_messages FROM {db_prefix}membergroups', array()); while ($row = $db->fetch_assoc($request)) { $message_limit_cache[$row['id_group']] = $row['max_messages']; } $db->free_result($request); } // Load the groups that are allowed to read PMs. // @todo move into a separate function on $permission. $allowed_groups = array(); $disallowed_groups = array(); $request = $db->query('', ' SELECT id_group, add_deny FROM {db_prefix}permissions WHERE permission = {string:read_permission}', array('read_permission' => 'pm_read')); while ($row = $db->fetch_assoc($request)) { if (empty($row['add_deny'])) { $disallowed_groups[] = $row['id_group']; } else { $allowed_groups[] = $row['id_group']; } } $db->free_result($request); if (empty($modSettings['permission_enable_deny'])) { $disallowed_groups = array(); } $request = $db->query('', ' SELECT member_name, real_name, id_member, email_address, lngfile, pm_email_notify, personal_messages,' . (allowedTo('moderate_forum') ? ' 0' : ' (receive_from = {int:admins_only}' . (empty($modSettings['enable_buddylist']) ? '' : ' OR (receive_from = {int:buddies_only} AND FIND_IN_SET({string:from_id}, buddy_list) = 0) OR (receive_from = {int:not_on_ignore_list} AND FIND_IN_SET({string:from_id}, pm_ignore_list) != 0)') . ')') . ' AS ignored, FIND_IN_SET({string:from_id}, buddy_list) != 0 AS is_buddy, is_activated, additional_groups, id_group, id_post_group FROM {db_prefix}members WHERE id_member IN ({array_int:recipients}) ORDER BY lngfile LIMIT {int:count_recipients}', array('not_on_ignore_list' => 1, 'buddies_only' => 2, 'admins_only' => 3, 'recipients' => $all_to, 'count_recipients' => count($all_to), 'from_id' => $from['id'])); $notifications = array(); while ($row = $db->fetch_assoc($request)) { // Don't do anything for members to be deleted! if (isset($deletes[$row['id_member']])) { continue; } // We need to know this members groups. $groups = explode(',', $row['additional_groups']); $groups[] = $row['id_group']; $groups[] = $row['id_post_group']; $message_limit = -1; // For each group see whether they've gone over their limit - assuming they're not an admin. if (!in_array(1, $groups)) { foreach ($groups as $id) { if (isset($message_limit_cache[$id]) && $message_limit != 0 && $message_limit < $message_limit_cache[$id]) { $message_limit = $message_limit_cache[$id]; } } if ($message_limit > 0 && $message_limit <= $row['personal_messages']) { $log['failed'][$row['id_member']] = sprintf($txt['pm_error_data_limit_reached'], $row['real_name']); unset($all_to[array_search($row['id_member'], $all_to)]); continue; } // Do they have any of the allowed groups? if (count(array_intersect($allowed_groups, $groups)) == 0 || count(array_intersect($disallowed_groups, $groups)) != 0) { $log['failed'][$row['id_member']] = sprintf($txt['pm_error_user_cannot_read'], $row['real_name']); unset($all_to[array_search($row['id_member'], $all_to)]); continue; } } // Note that PostgreSQL can return a lowercase t/f for FIND_IN_SET if (!empty($row['ignored']) && $row['ignored'] != 'f' && $row['id_member'] != $from['id']) { $log['failed'][$row['id_member']] = sprintf($txt['pm_error_ignored_by_user'], $row['real_name']); unset($all_to[array_search($row['id_member'], $all_to)]); continue; } // If the receiving account is banned (>=10) or pending deletion (4), refuse to send the PM. if ($row['is_activated'] >= 10 || $row['is_activated'] == 4 && !$user_info['is_admin']) { $log['failed'][$row['id_member']] = sprintf($txt['pm_error_user_cannot_read'], $row['real_name']); unset($all_to[array_search($row['id_member'], $all_to)]); continue; } // Send a notification, if enabled - taking the buddy list into account. if (!empty($row['email_address']) && ($row['pm_email_notify'] == 1 || $row['pm_email_notify'] > 1 && (!empty($modSettings['enable_buddylist']) && $row['is_buddy'])) && $row['is_activated'] == 1) { $notifications[empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']][] = $row['email_address']; } $log['sent'][$row['id_member']] = sprintf(isset($txt['pm_successfully_sent']) ? $txt['pm_successfully_sent'] : '', $row['real_name']); } $db->free_result($request); // Only 'send' the message if there are any recipients left. if (empty($all_to)) { return $log; } // Track the pm count for our stats if (!empty($modSettings['trackStats'])) { trackStats(array('pm' => '+')); } // Insert the message itself and then grab the last insert id. $db->insert('', '{db_prefix}personal_messages', array('id_pm_head' => 'int', 'id_member_from' => 'int', 'deleted_by_sender' => 'int', 'from_name' => 'string-255', 'msgtime' => 'int', 'subject' => 'string-255', 'body' => 'string-65534'), array($pm_head, $from['id'], $store_outbox ? 0 : 1, $from['username'], time(), $htmlsubject, $htmlmessage), array('id_pm')); $id_pm = $db->insert_id('{db_prefix}personal_messages', 'id_pm'); // Add the recipients. if (!empty($id_pm)) { // If this is new we need to set it part of it's own conversation. if (empty($pm_head)) { $db->query('', ' UPDATE {db_prefix}personal_messages SET id_pm_head = {int:id_pm_head} WHERE id_pm = {int:id_pm_head}', array('id_pm_head' => $id_pm)); } // Some people think manually deleting personal_messages is fun... it's not. We protect against it though :) $db->query('', ' DELETE FROM {db_prefix}pm_recipients WHERE id_pm = {int:id_pm}', array('id_pm' => $id_pm)); $insertRows = array(); $to_list = array(); foreach ($all_to as $to) { $insertRows[] = array($id_pm, $to, in_array($to, $recipients['bcc']) ? 1 : 0, isset($deletes[$to]) ? 1 : 0, 1); if (!in_array($to, $recipients['bcc'])) { $to_list[] = $to; } } $db->insert('insert', '{db_prefix}pm_recipients', array('id_pm' => 'int', 'id_member' => 'int', 'bcc' => 'int', 'deleted' => 'int', 'is_new' => 'int'), $insertRows, array('id_pm', 'id_member')); } $maillist = !empty($modSettings['maillist_enabled']) && !empty($modSettings['pbe_pm_enabled']); // If they have post by email enabled, override disallow_sendBody if (!$maillist && !empty($modSettings['disallow_sendBody'])) { $message = ''; censorText($subject); } else { require_once SUBSDIR . '/Emailpost.subs.php'; pbe_prepare_text($message, $subject); } $to_names = array(); if (count($to_list) > 1) { require_once SUBSDIR . '/Members.subs.php'; $result = getBasicMemberData($to_list); foreach ($result as $row) { $to_names[] = un_htmlspecialchars($row['real_name']); } } $replacements = array('SUBJECT' => $subject, 'MESSAGE' => $message, 'SENDER' => un_htmlspecialchars($from['name']), 'READLINK' => $scripturl . '?action=pm;pmsg=' . $id_pm . '#msg' . $id_pm, 'REPLYLINK' => $scripturl . '?action=pm;sa=send;f=inbox;pmsg=' . $id_pm . ';quote;u=' . $from['id'], 'TOLIST' => implode(', ', $to_names)); // Select the right template $email_template = ($maillist && empty($modSettings['disallow_sendBody']) ? 'pbe_' : '') . 'new_pm' . (empty($modSettings['disallow_sendBody']) ? '_body' : '') . (!empty($to_names) ? '_tolist' : ''); foreach ($notifications as $lang => $notification_list) { // Using maillist functionality if ($maillist) { $sender_details = query_sender_wrapper($from['id']); $from_wrapper = !empty($modSettings['maillist_mail_from']) ? $modSettings['maillist_mail_from'] : (empty($modSettings['maillist_sitename_address']) ? $webmaster_email : $modSettings['maillist_sitename_address']); // Add in the signature $replacements['SIGNATURE'] = $sender_details['signature']; // And off it goes, looking a bit more personal $mail = loadEmailTemplate($email_template, $replacements, $lang); $reference = !empty($pm_head) ? $pm_head : null; sendmail($notification_list, $mail['subject'], $mail['body'], $from['name'], 'p' . $id_pm, false, 2, null, true, $from_wrapper, $reference); } else { // Off the notification email goes! $mail = loadEmailTemplate($email_template, $replacements, $lang); sendmail($notification_list, $mail['subject'], $mail['body'], null, 'p' . $id_pm, false, 2, null, true); } } // Integrated After PMs call_integration_hook('integrate_personal_message_after', array(&$id_pm, &$log, &$recipients, &$from, &$subject, &$message)); // Back to what we were on before! loadLanguage('index+PersonalMessage'); // Add one to their unread and read message counts. foreach ($all_to as $k => $id) { if (isset($deletes[$id])) { unset($all_to[$k]); } } if (!empty($all_to)) { updateMemberData($all_to, array('personal_messages' => '+', 'unread_messages' => '+', 'new_pm' => 1)); } return $log; }
/** * Sends a group of emails from the mail queue. * * - Allows a batch of emails to be released every 5 to 10 seconds (based on per period limits) * - If batch size is not set, will determine a size such that it sends in 1/2 the period (buffer) * * @package Mail * @param int|false $batch_size = false the number to send each loop * @param boolean $override_limit = false bypassing our limit flaf * @param boolean $force_send = false * @return boolean */ function reduceMailQueue($batch_size = false, $override_limit = false, $force_send = false) { global $modSettings, $context, $webmaster_email, $scripturl; // Do we have another script to send out the queue? if (!empty($modSettings['mail_queue_use_cron']) && empty($force_send)) { return false; } // How many emails can we send each time we are called in a period if (!$batch_size) { // Batch size has been set in the ACP, use it if (!empty($modSettings['mail_batch_size'])) { $batch_size = $modSettings['mail_batch_size']; } elseif (empty($modSettings['mail_period_limit'])) { $batch_size = 5; } else { // Based on the number of times we will potentially be called each minute $delay = !empty($modSettings['mail_queue_delay']) ? $modSettings['mail_queue_delay'] : (!empty($modSettings['mail_period_limit']) && $modSettings['mail_period_limit'] <= 5 ? 10 : 5); $batch_size = ceil($modSettings['mail_period_limit'] / ceil(60 / $delay)); $batch_size = $batch_size == 1 && $modSettings['mail_period_limit'] > 1 ? 2 : $batch_size; } } // If we came with a timestamp, and that doesn't match the next event, then someone else has beaten us. if (isset($_GET['ts']) && $_GET['ts'] != $modSettings['mail_next_send'] && empty($force_send)) { return false; } // Prepare to send each email, and log that for future proof. require_once SUBSDIR . '/Maillist.subs.php'; // Set the delay for the next sending if (!$override_limit) { // Update next send time for our mail queue, if there was something to update. Otherwise bail out :P $delay = updateNextSendTime(); if ($delay === false) { return false; } $modSettings['mail_next_send'] = time() + $delay; } // If we're not overriding, do we have quota left in this mail period limit? if (!$override_limit && !empty($modSettings['mail_period_limit'])) { // See if we have quota left to send another batch_size this minute or if we have to wait list($mail_time, $mail_number) = isset($modSettings['mail_recent']) ? explode('|', $modSettings['mail_recent']) : array(0, 0); // Nothing worth noting... if (empty($mail_number) || $mail_time < time() - 60) { $mail_time = time(); $mail_number = $batch_size; } elseif ($mail_number < $modSettings['mail_period_limit']) { // If this is likely one of the last cycles for this period, then send any remaining quota if ($mail_time - (time() - 60) < $delay * 2) { $batch_size = $modSettings['mail_period_limit'] - $mail_number; } elseif ($mail_number + $batch_size > $modSettings['mail_period_limit']) { $batch_size = $modSettings['mail_period_limit'] - $mail_number; } $mail_number += $batch_size; } else { return false; } // Reflect that we're about to send some, do it now to be safe. updateSettings(array('mail_recent' => $mail_time . '|' . $mail_number)); } // Now we know how many we're sending, let's send them. list($ids, $emails) = emailsInfo($batch_size); // Delete, delete, delete!!! if (!empty($ids)) { deleteMailQueueItems($ids); } // Don't believe we have any left after this batch? if (count($ids) < $batch_size) { resetNextSendTime(); } if (empty($ids)) { return false; } // We have some to send, lets send them! $sent = array(); $failed_emails = array(); // Use sendmail or SMTP $use_sendmail = empty($modSettings['mail_type']) || $modSettings['smtp_host'] == ''; // Line breaks need to be \r\n only in windows or for SMTP. $line_break = !empty($context['server']['is_windows']) || !$use_sendmail ? "\r\n" : "\n"; foreach ($emails as $key => $email) { // Use the right mail resource if ($use_sendmail) { $email['subject'] = strtr($email['subject'], array("\r" => '', "\n" => '')); if (!empty($modSettings['mail_strip_carriage'])) { $email['body'] = strtr($email['body'], array("\r" => '')); $email['headers'] = strtr($email['headers'], array("\r" => '')); } $need_break = substr($email['headers'], -1) === "\n" || substr($email['headers'], -1) === "\r" ? false : true; // Create our unique reply to email header if this message needs one $unq_id = ''; $unq_head = ''; if (!empty($modSettings['maillist_enabled']) && $email['message_id'] !== null && strpos($email['headers'], 'List-Id: <') !== false) { $unq_head = md5($scripturl . microtime() . rand()) . '-' . $email['message_id']; $encoded_unq_head = base64_encode($line_break . $line_break . '[' . $unq_head . ']' . $line_break); $unq_id = ($need_break ? $line_break : '') . 'Message-ID: <' . $unq_head . strstr(empty($modSettings['maillist_mail_from']) ? $webmaster_email : $modSettings['maillist_mail_from'], '@') . '>'; $email['body_fail'] = $email['body']; $email['body'] = mail_insert_key($email['body'], $unq_head, $encoded_unq_head, $line_break); } elseif ($email['message_id'] !== null && empty($modSettings['mail_no_message_id'])) { $unq_id = ($need_break ? $line_break : '') . 'Message-ID: <' . md5($scripturl . microtime()) . '-' . $email['message_id'] . strstr(empty($modSettings['maillist_mail_from']) ? $webmaster_email : $modSettings['maillist_mail_from'], '@') . '>'; } // No point logging a specific error here, as we have no language. PHP error is helpful anyway... $result = mail(strtr($email['to'], array("\r" => '', "\n" => '')), $email['subject'], $email['body'], $email['headers'] . $unq_id); // If it sent, keep a record so we can save it in our allowed to reply log if (!empty($unq_head) && $result) { $sent[] = array($unq_head, time(), $email['to']); } // Track total emails sent if ($result && !empty($modSettings['trackStats'])) { trackStats(array('email' => '+')); } // Try to stop a timeout, this would be bad... @set_time_limit(300); if (function_exists('apache_reset_timeout')) { @apache_reset_timeout(); } } else { $result = smtp_mail(array($email['to']), $email['subject'], $email['body'], $email['send_html'] ? $email['headers'] : 'Mime-Version: 1.0' . "\r\n" . $email['headers'], $email['priority'], $email['message_id']); } // Hopefully it sent? if (!$result) { $failed_emails[] = array(time(), $email['to'], $email['body_fail'], $email['subject'], $email['headers'], $email['send_html'], $email['priority'], $email['private'], $email['message_id']); } } // Clear out the stat cache. trackStats(); // Log each of the sent emails. if (!empty($sent)) { log_email($sent); } // Any emails that didn't send? if (!empty($failed_emails)) { // If it failed, add it back to the queue updateFailedQueue($failed_emails); return false; } elseif (!empty($modSettings['mail_failed_attempts'])) { updateSuccessQueue(); } // Had something to send... return true; }
function obExit($header = null, $do_footer = null, $from_index = false, $from_fatal_error = false) { global $context, $settings, $modSettings, $txt, $smcFunc; static $header_done = false, $footer_done = false, $level = 0, $has_fatal_error = false; // Attempt to prevent a recursive loop. ++$level; if ($level > 1 && !$from_fatal_error && !$has_fatal_error) { exit; } if ($from_fatal_error) { $has_fatal_error = true; } // Clear out the stat cache. trackStats(); // If we have mail to send, send it. if (!empty($context['flush_mail'])) { AddMailQueue(true); } $do_header = $header === null ? !$header_done : $header; if ($do_footer === null) { $do_footer = $do_header; } // Has the template/header been done yet? if ($do_header) { // Was the page title set last minute? Also update the HTML safe one. if (!empty($context['page_title']) && empty($context['page_title_html_safe'])) { $context['page_title_html_safe'] = $smcFunc['htmlspecialchars'](un_htmlspecialchars($context['page_title'])); } // Start up the session URL fixer. ob_start('ob_sessrewrite'); if (!empty($settings['output_buffers']) && is_string($settings['output_buffers'])) { $buffers = explode(',', $settings['output_buffers']); } elseif (!empty($settings['output_buffers'])) { $buffers = $settings['output_buffers']; } else { $buffers = array(); } if (isset($modSettings['integrate_buffer'])) { $buffers = array_merge(explode(',', $modSettings['integrate_buffer']), $buffers); } if (!empty($buffers)) { foreach ($buffers as $function) { $function = trim($function); $call = strpos($function, '::') !== false ? explode('::', $function) : $function; // Is it valid? if (is_callable($call)) { ob_start($call); } } } // Display the screen in the logical order. template_header(); $header_done = true; } if ($do_footer) { if (WIRELESS && !isset($context['sub_template'])) { fatal_lang_error('wireless_error_notyet', false); } // Just show the footer, then. loadSubTemplate(isset($context['sub_template']) ? $context['sub_template'] : 'main'); // Anything special to put out? if (!empty($context['insert_after_template']) && !isset($_REQUEST['xml'])) { echo $context['insert_after_template']; } // Just so we don't get caught in an endless loop of errors from the footer... if (!$footer_done) { $footer_done = true; template_footer(); // (since this is just debugging... it's okay that it's after </html>.) if (!isset($_REQUEST['xml'])) { db_debug_junk(); } } } // Remember this URL in case someone doesn't like sending HTTP_REFERER. if (strpos($_SERVER['REQUEST_URL'], 'action=dlattach') === false && strpos($_SERVER['REQUEST_URL'], 'action=viewsmfile') === false) { $_SESSION['old_url'] = $_SERVER['REQUEST_URL']; } // For session check verfication.... don't switch browsers... $_SESSION['USER_AGENT'] = $_SERVER['HTTP_USER_AGENT']; if (!empty($settings['strict_doctype'])) { // The theme author wants to use the STRICT doctype (only God knows why). $temp = ob_get_contents(); if (function_exists('ob_clean')) { ob_clean(); } else { ob_end_clean(); ob_start('ob_sessrewrite'); } echo strtr($temp, array('var smf_iso_case_folding' => 'var target_blank = \'_blank\'; var smf_iso_case_folding', 'target="_blank"' => 'onclick="this.target=target_blank"')); } // Hand off the output to the portal, etc. we're integrated with. call_integration_hook('integrate_exit', array($do_footer && !WIRELESS)); // Don't exit if we're coming from index.php; that will pass through normally. if (!$from_index || WIRELESS) { exit; } }
function method_create_topic($is_post = false, $new_api = false) { global $mobdb, $mobsettings, $modSettings, $context, $scripturl, $sourcedir, $user_info, $board, $topic, $func, $language, $txt, $sc; // We need these for creating topics require_once $sourcedir . '/Subs-Post.php'; require_once $sourcedir . '/Post.php'; // Guest? No entry if ($user_info['is_guest']) { createErrorResponse(21); } // Figure out the parameters if ($is_post) { if ($new_api) { $_POST['board'] = intval($context['mob_request']['params'][0][0]); $_POST['topic'] = intval($context['mob_request']['params'][1][0]); $_POST['icon'] = 'xx'; $_POST['topic'] = intval($context['mob_request']['params'][1][0]); $_POST['subject'] = utf8ToAscii(base64_decode($context['mob_request']['params'][2][0])); $_POST['message'] = utf8ToAscii(base64_decode($context['mob_request']['params'][3][0])); $_POST['sc'] = $sc = ''; //$_POST['attachments'] = isset($request_params[4]) ? explode('.', implode('.', $request_params[4])) : array(); tt_clean_request(); loadBoard(); loadPermissions(); // Get a response prefix (like 'Re:') in the default forum language. if (!isset($context['response_prefix']) && !($context['response_prefix'] = cache_get_data('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'); } cache_put_data('response_prefix', $context['response_prefix'], 600); } $_POST['subject'] = $context['response_prefix'] . $_POST['subject']; $post_id = Post2(); outputRPCNewTopic($post_id, 1, true); } else { $id_topic = (int) $context['mob_request']['params'][0][0]; $body = base64_decode($context['mob_request']['params'][2][0]); $subject = base64_decode($context['mob_request']['params'][3][0]); if (isset($context['mob_request']['params'][4]) && $context['mob_request']['params'][4][0]) { $id_attach = (int) $context['mob_request']['params'][4][0]; } } } else { if ($new_api) { $_POST['board'] = intval($context['mob_request']['params'][0][0]); $_POST['icon'] = 'xx'; $_POST['subject'] = utf8ToAscii(base64_decode($context['mob_request']['params'][1][0])); $_POST['message'] = utf8ToAscii(base64_decode($context['mob_request']['params'][2][0])); $_POST['sc'] = $sc = ''; //$_POST['attachments'] = isset($request_params[4]) ? explode('.', implode('.', $request_params[4])) : array(); tt_clean_request(); loadBoard(); loadPermissions(); Post2(); outputRPCNewTopic($topic, 1, false); } else { $id_board = (int) $context['mob_request']['params'][0][0]; $subject = base64_decode($context['mob_request']['params'][1][0]); $body = base64_decode($context['mob_request']['params'][3][0]); if (isset($context['mob_request']['params'][4]) && $context['mob_request']['params'][4][0]) { $id_attach = (int) $context['mob_request']['params'][4][0]; } } } $subject = utf8ToAscii($subject); $body = utf8ToAscii($body); $_POST['subject'] = $subject; $_POST['message'] = $body; // Get a response prefix (like 'Re:') in the default forum language. if (!isset($context['response_prefix']) && !($context['response_prefix'] = cache_get_data('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'); } cache_put_data('response_prefix', $context['response_prefix'], 600); } if ($is_post) { $subject = $context['response_prefix'] . $subject; } // Trim out the whitespace $subject = trim($subject); $body = trim($body); // Missing? Oh man if ($is_post) { if (!$is_post && empty($id_board) || empty($body) || isset($id_attach) && empty($id_attach) || isset($id_topic) && empty($id_topic)) { createErrorResponse(8); } } else { if (!$is_post && empty($id_board) || empty($body) || empty($subject) || isset($id_attach) && empty($id_attach) || isset($id_topic) && empty($id_topic)) { createErrorResponse(8); } } // Does this board exist? $mobdb->query(' SELECT b.ID_BOARD FROM ' . (!empty($id_topic) ? '{db_prefix}topics AS t INNER JOIN {db_prefix}boards AS b ON (t.ID_BOARD = b.ID_BOARD)' : '{db_prefix}boards AS b') . ' WHERE {query_see_board} AND ' . (!empty($id_topic) ? 't.ID_TOPIC' : 'b.ID_BOARD') . ' = {int:value}', array('value' => empty($id_topic) ? $id_board : $id_topic)); if ($mobdb->num_rows() == 0) { createErrorResponse(4); } list($id_board) = $mobdb->fetch_row(); $mobdb->free_result(); // Can we actually post? if (!isset($id_topic)) { if (allowedTo('post_new', $id_board)) { $can_post = 1; } elseif ($modSettings['postmod_active'] && !allowedTo('post_new', $id_board) && allowedTo('post_unapproved_topics', $id_board)) { $can_post = 2; } else { createErrorResponse(25); } } else { $mobdb->query(' SELECT locked, isSticky AS is_sticky, 1 AS approved, numReplies AS num_replies, ID_FIRST_MSG AS id_first_msg, ID_MEMBER_STARTED AS id_member_started, ID_BOARD AS id_board, ID_POLL AS id_poll FROM {db_prefix}topics WHERE id_topic = {int:current_topic} LIMIT 1', array('current_topic' => $id_topic)); $topic_info = $mobdb->fetch_assoc(); $mobdb->free_result(); if ($topic_info['id_board'] != $id_board) { createErrorResponse(25); } // Locked? if ($topic_info['locked'] && !allowedTo('moderate_board', $id_board)) { createErrorResponse(25); } // Is this this guy's topic? if ($topic_info['id_member_started'] == $user_info['id']) { if (allowedTo('post_reply_own', $id_board)) { $can_post = 1; } elseif ($modSettings['postmod_active'] && !allowedTo('post_reply_own', $id_board) && allowedTo('post_unapproved_replies_own', $id_board)) { $can_post = 2; } else { createErrorResponse(25); } } else { if (allowedTo('post_reply_any', $id_board)) { $can_post = 1; } elseif ($modSettings['postmod_active'] && !allowedTo('post_reply_any', $id_board) && allowedTo('post_unapproved_replies_any', $id_board)) { $can_post = 2; } else { createErrorResponse(2); } } } // Alright, we passed the security tests, lets check the inputs //$subject = strtr(htmlspecialchars($subject), array("\r" => '', "\n" => '', "\t" => '')); //$body = htmlspecialchars($body); ######## Added by Sean to fix the issue can not post############## $subject = addslashes__recursive($subject); $body = addslashes__recursive($body); // Set up the inputs for the form. $body = $func['htmlspecialchars']($body, ENT_QUOTES); preparsecode($body); $subject = strtr($func['htmlspecialchars']($subject), array("\r" => '', "\n" => '', "\t" => '')); ################################################################## if (strlen($subject) > 100) { $subject = substr($subject, 0, 100); } // Are the attachments valid? if (isset($id_attach)) { // Does it even exist? $mobdb->query(' SELECT a.ID_ATTACH, a.ID_THUMB FROM {db_prefix}attachments AS a WHERE a.ID_ATTACH = {int:attach}', array('attach' => $id_attach)); // Not found? if ($mobdb->num_rows() == 0) { unset($id_attach); } list($id_attach, $id_thumb) = $mobdb->fetch_row(); $mobdb->free_result(); } // Get the parameters ready $msgOptions = array('id' => 0, 'subject' => $subject, 'body' => $body, 'icon' => isset($id_attach) ? 'clip' : 'xx', 'smileys_enabled' => true, 'attachments' => isset($id_attach) ? array($id_attach, $id_thumb) : null, 'approved' => $can_post == 2 ? false : true); $topicOptions = array('id' => isset($id_topic) ? $id_topic : 0, 'board' => $id_board, 'poll' => isset($topic_info) ? $topic_info['id_poll'] : null, 'lock_mode' => isset($topic_info) ? $topic_info['locked'] : null, 'sticky_mode' => isset($topic_info) ? $topic_info['is_sticky'] : null, 'mark_as_read' => true, 'is_approved' => $can_post == 2 ? false : true); $posterOptions = array('id' => $user_info['id'], 'name' => $user_info['name'], 'email' => $user_info['email'], 'update_post_count' => true); // Actually create the topic... createPost($msgOptions, $topicOptions, $posterOptions); if (empty($topicOptions['id'])) { createErrorResponse(8); } $id_topic = $topicOptions['id']; trackStats(); // Notifications anyone? $notifyData = array('body' => $body, 'subject' => $subject, 'name' => $user_info['name'], 'poster' => $user_info['id'], 'msg' => $msgOptions['id'], 'board' => $id_board, 'topic' => $id_topic); //!!! Stupid fix for SMF 1.1 $board = $id_board; $topic = $id_topic; if (!$is_post) { notifyMembersBoard($notifyData); } // Send out the response outputRPCNewTopic($is_post ? $msgOptions['id'] : $topicOptions['id'], $can_post, $is_post); }
function obExit($header = null, $do_footer = null, $from_index = false) { global $context, $settings, $modSettings, $txt; static $header_done = false, $footer_done = false; // Clear out the stat cache. trackStats(); $do_header = $header === null ? !$header_done : $header; if ($do_footer === null) { $do_footer = $do_header; } // Has the template/header been done yet? if ($do_header) { // Start up the session URL fixer. ob_start('ob_sessrewrite'); // Just in case we have anything bad already in there... if ((isset($_REQUEST['debug']) || isset($_REQUEST['xml']) || WIRELESS && WIRELESS_PROTOCOL == 'wap') && in_array($txt['lang_locale'], array('UTF-8', 'ISO-8859-1'))) { ob_start('validate_unicode__recursive'); } if (!empty($settings['output_buffers']) && is_string($settings['output_buffers'])) { $buffers = explode(',', $settings['output_buffers']); } elseif (!empty($settings['output_buffers'])) { $buffers = $settings['output_buffers']; } else { $buffers = array(); } if (isset($modSettings['integrate_buffer'])) { $buffers = array_merge(explode(',', $modSettings['integrate_buffer']), $buffers); } if (!empty($buffers)) { foreach ($buffers as $buffer_function) { if (function_exists(trim($buffer_function))) { ob_start(trim($buffer_function)); } } } // Display the screen in the logical order. template_header(); $header_done = true; } if ($do_footer) { if (WIRELESS && !isset($context['sub_template'])) { fatal_lang_error('wireless_error_notyet', false); } // Just show the footer, then. loadSubTemplate(isset($context['sub_template']) ? $context['sub_template'] : 'main'); // Just so we don't get caught in an endless loop of errors from the footer... if (!$footer_done) { $footer_done = true; template_footer(); // (since this is just debugging... it's okay that it's after </html>.) if (!isset($_REQUEST['xml'])) { db_debug_junk(); } } } // Remember this URL in case someone doesn't like sending HTTP_REFERER. if (strpos($_SERVER['REQUEST_URL'], 'action=dlattach') === false) { $_SESSION['old_url'] = $_SERVER['REQUEST_URL']; } // For session check verfication.... don't switch browsers... $_SESSION['USER_AGENT'] = $_SERVER['HTTP_USER_AGENT']; // Hand off the output to the portal, etc. we're integrated with. if (isset($modSettings['integrate_exit'], $context['template_layers']) && in_array('main', $context['template_layers']) && function_exists($modSettings['integrate_exit'])) { call_user_func($modSettings['integrate_exit'], $do_footer && !WIRELESS); } // Don't exit if we're coming from index.php; that will pass through normally. if (!$from_index || WIRELESS) { exit; } }
/** * Create a post, either as new topic (id_topic = 0) or in an existing one. * * The input parameters of this function assume: * - Strings have been escaped. * - Integers have been cast to integer. * - Mandatory parameters are set. * * @package Posts * @param mixed[] $msgOptions * @param mixed[] $topicOptions * @param mixed[] $posterOptions */ function createPost(&$msgOptions, &$topicOptions, &$posterOptions) { global $user_info, $txt, $modSettings; $db = database(); // Set optional parameters to the default value. $msgOptions['icon'] = empty($msgOptions['icon']) ? 'xx' : $msgOptions['icon']; $msgOptions['smileys_enabled'] = !empty($msgOptions['smileys_enabled']); $msgOptions['attachments'] = empty($msgOptions['attachments']) ? array() : $msgOptions['attachments']; $msgOptions['approved'] = isset($msgOptions['approved']) ? (int) $msgOptions['approved'] : 1; $topicOptions['id'] = empty($topicOptions['id']) ? 0 : (int) $topicOptions['id']; $topicOptions['poll'] = isset($topicOptions['poll']) ? (int) $topicOptions['poll'] : null; $topicOptions['lock_mode'] = isset($topicOptions['lock_mode']) ? $topicOptions['lock_mode'] : null; $topicOptions['sticky_mode'] = isset($topicOptions['sticky_mode']) ? $topicOptions['sticky_mode'] : null; $topicOptions['redirect_expires'] = isset($topicOptions['redirect_expires']) ? $topicOptions['redirect_expires'] : null; $topicOptions['redirect_topic'] = isset($topicOptions['redirect_topic']) ? $topicOptions['redirect_topic'] : null; $posterOptions['id'] = empty($posterOptions['id']) ? 0 : (int) $posterOptions['id']; $posterOptions['ip'] = empty($posterOptions['ip']) ? $user_info['ip'] : $posterOptions['ip']; // We need to know if the topic is approved. If we're told that's great - if not find out. if (!$modSettings['postmod_active']) { $topicOptions['is_approved'] = true; } elseif (!empty($topicOptions['id']) && !isset($topicOptions['is_approved'])) { $request = $db->query('', ' SELECT approved FROM {db_prefix}topics WHERE id_topic = {int:id_topic} LIMIT 1', array('id_topic' => $topicOptions['id'])); list($topicOptions['is_approved']) = $db->fetch_row($request); $db->free_result($request); } // If nothing was filled in as name/email address, try the member table. if (!isset($posterOptions['name']) || $posterOptions['name'] == '' || empty($posterOptions['email']) && !empty($posterOptions['id'])) { if (empty($posterOptions['id'])) { $posterOptions['id'] = 0; $posterOptions['name'] = $txt['guest_title']; $posterOptions['email'] = ''; } elseif ($posterOptions['id'] != $user_info['id']) { require_once SUBSDIR . '/Members.subs.php'; $result = getBasicMemberData($posterOptions['id']); // Couldn't find the current poster? if (empty($result)) { trigger_error('createPost(): Invalid member id ' . $posterOptions['id'], E_USER_NOTICE); $posterOptions['id'] = 0; $posterOptions['name'] = $txt['guest_title']; $posterOptions['email'] = ''; } else { $posterOptions['name'] = $result['member_name']; $posterOptions['email'] = $result['email_address']; } } else { $posterOptions['name'] = $user_info['name']; $posterOptions['email'] = $user_info['email']; } } // It's do or die time: forget any user aborts! $previous_ignore_user_abort = ignore_user_abort(true); $new_topic = empty($topicOptions['id']); $message_columns = array('id_board' => 'int', 'id_topic' => 'int', 'id_member' => 'int', 'subject' => 'string-255', 'body' => !empty($modSettings['max_messageLength']) && $modSettings['max_messageLength'] > 65534 ? 'string-' . $modSettings['max_messageLength'] : (empty($modSettings['max_messageLength']) ? 'string' : 'string-65534'), 'poster_name' => 'string-255', 'poster_email' => 'string-255', 'poster_time' => 'int', 'poster_ip' => 'string-255', 'smileys_enabled' => 'int', 'modified_name' => 'string', 'icon' => 'string-16', 'approved' => 'int'); $message_parameters = array('id_board' => $topicOptions['board'], 'id_topic' => $topicOptions['id'], 'id_member' => $posterOptions['id'], 'subject' => $msgOptions['subject'], 'body' => $msgOptions['body'], 'poster_name' => $posterOptions['name'], 'poster_email' => $posterOptions['email'], 'poster_time' => empty($posterOptions['time']) ? time() : $posterOptions['time'], 'poster_ip' => $posterOptions['ip'], 'smileys_enabled' => $msgOptions['smileys_enabled'] ? 1 : 0, 'modified_name' => '', 'icon' => $msgOptions['icon'], 'approved' => $msgOptions['approved']); // What if we want to do anything with posts? call_integration_hook('integrate_before_create_post', array(&$msgOptions, &$topicOptions, &$posterOptions, &$message_columns, &$message_parameters)); // Insert the post. $db->insert('', '{db_prefix}messages', $message_columns, $message_parameters, array('id_msg')); $msgOptions['id'] = $db->insert_id('{db_prefix}messages', 'id_msg'); // Something went wrong creating the message... if (empty($msgOptions['id'])) { return false; } // Fix the attachments. if (!empty($msgOptions['attachments'])) { $db->query('', ' UPDATE {db_prefix}attachments SET id_msg = {int:id_msg} WHERE id_attach IN ({array_int:attachment_list})', array('attachment_list' => $msgOptions['attachments'], 'id_msg' => $msgOptions['id'])); } // What if we want to export new posts out to a CMS? call_integration_hook('integrate_create_post', array($msgOptions, $topicOptions, $posterOptions, $message_columns, $message_parameters)); // Insert a new topic (if the topicID was left empty.) if ($new_topic) { $topic_columns = array('id_board' => 'int', 'id_member_started' => 'int', 'id_member_updated' => 'int', 'id_first_msg' => 'int', 'id_last_msg' => 'int', 'locked' => 'int', 'is_sticky' => 'int', 'num_views' => 'int', 'id_poll' => 'int', 'unapproved_posts' => 'int', 'approved' => 'int', 'redirect_expires' => 'int', 'id_redirect_topic' => 'int'); $topic_parameters = array('id_board' => $topicOptions['board'], 'id_member_started' => $posterOptions['id'], 'id_member_updated' => $posterOptions['id'], 'id_first_msg' => $msgOptions['id'], 'id_last_msg' => $msgOptions['id'], 'locked' => $topicOptions['lock_mode'] === null ? 0 : $topicOptions['lock_mode'], 'is_sticky' => $topicOptions['sticky_mode'] === null ? 0 : $topicOptions['sticky_mode'], 'num_views' => 0, 'id_poll' => $topicOptions['poll'] === null ? 0 : $topicOptions['poll'], 'unapproved_posts' => $msgOptions['approved'] ? 0 : 1, 'approved' => $msgOptions['approved'], 'redirect_expires' => $topicOptions['redirect_expires'] === null ? 0 : $topicOptions['redirect_expires'], 'id_redirect_topic' => $topicOptions['redirect_topic'] === null ? 0 : $topicOptions['redirect_topic']); call_integration_hook('integrate_before_create_topic', array(&$msgOptions, &$topicOptions, &$posterOptions, &$topic_columns, &$topic_parameters)); $db->insert('', '{db_prefix}topics', $topic_columns, $topic_parameters, array('id_topic')); $topicOptions['id'] = $db->insert_id('{db_prefix}topics', 'id_topic'); // The topic couldn't be created for some reason. if (empty($topicOptions['id'])) { // We should delete the post that did work, though... $db->query('', ' DELETE FROM {db_prefix}messages WHERE id_msg = {int:id_msg}', array('id_msg' => $msgOptions['id'])); return false; } // Fix the message with the topic. $db->query('', ' UPDATE {db_prefix}messages SET id_topic = {int:id_topic} WHERE id_msg = {int:id_msg}', array('id_topic' => $topicOptions['id'], 'id_msg' => $msgOptions['id'])); // There's been a new topic AND a new post today. trackStats(array('topics' => '+', 'posts' => '+')); updateStats('topic', true); updateStats('subject', $topicOptions['id'], $msgOptions['subject']); // What if we want to export new topics out to a CMS? call_integration_hook('integrate_create_topic', array($msgOptions, $topicOptions, $posterOptions)); } else { $update_parameters = array('poster_id' => $posterOptions['id'], 'id_msg' => $msgOptions['id'], 'locked' => $topicOptions['lock_mode'], 'is_sticky' => $topicOptions['sticky_mode'], 'id_topic' => $topicOptions['id'], 'counter_increment' => 1); if ($msgOptions['approved']) { $topics_columns = array('id_member_updated = {int:poster_id}', 'id_last_msg = {int:id_msg}', 'num_replies = num_replies + {int:counter_increment}'); } else { $topics_columns = array('unapproved_posts = unapproved_posts + {int:counter_increment}'); } if ($topicOptions['lock_mode'] !== null) { $topics_columns[] = 'locked = {int:locked}'; } if ($topicOptions['sticky_mode'] !== null) { $topics_columns[] = 'is_sticky = {int:is_sticky}'; } call_integration_hook('integrate_before_modify_topic', array(&$topics_columns, &$update_parameters, &$msgOptions, &$topicOptions, &$posterOptions)); // Update the number of replies and the lock/sticky status. $db->query('', ' UPDATE {db_prefix}topics SET ' . implode(', ', $topics_columns) . ' WHERE id_topic = {int:id_topic}', $update_parameters); // One new post has been added today. trackStats(array('posts' => '+')); } // Creating is modifying...in a way. // @todo id_msg_modified needs to be set when you create a post, now this query is // the only place it does get set for post creation. Why not set it on the insert? $db->query('', ' UPDATE {db_prefix}messages SET id_msg_modified = {int:id_msg} WHERE id_msg = {int:id_msg}', array('id_msg' => $msgOptions['id'])); // Increase the number of posts and topics on the board. if ($msgOptions['approved']) { $db->query('', ' UPDATE {db_prefix}boards SET num_posts = num_posts + 1' . ($new_topic ? ', num_topics = num_topics + 1' : '') . ' WHERE id_board = {int:id_board}', array('id_board' => $topicOptions['board'])); } else { $db->query('', ' UPDATE {db_prefix}boards SET unapproved_posts = unapproved_posts + 1' . ($new_topic ? ', unapproved_topics = unapproved_topics + 1' : '') . ' WHERE id_board = {int:id_board}', array('id_board' => $topicOptions['board'])); // Add to the approval queue too. $db->insert('', '{db_prefix}approval_queue', array('id_msg' => 'int'), array($msgOptions['id']), array()); } // Mark inserted topic as read (only for the user calling this function). if (!empty($topicOptions['mark_as_read']) && !$user_info['is_guest']) { // Since it's likely they *read* it before replying, let's try an UPDATE first. if (!$new_topic) { $db->query('', ' UPDATE {db_prefix}log_topics SET id_msg = {int:id_msg} WHERE id_member = {int:current_member} AND id_topic = {int:id_topic}', array('current_member' => $posterOptions['id'], 'id_msg' => $msgOptions['id'], 'id_topic' => $topicOptions['id'])); $flag = $db->affected_rows() != 0; } if (empty($flag)) { require_once SUBSDIR . '/Topic.subs.php'; markTopicsRead(array($posterOptions['id'], $topicOptions['id'], $msgOptions['id'], 0), false); } } // If there's a custom search index, it may need updating... require_once SUBSDIR . '/Search.subs.php'; $searchAPI = findSearchAPI(); if (is_callable(array($searchAPI, 'postCreated'))) { $searchAPI->postCreated($msgOptions, $topicOptions, $posterOptions); } // Increase the post counter for the user that created the post. if (!empty($posterOptions['update_post_count']) && !empty($posterOptions['id']) && $msgOptions['approved']) { // Are you the one that happened to create this post? if ($user_info['id'] == $posterOptions['id']) { $user_info['posts']++; } updateMemberData($posterOptions['id'], array('posts' => '+')); } // They've posted, so they can make the view count go up one if they really want. (this is to keep views >= replies...) $_SESSION['last_read_topic'] = 0; // Better safe than sorry. if (isset($_SESSION['topicseen_cache'][$topicOptions['board']])) { $_SESSION['topicseen_cache'][$topicOptions['board']]--; } // Update all the stats so everyone knows about this new topic and message. updateStats('message', true, $msgOptions['id']); // Update the last message on the board assuming it's approved AND the topic is. if ($msgOptions['approved']) { updateLastMessages($topicOptions['board'], $new_topic || !empty($topicOptions['is_approved']) ? $msgOptions['id'] : 0); } // Alright, done now... we can abort now, I guess... at least this much is done. ignore_user_abort($previous_ignore_user_abort); // Success. return true; }
function BoardIndex() { global $txt, $scripturl, $db_prefix, $ID_MEMBER, $user_info, $sourcedir; global $modSettings, $context, $settings; // For wireless, we use the Wireless template... if (WIRELESS) { $context['sub_template'] = WIRELESS_PROTOCOL . '_boardindex'; } else { loadTemplate('BoardIndex'); } // Remember the most recent topic for optimizing the recent posts feature. $most_recent_topic = array('timestamp' => 0, 'ref' => null); // Find all boards and categories, as well as related information. This will be sorted by the natural order of boards and categories, which we control. $result_boards = db_query("\n\t\tSELECT\n\t\t\tc.name AS catName, c.ID_CAT, b.ID_BOARD, b.name AS boardName, b.description,\n\t\t\tb.numPosts, b.numTopics, b.ID_PARENT, IFNULL(m.posterTime, 0) AS posterTime,\n\t\t\tIFNULL(mem.memberName, m.posterName) AS posterName, m.subject, m.ID_TOPIC,\n\t\t\tIFNULL(mem.realName, m.posterName) AS realName," . ($user_info['is_guest'] ? "\n\t\t\t1 AS isRead, 0 AS new_from" : "\n\t\t\t(IFNULL(lb.ID_MSG, 0) >= b.ID_MSG_UPDATED) AS isRead, IFNULL(lb.ID_MSG, -1) + 1 AS new_from,\n\t\t\tc.canCollapse, IFNULL(cc.ID_MEMBER, 0) AS isCollapsed") . ",\n\t\t\tIFNULL(mem.ID_MEMBER, 0) AS ID_MEMBER, m.ID_MSG,\n\t\t\tIFNULL(mods_mem.ID_MEMBER, 0) AS ID_MODERATOR, mods_mem.realName AS modRealName\n\t\tFROM {$db_prefix}boards AS b\n\t\t\tLEFT JOIN {$db_prefix}categories AS c ON (c.ID_CAT = b.ID_CAT)\n\t\t\tLEFT JOIN {$db_prefix}messages AS m ON (m.ID_MSG = b.ID_LAST_MSG)\n\t\t\tLEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = m.ID_MEMBER)" . (!$user_info['is_guest'] ? "\n\t\t\tLEFT JOIN {$db_prefix}log_boards AS lb ON (lb.ID_BOARD = b.ID_BOARD AND lb.ID_MEMBER = {$ID_MEMBER})\n\t\t\tLEFT JOIN {$db_prefix}collapsed_categories AS cc ON (cc.ID_CAT = c.ID_CAT AND cc.ID_MEMBER = {$ID_MEMBER})" : '') . "\n\t\t\tLEFT JOIN {$db_prefix}moderators AS mods ON (mods.ID_BOARD = b.ID_BOARD)\n\t\t\tLEFT JOIN {$db_prefix}members AS mods_mem ON (mods_mem.ID_MEMBER = mods.ID_MEMBER)\n\t\tWHERE {$user_info['query_see_board']}" . (empty($modSettings['countChildPosts']) ? "\n\t\t\tAND b.childLevel <= 1" : ''), __FILE__, __LINE__); // Run through the categories and boards.... $context['categories'] = array(); while ($row_board = mysql_fetch_assoc($result_boards)) { // Haven't set this category yet. if (empty($context['categories'][$row_board['ID_CAT']])) { $context['categories'][$row_board['ID_CAT']] = array('id' => $row_board['ID_CAT'], 'name' => $row_board['catName'], 'is_collapsed' => isset($row_board['canCollapse']) && $row_board['canCollapse'] == 1 && $row_board['isCollapsed'] > 0, 'can_collapse' => isset($row_board['canCollapse']) && $row_board['canCollapse'] == 1, 'collapse_href' => isset($row_board['canCollapse']) ? $scripturl . '?action=collapse;c=' . $row_board['ID_CAT'] . ';sa=' . ($row_board['isCollapsed'] > 0 ? 'expand' : 'collapse;') . '#' . $row_board['ID_CAT'] : '', 'collapse_image' => isset($row_board['canCollapse']) ? '<img src="' . $settings['images_url'] . '/' . ($row_board['isCollapsed'] > 0 ? 'expand.gif" alt="+"' : 'collapse.gif" alt="-"') . ' border="0" />' : '', 'href' => $scripturl . '#' . $row_board['ID_CAT'], 'boards' => array(), 'new' => false); $context['categories'][$row_board['ID_CAT']]['link'] = '<a name="' . $row_board['ID_CAT'] . '" href="' . (isset($row_board['canCollapse']) ? $context['categories'][$row_board['ID_CAT']]['collapse_href'] : $context['categories'][$row_board['ID_CAT']]['href']) . '">' . $row_board['catName'] . '</a>'; } // If this board has new posts in it (and isn't the recycle bin!) then the category is new. if (empty($modSettings['recycle_enable']) || $modSettings['recycle_board'] != $row_board['ID_BOARD']) { $context['categories'][$row_board['ID_CAT']]['new'] |= empty($row_board['isRead']) && $row_board['posterName'] != ''; } // Collapsed category - don't do any of this. if ($context['categories'][$row_board['ID_CAT']]['is_collapsed']) { continue; } // Let's save some typing. Climbing the array might be slower, anyhow. $this_category =& $context['categories'][$row_board['ID_CAT']]['boards']; // This is a parent board. if (empty($row_board['ID_PARENT'])) { // Is this a new board, or just another moderator? if (!isset($this_category[$row_board['ID_BOARD']])) { // Not a child. $isChild = false; $this_category[$row_board['ID_BOARD']] = array('new' => empty($row_board['isRead']), 'id' => $row_board['ID_BOARD'], 'name' => $row_board['boardName'], 'description' => $row_board['description'], 'moderators' => array(), 'link_moderators' => array(), 'children' => array(), 'link_children' => array(), 'children_new' => false, 'topics' => $row_board['numTopics'], 'posts' => $row_board['numPosts'], 'href' => $scripturl . '?board=' . $row_board['ID_BOARD'] . '.0', 'link' => '<a href="' . $scripturl . '?board=' . $row_board['ID_BOARD'] . '.0">' . $row_board['boardName'] . '</a>'); } if (!empty($row_board['ID_MODERATOR'])) { $this_category[$row_board['ID_BOARD']]['moderators'][$row_board['ID_MODERATOR']] = array('id' => $row_board['ID_MODERATOR'], 'name' => $row_board['modRealName'], 'href' => $scripturl . '?action=profile;u=' . $row_board['ID_MODERATOR'], 'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row_board['ID_MODERATOR'] . '" title="' . $txt[62] . '">' . $row_board['modRealName'] . '</a>'); $this_category[$row_board['ID_BOARD']]['link_moderators'][] = '<a href="' . $scripturl . '?action=profile;u=' . $row_board['ID_MODERATOR'] . '" title="' . $txt[62] . '">' . $row_board['modRealName'] . '</a>'; } } elseif (isset($this_category[$row_board['ID_PARENT']]['children']) && !isset($this_category[$row_board['ID_PARENT']]['children'][$row_board['ID_BOARD']])) { // A valid child! $isChild = true; $this_category[$row_board['ID_PARENT']]['children'][$row_board['ID_BOARD']] = array('id' => $row_board['ID_BOARD'], 'name' => $row_board['boardName'], 'description' => $row_board['description'], 'new' => empty($row_board['isRead']) && $row_board['posterName'] != '', 'topics' => $row_board['numTopics'], 'posts' => $row_board['numPosts'], 'href' => $scripturl . '?board=' . $row_board['ID_BOARD'] . '.0', 'link' => '<a href="' . $scripturl . '?board=' . $row_board['ID_BOARD'] . '.0">' . $row_board['boardName'] . '</a>'); // Counting child board posts is... slow :/. if (!empty($modSettings['countChildPosts'])) { $this_category[$row_board['ID_PARENT']]['posts'] += $row_board['numPosts']; $this_category[$row_board['ID_PARENT']]['topics'] += $row_board['numTopics']; } // Does this board contain new boards? $this_category[$row_board['ID_PARENT']]['children_new'] |= empty($row_board['isRead']); // This is easier to use in many cases for the theme.... $this_category[$row_board['ID_PARENT']]['link_children'][] =& $this_category[$row_board['ID_PARENT']]['children'][$row_board['ID_BOARD']]['link']; } elseif (!empty($modSettings['countChildPosts'])) { if (!isset($parent_map)) { $parent_map = array(); } if (!isset($parent_map[$row_board['ID_PARENT']])) { foreach ($this_category as $id => $board) { if (!isset($board['children'][$row_board['ID_PARENT']])) { continue; } $parent_map[$row_board['ID_PARENT']] = array(&$this_category[$id], &$this_category[$id]['children'][$row_board['ID_PARENT']]); $parent_map[$row_board['ID_BOARD']] = array(&$this_category[$id], &$this_category[$id]['children'][$row_board['ID_PARENT']]); break; } } if (isset($parent_map[$row_board['ID_PARENT']])) { $parent_map[$row_board['ID_PARENT']][0]['posts'] += $row_board['numPosts']; $parent_map[$row_board['ID_PARENT']][0]['topics'] += $row_board['numTopics']; $parent_map[$row_board['ID_PARENT']][1]['posts'] += $row_board['numPosts']; $parent_map[$row_board['ID_PARENT']][1]['topics'] += $row_board['numTopics']; continue; } continue; } else { continue; } // Prepare the subject, and make sure it's not too long. censorText($row_board['subject']); $row_board['short_subject'] = shorten_subject($row_board['subject'], 24); $this_last_post = array('id' => $row_board['ID_MSG'], 'time' => $row_board['posterTime'] > 0 ? timeformat($row_board['posterTime']) : $txt[470], 'timestamp' => forum_time(true, $row_board['posterTime']), 'subject' => $row_board['short_subject'], 'member' => array('id' => $row_board['ID_MEMBER'], 'username' => $row_board['posterName'] != '' ? $row_board['posterName'] : $txt[470], 'name' => $row_board['realName'], 'href' => $row_board['posterName'] != '' && !empty($row_board['ID_MEMBER']) ? $scripturl . '?action=profile;u=' . $row_board['ID_MEMBER'] : '', 'link' => $row_board['posterName'] != '' ? !empty($row_board['ID_MEMBER']) ? '<a href="' . $scripturl . '?action=profile;u=' . $row_board['ID_MEMBER'] . '">' . $row_board['realName'] . '</a>' : $row_board['realName'] : $txt[470]), 'start' => 'msg' . $row_board['new_from'], 'topic' => $row_board['ID_TOPIC']); // Provide the href and link. if ($row_board['subject'] != '') { $this_last_post['href'] = $scripturl . '?topic=' . $row_board['ID_TOPIC'] . '.msg' . ($user_info['is_guest'] ? $modSettings['maxMsgID'] : $row_board['new_from']) . (empty($row_board['isRead']) ? ';boardseen' : '') . '#new'; $this_last_post['link'] = '<a href="' . $this_last_post['href'] . '" title="' . $row_board['subject'] . '">' . $row_board['short_subject'] . '</a>'; } else { $this_last_post['href'] = ''; $this_last_post['link'] = $txt[470]; } // Set the last post in the parent board. if (empty($row_board['ID_PARENT']) || $isChild && !empty($row_board['posterTime']) && $this_category[$row_board['ID_PARENT']]['last_post']['timestamp'] < forum_time(true, $row_board['posterTime'])) { $this_category[$isChild ? $row_board['ID_PARENT'] : $row_board['ID_BOARD']]['last_post'] = $this_last_post; } // Just in the child...? if ($isChild) { $this_category[$row_board['ID_PARENT']]['children'][$row_board['ID_BOARD']]['last_post'] = $this_last_post; // If there are no posts in this board, it really can't be new... $this_category[$row_board['ID_PARENT']]['children'][$row_board['ID_BOARD']]['new'] &= $row_board['posterName'] != ''; } elseif ($row_board['posterName'] == '') { $this_category[$row_board['ID_BOARD']]['new'] = false; } // Determine a global most recent topic. if (!empty($row_board['posterTime']) && forum_time(true, $row_board['posterTime']) > $most_recent_topic['timestamp']) { $most_recent_topic = array('timestamp' => forum_time(true, $row_board['posterTime']), 'ref' => &$this_category[$isChild ? $row_board['ID_PARENT'] : $row_board['ID_BOARD']]['last_post']); } } mysql_free_result($result_boards); // Load the users online right now. $result = db_query("\n\t\tSELECT\n\t\t\tlo.ID_MEMBER, lo.logTime, mem.realName, mem.memberName, mem.showOnline,\n\t\t\tmg.onlineColor, mg.ID_GROUP, mg.groupName\n\t\tFROM {$db_prefix}log_online AS lo\n\t\t\tLEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = lo.ID_MEMBER)\n\t\t\tLEFT JOIN {$db_prefix}membergroups AS mg ON (mg.ID_GROUP = IF(mem.ID_GROUP = 0, mem.ID_POST_GROUP, mem.ID_GROUP))", __FILE__, __LINE__); $context['users_online'] = array(); $context['list_users_online'] = array(); $context['online_groups'] = array(); $context['num_guests'] = 0; $context['num_buddies'] = 0; $context['num_users_hidden'] = 0; $context['show_buddies'] = !empty($user_info['buddies']); while ($row = mysql_fetch_assoc($result)) { if (empty($row['realName'])) { $context['num_guests']++; continue; } elseif (empty($row['showOnline']) && !allowedTo('moderate_forum')) { $context['num_users_hidden']++; continue; } // Some basic color coding... if (!empty($row['onlineColor'])) { $link = '<a href="' . $scripturl . '?action=profile;u=' . $row['ID_MEMBER'] . '" style="color: ' . $row['onlineColor'] . ';">' . $row['realName'] . '</a>'; } else { $link = '<a href="' . $scripturl . '?action=profile;u=' . $row['ID_MEMBER'] . '">' . $row['realName'] . '</a>'; } $is_buddy = in_array($row['ID_MEMBER'], $user_info['buddies']); if ($is_buddy) { $context['num_buddies']++; $link = '<b>' . $link . '</b>'; } $context['users_online'][$row['logTime'] . $row['memberName']] = array('id' => $row['ID_MEMBER'], 'username' => $row['memberName'], 'name' => $row['realName'], 'group' => $row['ID_GROUP'], 'href' => $scripturl . '?action=profile;u=' . $row['ID_MEMBER'], 'link' => $link, 'is_buddy' => $is_buddy, 'hidden' => empty($row['showOnline'])); $context['list_users_online'][$row['logTime'] . $row['memberName']] = empty($row['showOnline']) ? '<i>' . $link . '</i>' : $link; if (!isset($context['online_groups'][$row['ID_GROUP']])) { $context['online_groups'][$row['ID_GROUP']] = array('id' => $row['ID_GROUP'], 'name' => $row['groupName'], 'color' => $row['onlineColor']); } } mysql_free_result($result); krsort($context['users_online']); krsort($context['list_users_online']); ksort($context['online_groups']); $context['num_users_online'] = count($context['users_online']) + $context['num_users_hidden']; // Track most online statistics? if (!empty($modSettings['trackStats'])) { // Determine the most users online - both all time and per day. $total_users = $context['num_guests'] + $context['num_users_online']; // More members on now than ever were? Update it! if (!isset($modSettings['mostOnline']) || $total_users >= $modSettings['mostOnline']) { updateSettings(array('mostOnline' => $total_users, 'mostDate' => time())); } $date = strftime('%Y-%m-%d', forum_time(false)); // One or more stats are not up-to-date? if (!isset($modSettings['mostOnlineUpdated']) || $modSettings['mostOnlineUpdated'] != $date) { $request = db_query("\n\t\t\t\tSELECT mostOn\n\t\t\t\tFROM {$db_prefix}log_activity\n\t\t\t\tWHERE date = '{$date}'\n\t\t\t\tLIMIT 1", __FILE__, __LINE__); // The log_activity hasn't got an entry for today? if (mysql_num_rows($request) == 0) { db_query("\n\t\t\t\t\tINSERT IGNORE INTO {$db_prefix}log_activity\n\t\t\t\t\t\t(date, mostOn)\n\t\t\t\t\tVALUES ('{$date}', {$total_users})", __FILE__, __LINE__); } else { list($modSettings['mostOnlineToday']) = mysql_fetch_row($request); if ($total_users > $modSettings['mostOnlineToday']) { trackStats(array('mostOn' => $total_users)); } $total_users = max($total_users, $modSettings['mostOnlineToday']); } mysql_free_result($request); updateSettings(array('mostOnlineUpdated' => $date, 'mostOnlineToday' => $total_users)); } elseif ($total_users > $modSettings['mostOnlineToday']) { trackStats(array('mostOn' => $total_users)); updateSettings(array('mostOnlineUpdated' => $date, 'mostOnlineToday' => $total_users)); } } // Set the latest member. $context['latest_member'] =& $context['common_stats']['latest_member']; // Load the most recent post? if (!empty($settings['number_recent_posts']) && $settings['number_recent_posts'] == 1 || $settings['show_sp1_info']) { $context['latest_post'] = $most_recent_topic['ref']; } if (!empty($settings['number_recent_posts']) && $settings['number_recent_posts'] > 1) { require_once $sourcedir . '/Recent.php'; if (($context['latest_posts'] = cache_get_data('boardindex-latest_posts:' . md5($user_info['query_see_board'] . $user_info['language']), 180)) == null) { $context['latest_posts'] = getLastPosts($settings['number_recent_posts']); cache_put_data('boardindex-latest_posts:' . md5($user_info['query_see_board'] . $user_info['language']), $context['latest_posts'], 180); } // We have to clean up the cached data a bit. foreach ($context['latest_posts'] as $k => $post) { $context['latest_posts'][$k]['time'] = timeformat($post['raw_timestamp']); $context['latest_posts'][$k]['timestamp'] = forum_time(true, $post['raw_timestamp']); } } $settings['display_recent_bar'] = !empty($settings['number_recent_posts']) ? $settings['number_recent_posts'] : 0; $settings['show_member_bar'] &= allowedTo('view_mlist'); $context['show_stats'] = allowedTo('view_stats') && !empty($modSettings['trackStats']); $context['show_member_list'] = allowedTo('view_mlist'); $context['show_who'] = allowedTo('who_view') && !empty($modSettings['who_enabled']); // Set some permission related settings. $context['show_login_bar'] = $user_info['is_guest'] && !empty($modSettings['enableVBStyleLogin']); $context['show_calendar'] = allowedTo('calendar_view') && !empty($modSettings['cal_enabled']); // Load the calendar? if ($context['show_calendar']) { $context['show_calendar'] = calendarDoIndex(); } $context['page_title'] = $txt[18]; }
function registerMember(&$regOptions) { global $scripturl, $txt, $modSettings, $db_prefix, $context, $sourcedir; global $user_info, $options, $settings, $func; loadLanguage('Login'); // We'll need some external functions. require_once $sourcedir . '/Subs-Auth.php'; require_once $sourcedir . '/Subs-Post.php'; // Registration from the admin center, let them sweat a little more. if ($regOptions['interface'] == 'admin') { is_not_guest(); isAllowedTo('moderate_forum'); } elseif ($regOptions['interface'] == 'guest') { spamProtection('register'); // You cannot register twice... if (empty($user_info['is_guest'])) { redirectexit(); } // Make sure they didn't just register with this session. if (!empty($_SESSION['just_registered']) && empty($modSettings['disableRegisterCheck'])) { fatal_lang_error('register_only_once', false); } } // No name?! How can you register with no name? if (empty($regOptions['username'])) { fatal_lang_error(37, false); } // Spaces and other odd characters are evil... $regOptions['username'] = preg_replace('~[\\t\\n\\r\\x0B\\0' . ($context['utf8'] ? $context['server']['complex_preg_chars'] ? '\\x{A0}' : pack('C*', 0xc2, 0xa0) : '\\xA0') . ']+~' . ($context['utf8'] ? 'u' : ''), ' ', $regOptions['username']); // Don't use too long a name. if ($func['strlen']($regOptions['username']) > 25) { $regOptions['username'] = $func['htmltrim']($func['substr']($regOptions['username'], 0, 25)); } // Only these characters are permitted. if (preg_match('~[<>&"\'=\\\\]~', $regOptions['username']) != 0 || $regOptions['username'] == '_' || $regOptions['username'] == '|' || strpos($regOptions['username'], '[code') !== false || strpos($regOptions['username'], '[/code') !== false) { fatal_lang_error(240, false); } if (stristr($regOptions['username'], $txt[28]) !== false) { fatal_lang_error(244, true, array($txt[28])); } // !!! Separate the sprintf? if (empty($regOptions['email']) || preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', stripslashes($regOptions['email'])) === 0 || strlen(stripslashes($regOptions['email'])) > 255) { fatal_error(sprintf($txt[500], $regOptions['username']), false); } if (!empty($regOptions['check_reserved_name']) && isReservedName($regOptions['username'], 0, false)) { if ($regOptions['password'] == 'chocolate cake') { fatal_error('Sorry, I don\'t take bribes... you\'ll need to come up with a different name.', false); } fatal_error('(' . htmlspecialchars($regOptions['username']) . ') ' . $txt[473], false); } // Generate a validation code if it's supposed to be emailed. $validation_code = ''; if ($regOptions['require'] == 'activation') { $validation_code = generateValidationCode(); } // If you haven't put in a password generated one. if ($regOptions['interface'] == 'admin' && $regOptions['password'] == '') { mt_srand(time() + 1277); $regOptions['password'] = generateValidationCode(); $regOptions['password_check'] = $regOptions['password']; } elseif ($regOptions['password'] != $regOptions['password_check']) { fatal_lang_error(213, false); } // That's kind of easy to guess... if ($regOptions['password'] == '') { fatal_lang_error(91, false); } // Now perform hard password validation as required. if (!empty($regOptions['check_password_strength'])) { $passwordError = validatePassword($regOptions['password'], $regOptions['username'], array($regOptions['email'])); // Password isn't legal? if ($passwordError != null) { fatal_lang_error('profile_error_password_' . $passwordError, false); } } // You may not be allowed to register this email. if (!empty($regOptions['check_email_ban'])) { isBannedEmail($regOptions['email'], 'cannot_register', $txt['ban_register_prohibited']); } // Check if the email address is in use. $request = db_query("\n\t\tSELECT ID_MEMBER\n\t\tFROM {$db_prefix}members\n\t\tWHERE emailAddress = '{$regOptions['email']}'\n\t\t\tOR emailAddress = '{$regOptions['username']}'\n\t\tLIMIT 1", __FILE__, __LINE__); // !!! Separate the sprintf? if (mysql_num_rows($request) != 0) { fatal_error(sprintf($txt[730], htmlspecialchars($regOptions['email'])), false); } mysql_free_result($request); // Some of these might be overwritten. (the lower ones that are in the arrays below.) $regOptions['register_vars'] = array('memberName' => "'{$regOptions['username']}'", 'emailAddress' => "'{$regOptions['email']}'", 'passwd' => '\'' . sha1(strtolower($regOptions['username']) . $regOptions['password']) . '\'', 'passwordSalt' => '\'' . substr(md5(mt_rand()), 0, 4) . '\'', 'posts' => 0, 'dateRegistered' => time(), 'memberIP' => "'{$user_info['ip']}'", 'memberIP2' => "'{$_SERVER['BAN_CHECK_IP']}'", 'validation_code' => "'{$validation_code}'", 'realName' => "'{$regOptions['username']}'", 'personalText' => '\'' . addslashes($modSettings['default_personalText']) . '\'', 'pm_email_notify' => 1, 'ID_THEME' => 0, 'ID_POST_GROUP' => 4, 'lngfile' => "''", 'buddy_list' => "''", 'pm_ignore_list' => "''", 'messageLabels' => "''", 'personalText' => "''", 'websiteTitle' => "''", 'websiteUrl' => "''", 'location' => "''", 'ICQ' => "''", 'AIM' => "''", 'YIM' => "''", 'MSN' => "''", 'timeFormat' => "''", 'signature' => "''", 'avatar' => "''", 'usertitle' => "''", 'secretQuestion' => "''", 'secretAnswer' => "''", 'additionalGroups' => "''", 'smileySet' => "''"); // Setup the activation status on this new account so it is correct - firstly is it an under age account? if ($regOptions['require'] == 'coppa') { $regOptions['register_vars']['is_activated'] = 5; // !!! This should be changed. To what should be it be changed?? $regOptions['register_vars']['validation_code'] = "''"; } elseif ($regOptions['require'] == 'nothing') { $regOptions['register_vars']['is_activated'] = 1; } elseif ($regOptions['require'] == 'activation') { $regOptions['register_vars']['is_activated'] = 0; } else { $regOptions['register_vars']['is_activated'] = 3; } if (isset($regOptions['memberGroup'])) { // Make sure the ID_GROUP will be valid, if this is an administator. $regOptions['register_vars']['ID_GROUP'] = $regOptions['memberGroup'] == 1 && !allowedTo('admin_forum') ? 0 : $regOptions['memberGroup']; // Check if this group is assignable. $unassignableGroups = array(-1, 3); $request = db_query("\n\t\t\tSELECT ID_GROUP\n\t\t\tFROM {$db_prefix}membergroups\n\t\t\tWHERE minPosts != -1", __FILE__, __LINE__); while ($row = mysql_fetch_assoc($request)) { $unassignableGroups[] = $row['ID_GROUP']; } mysql_free_result($request); if (in_array($regOptions['register_vars']['ID_GROUP'], $unassignableGroups)) { $regOptions['register_vars']['ID_GROUP'] = 0; } } // Integrate optional member settings to be set. if (!empty($regOptions['extra_register_vars'])) { foreach ($regOptions['extra_register_vars'] as $var => $value) { $regOptions['register_vars'][$var] = $value; } } // Integrate optional user theme options to be set. $theme_vars = array(); if (!empty($regOptions['theme_vars'])) { foreach ($regOptions['theme_vars'] as $var => $value) { $theme_vars[$var] = $value; } } // Call an optional function to validate the users' input. if (isset($modSettings['integrate_register']) && function_exists($modSettings['integrate_register'])) { $modSettings['integrate_register']($regOptions, $theme_vars); } // Register them into the database. db_query("\n\t\tINSERT INTO {$db_prefix}members\n\t\t\t(" . implode(', ', array_keys($regOptions['register_vars'])) . ")\n\t\tVALUES (" . implode(', ', $regOptions['register_vars']) . ')', __FILE__, __LINE__); $memberID = db_insert_id(); // Grab their real name and send emails using it. $realName = substr($regOptions['register_vars']['realName'], 1, -1); // Update the number of members and latest member's info - and pass the name, but remove the 's. updateStats('member', $memberID, $realName); // Theme variables too? if (!empty($theme_vars)) { $setString = ''; foreach ($theme_vars as $var => $val) { $setString .= "\n\t\t\t\t({$memberID}, SUBSTRING('{$var}', 1, 255), SUBSTRING('{$val}', 1, 65534)),"; } db_query("\n\t\t\tINSERT INTO {$db_prefix}themes\n\t\t\t\t(ID_MEMBER, variable, value)\n\t\t\tVALUES " . substr($setString, 0, -1), __FILE__, __LINE__); } // If it's enabled, increase the registrations for today. trackStats(array('registers' => '+')); // Administrative registrations are a bit different... if ($regOptions['interface'] == 'admin') { if ($regOptions['require'] == 'activation') { $email_message = 'register_activate_message'; } elseif (!empty($regOptions['send_welcome_email'])) { $email_message = 'register_immediate_message'; } if (isset($email_message)) { sendmail($regOptions['email'], $txt['register_subject'], sprintf($txt[$email_message], $realName, $regOptions['username'], $regOptions['password'], $validation_code, $scripturl . '?action=activate;u=' . $memberID . ';code=' . $validation_code)); } // All admins are finished here. return $memberID; } // Can post straight away - welcome them to your fantastic community... if ($regOptions['require'] == 'nothing') { if (!empty($regOptions['send_welcome_email'])) { sendmail($regOptions['email'], $txt['register_subject'], sprintf($txt['register_immediate_message'], $realName, $regOptions['username'], $regOptions['password'])); } // Send admin their notification. adminNotify('standard', $memberID, $regOptions['username']); } elseif ($regOptions['require'] == 'activation' || $regOptions['require'] == 'coppa') { sendmail($regOptions['email'], $txt['register_subject'], sprintf($txt['register_activate_message'], $realName, $regOptions['username'], $regOptions['password'], $validation_code, $scripturl . '?action=activate;u=' . $memberID . ';code=' . $validation_code)); } else { sendmail($regOptions['email'], $txt['register_subject'], sprintf($txt['register_pending_message'], $realName, $regOptions['username'], $regOptions['password'])); // Admin gets informed here... adminNotify('approval', $memberID, $regOptions['username']); } // Okay, they're for sure registered... make sure the session is aware of this for security. (Just married :P!) $_SESSION['just_registered'] = 1; return $memberID; }
public static function obExit($header = null, $do_footer = null, $from_index = false, $from_fatal_error = false) { global $context, $modSettings; static $header_done = false, $footer_done = false, $level = 0, $has_fatal_error = false; // Attempt to prevent a recursive loop. ++$level; if ($level > 1 && !$from_fatal_error && !$has_fatal_error) { exit; } if ($from_fatal_error) { $has_fatal_error = true; } // Clear out the stat cache. trackStats(); // If we have mail to send, send it. if (!empty($context['flush_mail'])) { AddMailQueue(true); } $do_header = $header === null ? !$header_done : $header; if ($do_footer === null) { $do_footer = $do_header; } // Has the template/header been done yet? if ($do_header) { // Was the page title set last minute? Also update the HTML safe one. if (!empty($context['page_title']) && empty($context['page_title_html_safe'])) { $context['page_title_html_safe'] = $context['forum_name_html_safe'] . ' - ' . commonAPI::htmlspecialchars(un_htmlspecialchars($context['page_title'])); } // Start up the session URL fixer. ob_start('ob_sessrewrite'); HookAPI::integrateOB(); //if(!empty($modSettings['simplesef_enable'])) // ob_start('SimpleSEF::ob_simplesef'); // Display the screen in the logical order. self::template_header(); $header_done = true; } if ($do_footer) { if (WIRELESS && !isset($context['sub_template'])) { fatal_lang_error('wireless_error_notyet', false); } self::Display(); // Just so we don't get caught in an endless loop of errors from the footer... if (!$footer_done) { $footer_done = true; // (since this is just debugging... it's okay that it's after </html>.) if (!isset($_REQUEST['xml'])) { db_debug_junk(); } } } // Remember this URL in case someone doesn't like sending HTTP_REFERER. if (strpos($_SERVER['REQUEST_URL'], 'action=dlattach') === false && strpos($_SERVER['REQUEST_URL'], 'action=viewsmfile') === false) { $_SESSION['old_url'] = $_SERVER['REQUEST_URL']; } // For session check verfication.... don't switch browsers... $_SESSION['USER_AGENT'] = $_SERVER['HTTP_USER_AGENT']; // Hand off the output to the portal, etc. we're integrated with. HookAPI::callHook('integrate_exit', array($do_footer)); if (!empty($modSettings['simplesef_enable'])) { SimpleSEF::fixXMLOutput($do_footer); } // Don't exit if we're coming from index.php; that will pass through normally. if (!$from_index) { exit; } }
function smf_main() { global $modSettings, $settings, $user_info, $board, $topic, $board_info, $maintenance, $sourcedir, $request_name, $txt, $user_settings, $mobiquo_config, $topic_per_page, $limit_num; // Load the user's cookie (or set as guest) and load their settings. loadUserSettings(); // Load the current board's information. loadBoard(); // Load the current user's permissions. loadPermissions(); // Attachments don't require the entire theme to be loaded. loadTheme(); header('Mobiquo_is_login:'******'context']['user']['is_logged'] ? 'true' : 'false')); // Check if the user should be disallowed access. if (!in_array($request_name, array('get_config', 'login'))) { is_not_banned(); } // If we are in a topic and don't have permission to approve it then duck out now. if (!empty($topic) && empty($board_info['cur_topic_approved']) && !allowedTo('approve_posts') && ($user_info['id'] != $board_info['cur_topic_starter'] || $user_info['is_guest'])) { //fatal_lang_error('not_a_topic', false); get_error('The topic is not approved'); } // Do some logging, unless this is an attachment, avatar, toggle of editor buttons, theme option, XML feed etc. if (empty($_REQUEST['action']) || !in_array($_REQUEST['action'], array('dlattach', 'findmember', 'jseditor', 'jsoption', 'requestmembers', 'smstats', '.xml', 'xmlhttp', 'verificationcode', 'viewquery', 'viewsmfile'))) { // Log this user as online. writeLog(); // Track forum statistics and hits...? if (!empty($modSettings['hitStats'])) { trackStats(array('hits' => '+')); } } // Is the forum in maintenance mode? (doesn't apply to administrators.) if (!empty($maintenance) && !allowedTo('admin_forum')) { if ($request_name != 'get_config' && $request_name != 'login') { get_error($txt['maintain_mode_on']); } } elseif (empty($modSettings['allow_guestAccess']) && $user_info['is_guest'] && (!isset($_REQUEST['action']) || !in_array($_REQUEST['action'], array('push_content_check', 'user_subscription', 'set_api_key', 'reset_push_slug', 'prefetch_account', 'update_password', 'forget_password', 'sign_in', 'coppa', 'login', 'login2', 'register', 'register2', 'reminder', 'activate', 'help', 'smstats', 'mailq', 'verificationcode', 'openidreturn')))) { if ($request_name != 'get_config' && $request_name != 'prefetch_account') { loadLanguage('Login'); get_error($txt['only_members_can_access']); //require_once($sourcedir . '/Subs-Auth.php'); //return 'KickGuest'; } } //-------------transform input data to local character set if needed utf8_to_local(); //-------------change some setting for tapatalk display $settings['message_index_preview'] = 1; $modSettings['todayMod_bak'] = $modSettings['todayMod']; $modSettings['todayMod'] = 0; $user_settings['pm_prefs'] = 0; $user_info['user_time_format'] = $user_info['time_format']; $user_info['time_format'] = '%Y%m%dT%H:%M:%S+00:00'; $modSettings['disableCustomPerPage'] = 1; $modSettings['disableCheckUA'] = 1; $modSettings['defaultMaxMessages'] = isset($limit_num) ? $limit_num : 20; $modSettings['defaultMaxMembers'] = 100; $modSettings['search_results_per_page'] = isset($topic_per_page) && $topic_per_page > 0 ? $topic_per_page : 20; $modSettings['defaultMaxTopics'] = isset($topic_per_page) && $topic_per_page > 0 ? $topic_per_page : 20; $modSettings['disable_pm_verification'] = $mobiquo_config['disable_pm_verification']; //-------------do something before action-------------- if (function_exists('before_action_' . $request_name)) { call_user_func('before_action_' . $request_name); } if (empty($_REQUEST['action']) && !empty($board)) { if (empty($topic)) { require_once 'include/MessageIndex.php'; return 'MessageIndex'; } else { require_once 'include/Display.php'; return 'Display'; } } // Here's the monstrous $_REQUEST['action'] array - $_REQUEST['action'] => array($file, $function). $actionArray = array('activate' => array('Register.php', 'Activate'), 'admin' => array('Admin.php', 'AdminMain'), 'announce' => array('Post.php', 'AnnounceTopic'), 'attachapprove' => array('ManageAttachments.php', 'ApproveAttach'), 'buddy' => array('Subs-Members.php', 'BuddyListToggle'), 'calendar' => array('Calendar.php', 'CalendarMain'), 'clock' => array('Calendar.php', 'clock'), 'collapse' => array('BoardIndex.php', 'CollapseCategory'), 'coppa' => array('Register.php', 'CoppaForm'), 'credits' => array('Who.php', 'Credits'), 'deletemsg' => array('RemoveTopic.php', 'DeleteMessage'), 'display' => array('Display.php', 'Display'), 'dlattach' => array('Display.php', 'Download'), 'editpoll' => array('Poll.php', 'EditPoll'), 'editpoll2' => array('Poll.php', 'EditPoll2'), 'emailuser' => array('SendTopic.php', 'EmailUser'), 'findmember' => array('Subs-Auth.php', 'JSMembers'), 'groups' => array('Groups.php', 'Groups'), 'help' => array('Help.php', 'ShowHelp'), 'helpadmin' => array('Help.php', 'ShowAdminHelp'), 'im' => array('PersonalMessage.php', 'MessageMain'), 'jseditor' => array('Subs-Editor.php', 'EditorMain'), 'jsmodify' => array('Post.php', 'JavaScriptModify'), 'jsoption' => array('Themes.php', 'SetJavaScript'), 'lock' => array('LockTopic.php', 'LockTopic'), 'lockvoting' => array('Poll.php', 'LockVoting'), 'login' => array('LogInOut.php', 'Login'), 'login2' => array('LogInOut.php', 'Login2'), 'logout' => array('LogInOut.php', 'Logout'), 'markasread' => array('Subs-Boards.php', 'MarkRead'), 'mergetopics' => array('SplitTopics.php', 'MergeTopics'), 'mlist' => array('Memberlist.php', 'Memberlist'), 'moderate' => array('ModerationCenter.php', 'ModerationMain'), 'modifycat' => array('ManageBoards.php', 'ModifyCat'), 'modifykarma' => array('Karma.php', 'ModifyKarma'), 'movetopic' => array('MoveTopic.php', 'MoveTopic'), 'movetopic2' => array('MoveTopic.php', 'MoveTopic2'), 'notify' => array('Notify.php', 'Notify'), 'notifyboard' => array('Notify.php', 'BoardNotify'), 'openidreturn' => array('Subs-OpenID.php', 'smf_openID_return'), 'pm' => array('PersonalMessage.php', 'MessageMain'), 'post' => array('Post.php', 'Post'), 'post2' => array('Post.php', 'Post2'), 'printpage' => array('Printpage.php', 'PrintTopic'), 'profile' => array('Profile.php', 'ModifyProfile'), 'quotefast' => array('Post.php', 'QuoteFast'), 'quickmod' => array('MessageIndex.php', 'QuickModeration'), 'quickmod2' => array('Display.php', 'QuickInTopicModeration'), 'recent' => array('Recent.php', 'RecentPosts'), 'register' => array('Register.php', 'Register'), 'register2' => array('Register.php', 'Register2'), 'reminder' => array('Reminder.php', 'RemindMe'), 'removepoll' => array('Poll.php', 'RemovePoll'), 'removetopic2' => array('RemoveTopic.php', 'RemoveTopic2'), 'reporttm' => array('SendTopic.php', 'ReportToModerator'), 'requestmembers' => array('Subs-Auth.php', 'RequestMembers'), 'restoretopic' => array('RemoveTopic.php', 'RestoreTopic'), 'search' => array('Search.php', 'PlushSearch1'), 'search2' => array('Search.php', 'PlushSearch2'), 'sendtopic' => array('SendTopic.php', 'EmailUser'), 'smstats' => array('Stats.php', 'SMStats'), 'suggest' => array('Subs-Editor.php', 'AutoSuggestHandler'), 'spellcheck' => array('Subs-Post.php', 'SpellCheck'), 'splittopics' => array('SplitTopics.php', 'SplitTopics'), 'stats' => array('Stats.php', 'DisplayStats'), 'sticky' => array('LockTopic.php', 'Sticky'), 'theme' => array('Themes.php', 'ThemesMain'), 'trackip' => array('Profile-View.php', 'trackIP'), 'about:mozilla' => array('Karma.php', 'BookOfUnknown'), 'about:unknown' => array('Karma.php', 'BookOfUnknown'), 'unread' => array('Recent.php', 'UnreadTopics'), 'unreadreplies' => array('Recent.php', 'UnreadTopics'), 'verificationcode' => array('Register.php', 'VerificationCode'), 'viewprofile' => array('Profile.php', 'ModifyProfile'), 'vote' => array('Poll.php', 'Vote'), 'viewquery' => array('ViewQuery.php', 'ViewQuery'), 'viewsmfile' => array('Admin.php', 'DisplayAdminFile'), 'who' => array('Who.php', 'Who'), '.xml' => array('News.php', 'ShowXmlFeed'), 'xmlhttp' => array('Xml.php', 'XMLhttpMain')); // Allow modifying $actionArray easily. call_integration_hook('integrate_actions', array(&$actionArray)); //error_log($request_name.'-'.$_REQUEST['action']); //for debugging // Get the function and file to include - if it's not there, do the board index. if (!isset($_REQUEST['action']) || !isset($actionArray[$_REQUEST['action']])) { if (function_exists('action_' . $request_name)) { return 'action_' . $request_name; } else { get_error('Invalid action'); } } $local_action = array('login2', 'post', 'post2', 'who', 'profile', 'notify', 'notifyboard', 'markasread', 'unread', 'search2', 'pm', 'logout'); // Otherwise, it was set - so let's go to that action. if (in_array($_REQUEST['action'], $local_action)) { if (file_exists(TT_ROOT . 'include/' . $actionArray[$_REQUEST['action']][0])) { require_once TT_ROOT . 'include/' . $actionArray[$_REQUEST['action']][0]; } else { if (file_exists($sourcedir . '/' . $actionArray[$_REQUEST['action']][0])) { require_once $sourcedir . '/' . $actionArray[$_REQUEST['action']][0]; } } } else { if (file_exists($sourcedir . '/' . $actionArray[$_REQUEST['action']][0])) { require_once $sourcedir . '/' . $actionArray[$_REQUEST['action']][0]; } } return $actionArray[$_REQUEST['action']][1]; }
/** * Registers a member to the forum. * * What it does: * - Allows two types of interface: 'guest' and 'admin'. The first * - includes hammering protection, the latter can perform the registration silently. * - The strings used in the options array are assumed to be escaped. * - Allows to perform several checks on the input, e.g. reserved names. * - The function will adjust member statistics. * - If an error is detected will fatal error on all errors unless return_errors is true. * * @package Members * @uses Auth.subs.php * @uses Mail.subs.php * @param mixed[] $regOptions * @param string $error_context * @return integer the ID of the newly created member */ function registerMember(&$regOptions, $error_context = 'register') { global $scripturl, $txt, $modSettings, $user_info; $db = database(); loadLanguage('Login'); // We'll need some external functions. require_once SUBSDIR . '/Auth.subs.php'; require_once SUBSDIR . '/Mail.subs.php'; // Put any errors in here. $reg_errors = Error_Context::context($error_context, 0); // Registration from the admin center, let them sweat a little more. if ($regOptions['interface'] == 'admin') { is_not_guest(); isAllowedTo('moderate_forum'); } elseif ($regOptions['interface'] == 'guest') { // You cannot register twice... if (empty($user_info['is_guest'])) { redirectexit(); } // Make sure they didn't just register with this session. if (!empty($_SESSION['just_registered']) && empty($modSettings['disableRegisterCheck'])) { fatal_lang_error('register_only_once', false); } } // What method of authorization are we going to use? if (empty($regOptions['auth_method']) || !in_array($regOptions['auth_method'], array('password', 'openid'))) { if (!empty($regOptions['openid'])) { $regOptions['auth_method'] = 'openid'; } else { $regOptions['auth_method'] = 'password'; } } // Spaces and other odd characters are evil... $regOptions['username'] = trim(preg_replace('~[\\t\\n\\r \\x0B\\0\\x{A0}\\x{AD}\\x{2000}-\\x{200F}\\x{201F}\\x{202F}\\x{3000}\\x{FEFF}]+~u', ' ', $regOptions['username'])); // Valid emails only require_once SUBSDIR . '/DataValidator.class.php'; if (!Data_Validator::is_valid($regOptions, array('email' => 'valid_email|required|max_length[255]'), array('email' => 'trim'))) { $reg_errors->addError('bad_email'); } validateUsername(0, $regOptions['username'], $error_context, !empty($regOptions['check_reserved_name'])); // Generate a validation code if it's supposed to be emailed. $validation_code = ''; if ($regOptions['require'] == 'activation') { $validation_code = generateValidationCode(); } // If you haven't put in a password generate one. if ($regOptions['interface'] == 'admin' && $regOptions['password'] == '' && $regOptions['auth_method'] == 'password') { mt_srand(time() + 1277); $regOptions['password'] = generateValidationCode(); $regOptions['password_check'] = $regOptions['password']; } elseif ($regOptions['password'] != $regOptions['password_check'] && $regOptions['auth_method'] == 'password') { $reg_errors->addError('passwords_dont_match'); } // That's kind of easy to guess... if ($regOptions['password'] == '') { if ($regOptions['auth_method'] == 'password') { $reg_errors->addError('no_password'); } else { $regOptions['password'] = sha1(mt_rand()); } } // Now perform hard password validation as required. if (!empty($regOptions['check_password_strength']) && $regOptions['password'] != '') { $passwordError = validatePassword($regOptions['password'], $regOptions['username'], array($regOptions['email'])); // Password isn't legal? if ($passwordError != null) { $reg_errors->addError('profile_error_password_' . $passwordError); } } // You may not be allowed to register this email. if (!empty($regOptions['check_email_ban'])) { isBannedEmail($regOptions['email'], 'cannot_register', $txt['ban_register_prohibited']); } // Check if the email address is in use. $request = $db->query('', ' SELECT id_member FROM {db_prefix}members WHERE email_address = {string:email_address} OR email_address = {string:username} LIMIT 1', array('email_address' => $regOptions['email'], 'username' => $regOptions['username'])); if ($db->num_rows($request) != 0) { $reg_errors->addError(array('email_in_use', array(htmlspecialchars($regOptions['email'], ENT_COMPAT, 'UTF-8')))); } $db->free_result($request); // Perhaps someone else wants to check this user call_integration_hook('integrate_register_check', array(&$regOptions, &$reg_errors)); // If there's any errors left return them at once! if ($reg_errors->hasErrors()) { return false; } $reservedVars = array('actual_theme_url', 'actual_images_url', 'base_theme_dir', 'base_theme_url', 'default_images_url', 'default_theme_dir', 'default_theme_url', 'default_template', 'images_url', 'number_recent_posts', 'smiley_sets_default', 'theme_dir', 'theme_id', 'theme_layers', 'theme_templates', 'theme_url'); // Can't change reserved vars. if (isset($regOptions['theme_vars']) && count(array_intersect(array_keys($regOptions['theme_vars']), $reservedVars)) != 0) { fatal_lang_error('no_theme'); } // New password hash require_once SUBSDIR . '/Auth.subs.php'; // Some of these might be overwritten. (the lower ones that are in the arrays below.) $regOptions['register_vars'] = array('member_name' => $regOptions['username'], 'email_address' => $regOptions['email'], 'passwd' => validateLoginPassword($regOptions['password'], '', $regOptions['username'], true), 'password_salt' => substr(md5(mt_rand()), 0, 4), 'posts' => 0, 'date_registered' => !empty($regOptions['time']) ? $regOptions['time'] : time(), 'member_ip' => $regOptions['interface'] == 'admin' ? '127.0.0.1' : $regOptions['ip'], 'member_ip2' => $regOptions['interface'] == 'admin' ? '127.0.0.1' : $regOptions['ip2'], 'validation_code' => $validation_code, 'real_name' => $regOptions['username'], 'personal_text' => $modSettings['default_personal_text'], 'pm_email_notify' => 1, 'id_theme' => 0, 'id_post_group' => 4, 'lngfile' => '', 'buddy_list' => '', 'pm_ignore_list' => '', 'message_labels' => '', 'website_title' => '', 'website_url' => '', 'location' => '', 'time_format' => '', 'signature' => '', 'avatar' => '', 'usertitle' => '', 'secret_question' => '', 'secret_answer' => '', 'additional_groups' => '', 'ignore_boards' => '', 'smiley_set' => '', 'openid_uri' => !empty($regOptions['openid']) ? $regOptions['openid'] : ''); // Setup the activation status on this new account so it is correct - firstly is it an under age account? if ($regOptions['require'] == 'coppa') { $regOptions['register_vars']['is_activated'] = 5; // @todo This should be changed. To what should be it be changed?? $regOptions['register_vars']['validation_code'] = ''; } elseif ($regOptions['require'] == 'nothing') { $regOptions['register_vars']['is_activated'] = 1; } elseif ($regOptions['require'] == 'activation') { $regOptions['register_vars']['is_activated'] = 0; } else { $regOptions['register_vars']['is_activated'] = 3; } if (isset($regOptions['memberGroup'])) { // Make sure the id_group will be valid, if this is an administator. $regOptions['register_vars']['id_group'] = $regOptions['memberGroup'] == 1 && !allowedTo('admin_forum') ? 0 : $regOptions['memberGroup']; // Check if this group is assignable. $unassignableGroups = array(-1, 3); $request = $db->query('', ' SELECT id_group FROM {db_prefix}membergroups WHERE min_posts != {int:min_posts}' . (allowedTo('admin_forum') ? '' : ' OR group_type = {int:is_protected}'), array('min_posts' => -1, 'is_protected' => 1)); while ($row = $db->fetch_assoc($request)) { $unassignableGroups[] = $row['id_group']; } $db->free_result($request); if (in_array($regOptions['register_vars']['id_group'], $unassignableGroups)) { $regOptions['register_vars']['id_group'] = 0; } } // Integrate optional member settings to be set. if (!empty($regOptions['extra_register_vars'])) { foreach ($regOptions['extra_register_vars'] as $var => $value) { $regOptions['register_vars'][$var] = $value; } } // Integrate optional user theme options to be set. $theme_vars = array(); if (!empty($regOptions['theme_vars'])) { foreach ($regOptions['theme_vars'] as $var => $value) { $theme_vars[$var] = $value; } } // Right, now let's prepare for insertion. $knownInts = array('date_registered', 'posts', 'id_group', 'last_login', 'personal_messages', 'unread_messages', 'notifications', 'new_pm', 'pm_prefs', 'gender', 'hide_email', 'show_online', 'pm_email_notify', 'karma_good', 'karma_bad', 'notify_announcements', 'notify_send_body', 'notify_regularity', 'notify_types', 'id_theme', 'is_activated', 'id_msg_last_visit', 'id_post_group', 'total_time_logged_in', 'warning'); $knownFloats = array('time_offset'); // Call an optional function to validate the users' input. call_integration_hook('integrate_register', array(&$regOptions, &$theme_vars, &$knownInts, &$knownFloats)); $column_names = array(); $values = array(); foreach ($regOptions['register_vars'] as $var => $val) { $type = 'string'; if (in_array($var, $knownInts)) { $type = 'int'; } elseif (in_array($var, $knownFloats)) { $type = 'float'; } elseif ($var == 'birthdate') { $type = 'date'; } $column_names[$var] = $type; $values[$var] = $val; } // Register them into the database. $db->insert('', '{db_prefix}members', $column_names, $values, array('id_member')); $memberID = $db->insert_id('{db_prefix}members', 'id_member'); // Update the number of members and latest member's info - and pass the name, but remove the 's. if ($regOptions['register_vars']['is_activated'] == 1) { updateMemberStats($memberID, $regOptions['register_vars']['real_name']); } else { updateMemberStats(); } // Theme variables too? if (!empty($theme_vars)) { $inserts = array(); foreach ($theme_vars as $var => $val) { $inserts[] = array($memberID, $var, $val); } $db->insert('insert', '{db_prefix}themes', array('id_member' => 'int', 'variable' => 'string-255', 'value' => 'string-65534'), $inserts, array('id_member', 'variable')); } // If it's enabled, increase the registrations for today. trackStats(array('registers' => '+')); // Administrative registrations are a bit different... if ($regOptions['interface'] == 'admin') { if ($regOptions['require'] == 'activation') { $email_message = 'admin_register_activate'; } elseif (!empty($regOptions['send_welcome_email'])) { $email_message = 'admin_register_immediate'; } if (isset($email_message)) { $replacements = array('REALNAME' => $regOptions['register_vars']['real_name'], 'USERNAME' => $regOptions['username'], 'PASSWORD' => $regOptions['password'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', 'ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $memberID . ';code=' . $validation_code, 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $memberID, 'ACTIVATIONCODE' => $validation_code); $emaildata = loadEmailTemplate($email_message, $replacements); sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); } } else { // Can post straight away - welcome them to your fantastic community... if ($regOptions['require'] == 'nothing') { if (!empty($regOptions['send_welcome_email'])) { $replacements = array('REALNAME' => $regOptions['register_vars']['real_name'], 'USERNAME' => $regOptions['username'], 'PASSWORD' => $regOptions['password'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', 'OPENID' => !empty($regOptions['openid']) ? $regOptions['openid'] : ''); $emaildata = loadEmailTemplate('register_' . ($regOptions['auth_method'] == 'openid' ? 'openid_' : '') . 'immediate', $replacements); sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); } // Send admin their notification. require_once SUBSDIR . '/Notification.subs.php'; sendAdminNotifications('standard', $memberID, $regOptions['username']); } elseif ($regOptions['require'] == 'activation' || $regOptions['require'] == 'coppa') { $replacements = array('REALNAME' => $regOptions['register_vars']['real_name'], 'USERNAME' => $regOptions['username'], 'PASSWORD' => $regOptions['password'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', 'OPENID' => !empty($regOptions['openid']) ? $regOptions['openid'] : ''); if ($regOptions['require'] == 'activation') { $replacements += array('ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $memberID . ';code=' . $validation_code, 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $memberID, 'ACTIVATIONCODE' => $validation_code); } else { $replacements += array('COPPALINK' => $scripturl . '?action=coppa;u=' . $memberID); } $emaildata = loadEmailTemplate('register_' . ($regOptions['auth_method'] == 'openid' ? 'openid_' : '') . ($regOptions['require'] == 'activation' ? 'activate' : 'coppa'), $replacements); sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); } else { $replacements = array('REALNAME' => $regOptions['register_vars']['real_name'], 'USERNAME' => $regOptions['username'], 'PASSWORD' => $regOptions['password'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', 'OPENID' => !empty($regOptions['openid']) ? $regOptions['openid'] : ''); $emaildata = loadEmailTemplate('register_' . ($regOptions['auth_method'] == 'openid' ? 'openid_' : '') . 'pending', $replacements); sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); // Admin gets informed here... require_once SUBSDIR . '/Notification.subs.php'; sendAdminNotifications('approval', $memberID, $regOptions['username']); } // Okay, they're for sure registered... make sure the session is aware of this for security. (Just married :P!) $_SESSION['just_registered'] = 1; } // If they are for sure registered, let other people to know about it call_integration_hook('integrate_register_after', array($regOptions, $memberID)); return $memberID; }
function createPost(&$msgOptions, &$topicOptions, &$posterOptions) { global $user_info, $txt, $modSettings, $context, $sourcedir; // Set optional parameters to the default value. $msgOptions['icon'] = empty($msgOptions['icon']) ? 'xx' : $msgOptions['icon']; $msgOptions['smileys_enabled'] = !empty($msgOptions['smileys_enabled']); $msgOptions['attachments'] = empty($msgOptions['attachments']) ? array() : $msgOptions['attachments']; $msgOptions['approved'] = isset($msgOptions['approved']) ? (int) $msgOptions['approved'] : 1; $msgOptions['locked'] = 0; $topicOptions['id'] = empty($topicOptions['id']) ? 0 : (int) $topicOptions['id']; $topicOptions['poll'] = isset($topicOptions['poll']) ? (int) $topicOptions['poll'] : null; $topicOptions['lock_mode'] = isset($topicOptions['lock_mode']) ? $topicOptions['lock_mode'] : null; $topicOptions['sticky_mode'] = isset($topicOptions['sticky_mode']) ? $topicOptions['sticky_mode'] : null; $posterOptions['id'] = empty($posterOptions['id']) ? 0 : (int) $posterOptions['id']; $posterOptions['ip'] = empty($posterOptions['ip']) ? $user_info['ip'] : $posterOptions['ip']; $context['can_tag_users'] = allowedTo('tag_users'); $tagged_users = handleUserTags($msgOptions['body']); // We need to know if the topic is approved. If we're told that's great - if not find out. if (!$modSettings['postmod_active']) { $topicOptions['is_approved'] = true; } elseif (!empty($topicOptions['id']) && !isset($topicOptions['is_approved'])) { $request = smf_db_query(' SELECT approved FROM {db_prefix}topics WHERE id_topic = {int:id_topic} LIMIT 1', array('id_topic' => $topicOptions['id'])); list($topicOptions['is_approved']) = mysql_fetch_row($request); mysql_free_result($request); } // If nothing was filled in as name/e-mail address, try the member table. if (!isset($posterOptions['name']) || $posterOptions['name'] == '' || empty($posterOptions['email']) && !empty($posterOptions['id'])) { if (empty($posterOptions['id'])) { $posterOptions['id'] = 0; $posterOptions['name'] = $txt['guest_title']; $posterOptions['email'] = ''; } elseif ($posterOptions['id'] != $user_info['id']) { $request = smf_db_query(' SELECT member_name, email_address, real_name FROM {db_prefix}members WHERE id_member = {int:id_member} LIMIT 1', array('id_member' => $posterOptions['id'])); // Couldn't find the current poster? if (mysql_num_rows($request) == 0) { trigger_error('createPost(): Invalid member id ' . $posterOptions['id'], E_USER_NOTICE); $posterOptions['id'] = 0; $posterOptions['name'] = $txt['guest_title']; $posterOptions['email'] = ''; } else { list($posterOptions['name'], $posterOptions['email'], $posterOptions['real_name']) = mysql_fetch_row($request); } mysql_free_result($request); } else { $posterOptions['name'] = $posterOptions['real_name'] = $user_info['name']; $posterOptions['email'] = $user_info['email']; } } else { $posterOptions['real_name'] = $user_info['name']; } // It's do or die time: forget any user aborts! $previous_ignore_user_abort = ignore_user_abort(true); $new_topic = empty($topicOptions['id']); // decide whether we should just update the last post or append a new one $automerge_posts = false; $want_automerge = isset($_REQUEST['want_automerge']) && $_REQUEST['want_automerge'] > 0 ? true : false; if (!$new_topic && ($topicOptions['automerge'] > 0 && $want_automerge) && $topicOptions['id_member_updated'] == $posterOptions['id'] && empty($topicOptions['poll'])) { $result = smf_db_query(' SELECT poster_time, modified_time, body FROM {db_prefix}messages WHERE id_msg = {int:last_id}', array('last_id' => $topicOptions['id_last_msg'])); list($ptime, $mtime, $oldbody) = mysql_fetch_row($result); if (smf_db_affected_rows() != 0) { if ($want_automerge || time() - max($ptime, $mtime) < $topicOptions['automerge'] * 60) { $automerge_posts = true; $msg_to_update = $topicOptions['id_last_msg']; } } mysql_free_result($result); } // Insert the post. if (false === $automerge_posts) { smf_db_insert('', '{db_prefix}messages', array('id_board' => 'int', 'id_topic' => 'int', 'id_member' => 'int', 'subject' => 'string-255', 'body' => !empty($modSettings['max_messageLength']) && $modSettings['max_messageLength'] > 65534 ? 'string-' . $modSettings['max_messageLength'] : 'string', 'poster_name' => 'string-255', 'poster_email' => 'string-255', 'poster_time' => 'int', 'poster_ip' => 'string-255', 'smileys_enabled' => 'int', 'modified_name' => 'string', 'icon' => 'string-16', 'approved' => 'int', 'locked' => 'int'), array($topicOptions['board'], $topicOptions['id'], $posterOptions['id'], $msgOptions['subject'], $msgOptions['body'], $posterOptions['name'], $posterOptions['email'], time(), $posterOptions['ip'], $msgOptions['smileys_enabled'] ? 1 : 0, '', $msgOptions['icon'], $msgOptions['approved'], $msgOptions['locked']), array('id_msg')); $msgOptions['id'] = smf_db_insert_id('{db_prefix}messages', 'id_msg'); if (count($tagged_users) > 0) { notifyTaggedUsers($tagged_users, array('id_topic' => $topicOptions['id'], 'id_message' => $msgOptions['id'])); } // Something went wrong creating the message... if (empty($msgOptions['id'])) { return false; } $msg_to_update = $msgOptions['id']; // needed for later tasks // Fix the attachments. if (!empty($msgOptions['attachments'])) { smf_db_query(' UPDATE {db_prefix}attachments SET id_msg = {int:id_msg} WHERE id_attach IN ({array_int:attachment_list})', array('attachment_list' => $msgOptions['attachments'], 'id_msg' => $msgOptions['id'])); } } else { if ($msg_to_update) { $newbody = $oldbody . "\n[hr][size=11px][color=red][b] Posted: [time]" . time() . "[/time][/b][/color][/size]\n" . $msgOptions['body']; // todo: make the separator customizable //todo: it should be possible to customize the separator smf_db_query(' UPDATE {db_prefix}messages SET body = {string:newbody}, modified_time = {int:now}, approved = {int:approved} WHERE id_msg = {int:id_msg}', array('newbody' => $newbody, 'now' => time(), 'id_msg' => $msg_to_update, 'approved' => $msgOptions['approved'])); smf_db_query('DELETE FROM {db_prefix}messages_cache WHERE id_msg = {int:id_msg}', array('id_msg' => $msg_to_update)); CacheAPI::clearCacheByPrefix('parse:' . trim($msg_to_update) . '-'); if (count($tagged_users) > 0) { notifyTaggedUsers($tagged_users, array('id_topic' => $topicOptions['id'], 'id_message' => $msgOptions['id'])); } if (empty($msgOptions['attachments'])) { $attachments[0] = -1; } else { $attachments = $msgOptions['attachments']; } // attachments must be fixed and "redirected" for the new post id... smf_db_query(' UPDATE {db_prefix}attachments SET id_msg = {int:id_msg} WHERE id_attach IN ({array_int:attachment_list})', array('attachment_list' => $attachments, 'id_msg' => $msg_to_update)); } else { return false; } // that should NOT happen... } // Insert a new topic (if the topicID was left empty.) if ($new_topic) { if (!isset($topicOptions['topic_prefix'])) { $topicOptions['topic_prefix'] = 0; } if (!isset($topicOptions['topic_layout'])) { $topicOptions['topic_layout'] = 0; } smf_db_insert('', '{db_prefix}topics', array('id_board' => 'int', 'id_member_started' => 'int', 'id_member_updated' => 'int', 'id_first_msg' => 'int', 'id_last_msg' => 'int', 'locked' => 'int', 'is_sticky' => 'int', 'num_views' => 'int', 'id_poll' => 'int', 'unapproved_posts' => 'int', 'approved' => 'int', 'id_prefix' => 'int', 'id_layout' => 'int'), array($topicOptions['board'], $posterOptions['id'], $posterOptions['id'], $msgOptions['id'], $msgOptions['id'], $topicOptions['lock_mode'] === null ? 0 : $topicOptions['lock_mode'], $topicOptions['sticky_mode'] === null ? 0 : $topicOptions['sticky_mode'], 0, $topicOptions['poll'] === null ? 0 : $topicOptions['poll'], $msgOptions['approved'] ? 0 : 1, $msgOptions['approved'], $topicOptions['topic_prefix'], $topicOptions['topic_layout']), array('id_topic')); $topicOptions['id'] = smf_db_insert_id('{db_prefix}topics', 'id_topic'); // The topic couldn't be created for some reason. if (empty($topicOptions['id'])) { // We should delete the post that did work, though... smf_db_query(' DELETE FROM {db_prefix}messages WHERE id_msg = {int:id_msg}', array('id_msg' => $msgOptions['id'])); return false; } // Fix the message with the topic. smf_db_query(' UPDATE {db_prefix}messages SET id_topic = {int:id_topic} WHERE id_msg = {int:id_msg}', array('id_topic' => $topicOptions['id'], 'id_msg' => $msgOptions['id'])); // There's been a new topic AND a new post today. trackStats(array('topics' => '+', 'posts' => '+')); updateStats('topic', true); updateStats('subject', $topicOptions['id'], $msgOptions['subject']); // todo supporting code for related topics mod (should go away - the mod is not included) if (isset($modSettings['have_related_topics']) && $modSettings['have_related_topics']) { require_once $sourcedir . '/lib/Subs-Related.php'; relatedUpdateTopics($topicOptions['id']); } // What if we want to export new topics out to a CMS? HookAPI::callHook('create_topic', array(&$msgOptions, &$topicOptions, &$posterOptions)); // record the activity if ($modSettings['astream_active'] && !$context['no_astream']) { require_once $sourcedir . '/lib/Subs-Activities.php'; aStreamAdd($posterOptions['id'], ACT_NEWTOPIC, array('member_name' => $posterOptions['real_name'], 'topic_title' => $msgOptions['subject']), $topicOptions['board'], $topicOptions['id'], $msgOptions['id'], $posterOptions['id']); } } else { if (false === $automerge_posts) { $countChange = $msgOptions['approved'] ? 'num_replies = num_replies + 1' : 'unapproved_posts = unapproved_posts + 1'; } else { // the # of replies and unapproved posts does not increase if we merge $countChange = $msgOptions['approved'] ? 'num_replies = num_replies' : 'unapproved_posts = unapproved_posts'; } // Update the number of replies and the lock/sticky status. smf_db_query(' UPDATE {db_prefix}topics SET ' . ($msgOptions['approved'] ? 'id_member_updated = {int:poster_id}, id_last_msg = {int:id_msg},' : '') . ' ' . $countChange . ($topicOptions['lock_mode'] === null ? '' : ', locked = {int:locked}') . ($topicOptions['sticky_mode'] === null ? '' : ', is_sticky = {int:is_sticky}') . ' WHERE id_topic = {int:id_topic}', array('poster_id' => $posterOptions['id'], 'id_msg' => $msg_to_update, 'locked' => $topicOptions['lock_mode'], 'is_sticky' => $topicOptions['sticky_mode'], 'id_topic' => $topicOptions['id'])); // One new post has been added today. if (false === $automerge_posts) { trackStats(array('posts' => '+')); } if ($modSettings['astream_active'] && !$context['no_astream']) { // add to activity stream, but do not notify when we reply to our own topic require_once $sourcedir . '/lib/Subs-Activities.php'; aStreamAdd($posterOptions['id'], ACT_REPLIED, array('member_name' => $posterOptions['real_name'], 'topic_title' => $msgOptions['subject']), $topicOptions['board'], $topicOptions['id'], $msg_to_update, $topicOptions['id_member_started'], 0, $posterOptions['id'] == $topicOptions['id_member_started'] ? true : false); } HookAPI::callHook('update_topic', array(&$msgOptions, &$topicOptions, &$posterOptions)); } // Creating is modifying...in a way. //!!! Why not set id_msg_modified on the insert? smf_db_query(' UPDATE {db_prefix}messages SET id_msg_modified = {int:id_msg} WHERE id_msg = {int:id_msg}', array('id_msg' => $automerge_posts ? $modSettings['maxMsgID'] : $msg_to_update)); // Increase the number of posts and topics on the board. if ($msgOptions['approved'] && false === $automerge_posts) { smf_db_query(' UPDATE {db_prefix}boards SET num_posts = num_posts + 1' . ($new_topic ? ', num_topics = num_topics + 1' : '') . ' WHERE id_board = {int:id_board}', array('id_board' => $topicOptions['board'])); } else { if (false === $automerge_posts) { smf_db_query(' UPDATE {db_prefix}boards SET unapproved_posts = unapproved_posts + 1' . ($new_topic ? ', unapproved_topics = unapproved_topics + 1' : '') . ' WHERE id_board = {int:id_board}', array('id_board' => $topicOptions['board'])); // Add to the approval queue too. smf_db_insert('', '{db_prefix}approval_queue', array('id_msg' => 'int'), array($msgOptions['id']), array()); } } // Mark inserted topic as read (only for the user calling this function). if (!empty($topicOptions['mark_as_read']) && !$user_info['is_guest']) { // Since it's likely they *read* it before replying, let's try an UPDATE first. if (!$new_topic) { smf_db_query(' UPDATE {db_prefix}log_topics SET id_msg = {int:id_msg} WHERE id_member = {int:current_member} AND id_topic = {int:id_topic}', array('current_member' => $posterOptions['id'], 'id_msg' => $msg_to_update, 'id_topic' => $topicOptions['id'])); $flag = smf_db_affected_rows() != 0; } if (empty($flag)) { smf_db_insert('ignore', '{db_prefix}log_topics', array('id_topic' => 'int', 'id_member' => 'int', 'id_msg' => 'int'), array($topicOptions['id'], $posterOptions['id'], $msg_to_update), array('id_topic', 'id_member')); } } // If there's a custom search index, it needs updating... if (!empty($modSettings['search_custom_index_config'])) { $customIndexSettings = unserialize($modSettings['search_custom_index_config']); if ($automerge_posts) { $text = $newbody; } else { $text = $msgOptions['body']; } $inserts = array(); foreach (text2words($text, $customIndexSettings['bytes_per_word'], true) as $word) { $inserts[] = array($word, $msg_to_update); } if (!empty($inserts)) { smf_db_insert('ignore', '{db_prefix}log_search_words', array('id_word' => 'int', 'id_msg' => 'int'), $inserts, array('id_word', 'id_msg')); } } // Increase the post counter for the user that created the post. if (!empty($posterOptions['update_post_count']) && !empty($posterOptions['id']) && $msgOptions['approved'] && false === $automerge_posts) { // Are you the one that happened to create this post? if ($user_info['id'] == $posterOptions['id']) { $user_info['posts']++; } updateMemberData($posterOptions['id'], array('posts' => '+')); } // They've posted, so they can make the view count go up one if they really want. (this is to keep views >= replies...) $_SESSION['last_read_topic'] = 0; // Better safe than sorry. if (isset($_SESSION['topicseen_cache'][$topicOptions['board']])) { $_SESSION['topicseen_cache'][$topicOptions['board']]--; } // Update all the stats so everyone knows about this new topic and message. if (false === $automerge_posts) { updateStats('message', true, $msg_to_update); } // Update the last message on the board assuming it's approved AND the topic is. if ($msgOptions['approved']) { updateLastMessages($topicOptions['board'], $new_topic || !empty($topicOptions['is_approved']) ? $msg_to_update : 0); } // Clear recent posts cache CacheAPI::clearCacheByPrefix('boardindex-latest_posts'); // Alright, done now... we can abort now, I guess... at least this much is done. ignore_user_abort($previous_ignore_user_abort); // Success. return true; }
/** * Check if the number of users online is a record and store it. * @param int $total_users_online */ function trackStatsUsersOnline($total_users_online) { global $modSettings, $smcFunc; $settingsToUpdate = array(); // More members on now than ever were? Update it! if (!isset($modSettings['mostOnline']) || $total_users_online >= $modSettings['mostOnline']) { $settingsToUpdate = array('mostOnline' => $total_users_online, 'mostDate' => time()); } $date = strftime('%Y-%m-%d', forum_time(false)); // No entry exists for today yet? if (!isset($modSettings['mostOnlineUpdated']) || $modSettings['mostOnlineUpdated'] != $date) { $request = $smcFunc['db_query']('', ' SELECT most_on FROM {db_prefix}log_activity WHERE date = {date:date} LIMIT 1', array('date' => $date)); // The log_activity hasn't got an entry for today? if ($smcFunc['db_num_rows']($request) === 0) { $smcFunc['db_insert']('ignore', '{db_prefix}log_activity', array('date' => 'date', 'most_on' => 'int'), array($date, $total_users_online), array('date')); } else { list($modSettings['mostOnlineToday']) = $smcFunc['db_fetch_row']($request); if ($total_users_online > $modSettings['mostOnlineToday']) { trackStats(array('most_on' => $total_users_online)); } $total_users_online = max($total_users_online, $modSettings['mostOnlineToday']); } $smcFunc['db_free_result']($request); $settingsToUpdate['mostOnlineUpdated'] = $date; $settingsToUpdate['mostOnlineToday'] = $total_users_online; } elseif ($total_users_online > $modSettings['mostOnlineToday']) { trackStats(array('most_on' => $total_users_online)); $settingsToUpdate['mostOnlineToday'] = $total_users_online; } if (!empty($settingsToUpdate)) { updateSettings($settingsToUpdate); } }
function registerMember(&$regOptions, $return_errors = false) { global $scripturl, $txt, $modSettings, $context, $sourcedir; global $user_info, $options, $settings, $smcFunc; loadLanguage('Login'); // We'll need some external functions. require_once $sourcedir . '/lib/Subs-Auth.php'; require_once $sourcedir . '/lib/Subs-Post.php'; // Put any errors in here. $reg_errors = array(); // Registration from the admin center, let them sweat a little more. if ($regOptions['interface'] == 'admin') { is_not_guest(); isAllowedTo('moderate_forum'); } elseif ($regOptions['interface'] == 'guest') { // You cannot register twice... if (empty($user_info['is_guest'])) { redirectexit(); } // Make sure they didn't just register with this session. if (!empty($_SESSION['just_registered']) && empty($modSettings['disableRegisterCheck'])) { fatal_lang_error('register_only_once', false); } } // What method of authorization are we going to use? if (empty($regOptions['auth_method']) || !in_array($regOptions['auth_method'], array('password', 'openid'))) { if (!empty($regOptions['openid'])) { $regOptions['auth_method'] = 'openid'; } else { $regOptions['auth_method'] = 'password'; } } // No name?! How can you register with no name? if (empty($regOptions['username'])) { $reg_errors[] = array('lang', 'need_username'); } // Spaces and other odd characters are evil... $regOptions['username'] = preg_replace('~[\\t\\n\\r\\x0B\\0' . ($context['server']['complex_preg_chars'] ? '\\x{A0}' : " ") . ']+~u', ' ', $regOptions['username']); // Don't use too long a name. if (commonAPI::strlen($regOptions['username']) > 25) { $reg_errors[] = array('lang', 'error_long_name'); } // Only these characters are permitted. if (preg_match('~[<>&"\'=\\\\]~', preg_replace('~&#(?:\\d{1,7}|x[0-9a-fA-F]{1,6});~', '', $regOptions['username'])) != 0 || $regOptions['username'] == '_' || $regOptions['username'] == '|' || strpos($regOptions['username'], '[code') !== false || strpos($regOptions['username'], '[/code') !== false) { $reg_errors[] = array('lang', 'error_invalid_characters_username'); } if (commonAPI::strtolower($regOptions['username']) === commonAPI::strtolower($txt['guest_title'])) { $reg_errors[] = array('lang', 'username_reserved', 'general', array($txt['guest_title'])); } // !!! Separate the sprintf? if (empty($regOptions['email']) || preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', $regOptions['email']) === 0 || strlen($regOptions['email']) > 255) { $reg_errors[] = array('done', sprintf($txt['valid_email_needed'], commonAPI::htmlspecialchars($regOptions['username']))); } if (!empty($regOptions['check_reserved_name']) && isReservedName($regOptions['username'], 0, false)) { if ($regOptions['password'] == 'chocolate cake') { $reg_errors[] = array('done', 'Sorry, I don\'t take bribes... you\'ll need to come up with a different name.'); } $reg_errors[] = array('done', '(' . htmlspecialchars($regOptions['username']) . ') ' . $txt['name_in_use']); } // Generate a validation code if it's supposed to be emailed. $validation_code = ''; if ($regOptions['require'] == 'activation') { $validation_code = generateValidationCode(); } // If you haven't put in a password generate one. if ($regOptions['interface'] == 'admin' && $regOptions['password'] == '' && $regOptions['auth_method'] == 'password') { mt_srand(time() + 1277); $regOptions['password'] = generateValidationCode(); $regOptions['password_check'] = $regOptions['password']; } elseif ($regOptions['password'] != $regOptions['password_check'] && $regOptions['auth_method'] == 'password') { $reg_errors[] = array('lang', 'passwords_dont_match'); } // That's kind of easy to guess... if ($regOptions['password'] == '') { if ($regOptions['auth_method'] == 'password') { $reg_errors[] = array('lang', 'no_password'); } else { $regOptions['password'] = sha1(mt_rand()); } } // Now perform hard password validation as required. if (!empty($regOptions['check_password_strength'])) { $passwordError = validatePassword($regOptions['password'], $regOptions['username'], array($regOptions['email'])); // Password isn't legal? if ($passwordError != null) { $reg_errors[] = array('lang', 'profile_error_password_' . $passwordError); } } // If they are using an OpenID that hasn't been verified yet error out. // !!! Change this so they can register without having to attempt a login first if ($regOptions['auth_method'] == 'openid' && (empty($_SESSION['openid']['verified']) || $_SESSION['openid']['openid_uri'] != $regOptions['openid'])) { $reg_errors[] = array('lang', 'openid_not_verified'); } // You may not be allowed to register this email. if (!empty($regOptions['check_email_ban'])) { isBannedEmail($regOptions['email'], 'cannot_register', $txt['ban_register_prohibited']); } // Check if the email address is in use. $request = smf_db_query(' SELECT id_member FROM {db_prefix}members WHERE email_address = {string:email_address} OR email_address = {string:username} LIMIT 1', array('email_address' => $regOptions['email'], 'username' => $regOptions['username'])); // !!! Separate the sprintf? if (mysql_num_rows($request) != 0) { $reg_errors[] = array('lang', 'email_in_use', false, array(htmlspecialchars($regOptions['email']))); } mysql_free_result($request); // If we found any errors we need to do something about it right away! foreach ($reg_errors as $key => $error) { /* Note for each error: 0 = 'lang' if it's an index, 'done' if it's clear text. 1 = The text/index. 2 = Whether to log. 3 = sprintf data if necessary. */ if ($error[0] == 'lang') { loadLanguage('Errors'); } $message = $error[0] == 'lang' ? empty($error[3]) ? $txt[$error[1]] : vsprintf($txt[$error[1]], $error[3]) : $error[1]; // What to do, what to do, what to do. if ($return_errors) { if (!empty($error[2])) { log_error($message, $error[2]); } $reg_errors[$key] = $message; } else { fatal_error($message, empty($error[2]) ? false : $error[2]); } } // If there's any errors left return them at once! if (!empty($reg_errors)) { return $reg_errors; } $reservedVars = array('actual_theme_url', 'actual_images_url', 'base_theme_dir', 'base_theme_url', 'default_images_url', 'default_theme_dir', 'default_theme_url', 'default_template', 'images_url', 'number_recent_posts', 'smiley_sets_default', 'theme_dir', 'theme_id', 'theme_layers', 'theme_templates', 'theme_url'); // Can't change reserved vars. if (isset($regOptions['theme_vars']) && array_intersect($regOptions['theme_vars'], $reservedVars) != array()) { fatal_lang_error('no_theme'); } // Some of these might be overwritten. (the lower ones that are in the arrays below.) $regOptions['register_vars'] = array('member_name' => $regOptions['username'], 'email_address' => $regOptions['email'], 'passwd' => sha1(strtolower($regOptions['username']) . $regOptions['password']), 'password_salt' => substr(md5(mt_rand()), 0, 4), 'posts' => 0, 'date_registered' => time(), 'member_ip' => $regOptions['interface'] == 'admin' ? '127.0.0.1' : $user_info['ip'], 'member_ip2' => $regOptions['interface'] == 'admin' ? '127.0.0.1' : $_SERVER['BAN_CHECK_IP'], 'validation_code' => $validation_code, 'real_name' => $regOptions['username'], 'personal_text' => $modSettings['default_personal_text'], 'pm_email_notify' => 1, 'id_theme' => 0, 'id_post_group' => 4, 'lngfile' => '', 'buddy_list' => '', 'pm_ignore_list' => '', 'message_labels' => '', 'location' => '', 'time_format' => '', 'signature' => '', 'avatar' => '', 'usertitle' => '', 'secret_question' => '', 'secret_answer' => '', 'additional_groups' => '', 'ignore_boards' => '', 'smiley_set' => '', 'openid_uri' => !empty($regOptions['openid']) ? $regOptions['openid'] : ''); // Setup the activation status on this new account so it is correct - firstly is it an under age account? if ($regOptions['require'] == 'coppa') { $regOptions['register_vars']['is_activated'] = 5; // !!! This should be changed. To what should be it be changed?? $regOptions['register_vars']['validation_code'] = ''; } elseif ($regOptions['require'] == 'nothing') { $regOptions['register_vars']['is_activated'] = 1; } elseif ($regOptions['require'] == 'activation') { $regOptions['register_vars']['is_activated'] = 0; } else { $regOptions['register_vars']['is_activated'] = 3; } if (isset($regOptions['memberGroup'])) { // Make sure the id_group will be valid, if this is an administator. $regOptions['register_vars']['id_group'] = $regOptions['memberGroup'] == 1 && !allowedTo('admin_forum') ? 0 : $regOptions['memberGroup']; // Check if this group is assignable. $unassignableGroups = array(-1, 3); $request = smf_db_query(' SELECT id_group FROM {db_prefix}membergroups WHERE min_posts != {int:min_posts}' . (allowedTo('admin_forum') ? '' : ' OR group_type = {int:is_protected}'), array('min_posts' => -1, 'is_protected' => 1)); while ($row = mysql_fetch_assoc($request)) { $unassignableGroups[] = $row['id_group']; } mysql_free_result($request); if (in_array($regOptions['register_vars']['id_group'], $unassignableGroups)) { $regOptions['register_vars']['id_group'] = 0; } } // Integrate optional member settings to be set. if (!empty($regOptions['extra_register_vars'])) { foreach ($regOptions['extra_register_vars'] as $var => $value) { $regOptions['register_vars'][$var] = $value; } } // Integrate optional user theme options to be set. $theme_vars = array(); if (!empty($regOptions['theme_vars'])) { foreach ($regOptions['theme_vars'] as $var => $value) { $theme_vars[$var] = $value; } } // Call an optional function to validate the users' input. HookAPI::callHook('integrate_register', array(&$regOptions, &$theme_vars)); // Right, now let's prepare for insertion. $knownInts = array('date_registered', 'posts', 'id_group', 'last_login', 'instant_messages', 'unread_messages', 'new_pm', 'pm_prefs', 'gender', 'hide_email', 'show_online', 'pm_email_notify', 'karma_good', 'karma_bad', 'notify_announcements', 'notify_send_body', 'notify_regularity', 'notify_types', 'id_theme', 'is_activated', 'id_msg_last_visit', 'id_post_group', 'total_time_logged_in', 'warning'); $knownFloats = array('time_offset'); $column_names = array(); $values = array(); foreach ($regOptions['register_vars'] as $var => $val) { $type = 'string'; if (in_array($var, $knownInts)) { $type = 'int'; } elseif (in_array($var, $knownFloats)) { $type = 'float'; } elseif ($var == 'birthdate') { $type = 'date'; } $column_names[$var] = $type; $values[$var] = $val; } // Register them into the database. smf_db_insert('', '{db_prefix}members', $column_names, $values, array('id_member')); $memberID = smf_db_insert_id('{db_prefix}members', 'id_member'); // Update the number of members and latest member's info - and pass the name, but remove the 's. if ($regOptions['register_vars']['is_activated'] == 1) { updateStats('member', $memberID, $regOptions['register_vars']['real_name']); } else { updateStats('member'); } // Theme variables too? if (!empty($theme_vars)) { $inserts = array(); foreach ($theme_vars as $var => $val) { $inserts[] = array($memberID, $var, $val); } smf_db_insert('insert', '{db_prefix}themes', array('id_member' => 'int', 'variable' => 'string-255', 'value' => 'string-65534'), $inserts, array('id_member', 'variable')); } // If it's enabled, increase the registrations for today. trackStats(array('registers' => '+')); // Administrative registrations are a bit different... if ($regOptions['interface'] == 'admin') { if ($regOptions['require'] == 'activation') { $email_message = 'admin_register_activate'; } elseif (!empty($regOptions['send_welcome_email'])) { $email_message = 'admin_register_immediate'; } if (isset($email_message)) { $replacements = array('REALNAME' => $regOptions['register_vars']['real_name'], 'USERNAME' => $regOptions['username'], 'PASSWORD' => $regOptions['password'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', 'ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $memberID . ';code=' . $validation_code, 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $memberID, 'ACTIVATIONCODE' => $validation_code); $emaildata = loadEmailTemplate($email_message, $replacements); sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); } // All admins are finished here. return $memberID; } // Can post straight away - welcome them to your fantastic community... if ($regOptions['require'] == 'nothing') { if (!empty($regOptions['send_welcome_email'])) { $replacements = array('REALNAME' => $regOptions['register_vars']['real_name'], 'USERNAME' => $regOptions['username'], 'PASSWORD' => $regOptions['password'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', 'OPENID' => !empty($regOptions['openid']) ? $regOptions['openid'] : ''); $emaildata = loadEmailTemplate('register_' . ($regOptions['auth_method'] == 'openid' ? 'openid_' : '') . 'immediate', $replacements); sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); } // Send admin their notification. adminNotify('standard', $memberID, $regOptions['username']); } elseif ($regOptions['require'] == 'activation' || $regOptions['require'] == 'coppa') { $replacements = array('REALNAME' => $regOptions['register_vars']['real_name'], 'USERNAME' => $regOptions['username'], 'PASSWORD' => $regOptions['password'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', 'OPENID' => !empty($regOptions['openid']) ? $regOptions['openid'] : ''); if ($regOptions['require'] == 'activation') { $replacements += array('ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $memberID . ';code=' . $validation_code, 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $memberID, 'ACTIVATIONCODE' => $validation_code); } else { $replacements += array('COPPALINK' => $scripturl . '?action=coppa;u=' . $memberID); } $emaildata = loadEmailTemplate('register_' . ($regOptions['auth_method'] == 'openid' ? 'openid_' : '') . ($regOptions['require'] == 'activation' ? 'activate' : 'coppa'), $replacements); sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); } else { $replacements = array('REALNAME' => $regOptions['register_vars']['real_name'], 'USERNAME' => $regOptions['username'], 'PASSWORD' => $regOptions['password'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', 'OPENID' => !empty($regOptions['openid']) ? $regOptions['openid'] : ''); $emaildata = loadEmailTemplate('register_' . ($regOptions['auth_method'] == 'openid' ? 'openid_' : '') . 'pending', $replacements); sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0); // Admin gets informed here... adminNotify('approval', $memberID, $regOptions['username']); } // Okay, they're for sure registered... make sure the session is aware of this for security. (Just married :P!) $_SESSION['just_registered'] = 1; return $memberID; }
function smf_main() { global $modSettings, $settings, $user_info, $board, $topic, $maintenance, $sourcedir; // Special case: session keep-alive. if (isset($_GET['action']) && $_GET['action'] == 'keepalive') { die; } // Load the user's cookie (or set as guest) and load their settings. loadUserSettings(); // Load the current board's information. loadBoard(); // Load the current theme. (note that ?theme=1 will also work, may be used for guest theming.) loadTheme(); // Check if the user should be disallowed access. // is_not_banned(); // Load the current user's permissions. loadPermissions(); // Do some logging, unless this is an attachment, avatar, theme option or XML feed. if (empty($_REQUEST['action']) || !in_array($_REQUEST['action'], array('dlattach', 'jsoption', '.xml'))) { // Log this user as online. writeLog(); // Track forum statistics and hits...? if (!empty($modSettings['hitStats'])) { trackStats(array('hits' => '+')); } } // Is the forum in maintenance mode? (doesn't apply to administrators.) if (!empty($maintenance) && !allowedTo('admin_forum')) { // You can only login.... otherwise, you're getting the "maintenance mode" display. if (isset($_REQUEST['action']) && ($_REQUEST['action'] == 'login2' || $_REQUEST['action'] == 'logout')) { require_once $sourcedir . '/LogInOut.php'; return $_REQUEST['action'] == 'login2' ? 'Login2' : 'Logout'; } else { require_once $sourcedir . '/Subs-Auth.php'; return 'InMaintenance'; } } elseif (empty($modSettings['allow_guestAccess']) && $user_info['is_guest'] && (!isset($_REQUEST['action']) || !in_array($_REQUEST['action'], array('coppa', 'login', 'login2', 'register', 'register2', 'reminder', 'activate', 'smstats', 'help', 'verificationcode')))) { require_once $sourcedir . '/Subs-Auth.php'; return 'KickGuest'; } elseif (empty($_REQUEST['action'])) { // Action and board are both empty... BoardIndex! if (empty($board) && empty($topic)) { require_once $sourcedir . '/BoardIndex.php'; return 'BoardIndex'; } elseif (empty($topic)) { require_once $sourcedir . '/MessageIndex.php'; return 'MessageIndex'; } else { require_once $sourcedir . '/Display.php'; return 'Display'; } } // Here's the monstrous $_REQUEST['action'] array - $_REQUEST['action'] => array($file, $function). $actionArray = array('activate' => array('Register.php', 'Activate'), 'admin' => array('Admin.php', 'Admin'), 'announce' => array('Post.php', 'AnnounceTopic'), 'ban' => array('ManageBans.php', 'Ban'), 'boardrecount' => array('Admin.php', 'AdminBoardRecount'), 'buddy' => array('Subs-Members.php', 'BuddyListToggle'), 'calendar' => array('Calendar.php', 'CalendarMain'), 'cleanperms' => array('Admin.php', 'CleanupPermissions'), 'collapse' => array('Subs-Boards.php', 'CollapseCategory'), 'convertentities' => array('Admin.php', 'ConvertEntities'), 'convertutf8' => array('Admin.php', 'ConvertUtf8'), 'coppa' => array('Register.php', 'CoppaForm'), 'deletemsg' => array('RemoveTopic.php', 'DeleteMessage'), 'detailedversion' => array('Admin.php', 'VersionDetail'), 'display' => array('Display.php', 'Display'), 'dlattach' => array('Display.php', 'Download'), 'dumpdb' => array('DumpDatabase.php', 'DumpDatabase2'), 'editpoll' => array('Poll.php', 'EditPoll'), 'editpoll2' => array('Poll.php', 'EditPoll2'), 'featuresettings' => array('ModSettings.php', 'ModifyFeatureSettings'), 'featuresettings2' => array('ModSettings.php', 'ModifyFeatureSettings2'), 'findmember' => array('Subs-Auth.php', 'JSMembers'), 'help' => array('Help.php', 'ShowHelp'), 'helpadmin' => array('Help.php', 'ShowAdminHelp'), 'im' => array('PersonalMessage.php', 'MessageMain'), 'jsoption' => array('Themes.php', 'SetJavaScript'), 'jsmodify' => array('Post.php', 'JavaScriptModify'), 'lock' => array('LockTopic.php', 'LockTopic'), 'lockVoting' => array('Poll.php', 'LockVoting'), 'login' => array('LogInOut.php', 'Login'), 'login2' => array('LogInOut.php', 'Login2'), 'logout' => array('LogInOut.php', 'Logout'), 'maintain' => array('Admin.php', 'Maintenance'), 'manageattachments' => array('ManageAttachments.php', 'ManageAttachments'), 'manageboards' => array('ManageBoards.php', 'ManageBoards'), 'managecalendar' => array('ManageCalendar.php', 'ManageCalendar'), 'managesearch' => array('ManageSearch.php', 'ManageSearch'), 'markasread' => array('Subs-Boards.php', 'MarkRead'), 'membergroups' => array('ManageMembergroups.php', 'ModifyMembergroups'), 'mergetopics' => array('SplitTopics.php', 'MergeTopics'), 'mlist' => array('Memberlist.php', 'Memberlist'), 'modifycat' => array('ManageBoards.php', 'ModifyCat'), 'modifykarma' => array('Karma.php', 'ModifyKarma'), 'modlog' => array('Modlog.php', 'ViewModlog'), 'movetopic' => array('MoveTopic.php', 'MoveTopic'), 'movetopic2' => array('MoveTopic.php', 'MoveTopic2'), 'news' => array('ManageNews.php', 'ManageNews'), 'notify' => array('Notify.php', 'Notify'), 'notifyboard' => array('Notify.php', 'BoardNotify'), 'optimizetables' => array('Admin.php', 'OptimizeTables'), 'packageget' => array('PackageGet.php', 'PackageGet'), 'packages' => array('Packages.php', 'Packages'), 'permissions' => array('ManagePermissions.php', 'ModifyPermissions'), 'pgdownload' => array('PackageGet.php', 'PackageGet'), 'pm' => array('PersonalMessage.php', 'MessageMain'), 'post' => array('Post.php', 'Post'), 'post2' => array('Post.php', 'Post2'), 'postsettings' => array('ManagePosts.php', 'ManagePostSettings'), 'printpage' => array('Printpage.php', 'PrintTopic'), 'profile' => array('Profile.php', 'ModifyProfile'), 'profile2' => array('Profile.php', 'ModifyProfile2'), 'quotefast' => array('Post.php', 'QuoteFast'), 'quickmod' => array('Subs-Boards.php', 'QuickModeration'), 'quickmod2' => array('Subs-Boards.php', 'QuickModeration2'), 'recent' => array('Recent.php', 'RecentPosts'), 'regcenter' => array('ManageRegistration.php', 'RegCenter'), 'register' => array('Register.php', 'Register'), 'register2' => array('Register.php', 'Register2'), 'reminder' => array('Reminder.php', 'RemindMe'), 'removetopic2' => array('RemoveTopic.php', 'RemoveTopic2'), 'removeoldtopics2' => array('RemoveTopic.php', 'RemoveOldTopics2'), 'removepoll' => array('Poll.php', 'RemovePoll'), 'repairboards' => array('RepairBoards.php', 'RepairBoards'), 'reporttm' => array('SendTopic.php', 'ReportToModerator'), 'reports' => array('Reports.php', 'ReportsMain'), 'requestmembers' => array('Subs-Auth.php', 'RequestMembers'), 'search' => array('Search.php', 'PlushSearch1'), 'search2' => array('Search.php', 'PlushSearch2'), 'sendtopic' => array('SendTopic.php', 'SendTopic'), 'serversettings' => array('ManageServer.php', 'ModifySettings'), 'serversettings2' => array('ManageServer.php', 'ModifySettings2'), 'smileys' => array('ManageSmileys.php', 'ManageSmileys'), 'smstats' => array('Stats.php', 'SMStats'), 'spellcheck' => array('Subs-Post.php', 'SpellCheck'), 'splittopics' => array('SplitTopics.php', 'SplitTopics'), 'stats' => array('Stats.php', 'DisplayStats'), 'sticky' => array('LockTopic.php', 'Sticky'), 'theme' => array('Themes.php', 'ThemesMain'), 'trackip' => array('Profile.php', 'trackIP'), 'about:mozilla' => array('Karma.php', 'BookOfUnknown'), 'about:unknown' => array('Karma.php', 'BookOfUnknown'), 'unread' => array('Recent.php', 'UnreadTopics'), 'unreadreplies' => array('Recent.php', 'UnreadTopics'), 'viewErrorLog' => array('ManageErrors.php', 'ViewErrorLog'), 'viewmembers' => array('ManageMembers.php', 'ViewMembers'), 'viewprofile' => array('Profile.php', 'ModifyProfile'), 'verificationcode' => array('Register.php', 'VerificationCode'), 'vote' => array('Poll.php', 'Vote'), 'viewquery' => array('ViewQuery.php', 'ViewQuery'), 'who' => array('Who.php', 'Who'), '.xml' => array('News.php', 'ShowXmlFeed')); // Get the function and file to include - if it's not there, do the board index. if (!isset($_REQUEST['action']) || !isset($actionArray[$_REQUEST['action']])) { // Catch the action with the theme? if (!empty($settings['catch_action'])) { require_once $sourcedir . '/Themes.php'; return 'WrapAction'; } // Fall through to the board index then... require_once $sourcedir . '/BoardIndex.php'; return 'BoardIndex'; } // Otherwise, it was set - so let's go to that action. require_once $sourcedir . '/' . $actionArray[$_REQUEST['action']][0]; return $actionArray[$_REQUEST['action']][1]; }
function smf_main() { global $modSettings, $settings, $user_info, $board, $topic, $board_info, $maintenance, $sourcedir; // Special case: session keep-alive, output a transparent pixel. if (isset($_GET['action']) && $_GET['action'] == 'keepalive') { header('Content-Type: image/gif'); die("GIF89a€!ù,D;"); } // Load the user's cookie (or set as guest) and load their settings. loadUserSettings(); // Load the current board's information. loadBoard(); // Load the current user's permissions. loadPermissions(); // Attachments don't require the entire theme to be loaded. if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'dlattach' && (!empty($modSettings['allow_guestAccess']) && $user_info['is_guest'])) { detectBrowser(); } else { loadTheme(); } // Check if the user should be disallowed access. is_not_banned(); // If we are in a topic and don't have permission to approve it then duck out now. if (!empty($topic) && empty($board_info['cur_topic_approved']) && !allowedTo('approve_posts') && ($user_info['id'] != $board_info['cur_topic_starter'] || $user_info['is_guest'])) { fatal_lang_error('not_a_topic', false); } // Do some logging, unless this is an attachment, avatar, toggle of editor buttons, theme option, XML feed etc. if (empty($_REQUEST['action']) || !in_array($_REQUEST['action'], array('dlattach', 'findmember', 'jseditor', 'jsoption', 'requestmembers', 'smstats', '.xml', 'xmlhttp', 'verificationcode', 'viewquery', 'viewsmfile'))) { // Log this user as online. writeLog(); // Don't track stats of portal xml actions. if (empty($_REQUEST['action']) || $_REQUEST['action'] != 'portal' || !isset($_GET['xml'])) { // Track forum statistics and hits...? if (!empty($modSettings['hitStats'])) { trackStats(array('hits' => '+')); } } } // Load SimplePortal. sportal_init(); // Is the forum in maintenance mode? (doesn't apply to administrators.) if (!empty($maintenance) && !allowedTo('admin_forum')) { // You can only login.... otherwise, you're getting the "maintenance mode" display. if (isset($_REQUEST['action']) && ($_REQUEST['action'] == 'login2' || $_REQUEST['action'] == 'logout')) { require_once $sourcedir . '/LogInOut.php'; return $_REQUEST['action'] == 'login2' ? 'Login2' : 'Logout'; } else { require_once $sourcedir . '/Subs-Auth.php'; return 'InMaintenance'; } } elseif (empty($modSettings['allow_guestAccess']) && $user_info['is_guest'] && (!isset($_REQUEST['action']) || !in_array($_REQUEST['action'], array('coppa', 'login', 'login2', 'register', 'register2', 'reminder', 'activate', 'help', 'smstats', 'mailq', 'verificationcode', 'openidreturn')))) { require_once $sourcedir . '/Subs-Auth.php'; return 'KickGuest'; } elseif (empty($_REQUEST['action'])) { // Go catch it boy! Catch it! $sp_action = sportal_catch_action(); if ($sp_action) { return $sp_action; } // Action and board are both empty... BoardIndex! if (empty($board) && empty($topic)) { require_once $sourcedir . '/BoardIndex.php'; return 'BoardIndex'; } elseif (empty($topic)) { require_once $sourcedir . '/MessageIndex.php'; return 'MessageIndex'; } else { require_once $sourcedir . '/Display.php'; return 'Display'; } } // Here's the monstrous $_REQUEST['action'] array - $_REQUEST['action'] => array($file, $function). $actionArray = array('activate' => array('Register.php', 'Activate'), 'admin' => array('Admin.php', 'AdminMain'), 'announce' => array('Post.php', 'AnnounceTopic'), 'attachapprove' => array('ManageAttachments.php', 'ApproveAttach'), 'buddy' => array('Subs-Members.php', 'BuddyListToggle'), 'calendar' => array('Calendar.php', 'CalendarMain'), 'clock' => array('Calendar.php', 'clock'), 'collapse' => array('BoardIndex.php', 'CollapseCategory'), 'coppa' => array('Register.php', 'CoppaForm'), 'credits' => array('Who.php', 'Credits'), 'deletemsg' => array('RemoveTopic.php', 'DeleteMessage'), 'display' => array('Display.php', 'Display'), 'dlattach' => array('Display.php', 'Download'), 'editpoll' => array('Poll.php', 'EditPoll'), 'editpoll2' => array('Poll.php', 'EditPoll2'), 'emailuser' => array('SendTopic.php', 'EmailUser'), 'findmember' => array('Subs-Auth.php', 'JSMembers'), 'forum' => array('BoardIndex.php', 'BoardIndex'), 'portal' => array('PortalMain.php', 'sportal_main'), 'groups' => array('Groups.php', 'Groups'), 'help' => array('Help.php', 'ShowHelp'), 'helpadmin' => array('Help.php', 'ShowAdminHelp'), 'im' => array('PersonalMessage.php', 'MessageMain'), 'jseditor' => array('Subs-Editor.php', 'EditorMain'), 'jsmodify' => array('Post.php', 'JavaScriptModify'), 'jsoption' => array('Themes.php', 'SetJavaScript'), 'lock' => array('LockTopic.php', 'LockTopic'), 'lockvoting' => array('Poll.php', 'LockVoting'), 'login' => array('LogInOut.php', 'Login'), 'login2' => array('LogInOut.php', 'Login2'), 'logout' => array('LogInOut.php', 'Logout'), 'markasread' => array('Subs-Boards.php', 'MarkRead'), 'mergetopics' => array('SplitTopics.php', 'MergeTopics'), 'mlist' => array('Memberlist.php', 'Memberlist'), 'moderate' => array('ModerationCenter.php', 'ModerationMain'), 'modifycat' => array('ManageBoards.php', 'ModifyCat'), 'modifykarma' => array('Karma.php', 'ModifyKarma'), 'movetopic' => array('MoveTopic.php', 'MoveTopic'), 'movetopic2' => array('MoveTopic.php', 'MoveTopic2'), 'notify' => array('Notify.php', 'Notify'), 'notifyboard' => array('Notify.php', 'BoardNotify'), 'openidreturn' => array('Subs-OpenID.php', 'smf_openID_return'), 'pm' => array('PersonalMessage.php', 'MessageMain'), 'post' => array('Post.php', 'Post'), 'post2' => array('Post.php', 'Post2'), 'printpage' => array('Printpage.php', 'PrintTopic'), 'profile' => array('Profile.php', 'ModifyProfile'), 'quotefast' => array('Post.php', 'QuoteFast'), 'quickmod' => array('MessageIndex.php', 'QuickModeration'), 'quickmod2' => array('Display.php', 'QuickInTopicModeration'), 'recent' => array('Recent.php', 'RecentPosts'), 'register' => array('Register.php', 'Register'), 'register2' => array('Register.php', 'Register2'), 'reminder' => array('Reminder.php', 'RemindMe'), 'removepoll' => array('Poll.php', 'RemovePoll'), 'removetopic2' => array('RemoveTopic.php', 'RemoveTopic2'), 'reporttm' => array('SendTopic.php', 'ReportToModerator'), 'requestmembers' => array('Subs-Auth.php', 'RequestMembers'), 'restoretopic' => array('RemoveTopic.php', 'RestoreTopic'), 'search' => array('Search.php', 'PlushSearch1'), 'search2' => array('Search.php', 'PlushSearch2'), 'sendtopic' => array('SendTopic.php', 'EmailUser'), 'smstats' => array('Stats.php', 'SMStats'), 'suggest' => array('Subs-Editor.php', 'AutoSuggestHandler'), 'spellcheck' => array('Subs-Post.php', 'SpellCheck'), 'splittopics' => array('SplitTopics.php', 'SplitTopics'), 'stats' => array('Stats.php', 'DisplayStats'), 'sticky' => array('LockTopic.php', 'Sticky'), 'theme' => array('Themes.php', 'ThemesMain'), 'trackip' => array('Profile-View.php', 'trackIP'), 'about:mozilla' => array('Karma.php', 'BookOfUnknown'), 'about:unknown' => array('Karma.php', 'BookOfUnknown'), 'unread' => array('Recent.php', 'UnreadTopics'), 'unreadreplies' => array('Recent.php', 'UnreadTopics'), 'verificationcode' => array('Register.php', 'VerificationCode'), 'viewprofile' => array('Profile.php', 'ModifyProfile'), 'vote' => array('Poll.php', 'Vote'), 'viewquery' => array('ViewQuery.php', 'ViewQuery'), 'viewsmfile' => array('Admin.php', 'DisplayAdminFile'), 'who' => array('Who.php', 'Who'), '.xml' => array('News.php', 'ShowXmlFeed'), 'xmlhttp' => array('Xml.php', 'XMLhttpMain')); // Allow modifying $actionArray easily. call_integration_hook('integrate_actions', array(&$actionArray)); if (!empty($context['disable_sp'])) { unset($actionArray['portal'], $actionArray['forum']); } // Get the function and file to include - if it's not there, do the board index. if (!isset($_REQUEST['action']) || !isset($actionArray[$_REQUEST['action']])) { // Catch the action with the theme? if (!empty($settings['catch_action'])) { require_once $sourcedir . '/Themes.php'; return 'WrapAction'; } // Fall through to the board index then... require_once $sourcedir . '/BoardIndex.php'; return 'BoardIndex'; } // Otherwise, it was set - so let's go to that action. require_once $sourcedir . '/' . $actionArray[$_REQUEST['action']][0]; return $actionArray[$_REQUEST['action']][1]; }
<?php require_once "../forum/SSI.php"; $_SESSION['login_url'] = 'http://www.simplywastingtime.com'; $_SESSION['logout_url'] = 'http://www.simplywastingtime.com'; trackStats(array('hits' => '+')); trackStats(); include_once '../includes/member_database.php';
function createPost(&$msgOptions, &$topicOptions, &$posterOptions) { global $db_prefix, $user_info, $ID_MEMBER, $txt, $modSettings; // Set optional parameters to the default value. $msgOptions['icon'] = empty($msgOptions['icon']) ? 'xx' : $msgOptions['icon']; $msgOptions['smileys_enabled'] = !empty($msgOptions['smileys_enabled']); $msgOptions['attachments'] = empty($msgOptions['attachments']) ? array() : $msgOptions['attachments']; $topicOptions['id'] = empty($topicOptions['id']) ? 0 : (int) $topicOptions['id']; $topicOptions['poll'] = isset($topicOptions['poll']) ? (int) $topicOptions['poll'] : null; $topicOptions['lock_mode'] = isset($topicOptions['lock_mode']) ? $topicOptions['lock_mode'] : null; $topicOptions['sticky_mode'] = isset($topicOptions['sticky_mode']) ? $topicOptions['sticky_mode'] : null; $posterOptions['id'] = empty($posterOptions['id']) ? 0 : (int) $posterOptions['id']; $posterOptions['ip'] = empty($posterOptions['ip']) ? $user_info['ip2'] : $posterOptions['ip']; // If nothing was filled in as name/e-mail address, try the member table. if (!isset($posterOptions['name']) || $posterOptions['name'] == '' || empty($posterOptions['email']) && !empty($posterOptions['id'])) { if (empty($posterOptions['id'])) { $posterOptions['id'] = 0; $posterOptions['name'] = $txt[28]; $posterOptions['email'] = ''; } elseif ($posterOptions['id'] != $ID_MEMBER) { $request = db_query("\n\t\t\t\tSELECT memberName, emailAddress\n\t\t\t\tFROM {$db_prefix}members\n\t\t\t\tWHERE ID_MEMBER = {$posterOptions['id']}\n\t\t\t\tLIMIT 1", __FILE__, __LINE__); // Couldn't find the current poster? if (mysql_num_rows($request) == 0) { trigger_error('createPost(): Invalid member id ' . $posterOptions['id'], E_USER_NOTICE); $posterOptions['id'] = 0; $posterOptions['name'] = $txt[28]; $posterOptions['email'] = ''; } else { list($posterOptions['name'], $posterOptions['email']) = mysql_fetch_row($request); } mysql_free_result($request); } else { $posterOptions['name'] = $user_info['name']; $posterOptions['email'] = $user_info['email']; } $posterOptions['email'] = addslashes($posterOptions['email']); } // It's do or die time: forget any user aborts! $previous_ignore_user_abort = ignore_user_abort(true); $new_topic = empty($topicOptions['id']); // Insert the post. db_query("\n\t\tINSERT INTO {$db_prefix}messages\n\t\t\t(ID_BOARD, ID_TOPIC, ID_MEMBER, subject, body, posterName, posterEmail, posterTime,\n\t\t\tposterIP, smileysEnabled, modifiedName, icon)\n\t\tVALUES ({$topicOptions['board']}, {$topicOptions['id']}, {$posterOptions['id']}, SUBSTRING('{$msgOptions['subject']}', 1, 255), SUBSTRING('{$msgOptions['body']}', 1, 65534), SUBSTRING('{$posterOptions['name']}', 1, 255), SUBSTRING('{$posterOptions['email']}', 1, 255), " . time() . ",\n\t\t\tSUBSTRING('{$posterOptions['ip']}', 1, 255), " . ($msgOptions['smileys_enabled'] ? '1' : '0') . ", '', SUBSTRING('{$msgOptions['icon']}', 1, 16))", __FILE__, __LINE__); $msgOptions['id'] = db_insert_id(); // Something went wrong creating the message... if (empty($msgOptions['id'])) { return false; } // Fix the attachments. if (!empty($msgOptions['attachments'])) { db_query("\n\t\t\tUPDATE {$db_prefix}attachments\n\t\t\tSET ID_MSG = {$msgOptions['id']}\n\t\t\tWHERE ID_ATTACH IN (" . implode(', ', $msgOptions['attachments']) . ')', __FILE__, __LINE__); } // Insert a new topic (if the topicID was left empty. if ($new_topic) { db_query("\n\t\t\tINSERT INTO {$db_prefix}topics\n\t\t\t\t(ID_BOARD, ID_MEMBER_STARTED, ID_MEMBER_UPDATED, ID_FIRST_MSG, ID_LAST_MSG, locked, isSticky, numViews, ID_POLL)\n\t\t\tVALUES ({$topicOptions['board']}, {$posterOptions['id']}, {$posterOptions['id']}, {$msgOptions['id']}, {$msgOptions['id']},\n\t\t\t\t" . ($topicOptions['lock_mode'] === null ? '0' : $topicOptions['lock_mode']) . ', ' . ($topicOptions['sticky_mode'] === null ? '0' : $topicOptions['sticky_mode']) . ", 0, " . ($topicOptions['poll'] === null ? '0' : $topicOptions['poll']) . ')', __FILE__, __LINE__); $topicOptions['id'] = db_insert_id(); // The topic couldn't be created for some reason. if (empty($topicOptions['id'])) { // We should delete the post that did work, though... db_query("\n\t\t\t\tDELETE FROM {$db_prefix}messages\n\t\t\t\tWHERE ID_MSG = {$msgOptions['id']}\n\t\t\t\tLIMIT 1", __FILE__, __LINE__); return false; } // Fix the message with the topic. db_query("\n\t\t\tUPDATE {$db_prefix}messages\n\t\t\tSET ID_TOPIC = {$topicOptions['id']}\n\t\t\tWHERE ID_MSG = {$msgOptions['id']}\n\t\t\tLIMIT 1", __FILE__, __LINE__); // There's been a new topic AND a new post today. trackStats(array('topics' => '+', 'posts' => '+')); updateStats('topic', true); updateStats('subject', $topicOptions['id'], $msgOptions['subject']); } else { // Update the number of replies and the lock/sticky status. db_query("\n\t\t\tUPDATE {$db_prefix}topics\n\t\t\tSET\n\t\t\t\tID_MEMBER_UPDATED = {$posterOptions['id']}, ID_LAST_MSG = {$msgOptions['id']},\n\t\t\t\tnumReplies = numReplies + 1" . ($topicOptions['lock_mode'] === null ? '' : ",\n\t\t\t\tlocked = {$topicOptions['lock_mode']}") . ($topicOptions['sticky_mode'] === null ? '' : ",\n\t\t\t\tisSticky = {$topicOptions['sticky_mode']}") . "\n\t\t\tWHERE ID_TOPIC = {$topicOptions['id']}\n\t\t\tLIMIT 1", __FILE__, __LINE__); // One new post has been added today. trackStats(array('posts' => '+')); } // Creating is modifying...in a way. db_query("\n\t\tUPDATE {$db_prefix}messages\n\t\tSET ID_MSG_MODIFIED = {$msgOptions['id']}\n\t\tWHERE ID_MSG = {$msgOptions['id']}", __FILE__, __LINE__); // Increase the number of posts and topics on the board. db_query("\n\t\tUPDATE {$db_prefix}boards\n\t\tSET numPosts = numPosts + 1" . ($new_topic ? ', numTopics = numTopics + 1' : '') . "\n\t\tWHERE ID_BOARD = {$topicOptions['board']}\n\t\tLIMIT 1", __FILE__, __LINE__); // Mark inserted topic as read (only for the user calling this function). if (!empty($topicOptions['mark_as_read']) && !$user_info['is_guest']) { // Since it's likely they *read* it before replying, let's try an UPDATE first. if (!$new_topic) { db_query("\n\t\t\t\tUPDATE {$db_prefix}log_topics\n\t\t\t\tSET ID_MSG = {$msgOptions['id']} + 1\n\t\t\t\tWHERE ID_MEMBER = {$ID_MEMBER}\n\t\t\t\t\tAND ID_TOPIC = {$topicOptions['id']}\n\t\t\t\tLIMIT 1", __FILE__, __LINE__); $flag = db_affected_rows() != 0; } if (empty($flag)) { db_query("\n\t\t\t\tREPLACE INTO {$db_prefix}log_topics\n\t\t\t\t\t(ID_TOPIC, ID_MEMBER, ID_MSG)\n\t\t\t\tVALUES ({$topicOptions['id']}, {$ID_MEMBER}, {$msgOptions['id']} + 1)", __FILE__, __LINE__); } } // If there's a custom search index, it needs updating... if (!empty($modSettings['search_custom_index_config'])) { //$index_settings = unserialize($modSettings['search_custom_index_config']); $inserts = ''; foreach (text2words(stripslashes($msgOptions['body']), 4, true) as $word) { $inserts .= "({$word}, {$msgOptions['id']}),\n"; } if (!empty($inserts)) { db_query("\n\t\t\t\tINSERT IGNORE INTO {$db_prefix}log_search_words\n\t\t\t\t\t(ID_WORD, ID_MSG)\n\t\t\t\tVALUES\n\t\t\t\t\t" . substr($inserts, 0, -2), __FILE__, __LINE__); } } // Increase the post counter for the user that created the post. if (!empty($posterOptions['update_post_count']) && !empty($posterOptions['id'])) { // Are you the one that happened to create this post? if ($ID_MEMBER == $posterOptions['id']) { $user_info['posts']++; } updateMemberData($posterOptions['id'], array('posts' => '+')); } // They've posted, so they can make the view count go up one if they really want. (this is to keep views >= replies...) $_SESSION['last_read_topic'] = 0; // Better safe than sorry. if (isset($_SESSION['topicseen_cache'][$topicOptions['board']])) { $_SESSION['topicseen_cache'][$topicOptions['board']]--; } // Update all the stats so everyone knows about this new topic and message. updateStats('message', true, $msgOptions['id']); updateLastMessages($topicOptions['board'], $msgOptions['id']); // Alright, done now... we can abort now, I guess... at least this much is done. ignore_user_abort($previous_ignore_user_abort); // Success. return true; }
/** * Ends execution. * * What it does: * - Takes care of template loading and remembering the previous URL. * - Calls ob_start() with ob_sessrewrite to fix URLs if necessary. * * @param bool|null $header = null * @param bool|null $do_footer = null * @param bool $from_index = false * @param bool $from_fatal_error = false */ function obExit($header = null, $do_footer = null, $from_index = false, $from_fatal_error = false) { global $context, $txt; static $header_done = false, $footer_done = false, $level = 0, $has_fatal_error = false; // Attempt to prevent a recursive loop. ++$level; if ($level > 1 && !$from_fatal_error && !$has_fatal_error) { exit; } if ($from_fatal_error) { $has_fatal_error = true; } // Clear out the stat cache. trackStats(); // If we have mail to send, send it. if (!empty($context['flush_mail'])) { // @todo this relies on 'flush_mail' being only set in AddMailQueue itself... :\ AddMailQueue(true); } $do_header = $header === null ? !$header_done : $header; if ($do_footer === null) { $do_footer = $do_header; } // Has the template/header been done yet? if ($do_header) { // Was the page title set last minute? Also update the HTML safe one. if (!empty($context['page_title']) && empty($context['page_title_html_safe'])) { $context['page_title_html_safe'] = Util::htmlspecialchars(un_htmlspecialchars($context['page_title'])) . (!empty($context['current_page']) ? ' - ' . $txt['page'] . ' ' . ($context['current_page'] + 1) : ''); } // Start up the session URL fixer. ob_start('ob_sessrewrite'); call_integration_buffer(); // Display the screen in the logical order. template_header(); $header_done = true; } if ($do_footer) { // Show the footer. loadSubTemplate(isset($context['sub_template']) ? $context['sub_template'] : 'main'); // Just so we don't get caught in an endless loop of errors from the footer... if (!$footer_done) { $footer_done = true; template_footer(); // (since this is just debugging... it's okay that it's after </html>.) if (!isset($_REQUEST['xml'])) { displayDebug(); } } } // Need user agent $req = request(); // Remember this URL in case someone doesn't like sending HTTP_REFERER. $invalid_old_url = array('action=dlattach', 'action=jsoption', 'action=viewadminfile', ';xml', ';api'); $make_old = true; foreach ($invalid_old_url as $url) { if (strpos($_SERVER['REQUEST_URL'], $url) !== false) { $make_old = false; break; } } if ($make_old === true) { $_SESSION['old_url'] = $_SERVER['REQUEST_URL']; } // For session check verification.... don't switch browsers... $_SESSION['USER_AGENT'] = $req->user_agent(); // Hand off the output to the portal, etc. we're integrated with. call_integration_hook('integrate_exit', array($do_footer)); // Don't exit if we're coming from index.php; that will pass through normally. if (!$from_index) { exit; } }