Exemplo n.º 1
0
function EditHoliday()
{
    global $txt, $context, $scripturl, $smcFunc;
    loadAdminTemplate('ManageCalendar');
    $context['is_new'] = !isset($_REQUEST['holiday']);
    $context['page_title'] = $context['is_new'] ? $txt['holidays_add'] : $txt['holidays_edit'];
    $context['sub_template'] = 'edit_holiday';
    // Cast this for safety...
    if (isset($_REQUEST['holiday'])) {
        $_REQUEST['holiday'] = (int) $_REQUEST['holiday'];
    }
    // Submitting?
    if (isset($_POST[$context['session_var']]) && (isset($_REQUEST['delete']) || $_REQUEST['title'] != '')) {
        checkSession();
        // Not too long good sir?
        $_REQUEST['title'] = commonAPI::substr($_REQUEST['title'], 0, 60);
        $_REQUEST['holiday'] = isset($_REQUEST['holiday']) ? (int) $_REQUEST['holiday'] : 0;
        if (isset($_REQUEST['delete'])) {
            smf_db_query('
				DELETE FROM {db_prefix}calendar_holidays
				WHERE id_holiday = {int:selected_holiday}', array('selected_holiday' => $_REQUEST['holiday']));
        } else {
            $date = strftime($_REQUEST['year'] <= 4 ? '0004-%m-%d' : '%Y-%m-%d', mktime(0, 0, 0, $_REQUEST['month'], $_REQUEST['day'], $_REQUEST['year']));
            if (isset($_REQUEST['edit'])) {
                smf_db_query('
					UPDATE {db_prefix}calendar_holidays
					SET event_date = {date:holiday_date}, title = {string:holiday_title}
					WHERE id_holiday = {int:selected_holiday}', array('holiday_date' => $date, 'selected_holiday' => $_REQUEST['holiday'], 'holiday_title' => $_REQUEST['title']));
            } else {
                smf_db_insert('', '{db_prefix}calendar_holidays', array('event_date' => 'date', 'title' => 'string-60'), array($date, $_REQUEST['title']), array('id_holiday'));
            }
        }
        updateSettings(array('calendar_updated' => time()));
        redirectexit('action=admin;area=managecalendar;sa=holidays');
    }
    // Default states...
    if ($context['is_new']) {
        $context['holiday'] = array('id' => 0, 'day' => date('d'), 'month' => date('m'), 'year' => '0000', 'title' => '');
    } else {
        $request = smf_db_query('
			SELECT id_holiday, YEAR(event_date) AS year, MONTH(event_date) AS month, DAYOFMONTH(event_date) AS day, title
			FROM {db_prefix}calendar_holidays
			WHERE id_holiday = {int:selected_holiday}
			LIMIT 1', array('selected_holiday' => $_REQUEST['holiday']));
        while ($row = mysql_fetch_assoc($request)) {
            $context['holiday'] = array('id' => $row['id_holiday'], 'day' => $row['day'], 'month' => $row['month'], 'year' => $row['year'] <= 4 ? 0 : $row['year'], 'title' => $row['title']);
        }
        mysql_free_result($request);
    }
    // Last day for the drop down?
    $context['holiday']['last_day'] = (int) strftime('%d', mktime(0, 0, 0, $context['holiday']['month'] == 12 ? 1 : $context['holiday']['month'] + 1, 0, $context['holiday']['month'] == 12 ? $context['holiday']['year'] + 1 : $context['holiday']['year']));
}
Exemplo n.º 2
0
/**
 * Save a new draft, or update an existing draft.
 */
function saveDraft()
{
    global $smcFunc, $topic, $board, $user_info, $options;
    if (!isset($_REQUEST['draft']) || $user_info['is_guest'] || empty($options['use_drafts'])) {
        return false;
    }
    $msgid = isset($_REQUEST['msg']) ? $_REQUEST['msg'] : 0;
    // Clean up what we may or may not have
    $subject = isset($_POST['subject']) ? $_POST['subject'] : '';
    $message = isset($_POST['message']) ? $_POST['message'] : '';
    $icon = isset($_POST['icon']) ? preg_replace('~[\\./\\\\*:"\'<>]~', '', $_POST['icon']) : 'xx';
    // Sanitise what we do have
    $subject = commonAPI::htmltrim(commonAPI::htmlspecialchars($subject));
    $message = commonAPI::htmlspecialchars($message, ENT_QUOTES);
    preparsecode($message);
    if (commonAPI::htmltrim(commonAPI::htmlspecialchars($subject)) === '' && commonAPI::htmltrim(commonAPI::htmlspecialchars($_POST['message']), ENT_QUOTES) === '') {
        fatal_lang_error('empty_draft', false);
    }
    // Hrm, so is this a new draft or not?
    if (isset($_REQUEST['draft_id']) && (int) $_REQUEST['draft_id'] > 0 || $msgid) {
        $_REQUEST['draft_id'] = (int) $_REQUEST['draft_id'];
        $id_cond = $msgid ? ' 1=1 ' : ' id_draft = {int:draft} ';
        $id_sel = $msgid ? ' AND id_msg = {int:message} ' : ' AND id_board = {int:board} AND id_topic = {int:topic} ';
        // Does this draft exist?
        smf_db_query('
			UPDATE {db_prefix}drafts
			SET subject = {string:subject},
				body = {string:body},
				updated = {int:post_time},
				icon = {string:post_icon},
				smileys = {int:smileys_enabled},
				is_locked = {int:locked},
				is_sticky = {int:sticky}
			WHERE ' . $id_cond . '
				AND id_member = {int:member}
				' . $id_sel . '
			LIMIT 1', array('draft' => $_REQUEST['draft_id'], 'board' => $board, 'topic' => $topic, 'message' => $msgid, 'member' => $user_info['id'], 'subject' => $subject, 'body' => $message, 'post_time' => time(), 'post_icon' => $icon, 'smileys_enabled' => !isset($_POST['ns']) ? 1 : 0, 'locked' => !empty($_POST['lock_draft']) ? 1 : 0, 'sticky' => isset($_POST['sticky']) ? 1 : 0));
        if (smf_db_affected_rows() != 0) {
            return $_REQUEST['draft_id'];
        }
    }
    smf_db_insert('insert', '{db_prefix}drafts', array('id_board' => 'int', 'id_topic' => 'int', 'id_msg' => 'int', 'id_member' => 'int', 'subject' => 'string', 'body' => 'string', 'updated' => 'int', 'icon' => 'string', 'smileys' => 'int', 'is_locked' => 'int', 'is_sticky' => 'int'), array($board, $topic, $msgid, $user_info['id'], $subject, $message, time(), $icon, !isset($_POST['ns']) ? 1 : 0, !empty($_POST['lock_draft']) ? 1 : 0, isset($_POST['sticky']) ? 1 : 0), array('id_draft'));
    return smf_db_insert_id('{db_prefix}drafts');
}
Exemplo n.º 3
0
function getLastPosts($latestPostOptions)
{
    global $scripturl, $txt, $user_info, $modSettings, $smcFunc, $context;
    // Find all the posts.  Newer ones will have higher IDs.  (assuming the last 20 * number are accessable...)
    // !!!SLOW This query is now slow, NEEDS to be fixed.  Maybe break into two?
    $request = smf_db_query('
		SELECT
			m.poster_time, m.subject, m.id_topic, m.id_member, m.id_msg, b.name, m1.subject AS first_subject,
			IFNULL(mem.real_name, m.poster_name) AS poster_name, t.id_board, b.name AS board_name,
			SUBSTRING(m.body, 1, 385) AS body, m.smileys_enabled
		FROM {db_prefix}messages AS m
			INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic)
			INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board)
			INNER JOIN {db_prefix}messages AS m1 ON (m1.id_msg = t.id_first_msg)
			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)
		WHERE m.id_msg >= {int:likely_max_msg}' . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? '
			AND b.id_board != {int:recycle_board}' : '') . '
			AND {query_wanna_see_board}' . ($modSettings['postmod_active'] ? '
			AND t.approved = {int:is_approved}
			AND m.approved = {int:is_approved}' : '') . '
		ORDER BY m.id_msg DESC
		LIMIT ' . $latestPostOptions['number_posts'], array('likely_max_msg' => max(0, $modSettings['maxMsgID'] - 50 * $latestPostOptions['number_posts']), 'recycle_board' => $modSettings['recycle_board'], 'is_approved' => 1));
    $posts = array();
    while ($row = mysql_fetch_assoc($request)) {
        // Censor the subject and post for the preview ;).
        censorText($row['subject']);
        censorText($row['body']);
        $row['body'] = strip_tags(strtr(parse_bbc($row['body'], $row['smileys_enabled'], $row['id_msg']), array('<br />' => '&#10;')));
        if (commonAPI::strlen($row['body']) > 128) {
            $row['body'] = commonAPI::substr($row['body'], 0, 128) . '...';
        }
        $bhref = URL::board($row['id_board'], $row['board_name'], 0, true);
        $mhref = URL::user($row['id_member'], $row['poster_name']);
        $thref = URL::topic($row['id_topic'], $row['first_subject'], 0, false, '.msg' . $row['id_msg'], ';topicseen#msg' . $row['id_msg']);
        // Build the array.
        $posts[] = array('board' => array('id' => $row['id_board'], 'name' => $row['board_name'], 'href' => $bhref, 'link' => '<a href="' . $bhref . '">' . $row['board_name'] . '</a>'), 'topic' => $row['id_topic'], 'poster' => array('id' => $row['id_member'], 'name' => $row['poster_name'], 'href' => empty($row['id_member']) ? '' : $mhref, 'link' => empty($row['id_member']) ? $row['poster_name'] : '<a href="' . $mhref . '">' . $row['poster_name'] . '</a>'), 'subject' => $row['subject'], 'short_subject' => shorten_subject($row['subject'], 35), 'preview' => $row['body'], 'time' => timeformat($row['poster_time']), 'timestamp' => forum_time(true, $row['poster_time']), 'raw_timestamp' => $row['poster_time'], 'href' => $thref, 'link' => '<a href="' . $thref . '" rel="nofollow">' . $row['first_subject'] . '</a>');
    }
    mysql_free_result($request);
    return $posts;
}
Exemplo n.º 4
0
function getLanguages($use_cache = true, $favor_utf8 = true)
{
    global $context, $settings, $modSettings;
    // Either we don't use the cache, or its expired.
    if (!$use_cache || ($context['languages'] = CacheAPI::getCache('known_languages' . ($favor_utf8 ? '' : '_all'), !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600)) == null) {
        // If we don't have our theme information yet, lets get it.
        if (empty($settings['default_theme_dir'])) {
            loadTheme(0, false);
        } else {
            $settings['actual_theme_url'] = $settings['theme_url'];
            $settings['actual_images_url'] = $settings['images_url'];
            $settings['actual_theme_dir'] = $settings['theme_dir'];
        }
        // Default language directories to try.
        $language_directories = array($settings['default_theme_dir'] . '/languages', $settings['actual_theme_dir'] . '/languages');
        // We possibly have a base theme directory.
        if (!empty($settings['base_theme_dir'])) {
            $language_directories[] = $settings['base_theme_dir'] . '/languages';
        }
        // Remove any duplicates.
        $language_directories = array_unique($language_directories);
        foreach ($language_directories as $language_dir) {
            // Can't look in here... doesn't exist!
            if (!file_exists($language_dir)) {
                continue;
            }
            $dir = dir($language_dir);
            while ($entry = $dir->read()) {
                // Look for the index language file....
                if (!preg_match('~^index\\.(.+)\\.php$~', $entry, $matches)) {
                    continue;
                }
                $context['languages'][$matches[1]] = array('name' => commonAPI::ucwords(strtr($matches[1], array('_' => ' '))), 'selected' => false, 'filename' => $matches[1], 'location' => $language_dir . '/index.' . $matches[1] . '.php');
            }
            $dir->close();
        }
        // Favoring UTF8? Then prevent us from selecting non-UTF8 versions.
        if ($favor_utf8) {
            foreach ($context['languages'] as $lang) {
                if (substr($lang['filename'], strlen($lang['filename']) - 5, 5) != '-utf8' && isset($context['languages'][$lang['filename'] . '-utf8'])) {
                    unset($context['languages'][$lang['filename']]);
                }
            }
        }
        // Lets cash in on this deal.
        if (!empty($modSettings['cache_enable'])) {
            CacheAPI::putCache('known_languages' . ($favor_utf8 ? '' : '_all'), $context['languages'], !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600);
        }
    }
    return $context['languages'];
}
Exemplo n.º 5
0
function PackageServerAdd()
{
    global $smcFunc;
    // Validate the user.
    checkSession();
    // If they put a slash on the end, get rid of it.
    if (substr($_POST['serverurl'], -1) == '/') {
        $_POST['serverurl'] = substr($_POST['serverurl'], 0, -1);
    }
    // Are they both nice and clean?
    $servername = trim(commonAPI::htmlspecialchars($_POST['servername']));
    $serverurl = trim(commonAPI::htmlspecialchars($_POST['serverurl']));
    // Make sure the URL has the correct prefix.
    if (strpos($serverurl, 'http://') !== 0 && strpos($serverurl, 'https://') !== 0) {
        $serverurl = 'http://' . $serverurl;
    }
    smf_db_insert('', '{db_prefix}package_servers', array('name' => 'string-255', 'url' => 'string-255'), array($servername, $serverurl), array('id_server'));
    redirectexit('action=admin;area=packages;get');
}
Exemplo n.º 6
0
    function __construct($request, $total_items, $not_profile = false)
    {
        global $context, $txt, $user_info, $scripturl, $options, $memberContext, $modSettings;
        if (!isset($context['pageindex_multiplier'])) {
            $context['pageindex_multiplier'] = commonAPI::getMessagesPerPage();
        }
        $cb_name = isset($context['cb_name']) ? $context['cb_name'] : 'topics[]';
        while ($row = mysql_fetch_assoc($request)) {
            censorText($row['subject']);
            $this->topic_ids[] = $row['id_topic'];
            $f_post_mem_href = !empty($row['id_member']) ? URL::user($row['id_member'], $row['first_member_name']) : '';
            $t_href = URL::topic($row['id_topic'], $row['subject'], 0);
            $l_post_mem_href = !empty($row['id_member_updated']) ? URL::user($row['id_member_updated'], $row['last_real_name']) : '';
            $l_post_msg_href = URL::topic($row['id_topic'], $row['last_subject'], $user_info['is_guest'] ? !empty($options['view_newest_first']) ? 0 : (int) ($row['num_replies'] / $context['pageindex_multiplier']) * $context['pageindex_multiplier'] : 0, $user_info['is_guest'] ? true : false, $user_info['is_guest'] ? '' : '.msg' . $row['id_last_msg'], $user_info['is_guest'] ? '#msg' . $row['id_last_msg'] : '#new');
            $this->topiclist[$row['id_topic']] = array('id' => $row['id_topic'], 'id_member_started' => empty($row['id_member']) ? 0 : $row['id_member'], 'first_post' => array('id' => $row['id_first_msg'], 'member' => array('username' => $row['first_member_name'], 'name' => $row['first_member_name'], 'id' => empty($row['id_member']) ? 0 : $row['id_member'], 'href' => $f_post_mem_href, 'link' => !empty($row['id_member']) ? '<a onclick="getMcard(' . $row['id_member'] . ', $(this));return(false);" href="' . $f_post_mem_href . '" title="' . $txt['profile_of'] . ' ' . $row['first_member_name'] . '">' . $row['first_member_name'] . '</a>' : $row['first_member_name']), 'time' => timeformat($row['first_poster_time']), 'timestamp' => forum_time(true, $row['first_poster_time']), 'subject' => $row['subject'], 'icon' => $row['first_icon'], 'icon_url' => getPostIcon($row['first_icon']), 'href' => $t_href, 'link' => '<a href="' . $t_href . '">' . $row['subject'] . '</a>'), 'last_post' => array('id' => $row['id_last_msg'], 'member' => array('username' => $row['last_real_name'], 'name' => $row['last_real_name'], 'id' => $row['id_member_updated'], 'href' => $l_post_mem_href, 'link' => !empty($row['id_member_updated']) ? '<a onclick="getMcard(' . $row['id_member_updated'] . ', $(this));return(false);" href="' . $l_post_mem_href . '">' . $row['last_real_name'] . '</a>' : $row['last_real_name']), 'time' => timeformat($row['last_post_time']), 'timestamp' => forum_time(true, $row['last_post_time']), 'subject' => $row['last_subject'], 'href' => $l_post_msg_href, 'link' => '<a href="' . $l_post_msg_href . ($row['num_replies'] == 0 ? '' : ' rel="nofollow"') . '>' . $row['last_subject'] . '</a>'), 'checkbox_name' => $cb_name, 'subject' => $row['subject'], 'new' => $row['new_from'] <= $row['id_msg_modified'], 'new_from' => $row['new_from'], 'newtime' => $row['new_from'], 'updated' => timeformat($row['poster_time']), 'new_href' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['new_from'] . '#new', 'new_link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['new_from'] . '#new">' . $row['subject'] . '</a>', 'replies' => comma_format($row['num_replies']), 'views' => comma_format($row['num_views']), 'approved' => $row['approved'], 'unapproved_posts' => $row['unapproved_posts'], 'is_old' => !empty($modSettings['oldTopicDays']) ? $context['time_now'] - $row['last_post_time'] > $modSettings['oldTopicDays'] * 86400 : false, 'is_posted_in' => false, 'prefix' => '', 'pages' => '', 'is_sticky' => !empty($modSettings['enableStickyTopics']) && !empty($row['is_sticky']), 'is_locked' => !empty($row['locked']), 'is_poll' => false, 'is_hot' => $row['num_replies'] >= $modSettings['hotTopicPosts'], 'is_very_hot' => $row['num_replies'] >= $modSettings['hotTopicVeryPosts'], 'board' => isset($row['id_board']) && !empty($row['id_board']) ? array('name' => $row['board_name'], 'id' => $row['id_board'], 'href' => URL::board($row['id_board'], $row['board_name'])) : array('name' => '', 'id' => 0, 'href' => ''));
            determineTopicClass($this->topiclist[$row['id_topic']]);
            if (!empty($row['id_member']) && ($row['id_member'] != $user_info['id'] || $not_profile)) {
                $this->users_to_load[$row['id_member']] = $row['id_member'];
            }
        }
        loadMemberData($this->users_to_load);
        foreach ($this->topiclist as &$topic) {
            if (!isset($memberContext[$topic['id_member_started']])) {
                loadMemberContext($topic['id_member_started']);
            }
            $topic['first_post']['member']['avatar'] =& $memberContext[$topic['id_member_started']]['avatar']['image'];
        }
        // figure out whether we have posted in a topic (but only if we are not the topic starter)
        if (!empty($modSettings['enableParticipation']) && !$user_info['is_guest'] && !empty($this->topic_ids)) {
            $result = smf_db_query('
				SELECT id_topic
				FROM {db_prefix}messages
				WHERE id_topic IN ({array_int:topic_list})
					AND id_member = {int:current_member}
				GROUP BY id_topic
				LIMIT ' . count($this->topic_ids), array('current_member' => $user_info['id'], 'topic_list' => $this->topic_ids));
            while ($row = mysql_fetch_assoc($result)) {
                if ($this->topiclist[$row['id_topic']]['first_post']['member']['id'] != $user_info['id']) {
                    $this->topiclist[$row['id_topic']]['is_posted_in'] = true;
                }
            }
            mysql_free_result($result);
        }
    }
Exemplo n.º 7
0
function isReservedName($name, $current_ID_MEMBER = 0, $is_name = true, $fatal = true)
{
    global $modSettings, $context;
    // No cheating with entities please.
    $replaceEntities = create_function('$string', '
		$num = substr($string, 0, 1) === \'x\' ? hexdec(substr($string, 1)) : (int) $string;
		if ($num === 0x202E || $num === 0x202D) return \'\'; if (in_array($num, array(0x22, 0x26, 0x27, 0x3C, 0x3E))) return \'&#\' . $num . \';\';' . 'return $num < 0x20 || $num > 0x10FFFF || ($num >= 0xD800 && $num <= 0xDFFF) ? \'\' : ($num < 0x80 ? chr($num) : ($num < 0x800 ? chr(192 | $num >> 6) . chr(128 | $num & 63) : ($num < 0x10000 ? chr(224 | $num >> 12) . chr(128 | $num >> 6 & 63) . chr(128 | $num & 63) : chr(240 | $num >> 18) . chr(128 | $num >> 12 & 63) . chr(128 | $num >> 6 & 63) . chr(128 | $num & 63))));');
    $name = preg_replace('~(&#(\\d{1,7}|x[0-9a-fA-F]{1,6});)~e', '$replaceEntities(\'\\2\')', $name);
    $checkName = commonAPI::strtolower($name);
    // Administrators are never restricted ;).
    if (!allowedTo('moderate_forum') && (!empty($modSettings['reserveName']) && $is_name || !empty($modSettings['reserveUser']) && !$is_name)) {
        $reservedNames = explode("\n", $modSettings['reserveNames']);
        // Case sensitive check?
        $checkMe = empty($modSettings['reserveCase']) ? $checkName : $name;
        // Check each name in the list...
        foreach ($reservedNames as $reserved) {
            if ($reserved == '') {
                continue;
            }
            // The admin might've used entities too, level the playing field.
            $reservedCheck = preg_replace('~(&#(\\d{1,7}|x[0-9a-fA-F]{1,6});)~e', '$replaceEntities(\'\\2\')', $reserved);
            // Case sensitive name?
            if (empty($modSettings['reserveCase'])) {
                $reservedCheck = commonAPI::strtolower($reservedCheck);
            }
            // If it's not just entire word, check for it in there somewhere...
            if ($checkMe == $reservedCheck || commonAPI::strpos($checkMe, $reservedCheck) !== false && empty($modSettings['reserveWord'])) {
                if ($fatal) {
                    fatal_lang_error('username_reserved', 'password', array($reserved));
                } else {
                    return true;
                }
            }
        }
        $censor_name = $name;
        if (censorText($censor_name) != $name) {
            if ($fatal) {
                fatal_lang_error('name_censored', 'password', array($name));
            } else {
                return true;
            }
        }
    }
    // Characters we just shouldn't allow, regardless.
    foreach (array('*') as $char) {
        if (strpos($checkName, $char) !== false) {
            if ($fatal) {
                fatal_lang_error('username_reserved', 'password', array($char));
            } else {
                return true;
            }
        }
    }
    // Get rid of any SQL parts of the reserved name...
    $checkName = strtr($name, array('_' => '\\_', '%' => '\\%'));
    // Make sure they don't want someone else's name.
    $request = smf_db_query('
		SELECT id_member
		FROM {db_prefix}members
		WHERE ' . (empty($current_ID_MEMBER) ? '' : 'id_member != {int:current_member}
			AND ') . '(real_name LIKE {string:check_name} OR member_name LIKE {string:check_name})
		LIMIT 1', array('current_member' => $current_ID_MEMBER, 'check_name' => $checkName));
    if (mysql_num_rows($request) > 0) {
        mysql_free_result($request);
        return true;
    }
    // Does name case insensitive match a member group name?
    $request = smf_db_query('
		SELECT id_group
		FROM {db_prefix}membergroups
		WHERE group_name LIKE {string:check_name}
		LIMIT 1', array('check_name' => $checkName));
    if (mysql_num_rows($request) > 0) {
        mysql_free_result($request);
        return true;
    }
    // Okay, they passed.
    return false;
}
Exemplo n.º 8
0
function sendpm($recipients, $subject, $message, $store_outbox = false, $from = null, $pm_head = 0)
{
    global $scripturl, $txt, $user_info, $language;
    global $modSettings, $sourcedir;
    // Make sure the PM language file is loaded, we might need something out of it.
    loadLanguage('PersonalMessage');
    $onBehalf = $from !== null;
    // 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 = commonAPI::htmlspecialchars($message, ENT_QUOTES);
    $htmlsubject = commonAPI::htmlspecialchars($subject);
    preparsecode($htmlmessage);
    // Integrated PMs
    HookAPI::callHook('integrate_personal_message', array($recipients, $from['username'], $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] = commonAPI::strtolower(trim(preg_replace('/[<>&"\'=\\\]/', '', $recipients[$rec_type][$id])));
                $recipients[$rec_type][$id] = commonAPI::strtolower(trim(preg_replace('/[<>&"\'=\\]/', '', $recipients[$rec_type][$id])));
                $usernames[$recipients[$rec_type][$id]] = 0;
            }
        }
    }
    if (!empty($usernames)) {
        $request = smf_db_query('
			SELECT id_member, member_name
			FROM {db_prefix}members
			WHERE ' . 'member_name' . ' IN ({array_string:usernames})', array('usernames' => array_keys($usernames)));
        while ($row = mysql_fetch_assoc($request)) {
            if (isset($usernames[commonAPI::strtolower($row['member_name'])])) {
                $usernames[commonAPI::strtolower($row['member_name'])] = $row['id_member'];
            }
        }
        mysql_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 = smf_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 = mysql_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) {
            $match = false;
            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;
        }
    }
    mysql_free_result($request);
    // Load the membergrounp message limits.
    //!!! Consider caching this?
    static $message_limit_cache = array();
    if (!allowedTo('moderate_forum') && empty($message_limit_cache)) {
        $request = smf_db_query('
			SELECT id_group, max_messages
			FROM {db_prefix}membergroups', array());
        while ($row = mysql_fetch_assoc($request)) {
            $message_limit_cache[$row['id_group']] = $row['max_messages'];
        }
        mysql_free_result($request);
    }
    // Load the groups that are allowed to read PMs.
    $allowed_groups = array();
    $disallowed_groups = array();
    $request = smf_db_query('
		SELECT id_group, add_deny
		FROM {db_prefix}permissions
		WHERE permission = {string:read_permission}', array('read_permission' => 'pm_read'));
    while ($row = mysql_fetch_assoc($request)) {
        if (empty($row['add_deny'])) {
            $disallowed_groups[] = $row['id_group'];
        } else {
            $allowed_groups[] = $row['id_group'];
        }
    }
    mysql_free_result($request);
    if (empty($modSettings['permission_enable_deny'])) {
        $disallowed_groups = array();
    }
    $request = smf_db_query('
		SELECT
			member_name, real_name, id_member, email_address, lngfile,
			pm_email_notify, instant_messages,' . (allowedTo('moderate_forum') ? ' 0' : '
			(pm_receive_from = {int:admins_only}' . (empty($modSettings['enable_buddylist']) ? '' : ' OR
			(pm_receive_from = {int:buddies_only} AND FIND_IN_SET({string:from_id}, buddy_list) = 0) OR
			(pm_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();
    $as_notifications = array();
    while ($row = mysql_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['instant_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'];
        }
        $as_notifications[] = $row['id_member'];
        $log['sent'][$row['id_member']] = sprintf(isset($txt['pm_successfully_sent']) ? $txt['pm_successfully_sent'] : '', $row['real_name']);
    }
    mysql_free_result($request);
    // Only 'send' the message if there are any recipients left.
    if (empty($all_to)) {
        return $log;
    }
    // Insert the message itself and then grab the last insert id.
    smf_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 = smf_db_insert_id('{db_prefix}personal_messages', 'id_pm');
    if ($modSettings['astream_active']) {
        require_once $sourcedir . '/lib/Subs-Activities.php';
        $id_act = aStreamAdd($from['id'], ACT_PM, array('member_name' => $from['username']), 0, 0, $id_pm, $from['id'], ACT_PLEVEL_PRIVATE);
        if ((int) $id_act > 0) {
            aStreamAddNotification($as_notifications, $id_act, ACT_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)) {
            smf_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 :)
        smf_db_query('
			DELETE FROM {db_prefix}pm_recipients
			WHERE id_pm = {int:id_pm}', array('id_pm' => $id_pm));
        $insertRows = array();
        foreach ($all_to as $to) {
            $insertRows[] = array($id_pm, $to, in_array($to, $recipients['bcc']) ? 1 : 0, isset($deletes[$to]) ? 1 : 0, 1);
        }
        smf_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'));
    }
    censorText($message);
    censorText($subject);
    $message = trim(un_htmlspecialchars(strip_tags(strtr(parse_bbc(htmlspecialchars($message), false), array('<br />' => "\n", '</div>' => "\n", '</li>' => "\n", '&#91;' => '[', '&#93;' => ']')))));
    foreach ($notifications as $lang => $notification_list) {
        // Make sure to use the right language.
        loadLanguage('index+PersonalMessage', $lang, false);
        // Replace the right things in the message strings.
        $mailsubject = str_replace(array('SUBJECT', 'SENDER'), array($subject, un_htmlspecialchars($from['name'])), $txt['new_pm_subject']);
        $mailmessage = str_replace(array('SUBJECT', 'MESSAGE', 'SENDER'), array($subject, $message, un_htmlspecialchars($from['name'])), $txt['pm_email']);
        $mailmessage .= "\n\n" . $txt['instant_reply'] . ' ' . $scripturl . '?action=pm;sa=send;f=inbox;pmsg=' . $id_pm . ';quote;u=' . $from['id'];
        // Off the notification email goes!
        sendmail($notification_list, $mailsubject, $mailmessage, null, 'p' . $id_pm, false, 2, null, true);
    }
    // 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('instant_messages' => '+', 'unread_messages' => '+', 'new_pm' => 1));
    }
    return $log;
}
Exemplo n.º 9
0
function ModifyLanguage()
{
    global $settings, $context, $txt, $modSettings, $boarddir, $sourcedir, $language;
    loadLanguage('ManageSettings');
    // Select the languages tab.
    $context['menu_data_' . $context['admin_menu_id']]['current_subsection'] = 'edit';
    $context['page_title'] = $txt['edit_languages'];
    $context['sub_template'] = 'modify_language_entries';
    $context['lang_id'] = $_GET['lid'];
    list($theme_id, $file_id) = empty($_REQUEST['tfid']) || strpos($_REQUEST['tfid'], '+') === false ? array(1, '') : explode('+', $_REQUEST['tfid']);
    // Clean the ID - just in case.
    preg_match('~([A-Za-z0-9_-]+)~', $context['lang_id'], $matches);
    $context['lang_id'] = $matches[1];
    // Get all the theme data.
    $request = smf_db_query('
		SELECT id_theme, variable, value
		FROM {db_prefix}themes
		WHERE id_theme != {int:default_theme}
			AND id_member = {int:no_member}
			AND variable IN ({string:name}, {string:theme_dir})', array('default_theme' => 1, 'no_member' => 0, 'name' => 'name', 'theme_dir' => 'theme_dir'));
    $themes = array(1 => array('name' => $txt['dvc_default'], 'theme_dir' => $settings['default_theme_dir']));
    while ($row = mysql_fetch_assoc($request)) {
        $themes[$row['id_theme']][$row['variable']] = $row['value'];
    }
    mysql_free_result($request);
    // This will be where we look
    $lang_dirs = array();
    // Check we have themes with a path and a name - just in case - and add the path.
    foreach ($themes as $id => $data) {
        if (count($data) != 2) {
            unset($themes[$id]);
        } elseif (is_dir($data['theme_dir'] . '/languages')) {
            $lang_dirs[$id] = $data['theme_dir'] . '/languages';
        }
        // How about image directories?
        if (is_dir($data['theme_dir'] . '/images/' . $context['lang_id'])) {
            $images_dirs[$id] = $data['theme_dir'] . '/images/' . $context['lang_id'];
        }
    }
    $current_file = $file_id ? $lang_dirs[$theme_id] . '/' . $file_id . '.' . $context['lang_id'] . '.php' : '';
    // Now for every theme get all the files and stick them in context!
    $context['possible_files'] = array();
    foreach ($lang_dirs as $theme => $theme_dir) {
        // Open it up.
        $dir = dir($theme_dir);
        while ($entry = $dir->read()) {
            // We're only after the files for this language.
            if (preg_match('~^([A-Za-z]+)\\.' . $context['lang_id'] . '\\.php$~', $entry, $matches) == 0) {
                continue;
            }
            //!!! Temp!
            if ($matches[1] == 'EmailTemplates') {
                continue;
            }
            if (!isset($context['possible_files'][$theme])) {
                $context['possible_files'][$theme] = array('id' => $theme, 'name' => $themes[$theme]['name'], 'files' => array());
            }
            $context['possible_files'][$theme]['files'][] = array('id' => $matches[1], 'name' => isset($txt['lang_file_desc_' . $matches[1]]) ? $txt['lang_file_desc_' . $matches[1]] : $matches[1], 'selected' => $theme_id == $theme && $file_id == $matches[1]);
        }
        $dir->close();
    }
    // We no longer wish to speak this language.
    if (!empty($_POST['delete_main']) && $context['lang_id'] != 'english') {
        checkSession();
        // !!! Todo: FTP Controls?
        require_once $sourcedir . '/lib/Subs-Package.php';
        // First, Make a backup?
        if (!empty($modSettings['package_make_backups']) && (!isset($_SESSION['last_backup_for']) || $_SESSION['last_backup_for'] != $context['lang_id'] . '$$$')) {
            $_SESSION['last_backup_for'] = $context['lang_id'] . '$$$';
            package_create_backup('backup_lang_' . $context['lang_id']);
        }
        // Second, loop through the array to remove the files.
        foreach ($lang_dirs as $curPath) {
            foreach ($context['possible_files'][1]['files'] as $lang) {
                if (file_exists($curPath . '/' . $lang['id'] . '.' . $context['lang_id'] . '.php')) {
                    unlink($curPath . '/' . $lang['id'] . '.' . $context['lang_id'] . '.php');
                }
            }
            // Check for the email template.
            if (file_exists($curPath . '/EmailTemplates.' . $context['lang_id'] . '.php')) {
                unlink($curPath . '/EmailTemplates.' . $context['lang_id'] . '.php');
            }
        }
        // Third, the agreement file.
        if (file_exists($boarddir . '/agreement.' . $context['lang_id'] . '.txt')) {
            unlink($boarddir . '/agreement.' . $context['lang_id'] . '.txt');
        }
        // Fourth, a related images folder?
        foreach ($images_dirs as $curPath) {
            if (is_dir($curPath)) {
                deltree($curPath);
            }
        }
        // Members can no longer use this language.
        smf_db_query('
			UPDATE {db_prefix}members
			SET lngfile = {string:empty_string}
			WHERE lngfile = {string:current_language}', array('empty_string' => '', 'current_language' => $context['lang_id']));
        // Fifth, update getLanguages() cache.
        if (!empty($modSettings['cache_enable'])) {
            CacheAPI::putCache('known_languages', null, !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600);
            CacheAPI::putCache('known_languages_all', null, !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600);
        }
        // Sixth, if we deleted the default language, set us back to english?
        if ($context['lang_id'] == $language) {
            require_once $sourcedir . '/lib/Subs-Admin.php';
            $language = 'english';
            updateSettingsFile(array('language' => '\'' . $language . '\''));
        }
        // Seventh, get out of here.
        redirectexit('action=admin;area=languages;sa=edit;' . $context['session_var'] . '=' . $context['session_id']);
    }
    // Saving primary settings?
    $madeSave = false;
    if (!empty($_POST['save_main']) && !$current_file) {
        checkSession();
        // Read in the current file.
        $current_data = implode('', file($settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php'));
        // These are the replacements. old => new
        $replace_array = array('~\\$txt\\[\'lang_character_set\'\\]\\s=\\s(\'|")[^\\r\\n]+~' => '$txt[\'lang_character_set\'] = \'' . addslashes($_POST['character_set']) . '\';', '~\\$txt\\[\'lang_locale\'\\]\\s=\\s(\'|")[^\\r\\n]+~' => '$txt[\'lang_locale\'] = \'' . addslashes($_POST['locale']) . '\';', '~\\$txt\\[\'lang_dictionary\'\\]\\s=\\s(\'|")[^\\r\\n]+~' => '$txt[\'lang_dictionary\'] = \'' . addslashes($_POST['dictionary']) . '\';', '~\\$txt\\[\'lang_spelling\'\\]\\s=\\s(\'|")[^\\r\\n]+~' => '$txt[\'lang_spelling\'] = \'' . addslashes($_POST['spelling']) . '\';', '~\\$txt\\[\'lang_rtl\'\\]\\s=\\s[A-Za-z0-9]+;~' => '$txt[\'lang_rtl\'] = ' . (!empty($_POST['rtl']) ? 'true' : 'false') . ';');
        $current_data = preg_replace(array_keys($replace_array), array_values($replace_array), $current_data);
        $fp = fopen($settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php', 'w+');
        fwrite($fp, $current_data);
        fclose($fp);
        $madeSave = true;
    }
    // Quickly load index language entries.
    $old_txt = $txt;
    require $settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php';
    $context['lang_file_not_writable_message'] = is_writable($settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php') ? '' : sprintf($txt['lang_file_not_writable'], $settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php');
    // Setup the primary settings context.
    $context['primary_settings'] = array('name' => commonAPI::ucwords(strtr($context['lang_id'], array('_' => ' ', '-utf8' => ''))), 'character_set' => $txt['lang_character_set'], 'locale' => $txt['lang_locale'], 'dictionary' => $txt['lang_dictionary'], 'spelling' => $txt['lang_spelling'], 'rtl' => $txt['lang_rtl']);
    // Restore normal service.
    $txt = $old_txt;
    // Are we saving?
    $save_strings = array();
    if (isset($_POST['save_entries']) && !empty($_POST['entry'])) {
        checkSession();
        // Clean each entry!
        foreach ($_POST['entry'] as $k => $v) {
            // Only try to save if it's changed!
            if ($_POST['entry'][$k] != $_POST['comp'][$k]) {
                $save_strings[$k] = cleanLangString($v, false);
            }
        }
    }
    // If we are editing a file work away at that.
    if ($current_file) {
        $context['entries_not_writable_message'] = is_writable($current_file) ? '' : sprintf($txt['lang_entries_not_writable'], $current_file);
        $entries = array();
        // We can't just require it I'm afraid - otherwise we pass in all kinds of variables!
        $multiline_cache = '';
        foreach (file($current_file) as $line) {
            // Got a new entry?
            if ($line[0] == '$' && !empty($multiline_cache)) {
                preg_match('~\\$(helptxt|txt)\\[\'(.+)\'\\]\\s=\\s(.+);~', strtr($multiline_cache, array("\n" => '', "\t" => '')), $matches);
                if (!empty($matches[3])) {
                    $entries[$matches[2]] = array('type' => $matches[1], 'full' => $matches[0], 'entry' => $matches[3]);
                    $multiline_cache = '';
                }
            }
            $multiline_cache .= $line . "\n";
        }
        // Last entry to add?
        if ($multiline_cache) {
            preg_match('~\\$(helptxt|txt)\\[\'(.+)\'\\]\\s=\\s(.+);~', strtr($multiline_cache, array("\n" => '', "\t" => '')), $matches);
            if (!empty($matches[3])) {
                $entries[$matches[2]] = array('type' => $matches[1], 'full' => $matches[0], 'entry' => $matches[3]);
            }
        }
        // These are the entries we can definitely save.
        $final_saves = array();
        $context['file_entries'] = array();
        foreach ($entries as $entryKey => $entryValue) {
            // Ignore some things we set separately.
            $ignore_files = array('lang_character_set', 'lang_locale', 'lang_dictionary', 'lang_spelling', 'lang_rtl');
            if (in_array($entryKey, $ignore_files)) {
                continue;
            }
            // These are arrays that need breaking out.
            $arrays = array('days', 'days_short', 'months', 'months_titles', 'months_short');
            if (in_array($entryKey, $arrays)) {
                // Get off the first bits.
                $entryValue['entry'] = substr($entryValue['entry'], strpos($entryValue['entry'], '(') + 1, strrpos($entryValue['entry'], ')') - strpos($entryValue['entry'], '('));
                $entryValue['entry'] = explode(',', strtr($entryValue['entry'], array(' ' => '')));
                // Now create an entry for each item.
                $cur_index = 0;
                $save_cache = array('enabled' => false, 'entries' => array());
                foreach ($entryValue['entry'] as $id => $subValue) {
                    // Is this a new index?
                    if (preg_match('~^(\\d+)~', $subValue, $matches)) {
                        $cur_index = $matches[1];
                        $subValue = substr($subValue, strpos($subValue, '\''));
                    }
                    // Clean up some bits.
                    $subValue = strtr($subValue, array('"' => '', '\'' => '', ')' => ''));
                    // Can we save?
                    if (isset($save_strings[$entryKey . '-+- ' . $cur_index])) {
                        $save_cache['entries'][$cur_index] = strtr($save_strings[$entryKey . '-+- ' . $cur_index], array('\'' => ''));
                        $save_cache['enabled'] = true;
                    } else {
                        $save_cache['entries'][$cur_index] = $subValue;
                    }
                    $context['file_entries'][] = array('key' => $entryKey . '-+- ' . $cur_index, 'value' => $subValue, 'rows' => 1);
                    $cur_index++;
                }
                // Do we need to save?
                if ($save_cache['enabled']) {
                    // Format the string, checking the indexes first.
                    $items = array();
                    $cur_index = 0;
                    foreach ($save_cache['entries'] as $k2 => $v2) {
                        // Manually show the custom index.
                        if ($k2 != $cur_index) {
                            $items[] = $k2 . ' => \'' . $v2 . '\'';
                            $cur_index = $k2;
                        } else {
                            $items[] = '\'' . $v2 . '\'';
                        }
                        $cur_index++;
                    }
                    // Now create the string!
                    $final_saves[$entryKey] = array('find' => $entryValue['full'], 'replace' => '$' . $entryValue['type'] . '[\'' . $entryKey . '\'] = array(' . implode(', ', $items) . ');');
                }
            } else {
                // Saving?
                if (isset($save_strings[$entryKey]) && $save_strings[$entryKey] != $entryValue['entry']) {
                    // !!! Fix this properly.
                    if ($save_strings[$entryKey] == '') {
                        $save_strings[$entryKey] = '\'\'';
                    }
                    // Set the new value.
                    $entryValue['entry'] = $save_strings[$entryKey];
                    // And we know what to save now!
                    $final_saves[$entryKey] = array('find' => $entryValue['full'], 'replace' => '$' . $entryValue['type'] . '[\'' . $entryKey . '\'] = ' . $save_strings[$entryKey] . ';');
                }
                $editing_string = cleanLangString($entryValue['entry'], true);
                $context['file_entries'][] = array('key' => $entryKey, 'value' => $editing_string, 'rows' => (int) (strlen($editing_string) / 38) + substr_count($editing_string, "\n") + 1);
            }
        }
        // Any saves to make?
        if (!empty($final_saves)) {
            checkSession();
            $file_contents = implode('', file($current_file));
            foreach ($final_saves as $save) {
                $file_contents = strtr($file_contents, array($save['find'] => $save['replace']));
            }
            // Save the actual changes.
            $fp = fopen($current_file, 'w+');
            fwrite($fp, $file_contents);
            fclose($fp);
            $madeSave = true;
        }
        // Another restore.
        $txt = $old_txt;
    }
    // If we saved, redirect.
    if ($madeSave) {
        redirectexit('action=admin;area=languages;sa=editlang;lid=' . $context['lang_id']);
    }
}
Exemplo n.º 10
0
function modifyBoard($board_id, &$boardOptions)
{
    global $sourcedir, $cat_tree, $boards, $boardList, $modSettings, $smcFunc;
    // Get some basic information about all boards and categories.
    getBoardTree();
    // Make sure given boards and categories exist.
    if (!isset($boards[$board_id]) || isset($boardOptions['target_board']) && !isset($boards[$boardOptions['target_board']]) || isset($boardOptions['target_category']) && !isset($cat_tree[$boardOptions['target_category']])) {
        fatal_lang_error('no_board');
    }
    // All things that will be updated in the database will be in $boardUpdates.
    $boardUpdates = array();
    $boardUpdateParameters = array();
    // In case the board has to be moved
    if (isset($boardOptions['move_to'])) {
        // Move the board to the top of a given category.
        if ($boardOptions['move_to'] == 'top') {
            $id_cat = $boardOptions['target_category'];
            $child_level = 0;
            $id_parent = 0;
            $after = $cat_tree[$id_cat]['last_board_order'];
        } elseif ($boardOptions['move_to'] == 'bottom') {
            $id_cat = $boardOptions['target_category'];
            $child_level = 0;
            $id_parent = 0;
            $after = 0;
            foreach ($cat_tree[$id_cat]['children'] as $id_board => $dummy) {
                $after = max($after, $boards[$id_board]['order']);
            }
        } elseif ($boardOptions['move_to'] == 'child') {
            $id_cat = $boards[$boardOptions['target_board']]['category'];
            $child_level = $boards[$boardOptions['target_board']]['level'] + 1;
            $id_parent = $boardOptions['target_board'];
            // People can be creative, in many ways...
            if (isChildOf($id_parent, $board_id)) {
                fatal_lang_error('mboards_parent_own_child_error', false);
            } elseif ($id_parent == $board_id) {
                fatal_lang_error('mboards_board_own_child_error', false);
            }
            $after = $boards[$boardOptions['target_board']]['order'];
            // Check if there are already children and (if so) get the max board order.
            if (!empty($boards[$id_parent]['tree']['children']) && empty($boardOptions['move_first_child'])) {
                foreach ($boards[$id_parent]['tree']['children'] as $childBoard_id => $dummy) {
                    $after = max($after, $boards[$childBoard_id]['order']);
                }
            }
        } elseif (in_array($boardOptions['move_to'], array('before', 'after'))) {
            $id_cat = $boards[$boardOptions['target_board']]['category'];
            $child_level = $boards[$boardOptions['target_board']]['level'];
            $id_parent = $boards[$boardOptions['target_board']]['parent'];
            $after = $boards[$boardOptions['target_board']]['order'] - ($boardOptions['move_to'] == 'before' ? 1 : 0);
        } else {
            trigger_error('modifyBoard(): The move_to value \'' . $boardOptions['move_to'] . '\' is incorrect', E_USER_ERROR);
        }
        // Get a list of children of this board.
        $childList = array();
        recursiveBoards($childList, $boards[$board_id]['tree']);
        // See if there are changes that affect children.
        $childUpdates = array();
        $levelDiff = $child_level - $boards[$board_id]['level'];
        if ($levelDiff != 0) {
            $childUpdates[] = 'child_level = child_level ' . ($levelDiff > 0 ? '+ ' : '') . '{int:level_diff}';
        }
        if ($id_cat != $boards[$board_id]['category']) {
            $childUpdates[] = 'id_cat = {int:category}';
        }
        // Fix the children of this board.
        if (!empty($childList) && !empty($childUpdates)) {
            smf_db_query('
				UPDATE {db_prefix}boards
				SET ' . implode(',
					', $childUpdates) . '
				WHERE id_board IN ({array_int:board_list})', array('board_list' => $childList, 'category' => $id_cat, 'level_diff' => $levelDiff));
        }
        // Make some room for this spot.
        smf_db_query('
			UPDATE {db_prefix}boards
			SET board_order = board_order + {int:new_order}
			WHERE board_order > {int:insert_after}
				AND id_board != {int:selected_board}', array('insert_after' => $after, 'selected_board' => $board_id, 'new_order' => 1 + count($childList)));
        $boardUpdates[] = 'id_cat = {int:id_cat}';
        $boardUpdates[] = 'id_parent = {int:id_parent}';
        $boardUpdates[] = 'child_level = {int:child_level}';
        $boardUpdates[] = 'board_order = {int:board_order}';
        $boardUpdateParameters += array('id_cat' => $id_cat, 'id_parent' => $id_parent, 'child_level' => $child_level, 'board_order' => $after + 1);
    }
    // This setting is a little twisted in the database...
    if (isset($boardOptions['posts_count'])) {
        $boardUpdates[] = 'count_posts = {int:count_posts}';
        $boardUpdateParameters['count_posts'] = $boardOptions['posts_count'] ? 0 : 1;
    }
    if (isset($boardOptions['allow_topics'])) {
        $boardUpdates[] = 'allow_topics = {int:allow_topics}';
        $boardUpdateParameters['allow_topics'] = $boardOptions['allow_topics'] ? 1 : 0;
    }
    if (isset($boardOptions['automerge'])) {
        $boardUpdates[] = 'automerge = {int:automerge}';
        $boardUpdateParameters['automerge'] = $boardOptions['automerge'];
    }
    if (isset($boardOptions['boardicon'])) {
        $boardUpdates[] = 'icon = {string:boardicon}';
        $boardUpdateParameters['boardicon'] = $boardOptions['boardicon'];
    }
    // Set the theme for this board.
    if (isset($boardOptions['board_theme'])) {
        $boardUpdates[] = 'id_theme = {int:id_theme}';
        $boardUpdateParameters['id_theme'] = (int) $boardOptions['board_theme'];
    }
    // Should the board theme override the user preferred theme?
    if (isset($boardOptions['override_theme'])) {
        $boardUpdates[] = 'override_theme = {int:override_theme}';
        $boardUpdateParameters['override_theme'] = $boardOptions['override_theme'] ? 1 : 0;
    }
    // Who's allowed to access this board.
    if (isset($boardOptions['access_groups'])) {
        $boardUpdates[] = 'member_groups = {string:member_groups}';
        $boardUpdateParameters['member_groups'] = implode(',', $boardOptions['access_groups']);
    }
    if (isset($boardOptions['board_name'])) {
        $boardUpdates[] = 'name = {string:board_name}';
        $boardUpdateParameters['board_name'] = $boardOptions['board_name'];
    }
    if (isset($boardOptions['board_description'])) {
        $boardUpdates[] = 'description = {string:board_description}';
        $boardUpdateParameters['board_description'] = $boardOptions['board_description'];
    }
    if (isset($boardOptions['profile'])) {
        $boardUpdates[] = 'id_profile = {int:profile}';
        $boardUpdateParameters['profile'] = (int) $boardOptions['profile'];
    }
    if (isset($boardOptions['redirect'])) {
        $boardUpdates[] = 'redirect = {string:redirect}';
        $boardUpdateParameters['redirect'] = $boardOptions['redirect'];
    }
    if (isset($boardOptions['num_posts'])) {
        $boardUpdates[] = 'num_posts = {int:num_posts}';
        $boardUpdateParameters['num_posts'] = (int) $boardOptions['num_posts'];
    }
    // Do the updates (if any).
    if (!empty($boardUpdates)) {
        $request = smf_db_query('
			UPDATE {db_prefix}boards
			SET
				' . implode(',
				', $boardUpdates) . '
			WHERE id_board = {int:selected_board}', array_merge($boardUpdateParameters, array('selected_board' => $board_id)));
    }
    // Set moderators of this board.
    if (isset($boardOptions['moderators']) || isset($boardOptions['moderator_string'])) {
        // Reset current moderators for this board - if there are any!
        smf_db_query('
			DELETE FROM {db_prefix}moderators
			WHERE id_board = {int:board_list}', array('board_list' => $board_id));
        // Validate and get the IDs of the new moderators.
        if (isset($boardOptions['moderator_string']) && trim($boardOptions['moderator_string']) != '') {
            // Divvy out the usernames, remove extra space.
            $moderator_string = strtr(commonAPI::htmlspecialchars($boardOptions['moderator_string'], ENT_QUOTES), array('&quot;' => '"'));
            preg_match_all('~"([^"]+)"~', $moderator_string, $matches);
            $moderators = array_merge($matches[1], explode(',', preg_replace('~"[^"]+"~', '', $moderator_string)));
            for ($k = 0, $n = count($moderators); $k < $n; $k++) {
                $moderators[$k] = trim($moderators[$k]);
                if (strlen($moderators[$k]) == 0) {
                    unset($moderators[$k]);
                }
            }
            // Find all the id_member's for the member_name's in the list.
            if (empty($boardOptions['moderators'])) {
                $boardOptions['moderators'] = array();
            }
            if (!empty($moderators)) {
                $request = smf_db_query('
					SELECT id_member
					FROM {db_prefix}members
					WHERE member_name IN ({array_string:moderator_list}) OR real_name IN ({array_string:moderator_list})
					LIMIT ' . count($moderators), array('moderator_list' => $moderators));
                while ($row = mysql_fetch_assoc($request)) {
                    $boardOptions['moderators'][] = $row['id_member'];
                }
                mysql_free_result($request);
            }
        }
        // Add the moderators to the board.
        if (!empty($boardOptions['moderators'])) {
            $inserts = array();
            foreach ($boardOptions['moderators'] as $moderator) {
                $inserts[] = array($board_id, $moderator);
            }
            smf_db_insert('insert', '{db_prefix}moderators', array('id_board' => 'int', 'id_member' => 'int'), $inserts, array('id_board', 'id_member'));
        }
        // Note that caches can now be wrong!
        updateSettings(array('settings_updated' => time()));
    }
    if (isset($boardOptions['move_to'])) {
        reorderBoards();
    }
    clean_cache('data');
    if (empty($boardOptions['dont_log'])) {
        logAction('edit_board', array('board' => $board_id), 'admin');
    }
}
Exemplo n.º 11
0
 public function prepareIndexes($word, &$wordsSearch, &$wordsExclude, $isExcluded)
 {
     global $modSettings, $smcFunc;
     $subwords = text2words($word, $this->min_word_length, true);
     if (empty($modSettings['search_force_index'])) {
         $wordsSearch['words'][] = $word;
     }
     // Excluded phrases don't benefit from being split into subwords.
     if (count($subwords) > 1 && $isExcluded) {
         continue;
     } else {
         foreach ($subwords as $subword) {
             if (commonAPI::strlen($subword) >= $this->min_word_length && !in_array($subword, $this->bannedWords)) {
                 $wordsSearch['indexed_words'][] = $subword;
                 if ($isExcluded) {
                     $wordsExclude[] = $subword;
                 }
             }
         }
     }
 }
Exemplo n.º 12
0
function Display()
{
    global $scripturl, $txt, $modSettings, $context, $settings, $memberContext, $output;
    global $options, $sourcedir, $user_info, $user_profile, $board_info, $topic, $board;
    global $attachments, $messages_request, $topicinfo, $language;
    $context['response_prefixlen'] = strlen($txt['response_prefix']);
    $context['need_synhlt'] = true;
    $context['is_display_std'] = true;
    $context['pcache_update_counter'] = !empty($modSettings['use_post_cache']) ? 0 : PCACHE_UPDATE_PER_VIEW + 1;
    $context['time_cutoff_ref'] = time();
    $context['template_hooks']['display'] = array('header' => '', 'extend_topicheader' => '', 'above_posts' => '', 'below_posts' => '', 'footer' => '');
    //EoS_Smarty::getConfigInstance()->registerHookTemplate('postbit_below', 'overrides/foo');
    if (!empty($modSettings['karmaMode'])) {
        require_once $sourcedir . '/lib/Subs-Ratings.php';
    } else {
        $context['can_see_like'] = $context['can_give_like'] = false;
    }
    // What are you gonna display if these are empty?!
    if (empty($topic)) {
        fatal_lang_error('no_board', false);
    }
    // Not only does a prefetch make things slower for the server, but it makes it impossible to know if they read it.
    if (isset($_SERVER['HTTP_X_MOZ']) && $_SERVER['HTTP_X_MOZ'] == 'prefetch') {
        ob_end_clean();
        header('HTTP/1.1 403 Prefetch Forbidden');
        die;
    }
    // How much are we sticking on each page?
    $context['messages_per_page'] = commonAPI::getMessagesPerPage();
    $context['page_number'] = isset($_REQUEST['start']) ? $_REQUEST['start'] / $context['messages_per_page'] : 0;
    // Let's do some work on what to search index.
    //$context['multiquote_cookiename'] = 'mq_' . $context['current_topic'];
    $context['multiquote_posts'] = array();
    if (isset($_COOKIE[$context['multiquote_cookiename']]) && strlen($_COOKIE[$context['multiquote_cookiename']]) > 1) {
        $context['multiquote_posts'] = explode(',', $_COOKIE[$context['multiquote_cookiename']]);
    }
    $context['multiquote_posts_count'] = count($context['multiquote_posts']);
    if (count($_GET) > 2) {
        foreach ($_GET as $k => $v) {
            if (!in_array($k, array('topic', 'board', 'start', session_name()))) {
                $context['robot_no_index'] = true;
            }
        }
    }
    if (!empty($_REQUEST['start']) && (!is_numeric($_REQUEST['start']) || $_REQUEST['start'] % $context['messages_per_page'] != 0)) {
        $context['robot_no_index'] = true;
    }
    // Find the previous or next topic.  Make a fuss if there are no more.
    if (isset($_REQUEST['prev_next']) && ($_REQUEST['prev_next'] == 'prev' || $_REQUEST['prev_next'] == 'next')) {
        // No use in calculating the next topic if there's only one.
        if ($board_info['num_topics'] > 1) {
            // Just prepare some variables that are used in the query.
            $gt_lt = $_REQUEST['prev_next'] == 'prev' ? '>' : '<';
            $order = $_REQUEST['prev_next'] == 'prev' ? '' : ' DESC';
            $request = smf_db_query('
				SELECT t2.id_topic
				FROM {db_prefix}topics AS t
					INNER JOIN {db_prefix}topics AS t2 ON (' . (empty($modSettings['enableStickyTopics']) ? '
					t2.id_last_msg ' . $gt_lt . ' t.id_last_msg' : '
					(t2.id_last_msg ' . $gt_lt . ' t.id_last_msg AND t2.is_sticky ' . $gt_lt . '= t.is_sticky) OR t2.is_sticky ' . $gt_lt . ' t.is_sticky') . ')
				WHERE t.id_topic = {int:current_topic}
					AND t2.id_board = {int:current_board}' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : '
					AND (t2.approved = {int:is_approved} OR (t2.id_member_started != {int:id_member_started} AND t2.id_member_started = {int:current_member}))') . '
				ORDER BY' . (empty($modSettings['enableStickyTopics']) ? '' : ' t2.is_sticky' . $order . ',') . ' t2.id_last_msg' . $order . '
				LIMIT 1', array('current_board' => $board, 'current_member' => $user_info['id'], 'current_topic' => $topic, 'is_approved' => 1, 'id_member_started' => 0));
            // No more left.
            if (mysql_num_rows($request) == 0) {
                mysql_free_result($request);
                // Roll over - if we're going prev, get the last - otherwise the first.
                $request = smf_db_query('
					SELECT id_topic
					FROM {db_prefix}topics
					WHERE id_board = {int:current_board}' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : '
						AND (approved = {int:is_approved} OR (id_member_started != {int:id_member_started} AND id_member_started = {int:current_member}))') . '
					ORDER BY' . (empty($modSettings['enableStickyTopics']) ? '' : ' is_sticky' . $order . ',') . ' id_last_msg' . $order . '
					LIMIT 1', array('current_board' => $board, 'current_member' => $user_info['id'], 'is_approved' => 1, 'id_member_started' => 0));
            }
            // Now you can be sure $topic is the id_topic to view.
            list($topic) = mysql_fetch_row($request);
            mysql_free_result($request);
            $context['current_topic'] = $topic;
        }
        // Go to the newest message on this topic.
        $_REQUEST['start'] = 'new';
    }
    // Add 1 to the number of views of this topic.
    if (empty($_SESSION['last_read_topic']) || $_SESSION['last_read_topic'] != $topic) {
        smf_db_query('
			UPDATE {db_prefix}topics
			SET num_views = num_views + 1
			WHERE id_topic = {int:current_topic}', array('current_topic' => $topic));
        $_SESSION['last_read_topic'] = $topic;
    }
    if ($modSettings['tags_active']) {
        $dbresult = smf_db_query('
		   SELECT t.tag,l.ID,t.ID_TAG FROM {db_prefix}tags_log as l, {db_prefix}tags as t
			WHERE t.ID_TAG = l.ID_TAG && l.ID_TOPIC = {int:topic}', array('topic' => $topic));
        $context['topic_tags'] = array();
        while ($row = mysql_fetch_assoc($dbresult)) {
            $context['topic_tags'][] = array('ID' => $row['ID'], 'ID_TAG' => $row['ID_TAG'], 'tag' => $row['tag']);
        }
        mysql_free_result($dbresult);
        $context['tags_active'] = true;
    } else {
        $context['topic_tags'] = $context['tags_active'] = 0;
    }
    // Get all the important topic info.
    $request = smf_db_query('SELECT
			t.num_replies, t.num_views, t.locked, ms.poster_name, ms.subject, ms.poster_email, ms.poster_time AS first_post_time, t.is_sticky, t.id_poll,
			t.id_member_started, t.id_first_msg, t.id_last_msg, t.approved, t.unapproved_posts, t.id_layout, 
			' . ($user_info['is_guest'] ? 't.id_last_msg + 1' : 'IFNULL(lt.id_msg, IFNULL(lmr.id_msg, -1)) + 1') . ' AS new_from
			' . (!empty($modSettings['recycle_board']) && $modSettings['recycle_board'] == $board ? ', id_previous_board, id_previous_topic' : '') . ',
			p.name AS prefix_name, ms1.poster_time AS last_post_time, ms1.modified_time AS last_modified_time, IFNULL(b.automerge, 0) AS automerge
		FROM {db_prefix}topics AS t
			INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board)
			INNER JOIN {db_prefix}messages AS ms1 ON (ms1.id_msg = t.id_last_msg)
			INNER JOIN {db_prefix}messages AS ms ON (ms.id_msg = t.id_first_msg)' . ($user_info['is_guest'] ? '' : '
			LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = {int:current_topic} AND lt.id_member = {int:current_member})
			LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = {int:current_board} AND lmr.id_member = {int:current_member})') . '
			LEFT JOIN {db_prefix}prefixes as p ON p.id_prefix = t.id_prefix 
		WHERE t.id_topic = {int:current_topic}
		LIMIT 1', array('current_member' => $user_info['id'], 'current_topic' => $topic, 'current_board' => $board));
    if (mysql_num_rows($request) == 0) {
        fatal_lang_error('not_a_topic', false);
    }
    // Added by Related Topics
    if (isset($modSettings['have_related_topics']) && $modSettings['have_related_topics'] && !empty($modSettings['relatedTopicsEnabled'])) {
        require_once $sourcedir . '/lib/Subs-Related.php';
        loadRelated($topic);
    }
    $topicinfo = mysql_fetch_assoc($request);
    mysql_free_result($request);
    $context['topic_banned_members'] = array();
    $request = smf_db_query('SELECT id_member FROM {db_prefix}topicbans WHERE id_topic = {int:topic}', array('topic' => $topic));
    if (mysql_num_rows($request) != 0) {
        while ($row = mysql_fetch_row($request)) {
            $context['topic_banned_members'][] = $row[0];
        }
    }
    mysql_free_result($request);
    $context['topic_banned_members_count'] = count($context['topic_banned_members']);
    $context['topic_last_modified'] = max($topicinfo['last_post_time'], $topicinfo['last_modified_time']);
    // todo: considering - make post cutoff time for the cache depend on the modification time of the topic's last post
    $context['real_num_replies'] = $context['num_replies'] = $topicinfo['num_replies'];
    $context['topic_first_message'] = $topicinfo['id_first_msg'];
    $context['topic_last_message'] = $topicinfo['id_last_msg'];
    $context['first_subject'] = $topicinfo['subject'];
    $context['prefix'] = !empty($topicinfo['prefix_name']) ? html_entity_decode($topicinfo['prefix_name']) . '&nbsp;' : '';
    $context['automerge'] = $topicinfo['automerge'] > 0;
    // Add up unapproved replies to get real number of replies...
    if ($modSettings['postmod_active'] && allowedTo('approve_posts')) {
        $context['real_num_replies'] += $topicinfo['unapproved_posts'] - ($topicinfo['approved'] ? 0 : 1);
    }
    // If this topic has unapproved posts, we need to work out how many posts the user can see, for page indexing.
    if ($modSettings['postmod_active'] && $topicinfo['unapproved_posts'] && !$user_info['is_guest'] && !allowedTo('approve_posts')) {
        $request = smf_db_query('
			SELECT COUNT(id_member) AS my_unapproved_posts
			FROM {db_prefix}messages
			WHERE id_topic = {int:current_topic}
				AND id_member = {int:current_member}
				AND approved = 0', array('current_topic' => $topic, 'current_member' => $user_info['id']));
        list($myUnapprovedPosts) = mysql_fetch_row($request);
        mysql_free_result($request);
        $context['total_visible_posts'] = $context['num_replies'] + $myUnapprovedPosts + ($topicinfo['approved'] ? 1 : 0);
    } else {
        $context['total_visible_posts'] = $context['num_replies'] + $topicinfo['unapproved_posts'] + ($topicinfo['approved'] ? 1 : 0);
    }
    // When was the last time this topic was replied to?  Should we warn them about it?
    /* redundant query? last_post_time is already in $topicinfo[]
    	$request = smf_db_query( '
    		SELECT poster_time
    		FROM {db_prefix}messages
    		WHERE id_msg = {int:id_last_msg}
    		LIMIT 1',
    		array(
    			'id_last_msg' => $topicinfo['id_last_msg'],
    		)
    	);
    
    	list ($lastPostTime) = mysql_fetch_row($request);
    	mysql_free_result($request);
    	*/
    $lastPostTime = $topicinfo['last_post_time'];
    $context['oldTopicError'] = !empty($modSettings['oldTopicDays']) && $lastPostTime + $modSettings['oldTopicDays'] * 86400 < time() && empty($sticky);
    // The start isn't a number; it's information about what to do, where to go.
    if (!is_numeric($_REQUEST['start'])) {
        // Redirect to the page and post with new messages, originally by Omar Bazavilvazo.
        if ($_REQUEST['start'] == 'new') {
            // Guests automatically go to the last post.
            if ($user_info['is_guest']) {
                $context['start_from'] = $context['total_visible_posts'] - 1;
                $_REQUEST['start'] = empty($options['view_newest_first']) ? $context['start_from'] : 0;
            } else {
                // Find the earliest unread message in the topic. (the use of topics here is just for both tables.)
                $request = smf_db_query('
					SELECT IFNULL(lt.id_msg, IFNULL(lmr.id_msg, -1)) + 1 AS new_from
					FROM {db_prefix}topics AS t
						LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = {int:current_topic} AND lt.id_member = {int:current_member})
						LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = {int:current_board} AND lmr.id_member = {int:current_member})
					WHERE t.id_topic = {int:current_topic}
					LIMIT 1', array('current_board' => $board, 'current_member' => $user_info['id'], 'current_topic' => $topic));
                list($new_from) = mysql_fetch_row($request);
                mysql_free_result($request);
                // Fall through to the next if statement.
                $_REQUEST['start'] = 'msg' . $new_from;
            }
        }
        // Start from a certain time index, not a message.
        if (substr($_REQUEST['start'], 0, 4) == 'from') {
            $timestamp = (int) substr($_REQUEST['start'], 4);
            if ($timestamp === 0) {
                $_REQUEST['start'] = 0;
            } else {
                // Find the number of messages posted before said time...
                $request = smf_db_query('
					SELECT COUNT(*)
					FROM {db_prefix}messages
					WHERE poster_time < {int:timestamp}
						AND id_topic = {int:current_topic}' . ($modSettings['postmod_active'] && $topicinfo['unapproved_posts'] && !allowedTo('approve_posts') ? '
						AND (approved = {int:is_approved}' . ($user_info['is_guest'] ? '' : ' OR id_member = {int:current_member}') . ')' : ''), array('current_topic' => $topic, 'current_member' => $user_info['id'], 'is_approved' => 1, 'timestamp' => $timestamp));
                list($context['start_from']) = mysql_fetch_row($request);
                mysql_free_result($request);
                // Handle view_newest_first options, and get the correct start value.
                $_REQUEST['start'] = empty($options['view_newest_first']) ? $context['start_from'] : $context['total_visible_posts'] - $context['start_from'] - 1;
            }
        } elseif (substr($_REQUEST['start'], 0, 3) == 'msg') {
            $virtual_msg = (int) substr($_REQUEST['start'], 3);
            if (!$topicinfo['unapproved_posts'] && $virtual_msg >= $topicinfo['id_last_msg']) {
                $context['start_from'] = $context['total_visible_posts'] - 1;
            } elseif (!$topicinfo['unapproved_posts'] && $virtual_msg <= $topicinfo['id_first_msg']) {
                $context['start_from'] = 0;
            } else {
                // Find the start value for that message......
                $request = smf_db_query('
					SELECT COUNT(*)
					FROM {db_prefix}messages
					WHERE id_msg < {int:virtual_msg}
						AND id_topic = {int:current_topic}' . ($modSettings['postmod_active'] && $topicinfo['unapproved_posts'] && !allowedTo('approve_posts') ? '
						AND (approved = {int:is_approved}' . ($user_info['is_guest'] ? '' : ' OR id_member = {int:current_member}') . ')' : ''), array('current_member' => $user_info['id'], 'current_topic' => $topic, 'virtual_msg' => $virtual_msg, 'is_approved' => 1, 'no_member' => 0));
                list($context['start_from']) = mysql_fetch_row($request);
                mysql_free_result($request);
            }
            // We need to reverse the start as well in this case.
            if (isset($_REQUEST['perma'])) {
                $_REQUEST['start'] = $virtual_msg;
            } else {
                $_REQUEST['start'] = empty($options['view_newest_first']) ? $context['start_from'] : $context['total_visible_posts'] - $context['start_from'] - 1;
            }
        }
    }
    // Create a previous next string if the selected theme has it as a selected option.
    $context['previous_next'] = $modSettings['enablePreviousNext'] ? '<a href="' . $scripturl . '?topic=' . $topic . '.0;prev_next=prev#new">' . $txt['previous_next_back'] . '</a> <a href="' . $scripturl . '?topic=' . $topic . '.0;prev_next=next#new">' . $txt['previous_next_forward'] . '</a>' : '';
    // Do we need to show the visual verification image?
    $context['require_verification'] = !$user_info['is_mod'] && !$user_info['is_admin'] && !empty($modSettings['posts_require_captcha']) && ($user_info['posts'] < $modSettings['posts_require_captcha'] || $user_info['is_guest'] && $modSettings['posts_require_captcha'] == -1);
    if ($context['require_verification']) {
        require_once $sourcedir . '/lib/Subs-Editor.php';
        $verificationOptions = array('id' => 'post', 'skip_template' => true);
        $context['require_verification'] = create_control_verification($verificationOptions);
        $context['visual_verification_id'] = $verificationOptions['id'];
    }
    // Are we showing signatures - or disabled fields?
    $context['signature_enabled'] = substr($modSettings['signature_settings'], 0, 1) == 1;
    $context['disabled_fields'] = isset($modSettings['disabled_profile_fields']) ? array_flip(explode(',', $modSettings['disabled_profile_fields'])) : array();
    // Censor the title...
    censorText($topicinfo['subject']);
    $context['page_title'] = $topicinfo['subject'] . ((int) $context['page_number'] > 0 ? ' - ' . $txt['page'] . ' ' . ($context['page_number'] + 1) : '');
    // Is this topic sticky, or can it even be?
    $topicinfo['is_sticky'] = empty($modSettings['enableStickyTopics']) ? '0' : $topicinfo['is_sticky'];
    // Default this topic to not marked for notifications... of course...
    $context['is_marked_notify'] = false;
    // Did we report a post to a moderator just now?
    $context['report_sent'] = isset($_GET['reportsent']);
    // Let's get nosey, who is viewing this topic?
    if (!empty($settings['display_who_viewing'])) {
        // Start out with no one at all viewing it.
        $context['view_members'] = array();
        $context['view_members_list'] = array();
        $context['view_num_hidden'] = 0;
        // Search for members who have this topic set in their GET data.
        $request = smf_db_query('
			SELECT
				lo.id_member, lo.log_time, mem.real_name, mem.member_name, mem.show_online, mem.id_group, mem.id_post_group
			FROM {db_prefix}log_online AS lo
				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lo.id_member)
			WHERE INSTR(lo.url, {string:in_url_string}) > 0 OR lo.session = {string:session}', array('in_url_string' => 's:5:"topic";i:' . $topic . ';', 'session' => $user_info['is_guest'] ? 'ip' . $user_info['ip'] : session_id()));
        while ($row = mysql_fetch_assoc($request)) {
            if (empty($row['id_member'])) {
                continue;
            }
            $class = 'member group_' . (empty($row['id_group']) ? $row['id_post_group'] : $row['id_group']) . (in_array($row['id_member'], $user_info['buddies']) ? ' buddy' : '');
            $href = URL::user($row['id_member'], $row['real_name']);
            if ($row['id_member'] == $user_info['id']) {
                $link = '<strong>' . $txt['you'] . '</strong>';
            } else {
                $link = '<a onclick="getMcard(' . $row['id_member'] . ');return(false);" class="' . $class . '" href="' . $href . '">' . $row['real_name'] . '</a>';
            }
            // Add them both to the list and to the more detailed list.
            if (!empty($row['show_online']) || allowedTo('moderate_forum')) {
                $context['view_members_list'][$row['log_time'] . $row['member_name']] = empty($row['show_online']) ? '<em>' . $link . '</em>' : $link;
            }
            $context['view_members'][$row['log_time'] . $row['member_name']] = array('id' => $row['id_member'], 'username' => $row['member_name'], 'name' => $row['real_name'], 'group' => $row['id_group'], 'href' => $href, 'link' => $link, 'hidden' => empty($row['show_online']));
            if (empty($row['show_online'])) {
                $context['view_num_hidden']++;
            }
        }
        // The number of guests is equal to the rows minus the ones we actually used ;).
        $context['view_num_guests'] = mysql_num_rows($request) - count($context['view_members']);
        mysql_free_result($request);
        // Sort the list.
        krsort($context['view_members']);
        krsort($context['view_members_list']);
    }
    // If all is set, but not allowed... just unset it.
    $can_show_all = !empty($modSettings['enableAllMessages']) && $context['total_visible_posts'] > $context['messages_per_page'] && $context['total_visible_posts'] < $modSettings['enableAllMessages'];
    if (isset($_REQUEST['all']) && !$can_show_all) {
        unset($_REQUEST['all']);
    } elseif (isset($_REQUEST['all'])) {
        $_REQUEST['start'] = -1;
    }
    // Construct the page index, allowing for the .START method...
    if (!isset($_REQUEST['perma'])) {
        $context['page_index'] = constructPageIndex(URL::topic($topic, $topicinfo['subject'], '%1$d'), $_REQUEST['start'], $context['total_visible_posts'], $context['messages_per_page'], true);
    }
    $context['start'] = $_REQUEST['start'];
    // This is information about which page is current, and which page we're on - in case you don't like the constructed page index. (again, wireles..)
    $context['page_info'] = array('current_page' => $_REQUEST['start'] / $context['messages_per_page'] + 1, 'num_pages' => floor(($context['total_visible_posts'] - 1) / $context['messages_per_page']) + 1);
    $context['links'] = array('first' => $_REQUEST['start'] >= $context['messages_per_page'] ? $scripturl . '?topic=' . $topic . '.0' : '', 'prev' => $_REQUEST['start'] >= $context['messages_per_page'] ? $scripturl . '?topic=' . $topic . '.' . ($_REQUEST['start'] - $context['messages_per_page']) : '', 'next' => $_REQUEST['start'] + $context['messages_per_page'] < $context['total_visible_posts'] ? $scripturl . '?topic=' . $topic . '.' . ($_REQUEST['start'] + $context['messages_per_page']) : '', 'last' => $_REQUEST['start'] + $context['messages_per_page'] < $context['total_visible_posts'] ? $scripturl . '?topic=' . $topic . '.' . floor($context['total_visible_posts'] / $context['messages_per_page']) * $context['messages_per_page'] : '', 'up' => $scripturl . '?board=' . $board . '.0');
    // If they are viewing all the posts, show all the posts, otherwise limit the number.
    if ($can_show_all) {
        if (isset($_REQUEST['all'])) {
            // No limit! (actually, there is a limit, but...)
            $context['messages_per_page'] = -1;
            $context['page_index'] .= '[<strong>' . $txt['all'] . '</strong>] ';
            // Set start back to 0...
            $_REQUEST['start'] = 0;
        } else {
            if (!isset($context['page_index'])) {
                $context['page_index'] = '';
            }
            $context['page_index'] .= '&nbsp;<a href="' . $scripturl . '?topic=' . $topic . '.0;all">' . $txt['all'] . '</a> ';
        }
    }
    // Build the link tree.
    $context['linktree'][] = array('url' => URL::topic($topic, $topicinfo['subject'], 0), 'name' => $topicinfo['subject'], 'extra_before' => $settings['linktree_inline'] ? $txt['topic'] . ': ' : '');
    // Build a list of this board's moderators.
    $context['moderators'] =& $board_info['moderators'];
    $context['link_moderators'] = array();
    if (!empty($board_info['moderators'])) {
        // Add a link for each moderator...
        foreach ($board_info['moderators'] as $mod) {
            $context['link_moderators'][] = '<a href="' . $scripturl . '?action=profile;u=' . $mod['id'] . '" title="' . $txt['board_moderator'] . '">' . $mod['name'] . '</a>';
        }
        // And show it after the board's name.
        //$context['linktree'][count($context['linktree']) - 2]['extra_after'] = ' (' . (count($context['link_moderators']) == 1 ? $txt['moderator'] : $txt['moderators']) . ': ' . implode(', ', $context['link_moderators']) . ')';
    }
    // Information about the current topic...
    $context['is_locked'] = $topicinfo['locked'];
    $context['is_sticky'] = $topicinfo['is_sticky'];
    $context['is_very_hot'] = $topicinfo['num_replies'] >= $modSettings['hotTopicVeryPosts'];
    $context['is_hot'] = $topicinfo['num_replies'] >= $modSettings['hotTopicPosts'];
    $context['is_approved'] = $topicinfo['approved'];
    // We don't want to show the poll icon in the topic class here, so pretend it's not one.
    $context['is_poll'] = false;
    determineTopicClass($context);
    $context['is_poll'] = $topicinfo['id_poll'] > 0 && $modSettings['pollMode'] == '1' && allowedTo('poll_view');
    // Did this user start the topic or not?
    $context['user']['started'] = $user_info['id'] == $topicinfo['id_member_started'] && !$user_info['is_guest'];
    $context['topic_starter_id'] = $topicinfo['id_member_started'];
    // Set the topic's information for the template.
    $context['subject'] = $topicinfo['subject'];
    $context['num_views'] = $topicinfo['num_views'];
    $context['mark_unread_time'] = $topicinfo['new_from'];
    // Set a canonical URL for this page.
    $context['canonical_url'] = URL::topic($topic, $topicinfo['subject'], $context['start']);
    $context['share_url'] = $scripturl . '?topic=' . $topic;
    // For quick reply we need a response prefix in the default forum language.
    if (!isset($context['response_prefix']) && !($context['response_prefix'] = CacheAPI::getCache('response_prefix', 600))) {
        if ($language === $user_info['language']) {
            $context['response_prefix'] = $txt['response_prefix'];
        } else {
            loadLanguage('index', $language, false);
            $context['response_prefix'] = $txt['response_prefix'];
            loadLanguage('index');
        }
        CacheAPI::putCache('response_prefix', $context['response_prefix'], 600);
    }
    // If we want to show event information in the topic, prepare the data.
    if (allowedTo('calendar_view') && !empty($modSettings['cal_showInTopic']) && !empty($modSettings['cal_enabled'])) {
        // First, try create a better time format, ignoring the "time" elements.
        if (preg_match('~%[AaBbCcDdeGghjmuYy](?:[^%]*%[AaBbCcDdeGghjmuYy])*~', $user_info['time_format'], $matches) == 0 || empty($matches[0])) {
            $date_string = $user_info['time_format'];
        } else {
            $date_string = $matches[0];
        }
        // Any calendar information for this topic?
        $request = smf_db_query('
			SELECT cal.id_event, cal.start_date, cal.end_date, cal.title, cal.id_member, mem.real_name
			FROM {db_prefix}calendar AS cal
				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = cal.id_member)
			WHERE cal.id_topic = {int:current_topic}
			ORDER BY start_date', array('current_topic' => $topic));
        $context['linked_calendar_events'] = array();
        while ($row = mysql_fetch_assoc($request)) {
            // Prepare the dates for being formatted.
            $start_date = sscanf($row['start_date'], '%04d-%02d-%02d');
            $start_date = mktime(12, 0, 0, $start_date[1], $start_date[2], $start_date[0]);
            $end_date = sscanf($row['end_date'], '%04d-%02d-%02d');
            $end_date = mktime(12, 0, 0, $end_date[1], $end_date[2], $end_date[0]);
            $context['linked_calendar_events'][] = array('id' => $row['id_event'], 'title' => $row['title'], 'can_edit' => allowedTo('calendar_edit_any') || $row['id_member'] == $user_info['id'] && allowedTo('calendar_edit_own'), 'modify_href' => $scripturl . '?action=post;msg=' . $topicinfo['id_first_msg'] . ';topic=' . $topic . '.0;calendar;eventid=' . $row['id_event'] . ';' . $context['session_var'] . '=' . $context['session_id'], 'start_date' => timeformat_static($start_date, $date_string, 'none'), 'start_timestamp' => $start_date, 'end_date' => timeformat_static($end_date, $date_string, 'none'), 'end_timestamp' => $end_date, 'is_last' => false);
        }
        mysql_free_result($request);
        if (!empty($context['linked_calendar_events'])) {
            $context['linked_calendar_events'][count($context['linked_calendar_events']) - 1]['is_last'] = true;
        }
    }
    // Create the poll info if it exists.
    if ($context['is_poll']) {
        // Get the question and if it's locked.
        $request = smf_db_query('
			SELECT
				p.question, p.voting_locked, p.hide_results, p.expire_time, p.max_votes, p.change_vote,
				p.guest_vote, p.id_member, IFNULL(mem.real_name, p.poster_name) AS poster_name, p.num_guest_voters, p.reset_poll
			FROM {db_prefix}polls AS p
				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = p.id_member)
			WHERE p.id_poll = {int:id_poll}
			LIMIT 1', array('id_poll' => $topicinfo['id_poll']));
        $pollinfo = mysql_fetch_assoc($request);
        mysql_free_result($request);
        $request = smf_db_query('
			SELECT COUNT(DISTINCT id_member) AS total
			FROM {db_prefix}log_polls
			WHERE id_poll = {int:id_poll}
				AND id_member != {int:not_guest}', array('id_poll' => $topicinfo['id_poll'], 'not_guest' => 0));
        list($pollinfo['total']) = mysql_fetch_row($request);
        mysql_free_result($request);
        // Total voters needs to include guest voters
        $pollinfo['total'] += $pollinfo['num_guest_voters'];
        // Get all the options, and calculate the total votes.
        $request = smf_db_query('
			SELECT pc.id_choice, pc.label, pc.votes, IFNULL(lp.id_choice, -1) AS voted_this
			FROM {db_prefix}poll_choices AS pc
				LEFT JOIN {db_prefix}log_polls AS lp ON (lp.id_choice = pc.id_choice AND lp.id_poll = {int:id_poll} AND lp.id_member = {int:current_member} AND lp.id_member != {int:not_guest})
			WHERE pc.id_poll = {int:id_poll}', array('current_member' => $user_info['id'], 'id_poll' => $topicinfo['id_poll'], 'not_guest' => 0));
        $pollOptions = array();
        $realtotal = 0;
        $pollinfo['has_voted'] = false;
        while ($row = mysql_fetch_assoc($request)) {
            censorText($row['label']);
            $pollOptions[$row['id_choice']] = $row;
            $realtotal += $row['votes'];
            $pollinfo['has_voted'] |= $row['voted_this'] != -1;
        }
        mysql_free_result($request);
        // If this is a guest we need to do our best to work out if they have voted, and what they voted for.
        if ($user_info['is_guest'] && $pollinfo['guest_vote'] && allowedTo('poll_vote')) {
            if (!empty($_COOKIE['guest_poll_vote']) && preg_match('~^[0-9,;]+$~', $_COOKIE['guest_poll_vote']) && strpos($_COOKIE['guest_poll_vote'], ';' . $topicinfo['id_poll'] . ',') !== false) {
                // ;id,timestamp,[vote,vote...]; etc
                $guestinfo = explode(';', $_COOKIE['guest_poll_vote']);
                // Find the poll we're after.
                foreach ($guestinfo as $i => $guestvoted) {
                    $guestvoted = explode(',', $guestvoted);
                    if ($guestvoted[0] == $topicinfo['id_poll']) {
                        break;
                    }
                }
                // Has the poll been reset since guest voted?
                if ($pollinfo['reset_poll'] > $guestvoted[1]) {
                    // Remove the poll info from the cookie to allow guest to vote again
                    unset($guestinfo[$i]);
                    if (!empty($guestinfo)) {
                        $_COOKIE['guest_poll_vote'] = ';' . implode(';', $guestinfo);
                    } else {
                        unset($_COOKIE['guest_poll_vote']);
                    }
                } else {
                    // What did they vote for?
                    unset($guestvoted[0], $guestvoted[1]);
                    foreach ($pollOptions as $choice => $details) {
                        $pollOptions[$choice]['voted_this'] = in_array($choice, $guestvoted) ? 1 : -1;
                        $pollinfo['has_voted'] |= $pollOptions[$choice]['voted_this'] != -1;
                    }
                    unset($choice, $details, $guestvoted);
                }
                unset($guestinfo, $guestvoted, $i);
            }
        }
        // Set up the basic poll information.
        $context['poll'] = array('id' => $topicinfo['id_poll'], 'image' => 'normal_' . (empty($pollinfo['voting_locked']) ? 'poll' : 'locked_poll'), 'question' => parse_bbc($pollinfo['question']), 'total_votes' => $pollinfo['total'], 'change_vote' => !empty($pollinfo['change_vote']), 'is_locked' => !empty($pollinfo['voting_locked']), 'options' => array(), 'lock' => allowedTo('poll_lock_any') || $context['user']['started'] && allowedTo('poll_lock_own'), 'edit' => allowedTo('poll_edit_any') || $context['user']['started'] && allowedTo('poll_edit_own'), 'allowed_warning' => $pollinfo['max_votes'] > 1 ? sprintf($txt['poll_options6'], min(count($pollOptions), $pollinfo['max_votes'])) : '', 'is_expired' => !empty($pollinfo['expire_time']) && $pollinfo['expire_time'] < time(), 'expire_time' => !empty($pollinfo['expire_time']) ? timeformat($pollinfo['expire_time']) : 0, 'has_voted' => !empty($pollinfo['has_voted']), 'starter' => array('id' => $pollinfo['id_member'], 'name' => $row['poster_name'], 'href' => $pollinfo['id_member'] == 0 ? '' : $scripturl . '?action=profile;u=' . $pollinfo['id_member'], 'link' => $pollinfo['id_member'] == 0 ? $row['poster_name'] : '<a href="' . $scripturl . '?action=profile;u=' . $pollinfo['id_member'] . '">' . $row['poster_name'] . '</a>'));
        // Make the lock and edit permissions defined above more directly accessible.
        $context['allow_lock_poll'] = $context['poll']['lock'];
        $context['allow_edit_poll'] = $context['poll']['edit'];
        // You're allowed to vote if:
        // 1. the poll did not expire, and
        // 2. you're either not a guest OR guest voting is enabled... and
        // 3. you're not trying to view the results, and
        // 4. the poll is not locked, and
        // 5. you have the proper permissions, and
        // 6. you haven't already voted before.
        $context['allow_vote'] = !$context['poll']['is_expired'] && (!$user_info['is_guest'] || $pollinfo['guest_vote'] && allowedTo('poll_vote')) && empty($pollinfo['voting_locked']) && allowedTo('poll_vote') && !$context['poll']['has_voted'];
        // You're allowed to view the results if:
        // 1. you're just a super-nice-guy, or
        // 2. anyone can see them (hide_results == 0), or
        // 3. you can see them after you voted (hide_results == 1), or
        // 4. you've waited long enough for the poll to expire. (whether hide_results is 1 or 2.)
        $context['allow_poll_view'] = allowedTo('moderate_board') || $pollinfo['hide_results'] == 0 || $pollinfo['hide_results'] == 1 && $context['poll']['has_voted'] || $context['poll']['is_expired'];
        $context['poll']['show_results'] = $context['allow_poll_view'] && (isset($_REQUEST['viewresults']) || isset($_REQUEST['viewResults']));
        $context['show_view_results_button'] = $context['allow_vote'] && (!$context['allow_poll_view'] || !$context['poll']['show_results'] || !$context['poll']['has_voted']);
        // You're allowed to change your vote if:
        // 1. the poll did not expire, and
        // 2. you're not a guest... and
        // 3. the poll is not locked, and
        // 4. you have the proper permissions, and
        // 5. you have already voted, and
        // 6. the poll creator has said you can!
        $context['allow_change_vote'] = !$context['poll']['is_expired'] && !$user_info['is_guest'] && empty($pollinfo['voting_locked']) && allowedTo('poll_vote') && $context['poll']['has_voted'] && $context['poll']['change_vote'];
        // You're allowed to return to voting options if:
        // 1. you are (still) allowed to vote.
        // 2. you are currently seeing the results.
        $context['allow_return_vote'] = $context['allow_vote'] && $context['poll']['show_results'];
        // Calculate the percentages and bar lengths...
        $divisor = $realtotal == 0 ? 1 : $realtotal;
        // Determine if a decimal point is needed in order for the options to add to 100%.
        $precision = $realtotal == 100 ? 0 : 1;
        // Now look through each option, and...
        foreach ($pollOptions as $i => $option) {
            // First calculate the percentage, and then the width of the bar...
            $bar = round($option['votes'] * 100 / $divisor, $precision);
            $barWide = $bar == 0 ? 1 : floor($bar * 8 / 3);
            // Now add it to the poll's contextual theme data.
            $context['poll']['options'][$i] = array('id' => 'options-' . $i, 'percent' => $bar, 'votes' => $option['votes'], 'voted_this' => $option['voted_this'] != -1, 'bar' => '<span style="white-space: nowrap;"><img src="' . $settings['images_url'] . '/poll_' . ($context['right_to_left'] ? 'right' : 'left') . '.gif" alt="" /><img src="' . $settings['images_url'] . '/poll_middle.gif" width="' . $barWide . '" height="12" alt="-" /><img src="' . $settings['images_url'] . '/poll_' . ($context['right_to_left'] ? 'left' : 'right') . '.gif" alt="" /></span>', 'bar_ndt' => $bar > 0 ? '<div class="bar" style="width: ' . ($bar * 3.5 + 4) . 'px;"></div>' : '', 'bar_width' => $barWide, 'option' => parse_bbc($option['label']), 'vote_button' => '<input type="' . ($pollinfo['max_votes'] > 1 ? 'checkbox' : 'radio') . '" name="options[]" id="options-' . $i . '" value="' . $i . '" class="input_' . ($pollinfo['max_votes'] > 1 ? 'check' : 'radio') . '" />');
        }
    }
    // Calculate the fastest way to get the messages!
    $ascending = empty($options['view_newest_first']);
    $start = $_REQUEST['start'];
    $limit = $context['messages_per_page'];
    $firstIndex = 0;
    if ($start >= $context['total_visible_posts'] / 2 && $context['messages_per_page'] != -1) {
        $ascending = !$ascending;
        $limit = $context['total_visible_posts'] <= $start + $limit ? $context['total_visible_posts'] - $start : $limit;
        $start = $context['total_visible_posts'] <= $start + $limit ? 0 : $context['total_visible_posts'] - $start - $limit;
        $firstIndex = $limit - 1;
    }
    if (!isset($_REQUEST['perma'])) {
        // Get each post and poster in this topic.
        $request = smf_db_query('
			SELECT id_msg, id_member, approved
			FROM {db_prefix}messages
			WHERE id_topic = {int:current_topic}' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : (!empty($modSettings['db_mysql_group_by_fix']) ? '' : '
			GROUP BY id_msg') . '
			HAVING (approved = {int:is_approved}' . ($user_info['is_guest'] ? '' : ' OR id_member = {int:current_member}') . ')') . '
			ORDER BY id_msg ' . ($ascending ? '' : 'DESC') . ($context['messages_per_page'] == -1 ? '' : '
			LIMIT ' . $start . ', ' . $limit), array('current_member' => $user_info['id'], 'current_topic' => $topic, 'is_approved' => 1, 'blank_id_member' => 0));
        $messages = array();
        $all_posters = array();
        while ($row = mysql_fetch_assoc($request)) {
            if (!empty($row['id_member'])) {
                $all_posters[$row['id_msg']] = $row['id_member'];
            }
            $messages[] = $row['id_msg'];
        }
        mysql_free_result($request);
        $posters[$context['topic_first_message']] = $context['topic_starter_id'];
        $posters = array_unique($all_posters);
    } else {
        $request = smf_db_query('
			SELECT id_member, approved
			FROM {db_prefix}messages
			WHERE id_msg = {int:id_msg}', array('id_msg' => $virtual_msg));
        list($id_member, $approved) = mysql_fetch_row($request);
        mysql_free_result($request);
        EoS_Smarty::loadTemplate('topic/topic_singlepost');
        //loadTemplate('DisplaySingle');
        $context['sub_template'] = isset($_REQUEST['xml']) ? 'single_post_xml' : 'single_post';
        if (isset($_REQUEST['xml'])) {
            $context['template_layers'] = array();
            header('Content-Type: text/xml; charset=UTF-8');
        }
        $messages = array($virtual_msg);
        $posters[$virtual_msg] = $id_member;
    }
    // Guests can't mark topics read or for notifications, just can't sorry.
    if (!$user_info['is_guest']) {
        $mark_at_msg = max($messages);
        if ($mark_at_msg >= $topicinfo['id_last_msg']) {
            $mark_at_msg = $modSettings['maxMsgID'];
        }
        if ($mark_at_msg >= $topicinfo['new_from']) {
            smf_db_insert($topicinfo['new_from'] == 0 ? 'ignore' : 'replace', '{db_prefix}log_topics', array('id_member' => 'int', 'id_topic' => 'int', 'id_msg' => 'int'), array($user_info['id'], $topic, $mark_at_msg), array('id_member', 'id_topic'));
        }
        // Check for notifications on this topic OR board.
        $request = smf_db_query('
			SELECT sent, id_topic
			FROM {db_prefix}log_notify
			WHERE (id_topic = {int:current_topic} OR id_board = {int:current_board})
				AND id_member = {int:current_member}
			LIMIT 2', array('current_board' => $board, 'current_member' => $user_info['id'], 'current_topic' => $topic));
        $do_once = true;
        while ($row = mysql_fetch_assoc($request)) {
            // Find if this topic is marked for notification...
            if (!empty($row['id_topic'])) {
                $context['is_marked_notify'] = true;
            }
            // Only do this once, but mark the notifications as "not sent yet" for next time.
            if (!empty($row['sent']) && $do_once) {
                smf_db_query('
					UPDATE {db_prefix}log_notify
					SET sent = {int:is_not_sent}
					WHERE (id_topic = {int:current_topic} OR id_board = {int:current_board})
						AND id_member = {int:current_member}', array('current_board' => $board, 'current_member' => $user_info['id'], 'current_topic' => $topic, 'is_not_sent' => 0));
                $do_once = false;
            }
        }
        // Have we recently cached the number of new topics in this board, and it's still a lot?
        if (isset($_REQUEST['topicseen']) && isset($_SESSION['topicseen_cache'][$board]) && $_SESSION['topicseen_cache'][$board] > 5) {
            $_SESSION['topicseen_cache'][$board]--;
        } elseif (isset($_REQUEST['topicseen'])) {
            // Use the mark read tables... and the last visit to figure out if this should be read or not.
            $request = smf_db_query('
				SELECT COUNT(*)
				FROM {db_prefix}topics AS t
					LEFT JOIN {db_prefix}log_boards AS lb ON (lb.id_board = {int:current_board} AND lb.id_member = {int:current_member})
					LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member})
				WHERE t.id_board = {int:current_board}
					AND t.id_last_msg > IFNULL(lb.id_msg, 0)
					AND t.id_last_msg > IFNULL(lt.id_msg, 0)' . (empty($_SESSION['id_msg_last_visit']) ? '' : '
					AND t.id_last_msg > {int:id_msg_last_visit}'), array('current_board' => $board, 'current_member' => $user_info['id'], 'id_msg_last_visit' => (int) $_SESSION['id_msg_last_visit']));
            list($numNewTopics) = mysql_fetch_row($request);
            mysql_free_result($request);
            // If there're no real new topics in this board, mark the board as seen.
            if (empty($numNewTopics)) {
                $_REQUEST['boardseen'] = true;
            } else {
                $_SESSION['topicseen_cache'][$board] = $numNewTopics;
            }
        } elseif (isset($_SESSION['topicseen_cache'][$board])) {
            $_SESSION['topicseen_cache'][$board]--;
        }
        // Mark board as seen if we came using last post link from BoardIndex. (or other places...)
        if (isset($_REQUEST['boardseen'])) {
            smf_db_insert('replace', '{db_prefix}log_boards', array('id_msg' => 'int', 'id_member' => 'int', 'id_board' => 'int'), array($modSettings['maxMsgID'], $user_info['id'], $board), array('id_member', 'id_board'));
        }
    }
    $attachments = array();
    // deal with possible sticky posts and different postbit layouts for
    // the first post
    // topic.id_layout meanings: bit 0-6 > layout id, bit 7 > first post sticky on every page.
    // don't blame me for using bit magic here. I'm a C guy and a 8bits can store more than just one bool :P
    $layout = (int) ($topicinfo['id_layout'] & 0x7f);
    $postbit_classes =& EoS_Smarty::getConfigInstance()->getPostbitClasses();
    // set defaults...
    $context['postbit_callbacks'] = array('firstpost' => 'template_postbit_normal', 'post' => 'template_postbit_normal');
    $context['postbit_template_class'] = array('firstpost' => $postbit_classes['normal'], 'post' => $postbit_classes['normal']);
    if ($topicinfo['id_layout']) {
        $this_start = isset($_REQUEST['perma']) ? 0 : (int) $_REQUEST['start'];
        if ((int) $topicinfo['id_layout'] & 0x80) {
            if ($this_start > 0) {
                array_unshift($messages, intval($topicinfo['id_first_msg']));
            }
            $context['postbit_callbacks']['firstpost'] = $layout == 0 ? 'template_postbit_normal' : ($layout == 2 ? 'template_postbit_clean' : 'template_postbit_lean');
            $context['postbit_callbacks']['post'] = $layout == 2 ? 'template_postbit_comment' : 'template_postbit_normal';
            $context['postbit_template_class']['firstpost'] = $layout == 0 ? $postbit_classes['normal'] : ($layout == 2 ? $postbit_classes['article'] : $postbit_classes['lean']);
            $context['postbit_template_class']['post'] = $layout == 2 ? $postbit_classes['commentstyle'] : $postbit_classes['normal'];
        } elseif ($layout) {
            $context['postbit_callbacks']['firstpost'] = $layout == 0 || $this_start != 0 ? 'template_postbit_normal' : ($layout == 2 ? 'template_postbit_clean' : 'template_postbit_lean');
            $context['postbit_callbacks']['post'] = $layout == 2 ? 'template_postbit_comment' : 'template_postbit_normal';
            $context['postbit_template_class']['firstpost'] = $layout == 0 || $this_start != 0 ? $postbit_classes['normal'] : ($layout == 2 ? $postbit_classes['article'] : $postbit_classes['lean']);
            $context['postbit_template_class']['post'] = $layout == 2 ? $postbit_classes['commentstyle'] : $postbit_classes['normal'];
        }
    }
    // now we know which display template we need
    if (!isset($_REQUEST['perma'])) {
        EoS_Smarty::loadTemplate($layout > 1 ? 'topic/topic_page' : 'topic/topic');
    }
    /*
    if($user_info['is_admin']) {
    	EoS_Smarty::init();
    	if(!isset($_REQUEST['perma']))
    		EoS_Smarty::loadTemplate($layout > 1 ? 'topic_page' : 'topic');
    }
    else {
    	if(!isset($_REQUEST['perma']))
    		loadTemplate($layout > 1 ? 'DisplayPage' : 'Display');
    	loadTemplate('Postbit');
    }
    */
    // If there _are_ messages here... (probably an error otherwise :!)
    if (!empty($messages)) {
        // Fetch attachments.
        if (!empty($modSettings['attachmentEnable']) && allowedTo('view_attachments')) {
            $request = smf_db_query('
				SELECT
					a.id_attach, a.id_folder, a.id_msg, a.filename, a.file_hash, IFNULL(a.size, 0) AS filesize, a.downloads, a.approved,
					a.width, a.height' . (empty($modSettings['attachmentShowImages']) || empty($modSettings['attachmentThumbnails']) ? '' : ',
					IFNULL(thumb.id_attach, 0) AS id_thumb, thumb.width AS thumb_width, thumb.height AS thumb_height') . '
				FROM {db_prefix}attachments AS a' . (empty($modSettings['attachmentShowImages']) || empty($modSettings['attachmentThumbnails']) ? '' : '
					LEFT JOIN {db_prefix}attachments AS thumb ON (thumb.id_attach = a.id_thumb)') . '
				WHERE a.id_msg IN ({array_int:message_list})
					AND a.attachment_type = {int:attachment_type}', array('message_list' => $messages, 'attachment_type' => 0, 'is_approved' => 1));
            $temp = array();
            while ($row = mysql_fetch_assoc($request)) {
                if (!$row['approved'] && $modSettings['postmod_active'] && !allowedTo('approve_posts') && (!isset($all_posters[$row['id_msg']]) || $all_posters[$row['id_msg']] != $user_info['id'])) {
                    continue;
                }
                $temp[$row['id_attach']] = $row;
                if (!isset($attachments[$row['id_msg']])) {
                    $attachments[$row['id_msg']] = array();
                }
            }
            mysql_free_result($request);
            // This is better than sorting it with the query...
            ksort($temp);
            foreach ($temp as $row) {
                $attachments[$row['id_msg']][] = $row;
            }
        }
        // What?  It's not like it *couldn't* be only guests in this topic...
        if (!isset($posters[$context['topic_starter_id']])) {
            $posters[] = $context['topic_starter_id'];
        }
        if (!empty($posters)) {
            loadMemberData($posters);
        }
        if (!isset($user_profile[$context['topic_starter_id']])) {
            $context['topicstarter']['name'] = $topicinfo['poster_name'];
            $context['topicstarter']['id'] = 0;
            $context['topicstarter']['group'] = $txt['guest_title'];
            $context['topicstarter']['link'] = $topicinfo['poster_name'];
            $context['topicstarter']['email'] = $topicinfo['poster_email'];
            $context['topicstarter']['show_email'] = showEmailAddress(true, 0);
            $context['topicstarter']['is_guest'] = true;
            $context['topicstarter']['avatar'] = array();
        } else {
            loadMemberContext($context['topic_starter_id'], true);
            $context['topicstarter'] =& $memberContext[$context['topic_starter_id']];
        }
        $context['topicstarter']['start_time'] = timeformat($topicinfo['first_post_time']);
        $sql_what = '
			m.id_msg, m.icon, m.subject, m.poster_time, m.poster_ip, m.id_member, m.modified_time, m.modified_name, m.body, mc.body AS cached_body,
			m.smileys_enabled, m.poster_name, m.poster_email, m.approved, m.locked,' . (!empty($modSettings['karmaMode']) ? 'c.likes_count, c.like_status, c.updated AS like_updated, l.rtype AS liked,' : '0 AS likes_count, 0 AS like_status, 0 AS like_updated, 0 AS liked,') . '
			m.id_msg_modified < {int:new_from} AS is_read';
        $sql_from_tables = '
			FROM {db_prefix}messages AS m';
        $sql_from_joins = (!empty($modSettings['karmaMode']) ? '
			LEFT JOIN {db_prefix}likes AS l ON (l.id_msg = m.id_msg AND l.ctype = 1 AND l.id_user = {int:id_user})
			LEFT JOIN {db_prefix}like_cache AS c ON (c.id_msg = m.id_msg AND c.ctype = 1)' : '') . '
			LEFT JOIN {db_prefix}messages_cache AS mc on mc.id_msg = m.id_msg AND mc.style = {int:style} AND mc.lang = {int:lang}';
        $sql_array = array('message_list' => $messages, 'new_from' => $topicinfo['new_from'], 'style' => $user_info['smiley_set_id'], 'lang' => $user_info['language_id'], 'id_user' => $user_info['id']);
        HookAPI::callHook('display_messagerequest', array(&$sql_what, &$sql_from_tables, &$sql_from_joins, &$sql_array));
        $messages_request = smf_db_query('
			SELECT ' . $sql_what . ' ' . $sql_from_tables . $sql_from_joins . '
			WHERE m.id_msg IN ({array_int:message_list})
			ORDER BY m.id_msg' . (empty($options['view_newest_first']) ? '' : ' DESC'), $sql_array);
        // Go to the last message if the given time is beyond the time of the last message.
        if (isset($context['start_from']) && $context['start_from'] >= $topicinfo['num_replies']) {
            $context['start_from'] = $topicinfo['num_replies'];
        }
        // Since the anchor information is needed on the top of the page we load these variables beforehand.
        $context['first_message'] = isset($messages[$firstIndex]) ? $messages[$firstIndex] : $messages[0];
        if (empty($options['view_newest_first'])) {
            $context['first_new_message'] = isset($context['start_from']) && $_REQUEST['start'] == $context['start_from'];
        } else {
            $context['first_new_message'] = isset($context['start_from']) && $_REQUEST['start'] == $topicinfo['num_replies'] - $context['start_from'];
        }
    } else {
        $messages_request = false;
        $context['first_message'] = 0;
        $context['first_new_message'] = false;
    }
    $context['jump_to'] = array('label' => addslashes(un_htmlspecialchars($txt['jump_to'])), 'board_name' => htmlspecialchars(strtr(strip_tags($board_info['name']), array('&amp;' => '&'))), 'child_level' => $board_info['child_level']);
    // Set the callback.  (do you REALIZE how much memory all the messages would take?!?)
    $context['get_message'] = 'prepareDisplayContext';
    // Now set all the wonderful, wonderful permissions... like moderation ones...
    $common_permissions = array('can_approve' => 'approve_posts', 'can_ban' => 'manage_bans', 'can_sticky' => 'make_sticky', 'can_merge' => 'merge_any', 'can_split' => 'split_any', 'calendar_post' => 'calendar_post', 'can_mark_notify' => 'mark_any_notify', 'can_send_topic' => 'send_topic', 'can_send_pm' => 'pm_send', 'can_report_moderator' => 'report_any', 'can_moderate_forum' => 'moderate_forum', 'can_issue_warning' => 'issue_warning', 'can_restore_topic' => 'move_any', 'can_restore_msg' => 'move_any');
    foreach ($common_permissions as $contextual => $perm) {
        $context[$contextual] = allowedTo($perm);
    }
    // Permissions with _any/_own versions.  $context[YYY] => ZZZ_any/_own.
    $anyown_permissions = array('can_move' => 'move', 'can_lock' => 'lock', 'can_delete' => 'remove', 'can_add_poll' => 'poll_add', 'can_remove_poll' => 'poll_remove', 'can_reply' => 'post_reply', 'can_reply_unapproved' => 'post_unapproved_replies');
    foreach ($anyown_permissions as $contextual => $perm) {
        $context[$contextual] = allowedTo($perm . '_any') || $context['user']['started'] && allowedTo($perm . '_own');
    }
    $context['can_add_tags'] = $context['user']['started'] && allowedTo('smftags_add') || allowedTo('smftags_manage');
    $context['can_delete_tags'] = $context['user']['started'] && allowedTo('smftags_del') || allowedTo('smftags_manage');
    $context['can_moderate_board'] = allowedTo('moderate_board');
    $context['can_modify_any'] = allowedTo('modify_any');
    $context['can_modify_replies'] = allowedTo('modify_replies');
    $context['can_modify_own'] = allowedTo('modify_own');
    $context['can_delete_any'] = allowedTo('delete_any');
    $context['can_delete_replies'] = allowedTo('delete_replies');
    $context['can_delete_own'] = allowedTo('delete_own');
    $context['use_share'] = !$user_info['possibly_robot'] && allowedTo('use_share') && ($context['user']['is_guest'] || (empty($options['use_share_bar']) ? 1 : !$options['use_share_bar']));
    $context['can_unapprove'] = $context['can_approve'] && !empty($modSettings['postmod_active']);
    $context['can_profile_view_any'] = allowedTo('profile_view_any');
    $context['can_profile_view_own'] = allowedTo('profile_view_own');
    $context['is_banned_from_topic'] = !$user_info['is_admin'] && !$context['can_moderate_forum'] && !$context['can_moderate_board'] && (!empty($context['topic_banned_members']) ? in_array($user_info['id'], $context['topic_banned_members']) : false);
    $context['banned_notice'] = $context['is_banned_from_topic'] ? $txt['topic_banned_notice'] : '';
    // Cleanup all the permissions with extra stuff...
    $context['can_mark_notify'] &= !$context['user']['is_guest'];
    $context['can_sticky'] &= !empty($modSettings['enableStickyTopics']);
    $context['calendar_post'] &= !empty($modSettings['cal_enabled']);
    $context['can_add_poll'] &= $modSettings['pollMode'] == '1' && $topicinfo['id_poll'] <= 0;
    $context['can_remove_poll'] &= $modSettings['pollMode'] == '1' && $topicinfo['id_poll'] > 0;
    $context['can_reply'] &= empty($topicinfo['locked']) || allowedTo('moderate_board');
    $context['can_reply_unapproved'] &= $modSettings['postmod_active'] && (empty($topicinfo['locked']) || allowedTo('moderate_board'));
    $context['can_issue_warning'] &= in_array('w', $context['admin_features']) && $modSettings['warning_settings'][0] == 1;
    // Handle approval flags...
    $context['can_reply_approved'] = $context['can_reply'];
    $context['can_reply'] |= $context['can_reply_unapproved'];
    $context['can_quote'] = $context['can_reply'] && (empty($modSettings['disabledBBC']) || !in_array('quote', explode(',', $modSettings['disabledBBC'])));
    $context['can_mark_unread'] = !$user_info['is_guest'] && $settings['show_mark_read'];
    $context['can_send_topic'] = (!$modSettings['postmod_active'] || $topicinfo['approved']) && allowedTo('send_topic');
    // Start this off for quick moderation - it will be or'd for each post.
    $context['can_remove_post'] = allowedTo('delete_any') || allowedTo('delete_replies') && $context['user']['started'];
    // Can restore topic?  That's if the topic is in the recycle board and has a previous restore state.
    $context['can_restore_topic'] &= !empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] == $board && !empty($topicinfo['id_previous_board']);
    $context['can_restore_msg'] &= !empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] == $board && !empty($topicinfo['id_previous_topic']);
    if ($context['is_banned_from_topic']) {
        $context['can_add_tags'] = $context['can_delete_tags'] = $context['can_modify_any'] = $context['can_modify_replies'] = $context['can_modify_own'] = $context['can_delete_any'] = $context['can_delete_replies'] = $context['can_delete_own'] = $context['can_lock'] = $context['can_sticky'] = $context['calendar_post'] = $context['can_add_poll'] = $context['can_remove_poll'] = $context['can_reply'] = $context['can_reply_unapproved'] = $context['can_quote'] = $context['can_remove_post'] = false;
    }
    // Load up the "double post" sequencing magic.
    if (!empty($options['display_quick_reply'])) {
        checkSubmitOnce('register');
        $context['name'] = isset($_SESSION['guest_name']) ? $_SESSION['guest_name'] : '';
        $context['email'] = isset($_SESSION['guest_email']) ? $_SESSION['guest_email'] : '';
    }
    // todo: drafts -> plugin
    $context['can_save_draft'] = false;
    //$context['can_reply'] && !$context['user']['is_guest'] && in_array('dr', $context['admin_features']) && !empty($options['use_drafts']) && allowedTo('drafts_allow');
    $context['can_autosave_draft'] = false;
    //$context['can_save_draft'] && !empty($modSettings['enableAutoSaveDrafts']) && allowedTo('drafts_autosave_allow');
    enqueueThemeScript('topic', 'scripts/topic.js', true);
    if ($context['can_autosave_draft']) {
        enqueueThemeScript('drafts', 'scripts/drafts.js', true);
    }
    $context['can_moderate_member'] = $context['can_issue_warning'] || $context['can_moderate_board'];
    $context['topic_has_banned_members_msg'] = $context['topic_banned_members_count'] > 0 && $context['can_moderate_board'] ? sprintf($txt['topic_has_bans_msg'], URL::parse('?action=moderate;area=topicbans;sa=bytopic;t=' . $topic)) : '';
    if (EoS_Smarty::isActive()) {
        if (isset($context['poll'])) {
            $context['poll_buttons'] = array('vote' => array('test' => 'allow_return_vote', 'text' => 'poll_return_vote', 'image' => 'poll_options.gif', 'lang' => true, 'url' => $scripturl . '?topic=' . $context['current_topic'] . '.' . $context['start']), 'results' => array('test' => 'show_view_results_button', 'text' => 'poll_results', 'image' => 'poll_results.gif', 'lang' => true, 'url' => $scripturl . '?topic=' . $context['current_topic'] . '.' . $context['start'] . ';viewresults'), 'change_vote' => array('test' => 'allow_change_vote', 'text' => 'poll_change_vote', 'image' => 'poll_change_vote.gif', 'lang' => true, 'url' => $scripturl . '?action=vote;topic=' . $context['current_topic'] . '.' . $context['start'] . ';poll=' . $context['poll']['id'] . ';' . $context['session_var'] . '=' . $context['session_id']), 'lock' => array('test' => 'allow_lock_poll', 'text' => !$context['poll']['is_locked'] ? 'poll_lock' : 'poll_unlock', 'image' => 'poll_lock.gif', 'lang' => true, 'url' => $scripturl . '?action=lockvoting;topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']), 'edit' => array('test' => 'allow_edit_poll', 'text' => 'poll_edit', 'image' => 'poll_edit.gif', 'lang' => true, 'url' => $scripturl . '?action=editpoll;topic=' . $context['current_topic'] . '.' . $context['start']), 'remove_poll' => array('test' => 'can_remove_poll', 'text' => 'poll_remove', 'image' => 'admin_remove_poll.gif', 'lang' => true, 'custom' => 'onclick="return Eos_Confirm(\'\', \'' . $txt['poll_remove_warn'] . '\', $(this).attr(\'href\'));"', 'url' => $scripturl . '?action=removepoll;topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']));
        }
        $context['normal_buttons'] = array('reply' => array('test' => 'can_reply', 'text' => 'reply', 'custom' => 'onclick="return oQuickReply.quote(0);" ', 'image' => 'reply.gif', 'lang' => true, 'url' => $scripturl . '?action=post;topic=' . $context['current_topic'] . '.' . $context['start'] . ';last_msg=' . $context['topic_last_message'], 'active' => true), 'add_poll' => array('test' => 'can_add_poll', 'text' => 'add_poll', 'image' => 'add_poll.gif', 'lang' => true, 'url' => $scripturl . '?action=editpoll;add;topic=' . $context['current_topic'] . '.' . $context['start']), 'mark_unread' => array('test' => 'can_mark_unread', 'text' => 'mark_unread', 'image' => 'markunread.gif', 'lang' => true, 'url' => $scripturl . '?action=markasread;sa=topic;t=' . $context['mark_unread_time'] . ';topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']));
        HookAPI::callHook('integrate_display_buttons', array(&$context['normal_buttons']));
        $remove_url = $scripturl . '?action=removetopic2;topic=' . $context['current_topic'] . '.0;' . $context['session_var'] . '=' . $context['session_id'];
        $context['mod_buttons'] = array('move' => array('test' => 'can_move', 'text' => 'move_topic', 'image' => 'admin_move.gif', 'lang' => true, 'url' => $scripturl . '?action=movetopic;topic=' . $context['current_topic'] . '.0'), 'delete' => array('test' => 'can_delete', 'text' => 'remove_topic', 'image' => 'admin_rem.gif', 'lang' => true, 'custom' => 'onclick="return Eos_Confirm(\'\',\'' . $txt['are_sure_remove_topic'] . '\',\'' . $remove_url . '\');"', 'url' => $remove_url), 'lock' => array('test' => 'can_lock', 'text' => empty($context['is_locked']) ? 'set_lock' : 'set_unlock', 'image' => 'admin_lock.gif', 'lang' => true, 'url' => $scripturl . '?action=lock;topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']), 'sticky' => array('test' => 'can_sticky', 'text' => empty($context['is_sticky']) ? 'set_sticky' : 'set_nonsticky', 'image' => 'admin_sticky.gif', 'lang' => true, 'url' => $scripturl . '?action=sticky;topic=' . $context['current_topic'] . '.' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id']), 'merge' => array('test' => 'can_merge', 'text' => 'merge', 'image' => 'merge.gif', 'lang' => true, 'url' => $scripturl . '?action=mergetopics;board=' . $context['current_board'] . '.0;from=' . $context['current_topic']), 'calendar' => array('test' => 'calendar_post', 'text' => 'calendar_link', 'image' => 'linktocal.gif', 'lang' => true, 'url' => $scripturl . '?action=post;calendar;msg=' . $context['topic_first_message'] . ';topic=' . $context['current_topic'] . '.0'));
        // Restore topic. eh?  No monkey business.
        if ($context['can_restore_topic']) {
            $context['mod_buttons'][] = array('text' => 'restore_topic', 'image' => '', 'lang' => true, 'url' => $scripturl . '?action=restoretopic;topics=' . $context['current_topic'] . ';' . $context['session_var'] . '=' . $context['session_id']);
        }
        // Allow adding new mod buttons easily.
        HookAPI::callHook('integrate_mod_buttons', array(&$context['mod_buttons']));
        $context['message_ids'] = $messages;
        $context['perma_request'] = isset($_REQUEST['perma']) ? true : false;
        $context['mod_buttons_style'] = array('id' => 'moderationbuttons_strip', 'class' => 'buttonlist');
        $context['full_members_viewing_list'] = empty($context['view_members_list']) ? '0 ' . $txt['members'] : implode(', ', $context['view_members_list']) . (empty($context['view_num_hidden']) || $context['can_moderate_forum'] ? '' : ' (+ ' . $context['view_num_hidden'] . ' ' . $txt['hidden'] . ')');
    }
    fetchNewsItems($board, $topic);
    HookAPI::callHook('display_general', array());
    /*
     * $message is always available in templates as global variable
     * prepareDisplayContext() just repopulates it and is called from
     * the topic display template via $SUPPORT object callback.
     */
    EoS_Smarty::getSmartyInstance()->assignByRef('message', $output);
}
Exemplo n.º 13
0
function MembergroupMembers()
{
    global $txt, $scripturl, $context, $modSettings, $sourcedir, $user_info, $settings, $smcFunc;
    $_REQUEST['group'] = isset($_REQUEST['group']) ? (int) $_REQUEST['group'] : 0;
    // No browsing of guests, membergroup 0 or moderators.
    if (in_array($_REQUEST['group'], array(-1, 0, 3))) {
        fatal_lang_error('membergroup_does_not_exist', false);
    }
    // Load up the group details.
    $request = smf_db_query('
		SELECT id_group AS id, group_name AS name, CASE WHEN min_posts = {int:min_posts} THEN 1 ELSE 0 END AS assignable, hidden, online_color,
			stars, description, CASE WHEN min_posts != {int:min_posts} THEN 1 ELSE 0 END AS is_post_group, group_type
		FROM {db_prefix}membergroups
		WHERE id_group = {int:id_group}
		LIMIT 1', array('min_posts' => -1, 'id_group' => $_REQUEST['group']));
    // Doesn't exist?
    if (mysql_num_rows($request) == 0) {
        fatal_lang_error('membergroup_does_not_exist', false);
    }
    $context['group'] = mysql_fetch_assoc($request);
    mysql_free_result($request);
    // Fix the stars.
    $context['group']['stars'] = explode('#', $context['group']['stars']);
    $context['group']['stars'] = !empty($context['group']['stars'][0]) && !empty($context['group']['stars'][1]) ? str_repeat('<img src="' . $settings['images_url'] . '/' . $context['group']['stars'][1] . '" alt="*" />', $context['group']['stars'][0]) : '';
    $context['group']['can_moderate'] = allowedTo('manage_membergroups') && (allowedTo('admin_forum') || $context['group']['group_type'] != 1);
    $context['linktree'][] = array('url' => $scripturl . '?action=groups;sa=members;group=' . $context['group']['id'], 'name' => $context['group']['name']);
    // Load all the group moderators, for fun.
    $request = smf_db_query('
		SELECT mem.id_member, mem.real_name
		FROM {db_prefix}group_moderators AS mods
			INNER JOIN {db_prefix}members AS mem ON (mem.id_member = mods.id_member)
		WHERE mods.id_group = {int:id_group}', array('id_group' => $_REQUEST['group']));
    $context['group']['moderators'] = array();
    while ($row = mysql_fetch_assoc($request)) {
        $context['group']['moderators'][] = array('id' => $row['id_member'], 'name' => $row['real_name']);
        if ($user_info['id'] == $row['id_member'] && $context['group']['group_type'] != 1) {
            $context['group']['can_moderate'] = true;
        }
    }
    mysql_free_result($request);
    // If this group is hidden then it can only "exists" if the user can moderate it!
    if ($context['group']['hidden'] && !$context['group']['can_moderate']) {
        fatal_lang_error('membergroup_does_not_exist', false);
    }
    // You can only assign membership if you are the moderator and/or can manage groups!
    if (!$context['group']['can_moderate']) {
        $context['group']['assignable'] = 0;
    } elseif ($context['group']['id'] == 1 && !allowedTo('admin_forum')) {
        $context['group']['assignable'] = 0;
    }
    // Removing member from group?
    if (isset($_POST['remove']) && !empty($_REQUEST['rem']) && is_array($_REQUEST['rem']) && $context['group']['assignable']) {
        checkSession();
        // Make sure we're dealing with integers only.
        foreach ($_REQUEST['rem'] as $key => $group) {
            $_REQUEST['rem'][$key] = (int) $group;
        }
        require_once $sourcedir . '/lib/Subs-Membergroups.php';
        removeMembersFromGroups($_REQUEST['rem'], $_REQUEST['group'], true);
    } elseif (isset($_REQUEST['add']) && (!empty($_REQUEST['toAdd']) || !empty($_REQUEST['member_add'])) && $context['group']['assignable']) {
        checkSession();
        $member_query = array();
        $member_parameters = array();
        // Get all the members to be added... taking into account names can be quoted ;)
        $_REQUEST['toAdd'] = strtr(commonAPI::htmlspecialchars($_REQUEST['toAdd'], ENT_QUOTES), array('&quot;' => '"'));
        preg_match_all('~"([^"]+)"~', $_REQUEST['toAdd'], $matches);
        $member_names = array_unique(array_merge($matches[1], explode(',', preg_replace('~"[^"]+"~', '', $_REQUEST['toAdd']))));
        foreach ($member_names as $index => $member_name) {
            $member_names[$index] = trim(commonAPI::strtolower($member_names[$index]));
            if (strlen($member_names[$index]) == 0) {
                unset($member_names[$index]);
            }
        }
        // Any passed by ID?
        $member_ids = array();
        if (!empty($_REQUEST['member_add'])) {
            foreach ($_REQUEST['member_add'] as $id) {
                if ($id > 0) {
                    $member_ids[] = (int) $id;
                }
            }
        }
        // Construct the query pelements.
        if (!empty($member_ids)) {
            $member_query[] = 'id_member IN ({array_int:member_ids})';
            $member_parameters['member_ids'] = $member_ids;
        }
        if (!empty($member_names)) {
            $member_query[] = 'LOWER(member_name) IN ({array_string:member_names})';
            $member_query[] = 'LOWER(real_name) IN ({array_string:member_names})';
            $member_parameters['member_names'] = $member_names;
        }
        $members = array();
        if (!empty($member_query)) {
            $request = smf_db_query('
				SELECT id_member
				FROM {db_prefix}members
				WHERE (' . implode(' OR ', $member_query) . ')
					AND id_group != {int:id_group}
					AND FIND_IN_SET({int:id_group}, additional_groups) = 0', array_merge($member_parameters, array('id_group' => $_REQUEST['group'])));
            while ($row = mysql_fetch_assoc($request)) {
                $members[] = $row['id_member'];
            }
            mysql_free_result($request);
        }
        // !!! Add $_POST['additional'] to templates!
        // Do the updates...
        if (!empty($members)) {
            require_once $sourcedir . '/lib/Subs-Membergroups.php';
            addMembersToGroup($members, $_REQUEST['group'], isset($_POST['additional']) || $context['group']['hidden'] ? 'only_additional' : 'auto', true);
        }
    }
    // Sort out the sorting!
    $sort_methods = array('name' => 'real_name', 'email' => allowedTo('moderate_forum') ? 'email_address' : 'hide_email ' . (isset($_REQUEST['desc']) ? 'DESC' : 'ASC') . ', email_address', 'active' => 'last_login', 'registered' => 'date_registered', 'posts' => 'posts');
    // They didn't pick one, default to by name..
    if (!isset($_REQUEST['sort']) || !isset($sort_methods[$_REQUEST['sort']])) {
        $context['sort_by'] = 'name';
        $querySort = 'real_name';
    } else {
        $context['sort_by'] = $_REQUEST['sort'];
        $querySort = $sort_methods[$_REQUEST['sort']];
    }
    $context['sort_direction'] = isset($_REQUEST['desc']) ? 'down' : 'up';
    // The where on the query is interesting. Non-moderators should only see people who are in this group as primary.
    if ($context['group']['can_moderate']) {
        $where = $context['group']['is_post_group'] ? 'id_post_group = {int:group}' : 'id_group = {int:group} OR FIND_IN_SET({int:group}, additional_groups) != 0';
    } else {
        $where = $context['group']['is_post_group'] ? 'id_post_group = {int:group}' : 'id_group = {int:group}';
    }
    // Count members of the group.
    $request = smf_db_query('
		SELECT COUNT(*)
		FROM {db_prefix}members
		WHERE ' . $where, array('group' => $_REQUEST['group']));
    list($context['total_members']) = mysql_fetch_row($request);
    mysql_free_result($request);
    $context['total_members'] = comma_format($context['total_members']);
    // Create the page index.
    $context['page_index'] = constructPageIndex($scripturl . '?action=' . ($context['group']['can_moderate'] ? 'moderate;area=viewgroups' : 'groups') . ';sa=members;group=' . $_REQUEST['group'] . ';sort=' . $context['sort_by'] . (isset($_REQUEST['desc']) ? ';desc' : ''), $_REQUEST['start'], $context['total_members'], $modSettings['defaultMaxMembers']);
    $context['start'] = $_REQUEST['start'];
    $context['can_moderate_forum'] = allowedTo('moderate_forum');
    // Load up all members of this group.
    $request = smf_db_query('
		SELECT id_member, member_name, real_name, email_address, member_ip, date_registered, last_login,
			hide_email, posts, is_activated, real_name
		FROM {db_prefix}members
		WHERE ' . $where . '
		ORDER BY ' . $querySort . ' ' . ($context['sort_direction'] == 'down' ? 'DESC' : 'ASC') . '
		LIMIT ' . $context['start'] . ', ' . $modSettings['defaultMaxMembers'], array('group' => $_REQUEST['group']));
    $context['members'] = array();
    while ($row = mysql_fetch_assoc($request)) {
        $last_online = empty($row['last_login']) ? $txt['never'] : timeformat($row['last_login']);
        // Italicize the online note if they aren't activated.
        if ($row['is_activated'] % 10 != 1) {
            $last_online = '<em title="' . $txt['not_activated'] . '">' . $last_online . '</em>';
        }
        $context['members'][] = array('id' => $row['id_member'], 'name' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>', 'email' => $row['email_address'], 'show_email' => showEmailAddress(!empty($row['hide_email']), $row['id_member']), 'ip' => '<a href="' . $scripturl . '?action=trackip;searchip=' . $row['member_ip'] . '">' . $row['member_ip'] . '</a>', 'registered' => timeformat($row['date_registered']), 'last_online' => $last_online, 'posts' => comma_format($row['posts']), 'is_activated' => $row['is_activated'] % 10 == 1);
    }
    mysql_free_result($request);
    if (isset($_REQUEST['action']) && $_REQUEST['action'] === 'moderate') {
        EoS_Smarty::loadTemplate('modcenter/modcenter_base');
        EoS_Smarty::getConfigInstance()->registerHookTemplate('modcenter_content_area', 'admin/group_list_members');
    } else {
        $context['sub_template'] = 'group_members';
    }
    $context['page_title'] = $txt['membergroups_members_title'] . ': ' . $context['group']['name'];
}
Exemplo n.º 14
0
function MoveTopic2()
{
    global $txt, $board, $topic, $scripturl, $sourcedir, $modSettings, $context;
    global $board, $language, $user_info, $smcFunc;
    if (empty($topic)) {
        fatal_lang_error('no_access', false);
    }
    // You can't choose to have a redirection topic and use an empty reason.
    if (isset($_POST['postRedirect']) && (!isset($_POST['reason']) || trim($_POST['reason']) == '')) {
        fatal_lang_error('movetopic_no_reason', false);
    }
    // Make sure this form hasn't been submitted before.
    checkSubmitOnce('check');
    $request = smf_db_query('
		SELECT id_member_started, id_first_msg, approved
		FROM {db_prefix}topics
		WHERE id_topic = {int:current_topic}
		LIMIT 1', array('current_topic' => $topic));
    list($id_member_started, $id_first_msg, $context['is_approved']) = mysql_fetch_row($request);
    mysql_free_result($request);
    // Can they see it?
    if (!$context['is_approved']) {
        isAllowedTo('approve_posts');
    }
    // Can they move topics on this board?
    if (!allowedTo('move_any')) {
        if ($id_member_started == $user_info['id']) {
            isAllowedTo('move_own');
            $boards = array_merge(boardsAllowedTo('move_own'), boardsAllowedTo('move_any'));
        } else {
            isAllowedTo('move_any');
        }
    } else {
        $boards = boardsAllowedTo('move_any');
    }
    // If this topic isn't approved don't let them move it if they can't approve it!
    if ($modSettings['postmod_active'] && !$context['is_approved'] && !allowedTo('approve_posts')) {
        // Only allow them to move it to other boards they can't approve it in.
        $can_approve = boardsAllowedTo('approve_posts');
        $boards = array_intersect($boards, $can_approve);
    }
    checkSession();
    require_once $sourcedir . '/lib/Subs-Post.php';
    // The destination board must be numeric.
    $_POST['toboard'] = (int) $_POST['toboard'];
    // Make sure they can see the board they are trying to move to (and get whether posts count in the target board).
    $request = smf_db_query('
		SELECT b.count_posts, b.name, m.subject
		FROM {db_prefix}boards AS b
			INNER JOIN {db_prefix}topics AS t ON (t.id_topic = {int:current_topic})
			INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg)
		WHERE {query_see_board}
			AND b.id_board = {int:to_board}
			AND b.redirect = {string:blank_redirect}
		LIMIT 1', array('current_topic' => $topic, 'to_board' => $_POST['toboard'], 'blank_redirect' => ''));
    if (mysql_num_rows($request) == 0) {
        fatal_lang_error('no_board');
    }
    list($pcounter, $board_name, $subject) = mysql_fetch_row($request);
    mysql_free_result($request);
    // Remember this for later.
    $_SESSION['move_to_topic'] = $_POST['toboard'];
    // Rename the topic...
    if (isset($_POST['reset_subject'], $_POST['custom_subject']) && $_POST['custom_subject'] != '') {
        $_POST['custom_subject'] = strtr(commonAPI::htmltrim(commonAPI::htmlspecialchars($_POST['custom_subject'])), array("\r" => '', "\n" => '', "\t" => ''));
        // Keep checking the length.
        if (commonAPI::strlen($_POST['custom_subject']) > 100) {
            $_POST['custom_subject'] = commonAPI::substr($_POST['custom_subject'], 0, 100);
        }
        // If it's still valid move onwards and upwards.
        if ($_POST['custom_subject'] != '') {
            if (isset($_POST['enforce_subject'])) {
                // Get a response prefix, but in the forum's default language.
                if (!isset($context['response_prefix']) && !($context['response_prefix'] = CacheAPI::getCache('response_prefix'))) {
                    if ($language === $user_info['language']) {
                        $context['response_prefix'] = $txt['response_prefix'];
                    } else {
                        loadLanguage('index', $language, false);
                        $context['response_prefix'] = $txt['response_prefix'];
                        loadLanguage('index');
                    }
                    CacheAPI::putCache('response_prefix', $context['response_prefix'], 600);
                }
                smf_db_query('
					UPDATE {db_prefix}messages
					SET subject = {string:subject}
					WHERE id_topic = {int:current_topic}', array('current_topic' => $topic, 'subject' => $context['response_prefix'] . $_POST['custom_subject']));
            }
            smf_db_query('
				UPDATE {db_prefix}messages
				SET subject = {string:custom_subject}
				WHERE id_msg = {int:id_first_msg}', array('id_first_msg' => $id_first_msg, 'custom_subject' => $_POST['custom_subject']));
            // Fix the subject cache.
            updateStats('subject', $topic, $_POST['custom_subject']);
        }
    }
    // Create a link to this in the old board.
    //!!! Does this make sense if the topic was unapproved before? I'd just about say so.
    if (isset($_POST['postRedirect'])) {
        // Should be in the boardwide language.
        if ($user_info['language'] != $language) {
            loadLanguage('index', $language);
        }
        $_POST['reason'] = commonAPI::htmlspecialchars($_POST['reason'], ENT_QUOTES);
        preparsecode($_POST['reason']);
        // Add a URL onto the message.
        $_POST['reason'] = strtr($_POST['reason'], array($txt['movetopic_auto_board'] => '[url=' . $scripturl . '?board=' . $_POST['toboard'] . '.0]' . $board_name . '[/url]', $txt['movetopic_auto_topic'] => '[iurl]' . $scripturl . '?topic=' . $topic . '.0[/iurl]'));
        $msgOptions = array('subject' => $txt['moved'] . ': ' . $subject, 'body' => $_POST['reason'], 'icon' => 'moved', 'smileys_enabled' => 1);
        $topicOptions = array('board' => $board, 'lock_mode' => 1, 'mark_as_read' => true, 'topic_prefix' => 0, 'topic_layout' => 0);
        $posterOptions = array('id' => $user_info['id'], 'update_post_count' => empty($pcounter));
        createPost($msgOptions, $topicOptions, $posterOptions);
    }
    $request = smf_db_query('
		SELECT count_posts
		FROM {db_prefix}boards
		WHERE id_board = {int:current_board}
		LIMIT 1', array('current_board' => $board));
    list($pcounter_from) = mysql_fetch_row($request);
    mysql_free_result($request);
    if ($pcounter_from != $pcounter) {
        $request = smf_db_query('
			SELECT id_member
			FROM {db_prefix}messages
			WHERE id_topic = {int:current_topic}
				AND approved = {int:is_approved}', array('current_topic' => $topic, 'is_approved' => 1));
        $posters = array();
        while ($row = mysql_fetch_assoc($request)) {
            if (!isset($posters[$row['id_member']])) {
                $posters[$row['id_member']] = 0;
            }
            $posters[$row['id_member']]++;
        }
        mysql_free_result($request);
        foreach ($posters as $id_member => $posts) {
            // The board we're moving from counted posts, but not to.
            if (empty($pcounter_from)) {
                updateMemberData($id_member, array('posts' => 'posts - ' . $posts));
            } else {
                updateMemberData($id_member, array('posts' => 'posts + ' . $posts));
            }
        }
    }
    // Do the move (includes statistics update needed for the redirect topic).
    moveTopics($topic, $_POST['toboard']);
    // Log that they moved this topic.
    if (!allowedTo('move_own') || $id_member_started != $user_info['id']) {
        logAction('move', array('topic' => $topic, 'board_from' => $board, 'board_to' => $_POST['toboard']));
    }
    // Notify people that this topic has been moved?
    sendNotifications($topic, 'move');
    // Why not go back to the original board in case they want to keep moving?
    if (!isset($_REQUEST['goback'])) {
        redirectexit('board=' . $board . '.0');
    } else {
        redirectexit('topic=' . $topic . '.0');
    }
}
Exemplo n.º 15
0
 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;
     }
 }
Exemplo n.º 16
0
function AdminSearch()
{
    global $txt, $context, $sourcedir, $backend_subdir;
    isAllowedTo('admin_forum');
    // What can we search for?
    $subactions = array('internal' => 'AdminSearchInternal', 'online' => 'AdminSearchOM', 'member' => 'AdminSearchMember');
    $context['search_type'] = !isset($_REQUEST['search_type']) || !isset($subactions[$_REQUEST['search_type']]) ? 'internal' : $_REQUEST['search_type'];
    $context['search_term'] = isset($_REQUEST['search_term']) ? commonAPI::htmlspecialchars($_REQUEST['search_term'], ENT_QUOTES) : '';
    $context['sub_template'] = 'admin_search_results';
    $context['page_title'] = $txt['admin_search_results'];
    // Keep track of what the admin wants.
    if (empty($context['admin_preferences']['sb']) || $context['admin_preferences']['sb'] != $context['search_type']) {
        $context['admin_preferences']['sb'] = $context['search_type'];
        // Update the preferences.
        require_once $sourcedir . '/lib/Subs-Admin.php';
        updateAdminPreferences();
    }
    if (trim($context['search_term']) == '') {
        $context['search_results'] = array();
    } else {
        $subactions[$context['search_type']]();
    }
}
Exemplo n.º 17
0
function RegisterCheckUsername()
{
    global $sourcedir, $context, $txt;
    // This is XML!
    loadTemplate('Xml');
    $context['sub_template'] = 'check_username';
    $context['checked_username'] = isset($_GET['username']) ? $_GET['username'] : '';
    $context['valid_username'] = true;
    // Clean it up like mother would.
    $context['checked_username'] = preg_replace('~[\\t\\n\\r\\x0B\\0' . ($context['server']['complex_preg_chars'] ? '\\x{A0}' : " ") . ']+~u', ' ', $context['checked_username']);
    if (commonAPI::strlen($context['checked_username']) > 25) {
        $context['checked_username'] = commonAPI::htmltrim(commonAPI::substr($context['checked_username'], 0, 25));
    }
    // Only these characters are permitted.
    if (preg_match('~[<>&"\'=\\\\]~', preg_replace('~&#(?:\\d{1,7}|x[0-9a-fA-F]{1,6});~', '', $context['checked_username'])) != 0 || $context['checked_username'] == '_' || $context['checked_username'] == '|' || strpos($context['checked_username'], '[code') !== false || strpos($context['checked_username'], '[/code') !== false) {
        $context['valid_username'] = false;
    }
    if (stristr($context['checked_username'], $txt['guest_title']) !== false) {
        $context['valid_username'] = false;
    }
    if (trim($context['checked_username']) == '') {
        $context['valid_username'] = false;
    } else {
        require_once $sourcedir . '/lib/Subs-Members.php';
        $context['valid_username'] &= isReservedName($context['checked_username'], 0, false, false) ? 0 : 1;
    }
}
Exemplo n.º 18
0
function ssi_boardNews($board = null, $limit = null, $start = null, $length = null, $output_method = 'echo')
{
    global $scripturl, $db_prefix, $txt, $settings, $modSettings, $context;
    global $smcFunc;
    loadLanguage('Stats');
    // Must be integers....
    if ($limit === null) {
        $limit = isset($_GET['limit']) ? (int) $_GET['limit'] : 5;
    } else {
        $limit = (int) $limit;
    }
    if ($start === null) {
        $start = isset($_GET['start']) ? (int) $_GET['start'] : 0;
    } else {
        $start = (int) $start;
    }
    if ($board !== null) {
        $board = (int) $board;
    } elseif (isset($_GET['board'])) {
        $board = (int) $_GET['board'];
    }
    if ($length === null) {
        $length = isset($_GET['length']) ? (int) $_GET['length'] : 0;
    } else {
        $length = (int) $length;
    }
    $limit = max(0, $limit);
    $start = max(0, $start);
    // Make sure guests can see this board.
    $request = $smcFunc['db_query']('', '
		SELECT id_board
		FROM {db_prefix}boards
		WHERE ' . ($board === null ? '' : 'id_board = {int:current_board}
			AND ') . 'FIND_IN_SET(-1, member_groups)
		LIMIT 1', array('current_board' => $board));
    if ($smcFunc['db_num_rows']($request) == 0) {
        if ($output_method == 'echo') {
            die($txt['ssi_no_guests']);
        } else {
            return array();
        }
    }
    list($board) = $smcFunc['db_fetch_row']($request);
    $smcFunc['db_free_result']($request);
    // Load the message icons - the usual suspects.
    $stable_icons = array('xx', 'thumbup', 'thumbdown', 'exclamation', 'question', 'lamp', 'smiley', 'angry', 'cheesy', 'grin', 'sad', 'wink', 'moved', 'recycled', 'wireless');
    $icon_sources = array();
    foreach ($stable_icons as $icon) {
        $icon_sources[$icon] = 'images_url';
    }
    // Find the post ids.
    $request = $smcFunc['db_query']('', '
		SELECT id_first_msg
		FROM {db_prefix}topics
		WHERE id_board = {int:current_board}' . ($modSettings['postmod_active'] ? '
			AND approved = {int:is_approved}' : '') . '
		ORDER BY id_first_msg DESC
		LIMIT ' . $start . ', ' . $limit, array('current_board' => $board, 'is_approved' => 1));
    $posts = array();
    while ($row = $smcFunc['db_fetch_assoc']($request)) {
        $posts[] = $row['id_first_msg'];
    }
    $smcFunc['db_free_result']($request);
    if (empty($posts)) {
        return array();
    }
    // Find the posts.
    $request = $smcFunc['db_query']('', '
		SELECT
			m.icon, m.subject, m.body, IFNULL(mem.real_name, m.poster_name) AS poster_name, m.poster_time,
			t.num_replies, t.id_topic, m.id_member, m.smileys_enabled, m.id_msg, t.locked, t.id_last_msg
		FROM {db_prefix}topics AS t
			INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg)
			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)
		WHERE t.id_first_msg IN ({array_int:post_list})
		ORDER BY t.id_first_msg DESC
		LIMIT ' . count($posts), array('post_list' => $posts));
    $return = array();
    while ($row = $smcFunc['db_fetch_assoc']($request)) {
        // If we want to limit the length of the post.
        if (!empty($length) && commonAPI::strlen($row['body']) > $length) {
            $row['body'] = commonAPI::substr($row['body'], 0, $length);
            // The first space or line break. (<br />, etc.)
            $cutoff = max(strrpos($row['body'], ' '), strrpos($row['body'], '<'));
            if ($cutoff !== false) {
                $row['body'] = commonAPI::substr($row['body'], 0, $cutoff);
            }
            $row['body'] .= '...';
        }
        $row['body'] = parse_bbc($row['body'], $row['smileys_enabled'], $row['id_msg']);
        // Check that this message icon is there...
        if (empty($modSettings['messageIconChecks_disable']) && !isset($icon_sources[$row['icon']])) {
            $icon_sources[$row['icon']] = file_exists($settings['theme_dir'] . '/images/post/' . $row['icon'] . '.gif') ? 'images_url' : 'default_images_url';
        }
        censorText($row['subject']);
        censorText($row['body']);
        $return[] = array('id' => $row['id_topic'], 'message_id' => $row['id_msg'], 'icon' => '<img src="' . $settings[$icon_sources[$row['icon']]] . '/post/' . $row['icon'] . '.gif" alt="' . $row['icon'] . '" />', 'subject' => $row['subject'], 'time' => timeformat($row['poster_time']), 'timestamp' => forum_time(true, $row['poster_time']), 'body' => $row['body'], 'href' => $scripturl . '?topic=' . $row['id_topic'] . '.0', 'link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.0">' . $row['num_replies'] . ' ' . ($row['num_replies'] == 1 ? $txt['ssi_comment'] : $txt['ssi_comments']) . '</a>', 'replies' => $row['num_replies'], 'comment_href' => !empty($row['locked']) ? '' : $scripturl . '?action=post;topic=' . $row['id_topic'] . '.' . $row['num_replies'] . ';last_msg=' . $row['id_last_msg'], 'comment_link' => !empty($row['locked']) ? '' : '<a href="' . $scripturl . '?action=post;topic=' . $row['id_topic'] . '.' . $row['num_replies'] . ';last_msg=' . $row['id_last_msg'] . '">' . $txt['ssi_write_comment'] . '</a>', 'new_comment' => !empty($row['locked']) ? '' : '<a href="' . $scripturl . '?action=post;topic=' . $row['id_topic'] . '.' . $row['num_replies'] . '">' . $txt['ssi_write_comment'] . '</a>', 'poster' => array('id' => $row['id_member'], 'name' => $row['poster_name'], 'href' => !empty($row['id_member']) ? $scripturl . '?action=profile;u=' . $row['id_member'] : '', 'link' => !empty($row['id_member']) ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['poster_name'] . '</a>' : $row['poster_name']), 'locked' => !empty($row['locked']), 'is_last' => false);
    }
    $smcFunc['db_free_result']($request);
    if (empty($return)) {
        return $return;
    }
    $return[count($return) - 1]['is_last'] = true;
    if ($output_method != 'echo') {
        return $return;
    }
    foreach ($return as $news) {
        echo '
			<div class="news_item">
				<h3 class="news_header">
					', $news['icon'], '
					<a href="', $news['href'], '">', $news['subject'], '</a>
				</h3>
				<div class="news_timestamp">', $news['time'], ' ', $txt['by'], ' ', $news['poster']['link'], '</div>
				<div class="news_body" style="padding: 2ex 0;">', $news['body'], '</div>
				', $news['link'], $news['locked'] ? '' : ' | ' . $news['comment_link'], '
			</div>';
        if (!$news['is_last']) {
            echo '
			<hr />';
        }
    }
}
Exemplo n.º 19
0
function PackageInstall()
{
    global $boarddir, $txt, $context, $boardurl, $scripturl, $sourcedir, $modSettings;
    global $user_info, $smcFunc;
    // Make sure we don't install this mod twice.
    checkSubmitOnce('check');
    checkSession();
    // If there's no file, what are we installing?
    if (!isset($_REQUEST['package']) || $_REQUEST['package'] == '') {
        redirectexit('action=admin;area=packages');
    }
    $context['filename'] = $_REQUEST['package'];
    // If this is an uninstall, we'll have an id.
    $context['install_id'] = isset($_REQUEST['pid']) ? (int) $_REQUEST['pid'] : 0;
    require_once $sourcedir . '/lib/Subs-Package.php';
    // !!! TODO: Perhaps do it in steps, if necessary?
    $context['uninstalling'] = $_REQUEST['sa'] == 'uninstall2';
    // Set up the linktree for other.
    $context['linktree'][count($context['linktree']) - 1] = array('url' => $scripturl . '?action=admin;area=packages;sa=browse', 'name' => $context['uninstalling'] ? $txt['uninstall'] : $txt['extracting']);
    $context['page_title'] .= ' - ' . ($context['uninstalling'] ? $txt['uninstall'] : $txt['extracting']);
    $context['sub_template'] = 'extract_package';
    if (!file_exists($boarddir . '/Packages/' . $context['filename'])) {
        fatal_lang_error('package_no_file', false);
    }
    // Load up the package FTP information?
    create_chmod_control(array(), array('destination_url' => $scripturl . '?action=admin;area=packages;sa=' . $_REQUEST['sa'] . ';package=' . $_REQUEST['package']));
    // Make sure temp directory exists and is empty!
    if (file_exists($boarddir . '/Packages/temp')) {
        deltree($boarddir . '/Packages/temp', false);
    } else {
        mktree($boarddir . '/Packages/temp', 0777);
    }
    // Let the unpacker do the work.
    if (is_file($boarddir . '/Packages/' . $context['filename'])) {
        $context['extracted_files'] = read_tgz_file($boarddir . '/Packages/' . $context['filename'], $boarddir . '/Packages/temp');
        if (!file_exists($boarddir . '/Packages/temp/package-info.xml')) {
            foreach ($context['extracted_files'] as $file) {
                if (basename($file['filename']) == 'package-info.xml') {
                    $context['base_path'] = dirname($file['filename']) . '/';
                    break;
                }
            }
        }
        if (!isset($context['base_path'])) {
            $context['base_path'] = '';
        }
    } elseif (is_dir($boarddir . '/Packages/' . $context['filename'])) {
        copytree($boarddir . '/Packages/' . $context['filename'], $boarddir . '/Packages/temp');
        $context['extracted_files'] = listtree($boarddir . '/Packages/temp');
        $context['base_path'] = '';
    } else {
        fatal_lang_error('no_access', false);
    }
    // Are we installing this into any custom themes?
    $custom_themes = array(1);
    $known_themes = explode(',', $modSettings['knownThemes']);
    if (!empty($_POST['custom_theme'])) {
        foreach ($_POST['custom_theme'] as $tid) {
            if (in_array($tid, $known_themes)) {
                $custom_themes[] = (int) $tid;
            }
        }
    }
    // Now load up the paths of the themes that we need to know about.
    $request = smf_db_query('
		SELECT id_theme, variable, value
		FROM {db_prefix}themes
		WHERE id_theme IN ({array_int:custom_themes})
			AND variable IN ({string:name}, {string:theme_dir})', array('custom_themes' => $custom_themes, 'name' => 'name', 'theme_dir' => 'theme_dir'));
    $theme_paths = array();
    $themes_installed = array(1);
    while ($row = mysql_fetch_assoc($request)) {
        $theme_paths[$row['id_theme']][$row['variable']] = $row['value'];
    }
    mysql_free_result($request);
    // Are there any theme copying that we want to take place?
    $context['theme_copies'] = array('require-file' => array(), 'require-dir' => array());
    if (!empty($_POST['theme_changes'])) {
        foreach ($_POST['theme_changes'] as $change) {
            if (empty($change)) {
                continue;
            }
            $theme_data = unserialize(base64_decode($change));
            if (empty($theme_data['type'])) {
                continue;
            }
            $themes_installed[] = $theme_data['id'];
            $context['theme_copies'][$theme_data['type']][$theme_data['orig']][] = $theme_data['future'];
        }
    }
    // Get the package info...
    $packageInfo = getPackageInfo($context['filename']);
    if (!is_array($packageInfo)) {
        fatal_lang_error($packageInfo);
    }
    $packageInfo['filename'] = $context['filename'];
    // Set the type of extraction...
    $context['extract_type'] = isset($packageInfo['type']) ? $packageInfo['type'] : 'modification';
    // Create a backup file to roll back to! (but if they do this more than once, don't run it a zillion times.)
    if (!empty($modSettings['package_make_backups']) && (!isset($_SESSION['last_backup_for']) || $_SESSION['last_backup_for'] != $context['filename'] . ($context['uninstalling'] ? '$$' : '$'))) {
        $_SESSION['last_backup_for'] = $context['filename'] . ($context['uninstalling'] ? '$$' : '$');
        // !!! Internationalize this?
        package_create_backup(($context['uninstalling'] ? 'backup_' : 'before_') . strtok($context['filename'], '.'));
    }
    // The mod isn't installed.... unless proven otherwise.
    $context['is_installed'] = false;
    // Is it actually installed?
    $request = smf_db_query('
		SELECT version, themes_installed, db_changes
		FROM {db_prefix}log_packages
		WHERE package_id = {string:current_package}
			AND install_state != {int:not_installed}
		ORDER BY time_installed DESC
		LIMIT 1', array('not_installed' => 0, 'current_package' => $packageInfo['id']));
    while ($row = mysql_fetch_assoc($request)) {
        $old_themes = explode(',', $row['themes_installed']);
        $old_version = $row['version'];
        $db_changes = empty($row['db_changes']) ? array() : unserialize($row['db_changes']);
    }
    mysql_free_result($request);
    // Wait, it's not installed yet!
    // !!! TODO: Replace with a better error message!
    if (!isset($old_version) && $context['uninstalling']) {
        deltree($boarddir . '/Packages/temp');
        fatal_error('Hacker?', false);
    } elseif ($context['uninstalling']) {
        $install_log = parsePackageInfo($packageInfo['xml'], false, 'uninstall');
        // Gadzooks!  There's no uninstaller at all!?
        if (empty($install_log)) {
            fatal_lang_error('package_uninstall_cannot', false);
        }
        // They can only uninstall from what it was originally installed into.
        foreach ($theme_paths as $id => $data) {
            if ($id != 1 && !in_array($id, $old_themes)) {
                unset($theme_paths[$id]);
            }
        }
    } elseif (isset($old_version) && $old_version != $packageInfo['version']) {
        // Look for an upgrade...
        $install_log = parsePackageInfo($packageInfo['xml'], false, 'upgrade', $old_version);
        // There was no upgrade....
        if (empty($install_log)) {
            $context['is_installed'] = true;
        } else {
            // Upgrade previous themes only!
            foreach ($theme_paths as $id => $data) {
                if ($id != 1 && !in_array($id, $old_themes)) {
                    unset($theme_paths[$id]);
                }
            }
        }
    } elseif (isset($old_version) && $old_version == $packageInfo['version']) {
        $context['is_installed'] = true;
    }
    if (!isset($old_version) || $context['is_installed']) {
        $install_log = parsePackageInfo($packageInfo['xml'], false, 'install');
    }
    $context['install_finished'] = false;
    // !!! TODO: Make a log of any errors that occurred and output them?
    if (!empty($install_log)) {
        $failed_steps = array();
        $failed_count = 0;
        foreach ($install_log as $action) {
            $failed_count++;
            if ($action['type'] == 'modification' && !empty($action['filename'])) {
                if ($action['boardmod']) {
                    $mod_actions = parseBoardMod(file_get_contents($boarddir . '/Packages/temp/' . $context['base_path'] . $action['filename']), false, $action['reverse'], $theme_paths);
                } else {
                    $mod_actions = parseModification(file_get_contents($boarddir . '/Packages/temp/' . $context['base_path'] . $action['filename']), false, $action['reverse'], $theme_paths);
                }
                // Any errors worth noting?
                foreach ($mod_actions as $key => $action) {
                    if ($action['type'] == 'failure') {
                        $failed_steps[] = array('file' => $action['filename'], 'large_step' => $failed_count, 'sub_step' => $key, 'theme' => 1);
                    }
                    // Gather the themes we installed into.
                    if (!empty($action['is_custom'])) {
                        $themes_installed[] = $action['is_custom'];
                    }
                }
            } elseif ($action['type'] == 'code' && !empty($action['filename'])) {
                // This is just here as reference for what is available.
                global $txt, $boarddir, $sourcedir, $modSettings, $context, $settings, $forum_version, $smcFunc;
                // Now include the file and be done with it ;).
                require $boarddir . '/Packages/temp/' . $context['base_path'] . $action['filename'];
            } elseif ($action['type'] == 'database' && !empty($action['filename']) && (!$context['uninstalling'] || !empty($_POST['do_db_changes']))) {
                // These can also be there for database changes.
                global $txt, $boarddir, $sourcedir, $modSettings, $context, $settings, $forum_version, $smcFunc;
                global $db_package_log;
                // We'll likely want the package specific database functionality!
                db_extend('packages');
                // Let the file work its magic ;)
                require $boarddir . '/Packages/temp/' . $context['base_path'] . $action['filename'];
            } elseif ($action['type'] == 'redirect' && !empty($action['redirect_url'])) {
                $context['redirect_url'] = $action['redirect_url'];
                $context['redirect_text'] = !empty($action['filename']) && file_exists($boarddir . '/Packages/temp/' . $context['base_path'] . $action['filename']) ? file_get_contents($boarddir . '/Packages/temp/' . $context['base_path'] . $action['filename']) : ($context['uninstalling'] ? $txt['package_uninstall_done'] : $txt['package_installed_done']);
                $context['redirect_timeout'] = $action['redirect_timeout'];
                // Parse out a couple of common urls.
                $urls = array('$boardurl' => $boardurl, '$scripturl' => $scripturl, '$session_var' => $context['session_var'], '$session_id' => $context['session_id']);
                $context['redirect_url'] = strtr($context['redirect_url'], $urls);
            }
        }
        package_flush_cache();
        // First, ensure this change doesn't get removed by putting a stake in the ground (So to speak).
        package_put_contents($boarddir . '/Packages/installed.list', time());
        // See if this is already installed, and change it's state as required.
        $request = smf_db_query('
			SELECT package_id, install_state, db_changes
			FROM {db_prefix}log_packages
			WHERE install_state != {int:not_installed}
				AND package_id = {string:current_package}
				' . ($context['install_id'] ? ' AND id_install = {int:install_id} ' : '') . '
			ORDER BY time_installed DESC
			LIMIT 1', array('not_installed' => 0, 'install_id' => $context['install_id'], 'current_package' => $packageInfo['id']));
        $is_upgrade = false;
        while ($row = mysql_fetch_assoc($request)) {
            // Uninstalling?
            if ($context['uninstalling']) {
                smf_db_query('
					UPDATE {db_prefix}log_packages
					SET install_state = {int:not_installed}, member_removed = {string:member_name}, id_member_removed = {int:current_member},
						time_removed = {int:current_time}
					WHERE package_id = {string:package_id}', array('current_member' => $user_info['id'], 'not_installed' => 0, 'current_time' => time(), 'package_id' => $row['package_id'], 'member_name' => $user_info['name']));
            } else {
                $is_upgrade = true;
                $old_db_changes = empty($row['db_changes']) ? array() : unserialize($row['db_changes']);
            }
        }
        // Assuming we're not uninstalling, add the entry.
        if (!$context['uninstalling']) {
            // Any db changes from older version?
            if (!empty($old_db_changes)) {
                $db_package_log = empty($db_package_log) ? $old_db_changes : array_merge($old_db_changes, $db_package_log);
            }
            // If there are some database changes we might want to remove then filter them out.
            if (!empty($db_package_log)) {
                // We're really just checking for entries which are create table AND add columns (etc).
                $tables = array();
                function sort_table_first($a, $b)
                {
                    if ($a[0] == $b[0]) {
                        return 0;
                    }
                    return $a[0] == 'remove_table' ? -1 : 1;
                }
                usort($db_package_log, 'sort_table_first');
                foreach ($db_package_log as $k => $log) {
                    if ($log[0] == 'remove_table') {
                        $tables[] = $log[1];
                    } elseif (in_array($log[1], $tables)) {
                        unset($db_package_log[$k]);
                    }
                }
                $db_changes = serialize($db_package_log);
            } else {
                $db_changes = '';
            }
            // What themes did we actually install?
            $themes_installed = array_unique($themes_installed);
            $themes_installed = implode(',', $themes_installed);
            // What failed steps?
            $failed_step_insert = serialize($failed_steps);
            smf_db_insert('', '{db_prefix}log_packages', array('filename' => 'string', 'name' => 'string', 'package_id' => 'string', 'version' => 'string', 'id_member_installed' => 'int', 'member_installed' => 'string', 'time_installed' => 'int', 'install_state' => 'int', 'failed_steps' => 'string', 'themes_installed' => 'string', 'member_removed' => 'int', 'db_changes' => 'string'), array($packageInfo['filename'], $packageInfo['name'], $packageInfo['id'], $packageInfo['version'], $user_info['id'], $user_info['name'], time(), $is_upgrade ? 2 : 1, $failed_step_insert, $themes_installed, 0, $db_changes), array('id_install'));
        }
        mysql_free_result($request);
        $context['install_finished'] = true;
    }
    // If there's database changes - and they want them removed - let's do it last!
    if (!empty($db_changes) && !empty($_POST['do_db_changes'])) {
        // We're gonna be needing the package db functions!
        db_extend('packages');
        foreach ($db_changes as $change) {
            if ($change[0] == 'remove_table' && isset($change[1])) {
                smf_db_drop_table($change[1]);
            } elseif ($change[0] == 'remove_column' && isset($change[2])) {
                smf_db_remove_column($change[1], $change[2]);
            } elseif ($change[0] == 'remove_index' && isset($change[2])) {
                smf_db_remove_index($change[1], $change[2]);
            }
        }
    }
    // Clean house... get rid of the evidence ;).
    if (file_exists($boarddir . '/Packages/temp')) {
        deltree($boarddir . '/Packages/temp');
    }
    // Log what we just did.
    logAction($context['uninstalling'] ? 'uninstall_package' : (!empty($is_upgrade) ? 'upgrade_package' : 'install_package'), array('package' => commonAPI::htmlspecialchars($packageInfo['name']), 'version' => commonAPI::htmlspecialchars($packageInfo['version'])), 'admin');
    // Just in case, let's clear the whole cache to avoid anything going up the swanny.
    clean_cache();
    // Restore file permissions?
    create_chmod_control(array(), array(), true);
}
Exemplo n.º 20
0
function JavaScriptModify()
{
    global $sourcedir, $modSettings, $board, $topic, $txt;
    global $user_info, $context, $language;
    // We have to have a topic!
    if (empty($topic)) {
        obExit(false);
    }
    checkSession('get');
    require_once $sourcedir . '/lib/Subs-Post.php';
    // Assume the first message if no message ID was given.
    $request = smf_db_query('
			SELECT
				t.locked, t.num_replies, t.id_member_started, t.id_first_msg,
				m.id_msg, m.id_member, m.poster_time, m.subject, m.smileys_enabled, m.body, m.icon,
				m.modified_time, m.modified_name, m.approved, ba.id_topic AS banned_from_topic
			FROM {db_prefix}messages AS m
				INNER JOIN {db_prefix}topics AS t ON (t.id_topic = {int:current_topic})
				LEFT JOIN {db_prefix}topicbans AS ba ON (ba.id_topic = {int:current_topic} AND ba.id_member = {int:current_member})
			WHERE m.id_msg = {raw:id_msg}
				AND m.id_topic = {int:current_topic}' . (allowedTo('approve_posts') ? '' : (!$modSettings['postmod_active'] ? '
				AND (m.id_member != {int:guest_id} AND m.id_member = {int:current_member})' : '
				AND (m.approved = {int:is_approved} OR (m.id_member != {int:guest_id} AND m.id_member = {int:current_member}))')), array('current_member' => $user_info['id'], 'current_topic' => $topic, 'id_msg' => empty($_REQUEST['msg']) ? 't.id_first_msg' : (int) $_REQUEST['msg'], 'is_approved' => 1, 'guest_id' => 0));
    if (mysql_num_rows($request) == 0) {
        fatal_lang_error('no_board', false);
    }
    $row = mysql_fetch_assoc($request);
    mysql_free_result($request);
    // Change either body or subject requires permissions to modify messages.
    if (isset($_POST['message']) || isset($_POST['subject']) || isset($_REQUEST['icon'])) {
        if (!empty($row['locked'])) {
            isAllowedTo('moderate_board');
        }
        if ($row['id_member'] == $user_info['id'] && !allowedTo('modify_any')) {
            if ((!$modSettings['postmod_active'] || $row['approved']) && !empty($modSettings['edit_disable_time']) && $row['poster_time'] + ($modSettings['edit_disable_time'] + 5) * 60 < time()) {
                fatal_lang_error('modify_post_time_passed', false);
            } elseif ($row['id_member_started'] == $user_info['id'] && !allowedTo('modify_own')) {
                isAllowedTo('modify_replies');
            } else {
                isAllowedTo('modify_own');
            }
        } elseif ($row['id_member_started'] == $user_info['id'] && !allowedTo('modify_any')) {
            isAllowedTo('modify_replies');
        } else {
            isAllowedTo('modify_any');
        }
        // check topic bans
        if ($row['banned_from_topic'] != 0 && !$user_info['is_admin'] && !allowedTo('moderate_board') && !allowedTo('moderate_forum')) {
            fatal_lang_error('banned_from_topic');
        }
        // Only log this action if it wasn't your message.
        $moderationAction = $row['id_member'] != $user_info['id'];
    }
    $post_errors = array();
    if (isset($_POST['subject']) && commonAPI::htmltrim(commonAPI::htmlspecialchars($_POST['subject'])) !== '') {
        $_POST['subject'] = strtr(commonAPI::htmlspecialchars($_POST['subject']), array("\r" => '', "\n" => '', "\t" => ''));
        // Maximum number of characters.
        if (commonAPI::strlen($_POST['subject']) > 100) {
            $_POST['subject'] = commonAPI::substr($_POST['subject'], 0, 100);
        }
    } elseif (isset($_POST['subject'])) {
        $post_errors[] = 'no_subject';
        unset($_POST['subject']);
    }
    if (isset($_POST['message'])) {
        if (commonAPI::htmltrim(commonAPI::htmlspecialchars($_POST['message'])) === '') {
            $post_errors[] = 'no_message';
            unset($_POST['message']);
        } elseif (!empty($modSettings['max_messageLength']) && commonAPI::strlen($_POST['message']) > $modSettings['max_messageLength']) {
            $post_errors[] = 'long_message';
            unset($_POST['message']);
        } else {
            $_POST['message'] = commonAPI::htmlspecialchars($_POST['message'], ENT_QUOTES);
            preparsecode($_POST['message']);
            if (commonAPI::htmltrim(strip_tags(parse_bbc($_POST['message'], false), '<img>')) === '') {
                $post_errors[] = 'no_message';
                unset($_POST['message']);
            }
        }
    }
    if (isset($_POST['lock'])) {
        if (!allowedTo(array('lock_any', 'lock_own')) || !allowedTo('lock_any') && $user_info['id'] != $row['id_member']) {
            unset($_POST['lock']);
        } elseif (!allowedTo('lock_any')) {
            if ($row['locked'] == 1) {
                unset($_POST['lock']);
            } else {
                $_POST['lock'] = empty($_POST['lock']) ? 0 : 2;
            }
        } elseif (!empty($row['locked']) && !empty($_POST['lock']) || $_POST['lock'] == $row['locked']) {
            unset($_POST['lock']);
        } else {
            $_POST['lock'] = empty($_POST['lock']) ? 0 : 1;
        }
    }
    if (isset($_POST['sticky']) && !allowedTo('make_sticky')) {
        unset($_POST['sticky']);
    }
    if (empty($post_errors)) {
        $msgOptions = array('id' => $row['id_msg'], 'subject' => isset($_POST['subject']) ? $_POST['subject'] : null, 'body' => isset($_POST['message']) ? $_POST['message'] : null, 'icon' => isset($_REQUEST['icon']) ? preg_replace('~[\\./\\\\*\':"<>]~', '', $_REQUEST['icon']) : null, 'id_owner' => $row['id_member']);
        $topicOptions = array('id' => $topic, 'board' => $board, 'lock_mode' => isset($_POST['lock']) ? (int) $_POST['lock'] : null, 'sticky_mode' => isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics']) ? (int) $_POST['sticky'] : null, 'mark_as_read' => true);
        $posterOptions = array();
        // Only consider marking as editing if they have edited the subject, message or icon.
        if (isset($_POST['subject']) && $_POST['subject'] != $row['subject'] || isset($_POST['message']) && $_POST['message'] != $row['body'] || isset($_REQUEST['icon']) && $_REQUEST['icon'] != $row['icon']) {
            // And even then only if the time has passed...
            if (time() - $row['poster_time'] > $modSettings['edit_wait_time'] || $user_info['id'] != $row['id_member']) {
                $msgOptions['modify_time'] = time();
                $msgOptions['modify_name'] = $user_info['name'];
            }
        } else {
            $moderationAction = false;
        }
        modifyPost($msgOptions, $topicOptions, $posterOptions);
        // If we didn't change anything this time but had before put back the old info.
        if (!isset($msgOptions['modify_time']) && !empty($row['modified_time'])) {
            $msgOptions['modify_time'] = $row['modified_time'];
            $msgOptions['modify_name'] = $row['modified_name'];
        }
        // Changing the first subject updates other subjects to 'Re: new_subject'.
        if (isset($_POST['subject']) && isset($_REQUEST['change_all_subjects']) && $row['id_first_msg'] == $row['id_msg'] && !empty($row['num_replies']) && (allowedTo('modify_any') || $row['id_member_started'] == $user_info['id'] && allowedTo('modify_replies'))) {
            // Get the proper (default language) response prefix first.
            if (!isset($context['response_prefix']) && !($context['response_prefix'] = CacheAPI::getCache('response_prefix'))) {
                if ($language === $user_info['language']) {
                    $context['response_prefix'] = $txt['response_prefix'];
                } else {
                    loadLanguage('index', $language, false);
                    $context['response_prefix'] = $txt['response_prefix'];
                    loadLanguage('index');
                }
                CacheAPI::putCache('response_prefix', $context['response_prefix'], 600);
            }
            smf_db_query('
				UPDATE {db_prefix}messages
				SET subject = {string:subject}
				WHERE id_topic = {int:current_topic}
					AND id_msg != {int:id_first_msg}', array('current_topic' => $topic, 'id_first_msg' => $row['id_first_msg'], 'subject' => $context['response_prefix'] . $_POST['subject']));
        }
        if (!empty($moderationAction)) {
            logAction('modify', array('topic' => $topic, 'message' => $row['id_msg'], 'member' => $row['id_member'], 'board' => $board));
        }
    }
    if (isset($_REQUEST['xml'])) {
        $context['sub_template'] = 'modifydone';
        if (empty($post_errors) && isset($msgOptions['subject']) && isset($msgOptions['body'])) {
            $context['message'] = array('id' => $row['id_msg'], 'modified' => array('time' => isset($msgOptions['modify_time']) ? timeformat($msgOptions['modify_time']) : '', 'timestamp' => isset($msgOptions['modify_time']) ? forum_time(true, $msgOptions['modify_time']) : 0, 'name' => isset($msgOptions['modify_time']) ? $msgOptions['modify_name'] : ''), 'subject' => $msgOptions['subject'], 'first_in_topic' => $row['id_msg'] == $row['id_first_msg'], 'body' => strtr($msgOptions['body'], array(']]>' => ']]]]><![CDATA[>')));
            censorText($context['message']['subject']);
            censorText($context['message']['body']);
            $cache_key = isset($msgOptions['modify_time']) ? $row['id_msg'] . '|' . $msgOptions['modify_time'] : $row['id_msg'];
            $context['message']['body'] = parse_bbc($context['message']['body'], $row['smileys_enabled'], $cache_key);
            parse_bbc_stage2($context['message']['body']);
        } elseif (empty($post_errors)) {
            $context['sub_template'] = 'modifytopicdone';
            $context['message'] = array('id' => $row['id_msg'], 'icon' => isset($_REQUEST['icon']) ? $_REQUEST['icon'] : '', 'modified' => array('time' => isset($msgOptions['modify_time']) ? timeformat($msgOptions['modify_time']) : '', 'timestamp' => isset($msgOptions['modify_time']) ? forum_time(true, $msgOptions['modify_time']) : 0, 'name' => isset($msgOptions['modify_time']) ? $msgOptions['modify_name'] : ''), 'subject' => isset($msgOptions['subject']) ? $msgOptions['subject'] : '');
            censorText($context['message']['subject']);
        } else {
            $context['message'] = array('id' => $row['id_msg'], 'errors' => array(), 'error_in_subject' => in_array('no_subject', $post_errors), 'error_in_body' => in_array('no_message', $post_errors) || in_array('long_message', $post_errors));
            loadLanguage('Errors');
            foreach ($post_errors as $post_error) {
                if ($post_error == 'long_message') {
                    $context['message']['errors'][] = sprintf($txt['error_' . $post_error], $modSettings['max_messageLength']);
                } else {
                    $context['message']['errors'][] = $txt['error_' . $post_error];
                }
            }
        }
    } else {
        obExit(false);
    }
}
Exemplo n.º 21
0
function generateSubscriptionError($text)
{
    global $modSettings, $notify_users, $smcFunc;
    // Send an email?
    if (!empty($modSettings['paid_email'])) {
        $replacements = array('ERROR' => $text);
        emailAdmins('paid_subscription_error', $replacements, $notify_users);
    }
    // Maybe we can try to give them the post data?
    if (!empty($_POST)) {
        foreach ($_POST as $key => $val) {
            $text .= '<br />' . commonAPI::htmlspecialchars($key) . ': ' . commonAPI::htmlspecialchars($val);
        }
    }
    // Then just log and die.
    log_error($text);
    exit;
}
Exemplo n.º 22
0
function issueWarning($memID)
{
    global $txt, $scripturl, $modSettings, $user_info, $mbname;
    global $context, $cur_profile, $memberContext, $smcFunc, $sourcedir;
    if (!isset($context['profile_template_support_context'])) {
        $context['profile_template_support_context'] = new ProfileContext();
    }
    // Get all the actual settings.
    list($modSettings['warning_enable'], $modSettings['user_limit']) = explode(',', $modSettings['warning_settings']);
    EoS_Smarty::loadTemplate('profile/profile_base');
    EoS_Smarty::getConfigInstance()->registerHookTemplate('profile_content_area', 'profile/issuewarning');
    // This stores any legitimate errors.
    $issueErrors = array();
    $context['replace_helper_array'] = array('"' => "'", "\n" => '\\n', "\r" => '');
    // Doesn't hurt to be overly cautious.
    if (empty($modSettings['warning_enable']) || $context['user']['is_owner'] && !$cur_profile['warning'] || !allowedTo('issue_warning')) {
        fatal_lang_error('no_access', false);
    }
    // Make sure things which are disabled stay disabled.
    $modSettings['warning_watch'] = !empty($modSettings['warning_watch']) ? $modSettings['warning_watch'] : 110;
    $modSettings['warning_moderate'] = !empty($modSettings['warning_moderate']) && !empty($modSettings['postmod_active']) ? $modSettings['warning_moderate'] : 110;
    $modSettings['warning_mute'] = !empty($modSettings['warning_mute']) ? $modSettings['warning_mute'] : 110;
    $context['warning_limit'] = allowedTo('admin_forum') ? 0 : $modSettings['user_limit'];
    $context['member']['warning'] = $cur_profile['warning'];
    $context['member']['name'] = $cur_profile['real_name'];
    // What are the limits we can apply?
    $context['min_allowed'] = 0;
    $context['max_allowed'] = 100;
    if ($context['warning_limit'] > 0) {
        // Make sure we cannot go outside of our limit for the day.
        $request = smf_db_query('
			SELECT SUM(counter)
			FROM {db_prefix}log_comments
			WHERE id_recipient = {int:selected_member}
				AND id_member = {int:current_member}
				AND comment_type = {string:warning}
				AND log_time > {int:day_time_period}', array('current_member' => $user_info['id'], 'selected_member' => $memID, 'day_time_period' => time() - 86400, 'warning' => 'warning'));
        list($current_applied) = mysql_fetch_row($request);
        mysql_free_result($request);
        $context['min_allowed'] = max(0, $cur_profile['warning'] - $current_applied - $context['warning_limit']);
        $context['max_allowed'] = min(100, $cur_profile['warning'] - $current_applied + $context['warning_limit']);
    }
    // Defaults.
    $context['warning_data'] = array('reason' => '', 'notify' => '', 'notify_subject' => '', 'notify_body' => '', 'topicban' => '', 'topicban_expire' => 0, 'topicban_id_topic' => 0);
    // Are we saving?
    if (isset($_POST['save'])) {
        // Security is good here.
        checkSession('post');
        // This cannot be empty!
        $_POST['warn_reason'] = isset($_POST['warn_reason']) ? trim($_POST['warn_reason']) : '';
        if ($_POST['warn_reason'] == '' && !$context['user']['is_owner']) {
            $issueErrors[] = 'warning_no_reason';
        }
        $_POST['warn_reason'] = commonAPI::htmlspecialchars($_POST['warn_reason']);
        // If the value hasn't changed it's either no JS or a real no change (Which this will pass)
        if ($_POST['warning_level'] == 'SAME') {
            $_POST['warning_level'] = $_POST['warning_level_nojs'];
        }
        $_POST['warning_level'] = (int) $_POST['warning_level'];
        $_POST['warning_level'] = max(0, min(100, $_POST['warning_level']));
        if ($_POST['warning_level'] < $context['min_allowed']) {
            $_POST['warning_level'] = $context['min_allowed'];
        } elseif ($_POST['warning_level'] > $context['max_allowed']) {
            $_POST['warning_level'] = $context['max_allowed'];
        }
        // Do we actually have to issue them with a PM?
        $id_notice = 0;
        if (!empty($_POST['warn_notify']) && empty($issueErrors)) {
            $_POST['warn_sub'] = trim($_POST['warn_sub']);
            $_POST['warn_body'] = trim($_POST['warn_body']);
            if (empty($_POST['warn_sub']) || empty($_POST['warn_body'])) {
                $issueErrors[] = 'warning_notify_blank';
            } else {
                require_once $sourcedir . '/lib/Subs-Post.php';
                $from = array('id' => 0, 'name' => $context['forum_name'], 'username' => $context['forum_name']);
                sendpm(array('to' => array($memID), 'bcc' => array()), $_POST['warn_sub'], $_POST['warn_body'], false, $from);
                // Log the notice!
                smf_db_insert('', '{db_prefix}log_member_notices', array('subject' => 'string-255', 'body' => 'string-65534'), array(commonAPI::htmlspecialchars($_POST['warn_sub']), commonAPI::htmlspecialchars($_POST['warn_body'])), array('id_notice'));
                $id_notice = smf_db_insert_id('{db_prefix}log_member_notices', 'id_notice');
            }
        }
        // Just in case - make sure notice is valid!
        $id_notice = (int) $id_notice;
        // What have we changed?
        $level_change = $_POST['warning_level'] - $cur_profile['warning'];
        // No errors? Proceed! Only log if you're not the owner.
        if (empty($issueErrors)) {
            // Log what we've done!
            if (!$context['user']['is_owner']) {
                smf_db_insert('', '{db_prefix}log_comments', array('id_member' => 'int', 'member_name' => 'string', 'comment_type' => 'string', 'id_recipient' => 'int', 'recipient_name' => 'string-255', 'log_time' => 'int', 'id_notice' => 'int', 'counter' => 'int', 'body' => 'string-65534'), array($user_info['id'], $user_info['name'], 'warning', $memID, $cur_profile['real_name'], time(), $id_notice, $level_change, $_POST['warn_reason']), array('id_comment'));
            }
            // Make the change.
            updateMemberData($memID, array('warning' => $_POST['warning_level']));
            // Leave a lovely message.
            $context['profile_updated'] = $context['user']['is_owner'] ? $txt['profile_updated_own'] : $txt['profile_warning_success'];
            // if we want to issue a topicban, do it now
            if (isset($_POST['warn_topicban']) && !empty($_POST['warn_topicban']) && isset($_POST['warn_topicban_id_topic']) && !empty($_POST['warn_topicban_id_topic'])) {
                $ban_reason = (isset($_REQUEST['warn_msg']) ? (int) $_REQUEST['warn_msg'] : 0) . '|' . $_POST['warn_reason'];
                $ban_expires = isset($_POST['warn_topicban_expire']) && !empty($_POST['warn_topicban_expire']) ? $context['time_now'] + 86400 * (int) $_POST['warn_topicban_expire'] : 0;
                smf_db_insert('', '{db_prefix}topicbans', array('id_topic' => 'int', 'id_member' => 'int', 'updated' => 'int', 'expires' => 'int', 'reason' => 'string'), array($_POST['warn_topicban_id_topic'], $memID, $context['time_now'], $ban_expires, $ban_reason), array('id'));
            }
        } else {
            // Get the base stuff done.
            loadLanguage('Errors');
            $context['custom_error_title'] = $txt['profile_warning_errors_occured'];
            // Fill in the suite of errors.
            $context['post_errors'] = array();
            foreach ($issueErrors as $error) {
                $context['post_errors'][] = $txt[$error];
            }
            // Try to remember some bits.
            $context['warning_data'] = array('reason' => $_POST['warn_reason'], 'notify' => !empty($_POST['warn_notify']), 'notify_subject' => isset($_POST['warn_sub']) ? $_POST['warn_sub'] : '', 'notify_body' => isset($_POST['warn_body']) ? $_POST['warn_body'] : '', 'topicban' => isset($_POST['warn_topicban']) && !empty($_POST['warn_topicban']) ? 1 : 0, 'topicban_expire' => isset($_POST['warn_topicban_expire']) && !empty($_POST['warn_topicban_expire']) ? (int) $_POST['warn_topicban_expire'] : 0, 'topicban_id_topic' => isset($_POST['warn_topicban_id_topic']) ? (int) $_POST['warn_topicban_id_topic'] : 0, 'msg' => isset($_POST['warn_msg']) && !empty($_POST['warn_msg']) ? (int) $_POST['warn_msg'] : 0);
        }
        // Show the new improved warning level.
        $context['member']['warning'] = $_POST['warning_level'];
    }
    $context['page_title'] = $txt['profile_issue_warning'];
    // Work our the various levels.
    $context['level_effects'] = array(0 => $txt['profile_warning_effect_none'], $modSettings['warning_watch'] => $txt['profile_warning_effect_watch'], $modSettings['warning_moderate'] => $txt['profile_warning_effect_moderation'], $modSettings['warning_mute'] => $txt['profile_warning_effect_mute']);
    $context['current_level'] = 0;
    foreach ($context['level_effects'] as $limit => $dummy) {
        if ($context['member']['warning'] >= $limit) {
            $context['current_level'] = $limit;
        }
    }
    // Load up all the old warnings - count first!
    $context['total_warnings'] = list_getUserWarningCount($memID);
    // Make the page index.
    $context['start'] = (int) $_REQUEST['start'];
    $perPage = (int) $modSettings['defaultMaxMessages'];
    $context['page_index'] = constructPageIndex($scripturl . '?action=profile;u=' . $memID . ';area=issuewarning', $context['start'], $context['total_warnings'], $perPage);
    // Now do the data itself.
    $context['previous_warnings'] = list_getUserWarnings($context['start'], $perPage, 'log_time DESC', $memID);
    // Are they warning because of a message?
    $context['warned_message_subject'] = '';
    if (isset($_REQUEST['msg']) && 0 < (int) $_REQUEST['msg']) {
        $request = smf_db_query('
			SELECT subject, id_topic
			FROM {db_prefix}messages AS m
				INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
			WHERE id_msg = {int:message}
				AND {query_see_board}
			LIMIT 1', array('message' => (int) $_REQUEST['msg']));
        if (mysql_num_rows($request) != 0) {
            $context['warning_for_message'] = (int) $_REQUEST['msg'];
            $context['warning_data']['msg'] = $context['warning_for_message'];
            list($context['warned_message_subject'], $context['warning_for_topic']) = mysql_fetch_row($request);
        }
        mysql_free_result($request);
    }
    if (isset($_POST['warn_topicban_id_topic'])) {
        $context['warning_for_message'] = (int) $_POST['warn_topicban_id_topic'];
    }
    // Didn't find the message?
    if (empty($context['warning_for_message'])) {
        $context['warning_for_message'] = $context['warning_for_topic'] = 0;
        $context['warned_message_subject'] = '';
    }
    // we can issue a topic ban, now check if the member doesn't have one already
    if (isset($context['warning_for_topic'])) {
        $context['can_issue_topicban'] = $context['warning_for_topic'];
        $request = smf_db_query('SELECT id_member FROM {db_prefix}topicbans WHERE id_topic = {int:topic} AND id_member = {int:member}', array('topic' => $context['warning_for_topic'], 'member' => $memID));
        if (mysql_num_rows($request) > 0) {
            $context['warning_for_topic'] = $context['can_issue_topicban'] = 0;
            $context['member_is_topic_banned'] = true;
        } else {
            $context['warning_data']['topicban_id_topic'] = $context['warning_for_topic'];
        }
        mysql_free_result($request);
    } else {
        $context['can_issue_topicban'] = 0;
    }
    // Any custom templates?
    $context['notification_templates'] = array();
    $request = smf_db_query('
		SELECT recipient_name AS template_title, body
		FROM {db_prefix}log_comments
		WHERE comment_type = {string:warntpl}
			AND (id_recipient = {int:generic} OR id_recipient = {int:current_member})', array('warntpl' => 'warntpl', 'generic' => 0, 'current_member' => $user_info['id']));
    while ($row = mysql_fetch_assoc($request)) {
        // If we're not warning for a message skip any that are.
        if (!$context['warning_for_message'] && strpos($row['body'], '{MESSAGE}') !== false) {
            continue;
        }
        $context['notification_templates'][] = array('title' => $row['template_title'], 'body' => $row['body']);
    }
    mysql_free_result($request);
    // Setup the "default" templates.
    foreach (array('spamming', 'offence', 'insulting') as $type) {
        $context['notification_templates'][] = array('title' => $txt['profile_warning_notify_title_' . $type], 'body' => sprintf($txt['profile_warning_notify_template_outline' . (!empty($context['warning_for_message']) ? '_post' : '')], $txt['profile_warning_notify_for_' . $type]));
    }
    // Replace all the common variables in the templates.
    foreach ($context['notification_templates'] as $k => $name) {
        $context['notification_templates'][$k]['body'] = strtr($name['body'], array('{MEMBER}' => un_htmlspecialchars($context['member']['name']), '{MESSAGE}' => '[url=' . $scripturl . '?msg=' . $context['warning_for_message'] . ']' . un_htmlspecialchars($context['warned_message_subject']) . '[/url]', '{SCRIPTURL}' => $scripturl, '{FORUMNAME}' => $mbname, '{REGARDS}' => $txt['regards_team']));
    }
}
Exemplo n.º 23
0
/**
 * @param $memID		int member id
 *
 * show activities, notifications and settings on the profile page. The latter two
 * are only handled when viewing your own profile.
 *
 * This is here because Profile-View.php is already big enough :)
 */
function showActivitiesProfile($memID)
{
    global $context, $user_info, $sourcedir, $user_profile, $txt, $modSettings, $options;
    $context['user']['is_owner'] = $memID == $user_info['id'];
    require_once $sourcedir . '/lib/Subs-Activities.php';
    Eos_Smarty::loadTemplate('profile/profile_base');
    loadLanguage('Activities');
    $sa = isset($_GET['sa']) ? $_GET['sa'] : 'activities';
    $start = isset($_GET['start']) ? (int) $_GET['start'] : 0;
    if ($sa == 'settings') {
        return showActivitiesProfileSettings($memID);
    }
    Eos_Smarty::getConfigInstance()->registerHookTemplate('profile_content_area', 'profile/activities_display');
    $context['page_title'] = $txt['showActivities'] . ' - ' . $user_profile[$memID]['real_name'];
    $context['pageindex_multiplier'] = commonAPI::getMessagesPerPage();
    $context['act_results'] = 0;
    $context['rich_output'] = true;
    $context[$context['profile_menu_name']]['tab_data'] = array('title' => $txt['showActivities'], 'description' => $txt['showActivitiesMenu'], 'tabs' => array());
    // these areas cannot be visited if it's not our own profile unless you are the mighty one
    if (($sa == 'notifications' || $sa == 'settings') && !$context['user']['is_owner'] && !$user_info['is_admin']) {
        fatal_lang_error('no_access');
    }
    $result = smf_db_query('
		SELECT a.*, t.*, b.name AS board_name FROM {db_prefix}log_activities AS a
		LEFT JOIN {db_prefix}activity_types AS t ON (t.id_type = a.id_type)
		LEFT JOIN {db_prefix}boards AS b ON(b.id_board = a.id_board)
		WHERE ({query_see_board} OR a.id_board = 0) AND (a.id_member = {int:id_user} OR a.id_owner = {int:id_user}) ORDER BY a.id_act DESC LIMIT {int:start}, 20', array('start' => $start, 'id_user' => $memID));
    $context['act_global'] = true;
    aStreamOutput($result);
    $context['titletext'] = $context['page_title'];
}
Exemplo n.º 24
0
function ReportToModerator2()
{
    global $txt, $scripturl, $topic, $board, $user_info, $modSettings, $sourcedir, $language, $context, $smcFunc;
    // You must have the proper permissions!
    isAllowedTo('report_any');
    // Make sure they aren't spamming.
    spamProtection('reporttm');
    require_once $sourcedir . '/lib/Subs-Post.php';
    // No errors, yet.
    $post_errors = array();
    // Check their session.
    if (checkSession('post', '', false) != '') {
        $post_errors[] = 'session_timeout';
    }
    // Make sure we have a comment and it's clean.
    if (!isset($_POST['comment']) || commonAPI::htmltrim($_POST['comment']) === '') {
        $post_errors[] = 'no_comment';
    }
    $poster_comment = strtr(commonAPI::htmlspecialchars($_POST['comment']), array("\r" => '', "\n" => '', "\t" => ''));
    // Guests need to provide their address!
    if ($user_info['is_guest']) {
        $_POST['email'] = !isset($_POST['email']) ? '' : trim($_POST['email']);
        if ($_POST['email'] === '') {
            $post_errors[] = 'no_email';
        } elseif (preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', $_POST['email']) == 0) {
            $post_errors[] = 'bad_email';
        }
        isBannedEmail($_POST['email'], 'cannot_post', sprintf($txt['you_are_post_banned'], $txt['guest_title']));
        $user_info['email'] = htmlspecialchars($_POST['email']);
    }
    // Could they get the right verification code?
    if ($user_info['is_guest'] && !empty($modSettings['guests_report_require_captcha'])) {
        require_once $sourcedir . '/lib/Subs-Editor.php';
        $verificationOptions = array('id' => 'report');
        $context['require_verification'] = create_control_verification($verificationOptions, true);
        if (is_array($context['require_verification'])) {
            $post_errors = array_merge($post_errors, $context['require_verification']);
        }
    }
    // Any errors?
    if (!empty($post_errors)) {
        loadLanguage('Errors');
        $context['post_errors'] = array();
        foreach ($post_errors as $post_error) {
            $context['post_errors'][] = $txt['error_' . $post_error];
        }
        return ReportToModerator();
    }
    // Get the basic topic information, and make sure they can see it.
    $_POST['msg'] = (int) $_POST['msg'];
    $request = smf_db_query('
		SELECT m.id_topic, m.id_board, m.subject, m.body, m.id_member AS id_poster, m.poster_name, mem.real_name
		FROM {db_prefix}messages AS m
			LEFT JOIN {db_prefix}members AS mem ON (m.id_member = mem.id_member)
		WHERE m.id_msg = {int:id_msg}
			AND m.id_topic = {int:current_topic}
		LIMIT 1', array('current_topic' => $topic, 'id_msg' => $_POST['msg']));
    if (mysql_num_rows($request) == 0) {
        fatal_lang_error('no_board', false);
    }
    $message = mysql_fetch_assoc($request);
    mysql_free_result($request);
    $poster_name = un_htmlspecialchars($message['real_name']) . ($message['real_name'] != $message['poster_name'] ? ' (' . $message['poster_name'] . ')' : '');
    $reporterName = un_htmlspecialchars($user_info['name']) . ($user_info['name'] != $user_info['username'] && $user_info['username'] != '' ? ' (' . $user_info['username'] . ')' : '');
    $subject = un_htmlspecialchars($message['subject']);
    // Get a list of members with the moderate_board permission.
    require_once $sourcedir . '/lib/Subs-Members.php';
    $moderators = membersAllowedTo('moderate_board', $board);
    $request = smf_db_query('
		SELECT id_member, email_address, lngfile, mod_prefs
		FROM {db_prefix}members
		WHERE id_member IN ({array_int:moderator_list})
			AND notify_types != {int:notify_types}
		ORDER BY lngfile', array('moderator_list' => $moderators, 'notify_types' => 4));
    // Check that moderators do exist!
    if (mysql_num_rows($request) == 0) {
        fatal_lang_error('no_mods', false);
    }
    // If we get here, I believe we should make a record of this, for historical significance, yabber.
    if (empty($modSettings['disable_log_report'])) {
        $request2 = smf_db_query('
			SELECT id_report, ignore_all
			FROM {db_prefix}log_reported
			WHERE id_msg = {int:id_msg}
				AND (closed = {int:not_closed} OR ignore_all = {int:ignored})
			ORDER BY ignore_all DESC', array('id_msg' => $_POST['msg'], 'not_closed' => 0, 'ignored' => 1));
        if (mysql_num_rows($request2) != 0) {
            list($id_report, $ignore) = mysql_fetch_row($request2);
        }
        mysql_free_result($request2);
        // If we're just going to ignore these, then who gives a monkeys...
        if (!empty($ignore)) {
            redirectexit('topic=' . $topic . '.msg' . $_POST['msg'] . '#msg' . $_POST['msg']);
        }
        // Already reported? My god, we could be dealing with a real rogue here...
        if (!empty($id_report)) {
            smf_db_query('
				UPDATE {db_prefix}log_reported
				SET num_reports = num_reports + 1, time_updated = {int:current_time}
				WHERE id_report = {int:id_report}', array('current_time' => time(), 'id_report' => $id_report));
        } else {
            if (empty($message['real_name'])) {
                $message['real_name'] = $message['poster_name'];
            }
            smf_db_insert('', '{db_prefix}log_reported', array('id_msg' => 'int', 'id_topic' => 'int', 'id_board' => 'int', 'id_member' => 'int', 'membername' => 'string', 'subject' => 'string', 'body' => 'string', 'time_started' => 'int', 'time_updated' => 'int', 'num_reports' => 'int', 'closed' => 'int'), array($_POST['msg'], $message['id_topic'], $message['id_board'], $message['id_poster'], $message['real_name'], $message['subject'], $message['body'], time(), time(), 1, 0), array('id_report'));
            $id_report = smf_db_insert_id('{db_prefix}log_reported', 'id_report');
        }
        // Now just add our report...
        if ($id_report) {
            smf_db_insert('', '{db_prefix}log_reported_comments', array('id_report' => 'int', 'id_member' => 'int', 'membername' => 'string', 'email_address' => 'string', 'member_ip' => 'string', 'comment' => 'string', 'time_sent' => 'int'), array($id_report, $user_info['id'], $user_info['name'], $user_info['email'], $user_info['ip'], $poster_comment, time()), array('id_comment'));
        }
    }
    // Find out who the real moderators are - for mod preferences.
    $request2 = smf_db_query('
		SELECT id_member
		FROM {db_prefix}moderators
		WHERE id_board = {int:current_board}', array('current_board' => $board));
    $real_mods = array();
    while ($row = mysql_fetch_assoc($request2)) {
        $real_mods[] = $row['id_member'];
    }
    mysql_free_result($request2);
    // Send every moderator an email.
    while ($row = mysql_fetch_assoc($request)) {
        // Maybe they don't want to know?!
        if (!empty($row['mod_prefs'])) {
            list(, , $pref_binary) = explode('|', $row['mod_prefs']);
            if (!($pref_binary & 1) && (!($pref_binary & 2) || !in_array($row['id_member'], $real_mods))) {
                continue;
            }
        }
        $replacements = array('TOPICSUBJECT' => $subject, 'POSTERNAME' => $poster_name, 'REPORTERNAME' => $reporterName, 'TOPICLINK' => $scripturl . '?topic=' . $topic . '.msg' . $_POST['msg'] . '#msg' . $_POST['msg'], 'REPORTLINK' => !empty($id_report) ? $scripturl . '?action=moderate;area=reports;report=' . $id_report : '', 'COMMENT' => $_POST['comment']);
        $emaildata = loadEmailTemplate('report_to_moderator', $replacements, empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']);
        // Send it to the moderator.
        sendmail($row['email_address'], $emaildata['subject'], $emaildata['body'], $user_info['email'], null, false, 2);
    }
    mysql_free_result($request);
    // Keep track of when the mod reports get updated, that way we know when we need to look again.
    updateSettings(array('last_mod_report_action' => time()));
    // Back to the post we reported!
    redirectexit('reportsent;topic=' . $topic . '.msg' . $_POST['msg'] . '#msg' . $_POST['msg']);
}
Exemplo n.º 25
0
function EditPoll2()
{
    global $txt, $topic, $board, $context;
    global $modSettings, $user_info, $smcFunc, $sourcedir;
    // Sneaking off, are we?
    if (empty($_POST)) {
        redirectexit('action=editpoll;topic=' . $topic . '.0');
    }
    if (checkSession('post', '', false) != '') {
        $poll_errors[] = 'session_timeout';
    }
    if (isset($_POST['preview'])) {
        return EditPoll();
    }
    // HACKERS (!!) can't edit :P.
    if (empty($topic)) {
        fatal_lang_error('no_access', false);
    }
    // Is this a new poll, or editing an existing?
    $isEdit = isset($_REQUEST['add']) ? 0 : 1;
    // Get the starter and the poll's ID - if it's an edit.
    $request = smf_db_query('
		SELECT t.id_member_started, t.id_poll, p.id_member AS poll_starter, p.expire_time
		FROM {db_prefix}topics AS t
			LEFT JOIN {db_prefix}polls AS p ON (p.id_poll = t.id_poll)
		WHERE t.id_topic = {int:current_topic}
		LIMIT 1', array('current_topic' => $topic));
    if (mysql_num_rows($request) == 0) {
        fatal_lang_error('no_board');
    }
    $bcinfo = mysql_fetch_assoc($request);
    mysql_free_result($request);
    // Check their adding/editing is valid.
    if (!$isEdit && !empty($bcinfo['id_poll'])) {
        fatal_lang_error('poll_already_exists');
    } elseif ($isEdit && empty($bcinfo['id_poll'])) {
        fatal_lang_error('poll_not_found');
    }
    // Check if they have the power to add or edit the poll.
    if ($isEdit && !allowedTo('poll_edit_any')) {
        isAllowedTo('poll_edit_' . ($user_info['id'] == $bcinfo['id_member_started'] || $bcinfo['poll_starter'] != 0 && $user_info['id'] == $bcinfo['poll_starter'] ? 'own' : 'any'));
    } elseif (!$isEdit && !allowedTo('poll_add_any')) {
        isAllowedTo('poll_add_' . ($user_info['id'] == $bcinfo['id_member_started'] ? 'own' : 'any'));
    }
    $optionCount = 0;
    // Ensure the user is leaving a valid amount of options - there must be at least two.
    foreach ($_POST['options'] as $k => $option) {
        if (trim($option) != '') {
            $optionCount++;
        }
    }
    if ($optionCount < 2) {
        $poll_errors[] = 'poll_few';
    }
    // Also - ensure they are not removing the question.
    if (trim($_POST['question']) == '') {
        $poll_errors[] = 'no_question';
    }
    // Got any errors to report?
    if (!empty($poll_errors)) {
        loadLanguage('Errors');
        // Previewing.
        $_POST['preview'] = true;
        $context['poll_error'] = array('messages' => array());
        foreach ($poll_errors as $poll_error) {
            $context['poll_error'][$poll_error] = true;
            $context['poll_error']['messages'][] = $txt['error_' . $poll_error];
        }
        return EditPoll();
    }
    // Prevent double submission of this form.
    checkSubmitOnce('check');
    // Now we've done all our error checking, let's get the core poll information cleaned... question first.
    $_POST['question'] = commonAPI::htmlspecialchars($_POST['question']);
    $_POST['question'] = commonAPI::truncate($_POST['question'], 255);
    $_POST['poll_hide'] = (int) $_POST['poll_hide'];
    $_POST['poll_expire'] = isset($_POST['poll_expire']) ? (int) $_POST['poll_expire'] : 0;
    $_POST['poll_change_vote'] = isset($_POST['poll_change_vote']) ? 1 : 0;
    $_POST['poll_guest_vote'] = isset($_POST['poll_guest_vote']) ? 1 : 0;
    // Make sure guests are actually allowed to vote generally.
    if ($_POST['poll_guest_vote']) {
        require_once $sourcedir . '/lib/Subs-Members.php';
        $allowedGroups = groupsAllowedTo('poll_vote', $board);
        if (!in_array(-1, $allowedGroups['allowed'])) {
            $_POST['poll_guest_vote'] = 0;
        }
    }
    // Ensure that the number options allowed makes sense, and the expiration date is valid.
    if (!$isEdit || allowedTo('moderate_board')) {
        $_POST['poll_expire'] = $_POST['poll_expire'] > 9999 ? 9999 : ($_POST['poll_expire'] < 0 ? 0 : $_POST['poll_expire']);
        if (empty($_POST['poll_expire']) && $_POST['poll_hide'] == 2) {
            $_POST['poll_hide'] = 1;
        } elseif (!$isEdit || $_POST['poll_expire'] != ceil($bcinfo['expire_time'] <= time() ? -1 : ($bcinfo['expire_time'] - time()) / (3600 * 24))) {
            $_POST['poll_expire'] = empty($_POST['poll_expire']) ? '0' : time() + $_POST['poll_expire'] * 3600 * 24;
        } else {
            $_POST['poll_expire'] = $bcinfo['expire_time'];
        }
        if (empty($_POST['poll_max_votes']) || $_POST['poll_max_votes'] <= 0) {
            $_POST['poll_max_votes'] = 1;
        } else {
            $_POST['poll_max_votes'] = (int) $_POST['poll_max_votes'];
        }
    }
    // If we're editing, let's commit the changes.
    if ($isEdit) {
        smf_db_query('
			UPDATE {db_prefix}polls
			SET question = {string:question}, change_vote = {int:change_vote},' . (allowedTo('moderate_board') ? '
				hide_results = {int:hide_results}, expire_time = {int:expire_time}, max_votes = {int:max_votes},
				guest_vote = {int:guest_vote}' : '
				hide_results = CASE WHEN expire_time = {int:expire_time_zero} AND {int:hide_results} = 2 THEN 1 ELSE {int:hide_results} END') . '
			WHERE id_poll = {int:id_poll}', array('change_vote' => $_POST['poll_change_vote'], 'hide_results' => $_POST['poll_hide'], 'expire_time' => !empty($_POST['poll_expire']) ? $_POST['poll_expire'] : 0, 'max_votes' => !empty($_POST['poll_max_votes']) ? $_POST['poll_max_votes'] : 0, 'guest_vote' => $_POST['poll_guest_vote'], 'expire_time_zero' => 0, 'id_poll' => $bcinfo['id_poll'], 'question' => $_POST['question']));
    } else {
        // Create the poll.
        smf_db_insert('', '{db_prefix}polls', array('question' => 'string-255', 'hide_results' => 'int', 'max_votes' => 'int', 'expire_time' => 'int', 'id_member' => 'int', 'poster_name' => 'string-255', 'change_vote' => 'int', 'guest_vote' => 'int'), array($_POST['question'], $_POST['poll_hide'], $_POST['poll_max_votes'], $_POST['poll_expire'], $user_info['id'], $user_info['username'], $_POST['poll_change_vote'], $_POST['poll_guest_vote']), array('id_poll'));
        // Set the poll ID.
        $bcinfo['id_poll'] = smf_db_insert_id('{db_prefix}polls', 'id_poll');
        // Link the poll to the topic
        smf_db_query('
			UPDATE {db_prefix}topics
			SET id_poll = {int:id_poll}
			WHERE id_topic = {int:current_topic}', array('current_topic' => $topic, 'id_poll' => $bcinfo['id_poll']));
    }
    // Get all the choices.  (no better way to remove all emptied and add previously non-existent ones.)
    $request = smf_db_query('
		SELECT id_choice
		FROM {db_prefix}poll_choices
		WHERE id_poll = {int:id_poll}', array('id_poll' => $bcinfo['id_poll']));
    $choices = array();
    while ($row = mysql_fetch_assoc($request)) {
        $choices[] = $row['id_choice'];
    }
    mysql_free_result($request);
    $delete_options = array();
    foreach ($_POST['options'] as $k => $option) {
        // Make sure the key is numeric for sanity's sake.
        $k = (int) $k;
        // They've cleared the box.  Either they want it deleted, or it never existed.
        if (trim($option) == '') {
            // They want it deleted.  Bye.
            if (in_array($k, $choices)) {
                $delete_options[] = $k;
            }
            // Skip the rest...
            continue;
        }
        // Dress the option up for its big date with the database.
        $option = commonAPI::htmlspecialchars($option);
        // If it's already there, update it.  If it's not... add it.
        if (in_array($k, $choices)) {
            smf_db_query('
				UPDATE {db_prefix}poll_choices
				SET label = {string:option_name}
				WHERE id_poll = {int:id_poll}
					AND id_choice = {int:id_choice}', array('id_poll' => $bcinfo['id_poll'], 'id_choice' => $k, 'option_name' => $option));
        } else {
            smf_db_insert('', '{db_prefix}poll_choices', array('id_poll' => 'int', 'id_choice' => 'int', 'label' => 'string-255', 'votes' => 'int'), array($bcinfo['id_poll'], $k, $option, 0), array());
        }
    }
    // I'm sorry, but... well, no one was choosing you.  Poor options, I'll put you out of your misery.
    if (!empty($delete_options)) {
        smf_db_query('
			DELETE FROM {db_prefix}log_polls
			WHERE id_poll = {int:id_poll}
				AND id_choice IN ({array_int:delete_options})', array('delete_options' => $delete_options, 'id_poll' => $bcinfo['id_poll']));
        smf_db_query('
			DELETE FROM {db_prefix}poll_choices
			WHERE id_poll = {int:id_poll}
				AND id_choice IN ({array_int:delete_options})', array('delete_options' => $delete_options, 'id_poll' => $bcinfo['id_poll']));
    }
    // Shall I reset the vote count, sir?
    if (isset($_POST['resetVoteCount'])) {
        smf_db_query('
			UPDATE {db_prefix}polls
			SET num_guest_voters = {int:no_votes}, reset_poll = {int:time}
			WHERE id_poll = {int:id_poll}', array('no_votes' => 0, 'id_poll' => $bcinfo['id_poll'], 'time' => time()));
        smf_db_query('
			UPDATE {db_prefix}poll_choices
			SET votes = {int:no_votes}
			WHERE id_poll = {int:id_poll}', array('no_votes' => 0, 'id_poll' => $bcinfo['id_poll']));
        smf_db_query('
			DELETE FROM {db_prefix}log_polls
			WHERE id_poll = {int:id_poll}', array('id_poll' => $bcinfo['id_poll']));
    }
    // Off we go.
    redirectexit('topic=' . $topic . '.' . $_REQUEST['start']);
}
Exemplo n.º 26
0
function validatePassword($password, $username, $restrict_in = array())
{
    global $modSettings, $smcFunc;
    // Perform basic requirements first.
    if (commonAPI::strlen($password) < (empty($modSettings['password_strength']) ? 4 : 8)) {
        return 'short';
    }
    // Is this enough?
    if (empty($modSettings['password_strength'])) {
        return null;
    }
    // Otherwise, perform the medium strength test - checking if password appears in the restricted string.
    if (preg_match('~\\b' . preg_quote($password, '~') . '\\b~', implode(' ', $restrict_in)) != 0) {
        return 'restricted_words';
    } elseif (commonAPI::strpos($password, $username) !== false) {
        return 'restricted_words';
    }
    // !!! If pspell is available, use it on the word, and return restricted_words if it doesn't give "bad spelling"?
    // If just medium, we're done.
    if ($modSettings['password_strength'] == 1) {
        return null;
    }
    // Otherwise, hard test next, check for numbers and letters, uppercase too.
    $good = preg_match('~(\\D\\d|\\d\\D)~', $password) != 0;
    $good &= commonAPI::strtolower($password) != $password;
    return $good ? null : 'chars';
}
Exemplo n.º 27
0
function getBoardIndex($boardIndexOptions)
{
    global $smcFunc, $scripturl, $user_info, $modSettings, $txt;
    global $settings, $context;
    // For performance, track the latest post while going through the boards.
    if (!empty($boardIndexOptions['set_latest_post'])) {
        $latest_post = array('timestamp' => 0, 'ref' => 0);
    }
    // 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 = smf_db_query('
		SELECT' . ($boardIndexOptions['include_categories'] ? '
			c.id_cat, c.name AS cat_name, c.description AS cat_desc,' : '') . '
			b.id_board, b.name AS board_name, b.description, b.redirect, b.icon AS boardicon,
			CASE WHEN b.redirect != {string:blank_string} THEN 1 ELSE 0 END AS is_redirect,
			b.num_posts, b.num_topics, b.unapproved_posts, b.unapproved_topics, b.id_parent, b.allow_topics,
			IFNULL(m.poster_time, 0) AS poster_time, IFNULL(mem.member_name, m.poster_name) AS poster_name,
			m.subject, m1.subject AS first_subject, m.id_topic, t.id_first_msg AS id_first_msg, t.id_prefix, m1.icon AS icon, IFNULL(mem.real_name, m.poster_name) AS real_name, p.name as topic_prefix,
			' . ($user_info['is_guest'] ? ' 1 AS is_read, 0 AS new_from,' : '
			(IFNULL(lb.id_msg, 0) >= b.id_msg_updated) AS is_read, IFNULL(lb.id_msg, -1) + 1 AS new_from,' . ($boardIndexOptions['include_categories'] ? '
			c.can_collapse, IFNULL(cc.id_member, 0) AS is_collapsed,' : '')) . '
			IFNULL(mem.id_member, 0) AS id_member, m.id_msg,
			IFNULL(mods_mem.id_member, 0) AS id_moderator, mods_mem.real_name AS mod_real_name
		FROM {db_prefix}boards AS b' . ($boardIndexOptions['include_categories'] ? '
			LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat)' : '') . '
			LEFT JOIN {db_prefix}messages AS m ON (m.id_msg = b.id_last_msg)
			LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic)
			LEFT JOIN {db_prefix}prefixes AS p ON (p.id_prefix = t.id_prefix)
			LEFT JOIN {db_prefix}messages AS m1 ON (m1.id_msg = t.id_first_msg)
			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)' . ($user_info['is_guest'] ? '' : '
			LEFT JOIN {db_prefix}log_boards AS lb ON (lb.id_board = b.id_board AND lb.id_member = {int:current_member})' . ($boardIndexOptions['include_categories'] ? '
			LEFT JOIN {db_prefix}collapsed_categories AS cc ON (cc.id_cat = c.id_cat AND cc.id_member = {int:current_member})' : '')) . '
			LEFT JOIN {db_prefix}moderators AS mods ON (mods.id_board = b.id_board)
			LEFT JOIN {db_prefix}members AS mods_mem ON (mods_mem.id_member = mods.id_member)
		WHERE {query_see_board}' . (empty($boardIndexOptions['countChildPosts']) ? empty($boardIndexOptions['base_level']) ? '' : '
			AND b.child_level >= {int:child_level}' : '
			AND b.child_level BETWEEN ' . $boardIndexOptions['base_level'] . ' AND ' . ($boardIndexOptions['base_level'] + 1)), array('current_member' => $user_info['id'], 'child_level' => $boardIndexOptions['base_level'], 'blank_string' => ''));
    // Start with an empty array.
    if ($boardIndexOptions['include_categories']) {
        $categories = array();
    } else {
        $this_category = array();
    }
    $total_ignored_boards = 0;
    // Run through the categories and boards (or only boards)....
    while ($row_board = mysql_fetch_assoc($result_boards)) {
        // Perhaps we are ignoring this board?
        $ignoreThisBoard = in_array($row_board['id_board'], $user_info['ignoreboards']);
        $total_ignored_boards += $ignoreThisBoard ? 1 : 0;
        $row_board['is_read'] = !empty($row_board['is_read']) || $ignoreThisBoard ? '1' : '0';
        if ($boardIndexOptions['include_categories']) {
            // Haven't set this category yet.
            if (empty($categories[$row_board['id_cat']])) {
                $categories[$row_board['id_cat']] = array('id' => $row_board['id_cat'], 'name' => $row_board['cat_name'], 'desc' => $row_board['cat_desc'], 'is_collapsed' => isset($row_board['can_collapse']) && $row_board['can_collapse'] == 1 && $row_board['is_collapsed'] > 0, 'can_collapse' => isset($row_board['can_collapse']) && $row_board['can_collapse'] == 1, 'collapse_href' => isset($row_board['can_collapse']) ? $scripturl . '?action=collapse;c=' . $row_board['id_cat'] . ';sa=' . ($row_board['is_collapsed'] > 0 ? 'expand;' : 'collapse;') . $context['session_var'] . '=' . $context['session_id'] . '#c' . $row_board['id_cat'] : '', 'collapse_image' => isset($row_board['can_collapse']) ? '<img class="clipsrc ' . ($row_board['is_collapsed'] ? ' _expand' : '_collapse') . '" src="' . $settings['images_url'] . '/clipsrc.png" alt="-" />' : '', 'href' => $scripturl . '#c' . $row_board['id_cat'], 'boards' => array(), 'is_root' => $row_board['cat_name'][0] === '!' ? true : false, 'new' => false);
                $categories[$row_board['id_cat']]['link'] = '<a id="c' . $row_board['id_cat'] . '"></a>' . ($categories[$row_board['id_cat']]['can_collapse'] ? '<a href="' . $categories[$row_board['id_cat']]['collapse_href'] . '">' . $row_board['cat_name'] . '</a>' : $row_board['cat_name']);
            }
            // 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']) {
                $categories[$row_board['id_cat']]['new'] |= empty($row_board['is_read']) && $row_board['poster_name'] != '';
            }
            // Avoid showing category unread link where it only has redirection boards.
            $categories[$row_board['id_cat']]['show_unread'] = !empty($categories[$row_board['id_cat']]['show_unread']) ? 1 : !$row_board['is_redirect'];
            // Collapsed category - don't do any of this.
            //if ($categories[$row_board['id_cat']]['is_collapsed'])
            //	continue;
            // Let's save some typing.  Climbing the array might be slower, anyhow.
            $this_category =& $categories[$row_board['id_cat']]['boards'];
        }
        // This is a parent board.
        if ($row_board['id_parent'] == $boardIndexOptions['parent_id']) {
            // Is this a new board, or just another moderator?
            if (!isset($this_category[$row_board['id_board']])) {
                // Not a child.
                $isChild = false;
                $href = URL::board($row_board['id_board'], $row_board['board_name'], 0, false);
                $this_category[$row_board['id_board']] = array('new' => empty($row_board['is_read']), 'id' => $row_board['id_board'], 'name' => $row_board['board_name'], 'description' => $row_board['description'], 'moderators' => array(), 'link_moderators' => array(), 'children' => array(), 'link_children' => array(), 'children_new' => false, 'topics' => $row_board['num_topics'], 'posts' => $row_board['num_posts'], 'is_redirect' => $row_board['is_redirect'], 'is_page' => !empty($row_board['redirect']) && $row_board['redirect'][0] === '%' && intval(substr($row_board['redirect'], 1)) > 0, 'redirect' => $row_board['redirect'], 'boardicon' => $row_board['boardicon'], 'unapproved_topics' => $row_board['unapproved_topics'], 'unapproved_posts' => $row_board['unapproved_posts'] - $row_board['unapproved_topics'], 'can_approve_posts' => !empty($user_info['mod_cache']['ap']) && ($user_info['mod_cache']['ap'] == array(0) || in_array($row_board['id_board'], $user_info['mod_cache']['ap'])), 'href' => $href, 'link' => '<a href="' . $href . '">' . $row_board['board_name'] . '</a>', 'act_as_cat' => $row_board['allow_topics'] ? false : true, 'ignored' => $ignoreThisBoard);
                $this_category[$row_board['id_board']]['page_link'] = $this_category[$row_board['id_board']]['is_page'] ? URL::topic(intval(substr($this_category[$row_board['id_board']]['redirect'], 1)), $this_category[$row_board['id_board']]['name'], 0) : '';
            }
            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['mod_real_name'], 'href' => $scripturl . '?action=profile;u=' . $row_board['id_moderator'], 'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row_board['id_moderator'] . '" title="' . $txt['board_moderator'] . '">' . $row_board['mod_real_name'] . '</a>');
                $this_category[$row_board['id_board']]['link_moderators'][] = '<a href="' . $scripturl . '?action=profile;u=' . $row_board['id_moderator'] . '" title="' . $txt['board_moderator'] . '">' . $row_board['mod_real_name'] . '</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;
            $href = URL::board($row_board['id_board'], $row_board['board_name'], 0, false);
            $this_category[$row_board['id_parent']]['children'][$row_board['id_board']] = array('id' => $row_board['id_board'], 'name' => $row_board['board_name'], 'description' => $row_board['description'], 'short_description' => !empty($row_board['description']) ? $modSettings['child_board_desc_shortened'] ? '(' . commonAPI::substr($row_board['description'], 0, $modSettings['child_board_desc_shortened']) . '...)' : '(' . $row_board['description'] . ')' : '', 'new' => empty($row_board['is_read']) && $row_board['poster_name'] != '', 'topics' => $row_board['num_topics'], 'posts' => $row_board['num_posts'], 'is_redirect' => $row_board['is_redirect'], 'is_page' => !empty($row_board['redirect']) && $row_board['redirect'][0] === '%' && intval(substr($row_board['redirect'], 1)) > 0, 'redirect' => $row_board['redirect'], 'boardicon' => $row_board['boardicon'], 'unapproved_topics' => $row_board['unapproved_topics'], 'unapproved_posts' => $row_board['unapproved_posts'] - $row_board['unapproved_topics'], 'can_approve_posts' => !empty($user_info['mod_cache']['ap']) && ($user_info['mod_cache']['ap'] == array(0) || in_array($row_board['id_board'], $user_info['mod_cache']['ap'])), 'href' => $href, 'link' => '<a href="' . $href . '">' . $row_board['board_name'] . '</a>', 'act_as_cat' => $row_board['allow_topics'] ? false : true, 'ignored' => $ignoreThisBoard);
            $this_category[$row_board['id_parent']]['children'][$row_board['id_board']]['page_link'] = $this_category[$row_board['id_parent']]['children'][$row_board['id_board']]['is_page'] ? URL::topic(intval(substr($this_category[$row_board['id_parent']]['children'][$row_board['id_board']]['redirect'], 1)), $this_category[$row_board['id_parent']]['children'][$row_board['id_board']]['name'], 0) : '';
            // Counting child board posts is... slow :/.
            if (!empty($boardIndexOptions['countChildPosts']) && !$row_board['is_redirect']) {
                $this_category[$row_board['id_parent']]['posts'] += $row_board['num_posts'];
                $this_category[$row_board['id_parent']]['topics'] += $row_board['num_topics'];
            }
            // Does this board contain new boards?
            $this_category[$row_board['id_parent']]['children_new'] |= empty($row_board['is_read']);
            // 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($boardIndexOptions['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']]) && !$row_board['is_redirect']) {
                $parent_map[$row_board['id_parent']][0]['posts'] += $row_board['num_posts'];
                $parent_map[$row_board['id_parent']][0]['topics'] += $row_board['num_topics'];
                $parent_map[$row_board['id_parent']][1]['posts'] += $row_board['num_posts'];
                $parent_map[$row_board['id_parent']][1]['topics'] += $row_board['num_topics'];
                continue;
            }
            continue;
        } else {
            continue;
        }
        // Prepare the subject, and make sure it's not too long.
        censorText($row_board['subject']);
        $mhref = $row_board['poster_name'] != '' && !empty($row_board['id_member']) ? URL::user($row_board['id_member'], $row_board['real_name']) : '';
        $this_last_post = array('id' => $row_board['id_msg'], 'time' => $row_board['poster_time'] > 0 ? timeformat($row_board['poster_time']) : $txt['not_applicable'], 'timestamp' => forum_time(true, $row_board['poster_time']), 'member' => array('id' => $row_board['id_member'], 'username' => $row_board['poster_name'] != '' ? $row_board['poster_name'] : $txt['not_applicable'], 'name' => $row_board['real_name'], 'href' => $mhref, 'link' => $row_board['poster_name'] != '' ? !empty($row_board['id_member']) ? '<a onclick="getMcard(' . $row_board['id_member'] . ', $(this));return(false);" href="' . $mhref . '">' . $row_board['real_name'] . '</a>' : $row_board['real_name'] : $txt['not_applicable']), 'start' => 'msg' . $row_board['new_from'], 'topic' => $row_board['id_topic'], 'prefix' => !empty($row_board['topic_prefix']) ? html_entity_decode($row_board['topic_prefix']) . '&nbsp;' : '');
        $row_board['short_subject'] = shorten_subject($row_board['subject'], 50);
        $this_last_post['subject'] = $row_board['short_subject'];
        $this_first_post = array('id' => $row_board['id_first_msg'], 'icon' => $row_board['icon'], 'icon_url' => getPostIcon($row_board['icon']));
        // Provide the href and link.
        if ($row_board['subject'] != '') {
            $this_last_post['href'] = URL::topic($row_board['id_topic'], $row_board['first_subject'], 0, false, '.msg' . ($user_info['is_guest'] ? $row_board['id_msg'] : $row_board['new_from']), '#new');
            if (empty($row_board['is_read'])) {
                $this_last_post['href'] = URL::addParam($this_last_post['href'], 'boardseen');
            }
            //$this_last_post['href'] = $scripturl . '?topic=' . $row_board['id_topic'] . '.msg' . ($user_info['is_guest'] ? $row_board['id_msg'] : $row_board['new_from']) . (empty($row_board['is_read']) ? ';boardseen' : '') . '#new';
            $this_last_post['link'] = '<a rel="nofollow" href="' . $this_last_post['href'] . '" title="' . $row_board['subject'] . '">' . $row_board['short_subject'] . '</a>';
            $this_last_post['topichref'] = URL::topic($row_board['id_topic'], $row_board['first_subject'], 0);
            // $scripturl . '?topic=' . $row_board['id_topic'];
            $this_last_post['topiclink'] = '<a href="' . $this_last_post['topichref'] . '" title="' . $row_board['first_subject'] . '">' . $row_board['short_subject'] . '</a>';
        } else {
            $this_last_post['href'] = '';
            $this_last_post['link'] = $txt['not_applicable'];
            $this_last_post['topiclink'] = $txt['not_applicable'];
        }
        // Set the last post in the parent board.
        if ($row_board['id_parent'] == $boardIndexOptions['parent_id'] || $isChild && !empty($row_board['poster_time']) && $this_category[$row_board['id_parent']]['last_post']['timestamp'] < forum_time(true, $row_board['poster_time'])) {
            $this_category[$isChild ? $row_board['id_parent'] : $row_board['id_board']]['last_post'] = $this_last_post;
            $this_category[$isChild ? $row_board['id_parent'] : $row_board['id_board']]['first_post'] = $this_first_post;
        }
        // Just in the child...?
        if ($isChild) {
            $this_category[$row_board['id_parent']]['children'][$row_board['id_board']]['last_post'] = $this_last_post;
            $this_category[$row_board['id_parent']]['children'][$row_board['id_board']]['first_post'] = $this_first_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['poster_name'] != '';
        } elseif ($row_board['poster_name'] == '') {
            $this_category[$row_board['id_board']]['new'] = false;
        }
        // Determine a global most recent topic.
        if (!empty($boardIndexOptions['set_latest_post']) && !empty($row_board['poster_time']) && $row_board['poster_time'] > $latest_post['timestamp'] && !$ignoreThisBoard) {
            $latest_post = array('timestamp' => $row_board['poster_time'], 'ref' => &$this_category[$isChild ? $row_board['id_parent'] : $row_board['id_board']]['last_post']);
        }
    }
    mysql_free_result($result_boards);
    // By now we should know the most recent post...if we wanna know it that is.
    if (!empty($boardIndexOptions['set_latest_post']) && !empty($latest_post['ref'])) {
        $context['latest_post'] = $latest_post['ref'];
    }
    $hidden_boards = $visible_boards = 0;
    $context['hidden_boards']['id'] = $context['hidden_boards']['is_collapsed'] = 0;
    // only run this if we actually have some boards on the ignore list to save cycles.
    if ($total_ignored_boards) {
        if ($boardIndexOptions['include_categories']) {
            foreach ($categories as &$cat) {
                $hidden_boards += hideIgnoredBoards($cat['boards']);
            }
        } else {
            if (count($this_category)) {
                $hidden_boards += hideIgnoredBoards($this_category);
            }
        }
        $context['hidden_boards']['notice'] = $txt[$hidden_boards > 1 ? 'hidden_boards_notice_many' : 'hidden_boards_notice_one'];
        $context['hidden_boards']['setup_notice'] = sprintf($txt['hidden_boards_setup_notice'], $scripturl . '?action=profile;area=ignoreboards');
    }
    $context['hidden_boards']['hidden_count'] = $hidden_boards;
    $context['hidden_boards']['visible_count'] = $visible_boards;
    return $boardIndexOptions['include_categories'] ? $categories : $this_category;
}
Exemplo n.º 28
0
function template_package_list()
{
    global $context, $settings, $options, $txt, $scripturl, $smcFunc;
    echo '
	<div id="admincenter">
		<div class="cat_bar">
			<h3>' . $context['page_title'] . '</h3>
		</div>
		<div class="blue_container">
			<div class="content">';
    // No packages, as yet.
    if (empty($context['package_list'])) {
        echo '
				<ul>
					<li>', $txt['no_packages'], '</li>
				</ul>';
    } else {
        echo '
				<ul id="package_list">';
        foreach ($context['package_list'] as $i => $packageSection) {
            echo '
					<li>
						<strong><img id="ps_img_', $i, '" src="', $settings['images_url'], '/upshrink.png" alt="*" style="display: none;" /> ', $packageSection['title'], '</strong>';
            if (!empty($packageSection['text'])) {
                echo '
						<div class="information">', $packageSection['text'], '</div>';
            }
            echo '
						<', $context['list_type'], ' id="package_section_', $i, '" class="packages">';
            $alt = false;
            foreach ($packageSection['items'] as $id => $package) {
                echo '
							<li>';
                // Textual message. Could be empty just for a blank line...
                if ($package['is_text']) {
                    echo '
								', empty($package['name']) ? '&nbsp;' : $package['name'];
                } elseif ($package['is_line']) {
                    echo '
							<hr class="hrcolor" />';
                } elseif ($package['is_remote']) {
                    echo '
							<strong>', $package['link'], '</strong>';
                } elseif ($package['is_heading'] || $package['is_title']) {
                    echo '
							<strong>', $package['name'], '</strong>';
                } else {
                    // 1. Some mod [ Download ].
                    echo '
							<strong><img id="ps_img_', $i, '_pkg_', $id, '" src="', $settings['images_url'], '/upshrink.png" alt="*" style="display: none;" /> ', $package['can_install'] ? '<strong>' . $package['name'] . '</strong> <a href="' . $package['download']['href'] . '">[ ' . $txt['download'] . ' ]</a>' : $package['name'];
                    // Mark as installed and current?
                    if ($package['is_installed'] && !$package['is_newer']) {
                        echo '<img src="', $settings['images_url'], '/icons/package_', $package['is_current'] ? 'installed' : 'old', '.gif" width="12" height="11" align="middle" style="margin-left: 2ex;" alt="', $package['is_current'] ? $txt['package_installed_current'] : $txt['package_installed_old'], '" />';
                    }
                    echo '
							</strong>
							<ul id="package_section_', $i, '_pkg_', $id, '" class="package_section">';
                    // Show the mod type?
                    if ($package['type'] != '') {
                        echo '
								<li class="package_section">', $txt['package_type'], ':&nbsp; ', commonAPI::ucwords(commonAPI::strtolower($package['type'])), '</li>';
                    }
                    // Show the version number?
                    if ($package['version'] != '') {
                        echo '
								<li class="package_section">', $txt['mod_version'], ':&nbsp; ', $package['version'], '</li>';
                    }
                    // How 'bout the author?
                    if (!empty($package['author']) && $package['author']['name'] != '' && isset($package['author']['link'])) {
                        echo '
								<li class="package_section">', $txt['mod_author'], ':&nbsp; ', $package['author']['link'], '</li>';
                    }
                    // The homepage....
                    if ($package['author']['website']['link'] != '') {
                        echo '
								<li class="package_section">', $txt['author_website'], ':&nbsp; ', $package['author']['website']['link'], '</li>';
                    }
                    // Desciption: bleh bleh!
                    // Location of file: http://someplace/.
                    echo '
								<li class="package_section">', $txt['file_location'], ':&nbsp; <a href="', $package['href'], '">', $package['href'], '</a></li>
								<li class="package_section"><div class="information">', $txt['package_description'], ':&nbsp; ', $package['description'], '</div></li>
							</ul>';
                }
                $alt = !$alt;
                echo '
						</li>';
            }
            echo '
					</', $context['list_type'], '>
						</li>';
        }
        echo '
				</ul>';
    }
    echo '
			</div>
		</div>
		<div class="padding smalltext floatleft">
			', $txt['package_installed_key'], '
			<img src="', $settings['images_url'], '/icons/package_installed.gif" alt="" align="middle" style="margin-left: 1ex;" /> ', $txt['package_installed_current'], '
			<img src="', $settings['images_url'], '/icons/package_old.gif" alt="" align="middle" style="margin-left: 2ex;" /> ', $txt['package_installed_old'], '
		</div>
	</div>
	<br class="clear" />

		';
    // Now go through and turn off all the sections.
    if (!empty($context['package_list'])) {
        $section_count = count($context['package_list']);
        echo '
			<script type="text/javascript"><!-- // --><![CDATA[';
        foreach ($context['package_list'] as $section => $ps) {
            echo '';
            foreach ($ps['items'] as $id => $package) {
                if (!$package['is_text'] && !$package['is_line'] && !$package['is_remote']) {
                    echo '';
                }
            }
        }
        echo '
			// ]]></script>';
    }
}
Exemplo n.º 29
0
function AutoSuggest_Search_Tags()
{
    global $user_info, $txt, $smcFunc;
    $_REQUEST['search'] = trim(commonAPI::strtolower($_REQUEST['search'])) . '*';
    $_REQUEST['search'] = strtr($_REQUEST['search'], array('%' => '\\%', '_' => '\\_', '*' => '%', '?' => '_', '&#038;' => '&amp;'));
    // Find tags
    $request = smf_db_query('
		SELECT id_member, real_name
		FROM {db_prefix}tags
		WHERE tag LIKE {string:search} 
		LIMIT ' . (strlen($_REQUEST['search']) <= 2 ? '100' : '800'), array('search' => $_REQUEST['search']));
    $xml_data = array('tags' => array('identifier' => 'tag', 'children' => array()));
    while ($row = mysql_fetch_assoc($request)) {
        $xml_data['tags']['children'][] = array('attributes' => array('id' => $row['id_tag']), 'value' => $row['tag']);
    }
    mysql_free_result($request);
    return $xml_data;
}
Exemplo n.º 30
0
function getXmlRecent($xml_format)
{
    global $user_info, $scripturl, $modSettings, $board;
    global $query_this_board, $smcFunc, $settings, $context;
    $done = false;
    $loops = 0;
    while (!$done) {
        $optimize_msg = implode(' AND ', $context['optimize_msg']);
        $request = smf_db_query('
			SELECT m.id_msg
			FROM {db_prefix}messages AS m
				INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
				INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic)
			WHERE ' . $query_this_board . (empty($optimize_msg) ? '' : '
				AND {raw:optimize_msg}') . (empty($board) ? '' : '
				AND m.id_board = {int:current_board}') . ($modSettings['postmod_active'] ? '
				AND m.approved = {int:is_approved}' : '') . '
			ORDER BY m.id_msg DESC
			LIMIT {int:limit}', array('limit' => $_GET['limit'], 'current_board' => $board, 'is_approved' => 1, 'optimize_msg' => $optimize_msg));
        // If we don't have $_GET['limit'] results, try again with an unoptimized version covering all rows.
        if ($loops < 2 && mysql_num_rows($request) < $_GET['limit']) {
            mysql_free_result($request);
            if (empty($_REQUEST['boards']) && empty($board)) {
                unset($context['optimize_msg']['lowest']);
            } else {
                $context['optimize_msg']['lowest'] = $loops ? 'm.id_msg >= t.id_first_msg' : 'm.id_msg >= (t.id_last_msg - t.id_first_msg) / 2';
            }
            $loops++;
        } else {
            $done = true;
        }
    }
    $messages = array();
    while ($row = mysql_fetch_assoc($request)) {
        $messages[] = $row['id_msg'];
    }
    mysql_free_result($request);
    if (empty($messages)) {
        return array();
    }
    // Find the most recent posts this user can see.
    $request = smf_db_query('
		SELECT
			m.smileys_enabled, m.poster_time, m.id_msg, m.subject, m.body, m.id_topic, t.id_board,
			b.name AS bname, t.num_replies, m.id_member, m.icon, mf.id_member AS id_first_member,
			IFNULL(mem.real_name, m.poster_name) AS poster_name, mf.subject AS first_subject,
			IFNULL(memf.real_name, mf.poster_name) AS first_poster_name, mem.hide_email,
			IFNULL(mem.email_address, m.poster_email) AS poster_email, m.modified_time
		FROM {db_prefix}messages AS m
			INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic)
			INNER JOIN {db_prefix}messages AS mf ON (mf.id_msg = t.id_first_msg)
			INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board)
			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)
			LEFT JOIN {db_prefix}members AS memf ON (memf.id_member = mf.id_member)
		WHERE m.id_msg IN ({array_int:message_list})
			' . (empty($board) ? '' : 'AND t.id_board = {int:current_board}') . '
		ORDER BY m.id_msg DESC
		LIMIT {int:limit}', array('limit' => $_GET['limit'], 'current_board' => $board, 'message_list' => $messages));
    $data = array();
    while ($row = mysql_fetch_assoc($request)) {
        // Limit the length of the message, if the option is set.
        if (!empty($modSettings['xmlnews_maxlen']) && commonAPI::strlen(str_replace('<br />', "\n", $row['body'])) > $modSettings['xmlnews_maxlen']) {
            $row['body'] = strtr(commonAPI::substr(str_replace('<br />', "\n", $row['body']), 0, $modSettings['xmlnews_maxlen'] - 3), array("\n" => '<br />')) . '...';
        }
        $row['body'] = parse_bbc($row['body'], $row['smileys_enabled'], $row['id_msg']);
        censorText($row['body']);
        censorText($row['subject']);
        // Doesn't work as well as news, but it kinda does..
        if ($xml_format == 'rss' || $xml_format == 'rss2') {
            $data[] = array('title' => $row['subject'], 'link' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'], 'description' => cdata_parse($row['body']), 'author' => in_array(showEmailAddress(!empty($row['hide_email']), $row['id_member']), array('yes', 'yes_permission_override')) ? $row['poster_email'] : null, 'category' => cdata_parse($row['bname']), 'comments' => $scripturl . '?action=post;topic=' . $row['id_topic'] . '.0', 'pubDate' => gmdate('D, d M Y H:i:s \\G\\M\\T', $row['poster_time']), 'guid' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg']);
        } elseif ($xml_format == 'rdf') {
            $data[] = array('title' => $row['subject'], 'link' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'], 'description' => cdata_parse($row['body']));
        } elseif ($xml_format == 'atom') {
            $data[] = array('title' => $row['subject'], 'link' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'], 'summary' => cdata_parse($row['body']), 'category' => array('term' => $row['id_board'], 'label' => cdata_parse($row['bname'])), 'author' => array('name' => $row['poster_name'], 'email' => in_array(showEmailAddress(!empty($row['hide_email']), $row['id_member']), array('yes', 'yes_permission_override')) ? $row['poster_email'] : null, 'uri' => !empty($row['id_member']) ? $scripturl . '?action=profile;u=' . $row['id_member'] : ''), 'published' => gmstrftime('%Y-%m-%dT%H:%M:%SZ', $row['poster_time']), 'updated' => gmstrftime('%Y-%m-%dT%H:%M:%SZ', empty($row['modified_time']) ? $row['poster_time'] : $row['modified_time']), 'id' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'], 'icon' => $settings['images_url'] . '/icons/' . $row['icon'] . '.gif');
        } else {
            $data[] = array('time' => htmlspecialchars(strip_tags(timeformat($row['poster_time']))), 'id' => $row['id_msg'], 'subject' => cdata_parse($row['subject']), 'body' => cdata_parse($row['body']), 'starter' => array('name' => cdata_parse($row['first_poster_name']), 'id' => $row['id_first_member'], 'link' => !empty($row['id_first_member']) ? $scripturl . '?action=profile;u=' . $row['id_first_member'] : ''), 'poster' => array('name' => cdata_parse($row['poster_name']), 'id' => $row['id_member'], 'link' => !empty($row['id_member']) ? $scripturl . '?action=profile;u=' . $row['id_member'] : ''), 'topic' => array('subject' => cdata_parse($row['first_subject']), 'id' => $row['id_topic'], 'link' => $scripturl . '?topic=' . $row['id_topic'] . '.new#new'), 'board' => array('name' => cdata_parse($row['bname']), 'id' => $row['id_board'], 'link' => $scripturl . '?board=' . $row['id_board'] . '.0'), 'link' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg']);
        }
    }
    mysql_free_result($request);
    return $data;
}