Example #1
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');
}
Example #2
0
    function updateTopics($topics)
    {
        global $context, $smcFunc;
        if (empty($topics)) {
            return;
        }
        // Get subject from database as we need it
        $request = smf_db_query('
			SELECT t.id_topic, mf.subject
			FROM {db_prefix}topics AS t
				INNER JOIN {db_prefix}messages AS mf ON (mf.id_msg = t.id_first_msg)
			WHERE t.id_topic IN({array_int:topics})' . (!empty($context['rt_ignore']) ? '
				AND t.id_board NOT IN({array_int:ignored})' : ''), array('topics' => $topics, 'ignored' => $context['rt_ignore']));
        $rows = array();
        while ($row = mysql_fetch_assoc($request)) {
            $rows[] = array($row['id_topic'], $row['subject']);
        }
        mysql_free_result($request);
        if (empty($rows)) {
            return true;
        }
        // Insert to cache
        smf_db_insert('replace', '{db_prefix}related_subjects', array('id_topic' => 'int', 'subject' => 'string-255'), $rows, array('id_topic'));
        // Search for relations
        $relatedRows = array();
        foreach ($rows as $id_topic) {
            list($id_topic, $subject) = $id_topic;
            $relatedTopics = $this->__searchRelated($subject);
            foreach ($relatedTopics as $id_topic_rel) {
                list($id_topic_rel, $score) = $id_topic_rel;
                if ($id_topic_rel == $id_topic) {
                    continue;
                }
                $relatedRows[] = array($id_topic, $id_topic_rel, $score);
            }
            unset($relatedTopics);
        }
        relatedAddRelatedTopic($relatedRows, 'fulltext');
        return true;
    }
Example #3
0
function EditMembergroup()
{
    global $context, $txt, $sourcedir, $modSettings, $backend_subdir;
    $_REQUEST['group'] = isset($_REQUEST['group']) && $_REQUEST['group'] > 0 ? (int) $_REQUEST['group'] : 0;
    // Make sure this group is editable.
    if (!empty($_REQUEST['group'])) {
        $request = smf_db_query('
			SELECT id_group
			FROM {db_prefix}membergroups
			WHERE id_group = {int:current_group}' . (allowedTo('admin_forum') ? '' : '
				AND group_type != {int:is_protected}') . '
			LIMIT {int:limit}', array('current_group' => $_REQUEST['group'], 'is_protected' => 1, 'limit' => 1));
        list($_REQUEST['group']) = mysql_fetch_row($request);
        mysql_free_result($request);
    }
    // Now, do we have a valid id?
    if (empty($_REQUEST['group'])) {
        fatal_lang_error('membergroup_does_not_exist', false);
    }
    // The delete this membergroup button was pressed.
    if (isset($_POST['delete'])) {
        checkSession();
        require_once $sourcedir . '/lib/Subs-Membergroups.php';
        deleteMembergroups($_REQUEST['group']);
        redirectexit('action=admin;area=membergroups;');
    } elseif (isset($_POST['submit'])) {
        // Validate the session.
        checkSession();
        // Can they really inherit from this group?
        if ($_POST['group_inherit'] != -2 && !allowedTo('admin_forum')) {
            $request = smf_db_query('
				SELECT group_type
				FROM {db_prefix}membergroups
				WHERE id_group = {int:inherit_from}
				LIMIT {int:limit}', array('inherit_from' => $_POST['group_inherit'], 'limit' => 1));
            list($inherit_type) = mysql_fetch_row($request);
            mysql_free_result($request);
        }
        // Set variables to their proper value.
        $_POST['max_messages'] = isset($_POST['max_messages']) ? (int) $_POST['max_messages'] : 0;
        $_POST['min_posts'] = isset($_POST['min_posts']) && isset($_POST['group_type']) && $_POST['group_type'] == -1 && $_REQUEST['group'] > 3 ? abs($_POST['min_posts']) : ($_REQUEST['group'] == 4 ? 0 : -1);
        $_POST['stars'] = empty($_POST['star_count']) || $_POST['star_count'] < 0 ? '' : min((int) $_POST['star_count'], 99) . '#' . $_POST['star_image'];
        $_POST['group_desc'] = isset($_POST['group_desc']) && ($_REQUEST['group'] == 1 || isset($_POST['group_type']) && $_POST['group_type'] != -1) ? trim($_POST['group_desc']) : '';
        $_POST['group_type'] = !isset($_POST['group_type']) || $_POST['group_type'] < 0 || $_POST['group_type'] > 3 || $_POST['group_type'] == 1 && !allowedTo('admin_forum') ? 0 : (int) $_POST['group_type'];
        $_POST['group_hidden'] = empty($_POST['group_hidden']) || $_POST['min_posts'] != -1 || $_REQUEST['group'] == 3 ? 0 : (int) $_POST['group_hidden'];
        $_POST['group_inherit'] = $_REQUEST['group'] > 1 && $_REQUEST['group'] != 3 && (empty($inherit_type) || $inherit_type != 1) ? (int) $_POST['group_inherit'] : -2;
        // !!! Don't set online_color for the Moderators group?
        // Do the update of the membergroup settings.
        smf_db_query('
			UPDATE {db_prefix}membergroups
			SET group_name = {string:group_name}, online_color = {string:online_color},
				max_messages = {int:max_messages}, min_posts = {int:min_posts}, stars = {string:stars},
				description = {string:group_desc}, group_type = {int:group_type}, hidden = {int:group_hidden},
				id_parent = {int:group_inherit}
			WHERE id_group = {int:current_group}', array('max_messages' => $_POST['max_messages'], 'min_posts' => $_POST['min_posts'], 'group_type' => $_POST['group_type'], 'group_hidden' => $_POST['group_hidden'], 'group_inherit' => $_POST['group_inherit'], 'current_group' => (int) $_REQUEST['group'], 'group_name' => $_POST['group_name'], 'online_color' => $_POST['online_color'], 'stars' => $_POST['stars'], 'group_desc' => $_POST['group_desc']));
        // Time to update the boards this membergroup has access to.
        if ($_REQUEST['group'] == 2 || $_REQUEST['group'] > 3) {
            $_POST['boardaccess'] = empty($_POST['boardaccess']) || !is_array($_POST['boardaccess']) ? array() : $_POST['boardaccess'];
            foreach ($_POST['boardaccess'] as $key => $value) {
                $_POST['boardaccess'][$key] = (int) $value;
            }
            // Find all board this group is in, but shouldn't be in.
            $request = smf_db_query('
				SELECT id_board, member_groups
				FROM {db_prefix}boards
				WHERE FIND_IN_SET({string:current_group}, member_groups) != 0' . (empty($_POST['boardaccess']) ? '' : '
					AND id_board NOT IN ({array_int:board_access_list})'), array('current_group' => (int) $_REQUEST['group'], 'board_access_list' => $_POST['boardaccess']));
            while ($row = mysql_fetch_assoc($request)) {
                smf_db_query('
					UPDATE {db_prefix}boards
					SET member_groups = {string:member_group_access}
					WHERE id_board = {int:current_board}', array('current_board' => $row['id_board'], 'member_group_access' => implode(',', array_diff(explode(',', $row['member_groups']), array($_REQUEST['group'])))));
            }
            mysql_free_result($request);
            // Add the membergroup to all boards that hadn't been set yet.
            if (!empty($_POST['boardaccess'])) {
                smf_db_query('
					UPDATE {db_prefix}boards
					SET member_groups = CASE WHEN member_groups = {string:blank_string} THEN {string:group_id_string} ELSE CONCAT(member_groups, {string:comma_group}) END
					WHERE id_board IN ({array_int:board_list})
						AND FIND_IN_SET({int:current_group}, member_groups) = 0', array('board_list' => $_POST['boardaccess'], 'blank_string' => '', 'current_group' => (int) $_REQUEST['group'], 'group_id_string' => (string) (int) $_REQUEST['group'], 'comma_group' => ',' . $_REQUEST['group']));
            }
        }
        // Remove everyone from this group!
        if ($_POST['min_posts'] != -1) {
            smf_db_query('
				UPDATE {db_prefix}members
				SET id_group = {int:regular_member}
				WHERE id_group = {int:current_group}', array('regular_member' => 0, 'current_group' => (int) $_REQUEST['group']));
            $request = smf_db_query('
				SELECT id_member, additional_groups
				FROM {db_prefix}members
				WHERE FIND_IN_SET({string:current_group}, additional_groups) != 0', array('current_group' => (int) $_REQUEST['group']));
            $updates = array();
            while ($row = mysql_fetch_assoc($request)) {
                $updates[$row['additional_groups']][] = $row['id_member'];
            }
            mysql_free_result($request);
            foreach ($updates as $additional_groups => $memberArray) {
                updateMemberData($memberArray, array('additional_groups' => implode(',', array_diff(explode(',', $additional_groups), array((int) $_REQUEST['group'])))));
            }
        } elseif ($_REQUEST['group'] != 3) {
            // Making it a hidden group? If so remove everyone with it as primary group (Actually, just make them additional).
            if ($_POST['group_hidden'] == 2) {
                $request = smf_db_query('
					SELECT id_member, additional_groups
					FROM {db_prefix}members
					WHERE id_group = {int:current_group}
						AND FIND_IN_SET({int:current_group}, additional_groups) = 0', array('current_group' => (int) $_REQUEST['group']));
                $updates = array();
                while ($row = mysql_fetch_assoc($request)) {
                    $updates[$row['additional_groups']][] = $row['id_member'];
                }
                mysql_free_result($request);
                foreach ($updates as $additional_groups => $memberArray) {
                    updateMemberData($memberArray, array('additional_groups' => implode(',', array_merge(explode(',', $additional_groups), array((int) $_REQUEST['group'])))));
                }
                smf_db_query('
					UPDATE {db_prefix}members
					SET id_group = {int:regular_member}
					WHERE id_group = {int:current_group}', array('regular_member' => 0, 'current_group' => $_REQUEST['group']));
            }
            // Either way, let's check our "show group membership" setting is correct.
            $request = smf_db_query('
				SELECT COUNT(*)
				FROM {db_prefix}membergroups
				WHERE group_type > {int:non_joinable}', array('non_joinable' => 1));
            list($have_joinable) = mysql_fetch_row($request);
            mysql_free_result($request);
            // Do we need to update the setting?
            if (empty($modSettings['show_group_membership']) && $have_joinable || !empty($modSettings['show_group_membership']) && !$have_joinable) {
                updateSettings(array('show_group_membership' => $have_joinable ? 1 : 0));
            }
        }
        // Do we need to set inherited permissions?
        if ($_POST['group_inherit'] != -2 && $_POST['group_inherit'] != $_POST['old_inherit']) {
            require_once $sourcedir . '/' . $backend_subdir . '/ManagePermissions.php';
            updateChildPermissions($_POST['group_inherit']);
        }
        // Finally, moderators!
        $moderator_string = isset($_POST['group_moderators']) ? trim($_POST['group_moderators']) : '';
        smf_db_query('
			DELETE FROM {db_prefix}group_moderators
			WHERE id_group = {int:current_group}', array('current_group' => $_REQUEST['group']));
        if ((!empty($moderator_string) || !empty($_POST['moderator_list'])) && $_POST['min_posts'] == -1 && $_REQUEST['group'] != 3) {
            // Get all the usernames from the string
            if (!empty($moderator_string)) {
                $moderator_string = strtr(preg_replace('~&amp;#(\\d{4,5}|[2-9]\\d{2,4}|1[2-9]\\d);~', '&#$1;', htmlspecialchars($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.
                $group_moderators = array();
                if (!empty($moderators)) {
                    $request = smf_db_query('
						SELECT id_member
						FROM {db_prefix}members
						WHERE member_name IN ({array_string:moderators}) OR real_name IN ({array_string:moderators})
						LIMIT ' . count($moderators), array('moderators' => $moderators));
                    while ($row = mysql_fetch_assoc($request)) {
                        $group_moderators[] = $row['id_member'];
                    }
                    mysql_free_result($request);
                }
            } else {
                $moderators = array();
                foreach ($_POST['moderator_list'] as $moderator) {
                    $moderators[] = (int) $moderator;
                }
                $group_moderators = array();
                if (!empty($moderators)) {
                    $request = smf_db_query('
						SELECT id_member
						FROM {db_prefix}members
						WHERE id_member IN ({array_int:moderators})
						LIMIT {int:num_moderators}', array('moderators' => $moderators, 'num_moderators' => count($moderators)));
                    while ($row = mysql_fetch_assoc($request)) {
                        $group_moderators[] = $row['id_member'];
                    }
                    mysql_free_result($request);
                }
            }
            // Found some?
            if (!empty($group_moderators)) {
                $mod_insert = array();
                foreach ($group_moderators as $moderator) {
                    $mod_insert[] = array($_REQUEST['group'], $moderator);
                }
                smf_db_insert('insert', '{db_prefix}group_moderators', array('id_group' => 'int', 'id_member' => 'int'), $mod_insert, array('id_group', 'id_member'));
            }
        }
        // There might have been some post group changes.
        updateStats('postgroups');
        // We've definetely changed some group stuff.
        updateSettings(array('settings_updated' => time()));
        // Log the edit.
        logAction('edited_group', array('group' => $_POST['group_name']), 'admin');
        regenerateColorStyle();
        redirectexit('action=admin;area=membergroups');
    }
    // Fetch the current group information.
    $request = smf_db_query('
		SELECT group_name, description, min_posts, online_color, max_messages, stars, group_type, hidden, id_parent
		FROM {db_prefix}membergroups
		WHERE id_group = {int:current_group}
		LIMIT 1', array('current_group' => (int) $_REQUEST['group']));
    if (mysql_num_rows($request) == 0) {
        fatal_lang_error('membergroup_does_not_exist', false);
    }
    $row = mysql_fetch_assoc($request);
    mysql_free_result($request);
    $row['stars'] = explode('#', $row['stars']);
    $context['group'] = array('id' => $_REQUEST['group'], 'name' => $row['group_name'], 'description' => htmlspecialchars($row['description']), 'editable_name' => htmlspecialchars($row['group_name']), 'color' => $row['online_color'], 'min_posts' => $row['min_posts'], 'max_messages' => $row['max_messages'], 'star_count' => (int) $row['stars'][0], 'star_image' => isset($row['stars'][1]) ? $row['stars'][1] : '', 'is_post_group' => $row['min_posts'] != -1, 'type' => $row['min_posts'] != -1 ? 0 : $row['group_type'], 'hidden' => $row['min_posts'] == -1 ? $row['hidden'] : 0, 'inherited_from' => $row['id_parent'], 'allow_post_group' => $_REQUEST['group'] == 2 || $_REQUEST['group'] > 4, 'allow_delete' => $_REQUEST['group'] == 2 || $_REQUEST['group'] > 4, 'allow_protected' => allowedTo('admin_forum'));
    // Get any moderators for this group
    $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:current_group}', array('current_group' => $_REQUEST['group']));
    $context['group']['moderators'] = array();
    while ($row = mysql_fetch_assoc($request)) {
        $context['group']['moderators'][$row['id_member']] = $row['real_name'];
    }
    mysql_free_result($request);
    $context['group']['moderator_list'] = empty($context['group']['moderators']) ? '' : '&quot;' . implode('&quot;, &quot;', $context['group']['moderators']) . '&quot;';
    if (!empty($context['group']['moderators'])) {
        list($context['group']['last_moderator_id']) = array_slice(array_keys($context['group']['moderators']), -1);
    }
    // Get a list of boards this membergroup is allowed to see.
    $context['boards'] = array();
    if ($_REQUEST['group'] == 2 || $_REQUEST['group'] > 3) {
        $result = smf_db_query('
			SELECT id_board, name, child_level, FIND_IN_SET({string:current_group}, member_groups) != 0 AS can_access
			FROM {db_prefix}boards
			ORDER BY board_order', array('current_group' => (int) $_REQUEST['group']));
        while ($row = mysql_fetch_assoc($result)) {
            $context['boards'][] = array('id' => $row['id_board'], 'name' => $row['name'], 'child_level' => $row['child_level'], 'selected' => !(empty($row['can_access']) || $row['can_access'] == 'f'));
        }
        mysql_free_result($result);
    }
    // Finally, get all the groups this could be inherited off.
    $request = smf_db_query('
		SELECT id_group, group_name
		FROM {db_prefix}membergroups
		WHERE id_group != {int:current_group}' . (empty($modSettings['permission_enable_postgroups']) ? '
			AND min_posts = {int:min_posts}' : '') . (allowedTo('admin_forum') ? '' : '
			AND group_type != {int:is_protected}') . '
			AND id_group NOT IN (1, 3)
			AND id_parent = {int:not_inherited}', array('current_group' => (int) $_REQUEST['group'], 'min_posts' => -1, 'not_inherited' => -2, 'is_protected' => 1));
    $context['inheritable_groups'] = array();
    while ($row = mysql_fetch_assoc($request)) {
        $context['inheritable_groups'][$row['id_group']] = $row['group_name'];
    }
    mysql_free_result($request);
    $context['sub_template'] = 'edit_group';
    $context['page_title'] = $txt['membergroups_edit_group'];
}
Example #4
0
function ModifyKarma()
{
    global $modSettings, $txt, $user_info, $topic, $smcFunc, $context;
    // If the mod is disabled, show an error.
    if (empty($modSettings['karmaMode'])) {
        fatal_lang_error('feature_disabled', true);
    }
    // If you're a guest or can't do this, blow you off...
    is_not_guest();
    isAllowedTo('karma_edit');
    checkSession('get');
    // If you don't have enough posts, tough luck.
    // !!! Should this be dropped in favor of post group permissions?  Should this apply to the member you are smiting/applauding?
    if (!$user_info['is_admin'] && $user_info['posts'] < $modSettings['karmaMinPosts']) {
        fatal_lang_error('not_enough_posts_karma', true, array($modSettings['karmaMinPosts']));
    }
    // And you can't modify your own, punk! (use the profile if you need to.)
    if (empty($_REQUEST['uid']) || (int) $_REQUEST['uid'] == $user_info['id']) {
        fatal_lang_error('cant_change_own_karma', false);
    }
    // The user ID _must_ be a number, no matter what.
    $_REQUEST['uid'] = (int) $_REQUEST['uid'];
    // Applauding or smiting?
    $dir = $_REQUEST['sa'] != 'applaud' ? -1 : 1;
    // Delete any older items from the log. (karmaWaitTime is by hour.)
    smf_db_query('
		DELETE FROM {db_prefix}log_karma
		WHERE {int:current_time} - log_time > {int:wait_time}', array('wait_time' => (int) ($modSettings['karmaWaitTime'] * 3600), 'current_time' => time()));
    // Start off with no change in karma.
    $action = 0;
    // Not an administrator... or one who is restricted as well.
    if (!empty($modSettings['karmaTimeRestrictAdmins']) || !allowedTo('moderate_forum')) {
        // Find out if this user has done this recently...
        $request = smf_db_query('
			SELECT action
			FROM {db_prefix}log_karma
			WHERE id_target = {int:id_target}
				AND id_executor = {int:current_member}
			LIMIT 1', array('current_member' => $user_info['id'], 'id_target' => $_REQUEST['uid']));
        if (mysql_num_rows($request) > 0) {
            list($action) = mysql_fetch_row($request);
        }
        mysql_free_result($request);
    }
    // They haven't, not before now, anyhow.
    if (empty($action) || empty($modSettings['karmaWaitTime'])) {
        // Put it in the log.
        smf_db_insert('replace', '{db_prefix}log_karma', array('action' => 'int', 'id_target' => 'int', 'id_executor' => 'int', 'log_time' => 'int'), array($dir, $_REQUEST['uid'], $user_info['id'], time()), array('id_target', 'id_executor'));
        // Change by one.
        updateMemberData($_REQUEST['uid'], array($dir == 1 ? 'karma_good' : 'karma_bad' => '+'));
    } else {
        // If you are gonna try to repeat.... don't allow it.
        if ($action == $dir) {
            fatal_lang_error('karma_wait_time', false, array($modSettings['karmaWaitTime'], $txt['hours']));
        }
        // You decided to go back on your previous choice?
        smf_db_query('
			UPDATE {db_prefix}log_karma
			SET action = {int:action}, log_time = {int:current_time}
			WHERE id_target = {int:id_target}
				AND id_executor = {int:current_member}', array('current_member' => $user_info['id'], 'action' => $dir, 'current_time' => time(), 'id_target' => $_REQUEST['uid']));
        // It was recently changed the OTHER way... so... reverse it!
        if ($dir == 1) {
            updateMemberData($_REQUEST['uid'], array('karma_good' => '+', 'karma_bad' => '-'));
        } else {
            updateMemberData($_REQUEST['uid'], array('karma_bad' => '+', 'karma_good' => '-'));
        }
    }
    // Figure out where to go back to.... the topic?
    if (!empty($topic)) {
        redirectexit('topic=' . $topic . '.' . $_REQUEST['start'] . '#msg' . (int) $_REQUEST['m']);
    } elseif (isset($_REQUEST['f'])) {
        redirectexit('action=pm;f=' . $_REQUEST['f'] . ';start=' . $_REQUEST['start'] . (isset($_REQUEST['l']) ? ';l=' . (int) $_REQUEST['l'] : '') . (isset($_REQUEST['pm']) ? '#' . (int) $_REQUEST['pm'] : ''));
    } else {
        echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"', $context['right_to_left'] ? ' dir="rtl"' : '', '>
	<head>
		<title>...</title>
		<script type="text/javascript"><!-- // --><![CDATA[
			history.go(-1);
		// ]]></script>
	</head>
	<body>&laquo;</body>
</html>';
        obExit(false);
    }
}
Example #5
0
function ReduceMailQueue($number = false, $override_limit = false, $force_send = false)
{
    global $modSettings, $smcFunc, $sourcedir;
    // Are we intending another script to be sending out the queue?
    if (!empty($modSettings['mail_queue_use_cron']) && empty($force_send)) {
        return false;
    }
    // By default send 5 at once.
    if (!$number) {
        $number = empty($modSettings['mail_quantity']) ? 5 : $modSettings['mail_quantity'];
    }
    // If we came with a timestamp, and that doesn't match the next event, then someone else has beaten us.
    if (isset($_GET['ts']) && $_GET['ts'] != $modSettings['mail_next_send'] && empty($force_send)) {
        return false;
    }
    // By default move the next sending on by 10 seconds, and require an affected row.
    if (!$override_limit) {
        $delay = !empty($modSettings['mail_queue_delay']) ? $modSettings['mail_queue_delay'] : (!empty($modSettings['mail_limit']) && $modSettings['mail_limit'] < 5 ? 10 : 5);
        smf_db_query('
			UPDATE {db_prefix}settings
			SET value = {string:next_mail_send}
			WHERE variable = {string:mail_next_send}
				AND value = {string:last_send}', array('next_mail_send' => time() + $delay, 'mail_next_send' => 'mail_next_send', 'last_send' => $modSettings['mail_next_send']));
        if (smf_db_affected_rows() == 0) {
            return false;
        }
        $modSettings['mail_next_send'] = time() + $delay;
    }
    // If we're not overriding how many are we allow to send?
    if (!$override_limit && !empty($modSettings['mail_limit'])) {
        list($mt, $mn) = @explode('|', $modSettings['mail_recent']);
        // Nothing worth noting...
        if (empty($mn) || $mt < time() - 60) {
            $mt = time();
            $mn = $number;
        } elseif ($mn < $modSettings['mail_limit']) {
            $mn += $number;
        } else {
            return false;
        }
        // Reflect that we're about to send some, do it now to be safe.
        updateSettings(array('mail_recent' => $mt . '|' . $mn));
    }
    // Now we know how many we're sending, let's send them.
    $request = smf_db_query('
		SELECT /*!40001 SQL_NO_CACHE */ id_mail, recipient, body, subject, headers, send_html
		FROM {db_prefix}mail_queue
		ORDER BY priority ASC, id_mail ASC
		LIMIT ' . $number, array());
    $ids = array();
    $emails = array();
    while ($row = mysql_fetch_assoc($request)) {
        // We want to delete these from the database ASAP, so just get the data and go.
        $ids[] = $row['id_mail'];
        $emails[] = array('to' => $row['recipient'], 'body' => $row['body'], 'subject' => $row['subject'], 'headers' => $row['headers'], 'send_html' => $row['send_html']);
    }
    mysql_free_result($request);
    // Delete, delete, delete!!!
    if (!empty($ids)) {
        smf_db_query('
			DELETE FROM {db_prefix}mail_queue
			WHERE id_mail IN ({array_int:mail_list})', array('mail_list' => $ids));
    }
    // Don't believe we have any left?
    if (count($ids) < $number) {
        // Only update the setting if no-one else has beaten us to it.
        smf_db_query('
			UPDATE {db_prefix}settings
			SET value = {string:no_send}
			WHERE variable = {string:mail_next_send}
				AND value = {string:last_mail_send}', array('no_send' => '0', 'mail_next_send' => 'mail_next_send', 'last_mail_send' => $modSettings['mail_next_send']));
    }
    if (empty($ids)) {
        return false;
    }
    if (!empty($modSettings['mail_type']) && $modSettings['smtp_host'] != '') {
        require_once $sourcedir . '/lib/Subs-Post.php';
    }
    // Send each email, yea!
    $failed_emails = array();
    foreach ($emails as $key => $email) {
        if (empty($modSettings['mail_type']) || $modSettings['smtp_host'] == '') {
            $email['subject'] = strtr($email['subject'], array("\r" => '', "\n" => ''));
            if (!empty($modSettings['mail_strip_carriage'])) {
                $email['body'] = strtr($email['body'], array("\r" => ''));
                $email['headers'] = strtr($email['headers'], array("\r" => ''));
            }
            // No point logging a specific error here, as we have no language. PHP error is helpful anyway...
            $result = mail(strtr($email['to'], array("\r" => '', "\n" => '')), $email['subject'], $email['body'], $email['headers']);
            // Try to stop a timeout, this would be bad...
            @set_time_limit(300);
            if (function_exists('apache_reset_timeout')) {
                @apache_reset_timeout();
            }
        } else {
            $result = smtp_mail(array($email['to']), $email['subject'], $email['body'], $email['send_html'] ? $email['headers'] : 'Mime-Version: 1.0' . "\r\n" . $email['headers']);
        }
        // Hopefully it sent?
        if (!$result) {
            $failed_emails[] = array($email['to'], $email['body'], $email['subject'], $email['headers'], $email['send_html']);
        }
    }
    // Any emails that didn't send?
    if (!empty($failed_emails)) {
        // Update the failed attempts check.
        smf_db_insert('replace', '{db_prefix}settings', array('variable' => 'string', 'value' => 'string'), array('mail_failed_attempts', empty($modSettings['mail_failed_attempts']) ? 1 : ++$modSettings['mail_failed_attempts']), array('variable'));
        // If we have failed to many times, tell mail to wait a bit and try again.
        if ($modSettings['mail_failed_attempts'] > 5) {
            smf_db_query('
				UPDATE {db_prefix}settings
				SET value = {string:mail_next_send}
				WHERE variable = {string:next_mail_send}
					AND value = {string:last_send}', array('next_mail_send' => time() + 60, 'mail_next_send' => 'mail_next_send', 'last_send' => $modSettings['mail_next_send']));
        }
        // Add our email back to the queue, manually.
        smf_db_insert('insert', '{db_prefix}mail_queue', array('recipient' => 'string', 'body' => 'string', 'subject' => 'string', 'headers' => 'string', 'send_html' => 'string'), $failed_emails, array('id_mail'));
        return false;
    } elseif (!empty($modSettings['mail_failed_attempts'])) {
        smf_db_query('
			UPDATE {db_prefix}settings
			SET value = {string:zero}
			WHERE variable = {string:mail_failed_attempts}', array('zero' => '0', 'mail_failed_attempts' => 'mail_failed_attempts'));
    }
    // Had something to send...
    return true;
}
Example #6
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']);
}
Example #7
0
function sendApprovalNotifications(&$topicData)
{
    global $scripturl, $language, $user_info;
    global $modSettings;
    // Clean up the data...
    if (!is_array($topicData) || empty($topicData)) {
        return;
    }
    $topics = array();
    $digest_insert = array();
    foreach ($topicData as $topic => $msgs) {
        foreach ($msgs as $msgKey => $msg) {
            censorText($topicData[$topic][$msgKey]['subject']);
            censorText($topicData[$topic][$msgKey]['body']);
            $topicData[$topic][$msgKey]['subject'] = un_htmlspecialchars($topicData[$topic][$msgKey]['subject']);
            $topicData[$topic][$msgKey]['body'] = trim(un_htmlspecialchars(strip_tags(strtr(parse_bbc($topicData[$topic][$msgKey]['body'], false), array('<br />' => "\n", '</div>' => "\n", '</li>' => "\n", '&#91;' => '[', '&#93;' => ']')))));
            $topics[] = $msg['id'];
            $digest_insert[] = array($msg['topic'], $msg['id'], 'reply', $user_info['id']);
        }
    }
    // These need to go into the digest too...
    smf_db_insert('', '{db_prefix}log_digest', array('id_topic' => 'int', 'id_msg' => 'int', 'note_type' => 'string', 'exclude' => 'int'), $digest_insert, array());
    // Find everyone who needs to know about this.
    $members = smf_db_query('
		SELECT
			mem.id_member, mem.email_address, mem.notify_regularity, mem.notify_types, mem.notify_send_body, mem.lngfile,
			ln.sent, mem.id_group, mem.additional_groups, b.member_groups, mem.id_post_group, t.id_member_started,
			ln.id_topic
		FROM {db_prefix}log_notify AS ln
			INNER JOIN {db_prefix}members AS mem ON (mem.id_member = ln.id_member)
			INNER JOIN {db_prefix}topics AS t ON (t.id_topic = ln.id_topic)
			INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board)
		WHERE ln.id_topic IN ({array_int:topic_list})
			AND mem.is_activated = {int:is_activated}
			AND mem.notify_types < {int:notify_types}
			AND mem.notify_regularity < {int:notify_regularity}
		GROUP BY mem.id_member, ln.id_topic, mem.email_address, mem.notify_regularity, mem.notify_types, mem.notify_send_body, mem.lngfile, ln.sent, mem.id_group, mem.additional_groups, b.member_groups, mem.id_post_group, t.id_member_started
		ORDER BY mem.lngfile', array('topic_list' => $topics, 'is_activated' => 1, 'notify_types' => 4, 'notify_regularity' => 2));
    $sent = 0;
    while ($row = mysql_fetch_assoc($members)) {
        if ($row['id_group'] != 1) {
            $allowed = explode(',', $row['member_groups']);
            $row['additional_groups'] = explode(',', $row['additional_groups']);
            $row['additional_groups'][] = $row['id_group'];
            $row['additional_groups'][] = $row['id_post_group'];
            if (count(array_intersect($allowed, $row['additional_groups'])) == 0) {
                continue;
            }
        }
        $needed_language = empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile'];
        if (empty($current_language) || $current_language != $needed_language) {
            $current_language = loadLanguage('Post', $needed_language, false);
        }
        $sent_this_time = false;
        // Now loop through all the messages to send.
        foreach ($topicData[$row['id_topic']] as $msg) {
            $replacements = array('TOPICSUBJECT' => $topicData[$row['id_topic']]['subject'], 'POSTERNAME' => un_htmlspecialchars($topicData[$row['id_topic']]['name']), 'TOPICLINK' => $scripturl . '?topic=' . $row['id_topic'] . '.new;topicseen#new', 'UNSUBSCRIBELINK' => $scripturl . '?action=notify;topic=' . $row['id_topic'] . '.0');
            $message_type = 'notification_reply';
            // Do they want the body of the message sent too?
            if (!empty($row['notify_send_body']) && empty($modSettings['disallow_sendBody'])) {
                $message_type .= '_body';
                $replacements['BODY'] = $topicData[$row['id_topic']]['body'];
            }
            if (!empty($row['notify_regularity'])) {
                $message_type .= '_once';
            }
            // Send only if once is off or it's on and it hasn't been sent.
            if (empty($row['notify_regularity']) || empty($row['sent']) && !$sent_this_time) {
                $emaildata = loadEmailTemplate($message_type, $replacements, $needed_language);
                sendmail($row['email_address'], $emaildata['subject'], $emaildata['body'], null, 'm' . $topicData[$row['id_topic']]['last_id']);
                $sent++;
            }
            $sent_this_time = true;
        }
    }
    mysql_free_result($members);
    if (isset($current_language) && $current_language != $user_info['language']) {
        loadLanguage('Post');
    }
    // Sent!
    if (!empty($sent)) {
        smf_db_query('
			UPDATE {db_prefix}log_notify
			SET sent = {int:is_sent}
			WHERE id_topic IN ({array_int:topic_list})
				AND id_member != {int:current_member}', array('current_member' => $user_info['id'], 'topic_list' => $topics, 'is_sent' => 1));
    }
}
Example #8
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);
}
Example #9
0
/**
 * add a stream activity
 *
 * @param int $id_member	the member id who owns this activity (= who did it)
 * @param int $atype		activity type (numeric)
 * @param $params			array with parameters, mostly for formatting
 * @param int $id_board		the board id where it happened (if applicable)
 * @param int $id_topic		the topic id where it happened (if applicable)
 * @param int $id_content	the content id. this can be a message id but could also be a user id
 * 							(e.g. when a member posts on the profile of another member). depends on the context
 * @param int $id_owner     the content owner (id_member)
 * @param int $priv_level   privacy level for is_private.
 * @param int $dont_notify  do not send the owner a notification for the activity.
 *
 * @return unique id (positive integer) of the inserted activity type, 0 if something went wrong.
 */
function aStreamAdd($id_member, $atype, $params, $id_board = 0, $id_topic = 0, $id_content = 0, $id_owner = 0, $priv_level = 0, $dont_notify = false)
{
    global $user_info;
    $act_must_notify = array(ACT_LIKE, ACT_REPLIED);
    // these activity types will trigger a *mandatory*
    if (0 == $id_member || 0 == $id_owner) {
        // notification for $id_owner unless $dont_notify indicates otherwise
        return 0;
    }
    if (0 == $atype) {
        $_s = sprintf('Warning: tried to add atype==0 with id_member=%d, params=%s, id_board=%d, id_topic=%d', $id_member, @serialize($params), $id_board, $id_topic);
        log_error($_s);
        return 0;
    }
    // respect opt out setting
    if (!empty($user_info['act_optout'])) {
        if (in_array($atype, explode(',', $user_info['act_optout'])) !== false) {
            return 0;
        }
    }
    smf_db_insert('', '{db_prefix}log_activities', array('id_member' => 'int', 'id_type' => 'int', 'updated' => 'int', 'params' => 'string', 'is_private' => 'int', 'id_board' => 'int', 'id_topic' => 'int', 'id_content' => 'int', 'id_owner' => 'int'), array((int) $id_member, (int) $atype, time(), serialize($params), $priv_level, (int) $id_board, (int) $id_topic, (int) $id_content, (int) $id_owner), array('id_act'));
    $id_act = smf_db_insert_id('{db_prefix}log_activities', 'id_act');
    // if this activity triggers a notification for the id_owner, use the $id_act to link it
    // to the notifications table.
    if ($id_act && $id_owner && in_array($atype, $act_must_notify) && !$dont_notify) {
        aStreamAddNotification($id_owner, $id_act, $atype);
    }
    $data = array('id_member' => $id_member, 'type' => $atype, 'params' => $params, 'board' => $id_board, 'topic' => $id_topic, 'content_id' => $id_content, 'id_owner' => $id_owner, 'plevel' => $priv_level, 'event_id' => $id_act);
    HookAPI::callHook('astream_event_added', array(&$data));
    return $id_act;
}
Example #10
0
function smf_openID_makeAssociation($server)
{
    global $smcFunc, $modSettings, $p;
    $parameters = array('openid.mode=associate');
    // We'll need to get our keys for the Diffie-Hellman key exchange.
    $dh_keys = smf_openID_setup_DH();
    // If we don't support DH we'll have to see if the provider will accept no encryption.
    if ($dh_keys === false) {
        $parameters[] = 'openid.session_type=';
    } else {
        $parameters[] = 'openid.session_type=DH-SHA1';
        $parameters[] = 'openid.dh_consumer_public=' . urlencode(base64_encode(long_to_binary($dh_keys['public'])));
        $parameters[] = 'openid.assoc_type=HMAC-SHA1';
    }
    // The data to post to the server.
    $post_data = implode('&', $parameters);
    $data = fetch_web_data($server, $post_data);
    // Parse the data given.
    preg_match_all('~^([^:]+):(.+)$~m', $data, $matches);
    $assoc_data = array();
    foreach ($matches[1] as $key => $match) {
        $assoc_data[$match] = $matches[2][$key];
    }
    if (!isset($assoc_data['assoc_type']) || empty($assoc_data['mac_key']) && empty($assoc_data['enc_mac_key'])) {
        fatal_lang_error('openid_server_bad_response');
    }
    // Clean things up a bit.
    $handle = isset($assoc_data['assoc_handle']) ? $assoc_data['assoc_handle'] : '';
    $issued = time();
    $expires = $issued + min((int) $assoc_data['expires_in'], 60);
    $assoc_type = isset($assoc_data['assoc_type']) ? $assoc_data['assoc_type'] : '';
    // !!! Is this really needed?
    foreach (array('dh_server_public', 'enc_mac_key') as $key) {
        if (isset($assoc_data[$key])) {
            $assoc_data[$key] = str_replace(' ', '+', $assoc_data[$key]);
        }
    }
    // Figure out the Diffie-Hellman secret.
    if (!empty($assoc_data['enc_mac_key'])) {
        $dh_secret = bcpowmod(binary_to_long(base64_decode($assoc_data['dh_server_public'])), $dh_keys['private'], $p);
        $secret = base64_encode(binary_xor(sha1_raw(long_to_binary($dh_secret)), base64_decode($assoc_data['enc_mac_key'])));
    } else {
        $secret = $assoc_data['mac_key'];
    }
    // Store the data
    smf_db_insert('replace', '{db_prefix}openid_assoc', array('server_url' => 'string', 'handle' => 'string', 'secret' => 'string', 'issued' => 'int', 'expires' => 'int', 'assoc_type' => 'string'), array($server, $handle, $secret, $issued, $expires, $assoc_type), array('server_url', 'handle'));
    return array('server' => $server, 'handle' => $assoc_data['assoc_handle'], 'secret' => $secret, 'issued' => $issued, 'expires' => $expires, 'assoc_type' => $assoc_data['assoc_type']);
}
Example #11
0
function EditCustomProfiles()
{
    global $txt, $scripturl, $context, $settings, $sc, $smcFunc;
    // Sort out the context!
    $context['fid'] = isset($_GET['fid']) ? (int) $_GET['fid'] : 0;
    $context[$context['admin_menu_name']]['current_subsection'] = 'profile';
    $context['page_title'] = $context['fid'] ? $txt['custom_edit_title'] : $txt['custom_add_title'];
    $context['sub_template'] = 'edit_profile_field';
    // Load the profile language for section names.
    loadLanguage('Profile');
    if ($context['fid']) {
        $request = smf_db_query('
			SELECT
				id_field, col_name, field_name, field_desc, field_type, field_length, field_options,
				show_reg, show_display, show_profile, private, active, default_value, can_search,
				bbc, mask, enclose, placement
			FROM {db_prefix}custom_fields
			WHERE id_field = {int:current_field}', array('current_field' => $context['fid']));
        $context['field'] = array();
        while ($row = mysql_fetch_assoc($request)) {
            if ($row['field_type'] == 'textarea') {
                @(list($rows, $cols) = @explode(',', $row['default_value']));
            } else {
                $rows = 3;
                $cols = 30;
            }
            $context['field'] = array('name' => $row['field_name'], 'desc' => $row['field_desc'], 'colname' => $row['col_name'], 'profile_area' => $row['show_profile'], 'reg' => $row['show_reg'], 'display' => $row['show_display'], 'type' => $row['field_type'], 'max_length' => $row['field_length'], 'rows' => $rows, 'cols' => $cols, 'bbc' => $row['bbc'] ? true : false, 'default_check' => $row['field_type'] == 'check' && $row['default_value'] ? true : false, 'default_select' => $row['field_type'] == 'select' || $row['field_type'] == 'radio' ? $row['default_value'] : '', 'options' => strlen($row['field_options']) > 1 ? explode(',', $row['field_options']) : array('', '', ''), 'active' => $row['active'], 'private' => $row['private'], 'can_search' => $row['can_search'], 'mask' => $row['mask'], 'regex' => substr($row['mask'], 0, 5) == 'regex' ? substr($row['mask'], 5) : '', 'enclose' => $row['enclose'], 'placement' => $row['placement']);
        }
        mysql_free_result($request);
    }
    // Setup the default values as needed.
    if (empty($context['field'])) {
        $context['field'] = array('name' => '', 'colname' => '???', 'desc' => '', 'profile_area' => 'forumprofile', 'reg' => false, 'display' => false, 'type' => 'text', 'max_length' => 255, 'rows' => 4, 'cols' => 30, 'bbc' => false, 'default_check' => false, 'default_select' => '', 'options' => array('', '', ''), 'active' => true, 'private' => false, 'can_search' => false, 'mask' => 'nohtml', 'regex' => '', 'enclose' => '', 'placement' => 0);
    }
    // Are we saving?
    if (isset($_POST['save'])) {
        checkSession();
        // Everyone needs a name - even the (bracket) unknown...
        if (trim($_POST['field_name']) == '') {
            fatal_lang_error('custom_option_need_name');
        }
        $_POST['field_name'] = commonAPI::htmlspecialchars($_POST['field_name']);
        $_POST['field_desc'] = commonAPI::htmlspecialchars($_POST['field_desc']);
        // Checkboxes...
        $show_reg = isset($_POST['reg']) ? (int) $_POST['reg'] : 0;
        $show_display = isset($_POST['display']) ? 1 : 0;
        $bbc = isset($_POST['bbc']) ? 1 : 0;
        $show_profile = $_POST['profile_area'];
        $active = isset($_POST['active']) ? 1 : 0;
        $private = isset($_POST['private']) ? (int) $_POST['private'] : 0;
        $can_search = isset($_POST['can_search']) ? 1 : 0;
        // Some masking stuff...
        $mask = isset($_POST['mask']) ? $_POST['mask'] : '';
        if ($mask == 'regex' && isset($_POST['regex'])) {
            $mask .= $_POST['regex'];
        }
        $field_length = isset($_POST['max_length']) ? (int) $_POST['max_length'] : 255;
        $enclose = isset($_POST['enclose']) ? $_POST['enclose'] : '';
        $placement = isset($_POST['placement']) ? (int) $_POST['placement'] : 0;
        // Select options?
        $field_options = '';
        $newOptions = array();
        $default = isset($_POST['default_check']) && $_POST['field_type'] == 'check' ? 1 : '';
        if (!empty($_POST['select_option']) && ($_POST['field_type'] == 'select' || $_POST['field_type'] == 'radio')) {
            foreach ($_POST['select_option'] as $k => $v) {
                // Clean, clean, clean...
                $v = commonAPI::htmlspecialchars($v);
                $v = strtr($v, array(',' => ''));
                // Nada, zip, etc...
                if (trim($v) == '') {
                    continue;
                }
                // Otherwise, save it boy.
                $field_options .= $v . ',';
                // This is just for working out what happened with old options...
                $newOptions[$k] = $v;
                // Is it default?
                if (isset($_POST['default_select']) && $_POST['default_select'] == $k) {
                    $default = $v;
                }
            }
            $field_options = substr($field_options, 0, -1);
        }
        // Text area has default has dimensions
        if ($_POST['field_type'] == 'textarea') {
            $default = (int) $_POST['rows'] . ',' . (int) $_POST['cols'];
        }
        // Come up with the unique name?
        if (empty($context['fid'])) {
            $colname = commonAPI::substr(strtr($_POST['field_name'], array(' ' => '')), 0, 6);
            preg_match('~([\\w\\d_-]+)~', $colname, $matches);
            // If there is nothing to the name, then let's start out own - for foreign languages etc.
            if (isset($matches[1])) {
                $colname = $initial_colname = 'cust_' . strtolower($matches[1]);
            } else {
                $colname = $initial_colname = 'cust_' . mt_rand(1, 999);
            }
            // Make sure this is unique.
            // !!! This may not be the most efficient way to do this.
            $unique = false;
            for ($i = 0; !$unique && $i < 9; $i++) {
                $request = smf_db_query('
					SELECT id_field
					FROM {db_prefix}custom_fields
					WHERE col_name = {string:current_column}', array('current_column' => $colname));
                if (mysql_num_rows($request) == 0) {
                    $unique = true;
                } else {
                    $colname = $initial_colname . $i;
                }
                mysql_free_result($request);
            }
            // Still not a unique colum name? Leave it up to the user, then.
            if (!$unique) {
                fatal_lang_error('custom_option_not_unique');
            }
        } else {
            // Anything going to check or select is pointless keeping - as is anything coming from check!
            if ($_POST['field_type'] == 'check' && $context['field']['type'] != 'check' || ($_POST['field_type'] == 'select' || $_POST['field_type'] == 'radio') && $context['field']['type'] != 'select' && $context['field']['type'] != 'radio' || $context['field']['type'] == 'check' && $_POST['field_type'] != 'check') {
                smf_db_query('
					DELETE FROM {db_prefix}themes
					WHERE variable = {string:current_column}
						AND id_member > {int:no_member}', array('no_member' => 0, 'current_column' => $context['field']['colname']));
            } elseif ($_POST['field_type'] == 'select' || $_POST['field_type'] == 'radio') {
                $optionChanges = array();
                $takenKeys = array();
                // Work out what's changed!
                foreach ($context['field']['options'] as $k => $option) {
                    if (trim($option) == '') {
                        continue;
                    }
                    // Still exists?
                    if (in_array($option, $newOptions)) {
                        $takenKeys[] = $k;
                        continue;
                    }
                }
                // Finally - have we renamed it - or is it really gone?
                foreach ($optionChanges as $k => $option) {
                    // Just been renamed?
                    if (!in_array($k, $takenKeys) && !empty($newOptions[$k])) {
                        smf_db_query('
							UPDATE {db_prefix}themes
							SET value = {string:new_value}
							WHERE variable = {string:current_column}
								AND value = {string:old_value}
								AND id_member > {int:no_member}', array('no_member' => 0, 'new_value' => $newOptions[$k], 'current_column' => $context['field']['colname'], 'old_value' => $option));
                    }
                }
            }
            //!!! Maybe we should adjust based on new text length limits?
        }
        // Do the insertion/updates.
        if ($context['fid']) {
            smf_db_query('
				UPDATE {db_prefix}custom_fields
				SET
					field_name = {string:field_name}, field_desc = {string:field_desc},
					field_type = {string:field_type}, field_length = {int:field_length},
					field_options = {string:field_options}, show_reg = {int:show_reg},
					show_display = {int:show_display}, show_profile = {string:show_profile},
					private = {int:private}, active = {int:active}, default_value = {string:default_value},
					can_search = {int:can_search}, bbc = {int:bbc}, mask = {string:mask},
					enclose = {string:enclose}, placement = {int:placement}
				WHERE id_field = {int:current_field}', array('field_length' => $field_length, 'show_reg' => $show_reg, 'show_display' => $show_display, 'private' => $private, 'active' => $active, 'can_search' => $can_search, 'bbc' => $bbc, 'current_field' => $context['fid'], 'field_name' => $_POST['field_name'], 'field_desc' => $_POST['field_desc'], 'field_type' => $_POST['field_type'], 'field_options' => $field_options, 'show_profile' => $show_profile, 'default_value' => $default, 'mask' => $mask, 'enclose' => $enclose, 'placement' => $placement));
            // Just clean up any old selects - these are a pain!
            if (($_POST['field_type'] == 'select' || $_POST['field_type'] == 'radio') && !empty($newOptions)) {
                smf_db_query('
					DELETE FROM {db_prefix}themes
					WHERE variable = {string:current_column}
						AND value NOT IN ({array_string:new_option_values})
						AND id_member > {int:no_member}', array('no_member' => 0, 'new_option_values' => $newOptions, 'current_column' => $context['field']['colname']));
            }
        } else {
            smf_db_insert('', '{db_prefix}custom_fields', array('col_name' => 'string', 'field_name' => 'string', 'field_desc' => 'string', 'field_type' => 'string', 'field_length' => 'string', 'field_options' => 'string', 'show_reg' => 'int', 'show_display' => 'int', 'show_profile' => 'string', 'private' => 'int', 'active' => 'int', 'default_value' => 'string', 'can_search' => 'int', 'bbc' => 'int', 'mask' => 'string', 'enclose' => 'string', 'placement' => 'int'), array($colname, $_POST['field_name'], $_POST['field_desc'], $_POST['field_type'], $field_length, $field_options, $show_reg, $show_display, $show_profile, $private, $active, $default, $can_search, $bbc, $mask, $enclose, $placement), array('id_field'));
        }
        // As there's currently no option to priorize certain fields over others, let's order them alphabetically.
        smf_db_query('
			ALTER TABLE {db_prefix}custom_fields
			ORDER BY field_name', array('db_error_skip' => true));
    } elseif (isset($_POST['delete']) && $context['field']['colname']) {
        checkSession();
        // Delete the user data first.
        smf_db_query('
			DELETE FROM {db_prefix}themes
			WHERE variable = {string:current_column}
				AND id_member > {int:no_member}', array('no_member' => 0, 'current_column' => $context['field']['colname']));
        // Finally - the field itself is gone!
        smf_db_query('
			DELETE FROM {db_prefix}custom_fields
			WHERE id_field = {int:current_field}', array('current_field' => $context['fid']));
    }
    // Rebuild display cache etc.
    if (isset($_POST['delete']) || isset($_POST['save'])) {
        checkSession();
        $request = smf_db_query('
			SELECT col_name, field_name, field_type, bbc, enclose, placement
			FROM {db_prefix}custom_fields
			WHERE show_display = {int:is_displayed}
				AND active = {int:active}
				AND private != {int:not_owner_only}
				AND private != {int:not_admin_only}', array('is_displayed' => 1, 'active' => 1, 'not_owner_only' => 2, 'not_admin_only' => 3));
        $fields = array();
        while ($row = mysql_fetch_assoc($request)) {
            $fields[] = array('colname' => strtr($row['col_name'], array('|' => '', ';' => '')), 'title' => strtr($row['field_name'], array('|' => '', ';' => '')), 'type' => $row['field_type'], 'bbc' => $row['bbc'] ? '1' : '0', 'placement' => !empty($row['placement']) ? $row['placement'] : '0', 'enclose' => !empty($row['enclose']) ? $row['enclose'] : '');
        }
        mysql_free_result($request);
        updateSettings(array('displayFields' => serialize($fields)));
        redirectexit('action=admin;area=featuresettings;sa=profile');
    }
}
Example #12
0
function groupMembership2($profile_vars, $post_errors, $memID)
{
    global $user_info, $sourcedir, $context, $user_profile, $modSettings, $txt, $smcFunc, $scripturl, $language;
    // Let's be extra cautious...
    if (!$context['user']['is_owner'] || empty($modSettings['show_group_membership'])) {
        isAllowedTo('manage_membergroups');
    }
    if (!isset($_REQUEST['gid']) && !isset($_POST['primary'])) {
        fatal_lang_error('no_access', false);
    }
    checkSession(isset($_GET['gid']) ? 'get' : 'post');
    $old_profile =& $user_profile[$memID];
    $context['can_manage_membergroups'] = allowedTo('manage_membergroups');
    $context['can_manage_protected'] = allowedTo('admin_forum');
    // By default the new primary is the old one.
    $newPrimary = $old_profile['id_group'];
    $addGroups = array_flip(explode(',', $old_profile['additional_groups']));
    $canChangePrimary = $old_profile['id_group'] == 0 ? 1 : 0;
    $changeType = isset($_POST['primary']) ? 'primary' : (isset($_POST['req']) ? 'request' : 'free');
    // One way or another, we have a target group in mind...
    $group_id = isset($_REQUEST['gid']) ? (int) $_REQUEST['gid'] : (int) $_POST['primary'];
    $foundTarget = $changeType == 'primary' && $group_id == 0 ? true : false;
    // Sanity check!!
    if ($group_id == 1) {
        isAllowedTo('admin_forum');
    } else {
        $request = smf_db_query('
			SELECT group_type
			FROM {db_prefix}membergroups
			WHERE id_group = {int:current_group}
			LIMIT {int:limit}', array('current_group' => $group_id, 'limit' => 1));
        list($is_protected) = mysql_fetch_row($request);
        mysql_free_result($request);
        if ($is_protected == 1) {
            isAllowedTo('admin_forum');
        }
    }
    // What ever we are doing, we need to determine if changing primary is possible!
    $request = smf_db_query('
		SELECT id_group, group_type, hidden, group_name
		FROM {db_prefix}membergroups
		WHERE id_group IN ({int:group_list}, {int:current_group})', array('group_list' => $group_id, 'current_group' => $old_profile['id_group']));
    while ($row = mysql_fetch_assoc($request)) {
        // Is this the new group?
        if ($row['id_group'] == $group_id) {
            $foundTarget = true;
            $group_name = $row['group_name'];
            // Does the group type match what we're doing - are we trying to request a non-requestable group?
            if ($changeType == 'request' && $row['group_type'] != 2) {
                fatal_lang_error('no_access', false);
            } elseif ($changeType == 'free' && $row['group_type'] == 2 && $old_profile['id_group'] != $row['id_group'] && !isset($addGroups[$row['id_group']])) {
                fatal_lang_error('no_access', false);
            } elseif ($changeType == 'free' && $row['group_type'] != 3 && $row['group_type'] != 2) {
                fatal_lang_error('no_access', false);
            }
            // We can't change the primary group if this is hidden!
            if ($row['hidden'] == 2) {
                $canChangePrimary = false;
            }
        }
        // If this is their old primary, can we change it?
        if ($row['id_group'] == $old_profile['id_group'] && ($row['group_type'] > 1 || $context['can_manage_membergroups']) && $canChangePrimary !== false) {
            $canChangePrimary = 1;
        }
        // If we are not doing a force primary move, don't do it automatically if current primary is not 0.
        if ($changeType != 'primary' && $old_profile['id_group'] != 0) {
            $canChangePrimary = false;
        }
        // If this is the one we are acting on, can we even act?
        if (!$context['can_manage_protected'] && $row['group_type'] == 1 || !$context['can_manage_membergroups'] && $row['group_type'] == 0) {
            $canChangePrimary = false;
        }
    }
    mysql_free_result($request);
    // Didn't find the target?
    if (!$foundTarget) {
        fatal_lang_error('no_access', false);
    }
    // Final security check, don't allow users to promote themselves to admin.
    if ($context['can_manage_membergroups'] && !allowedTo('admin_forum')) {
        $request = smf_db_query('
			SELECT COUNT(permission)
			FROM {db_prefix}permissions
			WHERE id_group = {int:selected_group}
				AND permission = {string:admin_forum}
				AND add_deny = {int:not_denied}', array('selected_group' => $group_id, 'not_denied' => 1, 'admin_forum' => 'admin_forum'));
        list($disallow) = mysql_fetch_row($request);
        mysql_free_result($request);
        if ($disallow) {
            isAllowedTo('admin_forum');
        }
    }
    // If we're requesting, add the note then return.
    if ($changeType == 'request') {
        $request = smf_db_query('
			SELECT id_member
			FROM {db_prefix}log_group_requests
			WHERE id_member = {int:selected_member}
				AND id_group = {int:selected_group}', array('selected_member' => $memID, 'selected_group' => $group_id));
        if (mysql_num_rows($request) != 0) {
            fatal_lang_error('profile_error_already_requested_group');
        }
        mysql_free_result($request);
        // Log the request.
        smf_db_insert('', '{db_prefix}log_group_requests', array('id_member' => 'int', 'id_group' => 'int', 'time_applied' => 'int', 'reason' => 'string-65534'), array($memID, $group_id, time(), $_POST['reason']), array('id_request'));
        // Send an email to all group moderators etc.
        require_once $sourcedir . '/lib/Subs-Post.php';
        // Do we have any group moderators?
        $request = smf_db_query('
			SELECT id_member
			FROM {db_prefix}group_moderators
			WHERE id_group = {int:selected_group}', array('selected_group' => $group_id));
        $moderators = array();
        while ($row = mysql_fetch_assoc($request)) {
            $moderators[] = $row['id_member'];
        }
        mysql_free_result($request);
        // Otherwise this is the backup!
        if (empty($moderators)) {
            require_once $sourcedir . '/lib/Subs-Members.php';
            $moderators = membersAllowedTo('manage_membergroups');
        }
        if (!empty($moderators)) {
            $request = smf_db_query('
				SELECT id_member, email_address, lngfile, member_name, mod_prefs
				FROM {db_prefix}members
				WHERE id_member IN ({array_int:moderator_list})
					AND notify_types != {int:no_notifications}
				ORDER BY lngfile', array('moderator_list' => $moderators, 'no_notifications' => 4));
            while ($row = mysql_fetch_assoc($request)) {
                // Check whether they are interested.
                if (!empty($row['mod_prefs'])) {
                    list(, , $pref_binary) = explode('|', $row['mod_prefs']);
                    if (!($pref_binary & 4)) {
                        continue;
                    }
                }
                $replacements = array('RECPNAME' => $row['member_name'], 'APPYNAME' => $old_profile['member_name'], 'GROUPNAME' => $group_name, 'REASON' => $_POST['reason'], 'MODLINK' => $scripturl . '?action=moderate;area=groups;sa=requests');
                $emaildata = loadEmailTemplate('request_membership', $replacements, empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']);
                sendmail($row['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 2);
            }
            mysql_free_result($request);
        }
        return $changeType;
    } elseif ($changeType == 'free') {
        // Are we leaving?
        if ($old_profile['id_group'] == $group_id || isset($addGroups[$group_id])) {
            if ($old_profile['id_group'] == $group_id) {
                $newPrimary = 0;
            } else {
                unset($addGroups[$group_id]);
            }
        } else {
            // Can we change the primary, and do we want to?
            if ($canChangePrimary) {
                if ($old_profile['id_group'] != 0) {
                    $addGroups[$old_profile['id_group']] = -1;
                }
                $newPrimary = $group_id;
            } else {
                $addGroups[$group_id] = -1;
            }
        }
    } elseif ($canChangePrimary) {
        if ($old_profile['id_group'] != 0) {
            $addGroups[$old_profile['id_group']] = -1;
        }
        if (isset($addGroups[$group_id])) {
            unset($addGroups[$group_id]);
        }
        $newPrimary = $group_id;
    }
    // Finally, we can make the changes!
    foreach ($addGroups as $id => $dummy) {
        if (empty($id)) {
            unset($addGroups[$id]);
        }
    }
    $addGroups = implode(',', array_flip($addGroups));
    // Ensure that we don't cache permissions if the group is changing.
    if ($context['user']['is_owner']) {
        $_SESSION['mc']['time'] = 0;
    } else {
        updateSettings(array('settings_updated' => time()));
    }
    updateMemberData($memID, array('id_group' => $newPrimary, 'additional_groups' => $addGroups));
    return $changeType;
}
Example #13
0
function addSubscription($id_subscribe, $id_member, $renewal = 0, $forceStartTime = 0, $forceEndTime = 0)
{
    global $context, $smcFunc;
    // Take the easy way out...
    loadSubscriptions();
    // Exists, yes?
    if (!isset($context['subscriptions'][$id_subscribe])) {
        return;
    }
    $curSub = $context['subscriptions'][$id_subscribe];
    // Grab the duration.
    $duration = $curSub['num_length'];
    // If this is a renewal change the duration to be correct.
    if (!empty($renewal)) {
        switch ($renewal) {
            case 'D':
                $duration = 86400;
                break;
            case 'W':
                $duration = 604800;
                break;
            case 'M':
                $duration = 2629743;
                break;
            case 'Y':
                $duration = 31556926;
                break;
            default:
                break;
        }
    }
    // Firstly, see whether it exists, and is active. If so then this is meerly an extension.
    $request = smf_db_query('
		SELECT id_sublog, end_time, start_time
		FROM {db_prefix}log_subscribed
		WHERE id_subscribe = {int:current_subscription}
			AND id_member = {int:current_member}
			AND status = {int:is_active}', array('current_subscription' => $id_subscribe, 'current_member' => $id_member, 'is_active' => 1));
    if (mysql_num_rows($request) != 0) {
        list($id_sublog, $endtime, $starttime) = mysql_fetch_row($request);
        // If this has already expired but is active, extension means the period from now.
        if ($endtime < time()) {
            $endtime = time();
        }
        if ($starttime == 0) {
            $starttime = time();
        }
        // Work out the new expiry date.
        $endtime += $duration;
        if ($forceEndTime != 0) {
            $endtime = $forceEndTime;
        }
        // As everything else should be good, just update!
        smf_db_query('
			UPDATE {db_prefix}log_subscribed
			SET end_time = {int:end_time}, start_time = {int:start_time}
			WHERE id_sublog = {int:current_subscription_item}', array('end_time' => $endtime, 'start_time' => $starttime, 'current_subscription_item' => $id_sublog));
        return;
    }
    mysql_free_result($request);
    // If we're here, that means we don't have an active subscription - that means we need to do some work!
    $request = smf_db_query('
		SELECT m.id_group, m.additional_groups
		FROM {db_prefix}members AS m
		WHERE m.id_member = {int:current_member}', array('current_member' => $id_member));
    // Just in case the member doesn't exist.
    if (mysql_num_rows($request) == 0) {
        return;
    }
    list($old_id_group, $additional_groups) = mysql_fetch_row($request);
    mysql_free_result($request);
    // Prepare additional groups.
    $newAddGroups = explode(',', $curSub['add_groups']);
    $curAddGroups = explode(',', $additional_groups);
    $newAddGroups = array_merge($newAddGroups, $curAddGroups);
    // Simple, simple, simple - hopefully... id_group first.
    if ($curSub['prim_group'] != 0) {
        $id_group = $curSub['prim_group'];
        // Ensure their old privileges are maintained.
        if ($old_id_group != 0) {
            $newAddGroups[] = $old_id_group;
        }
    } else {
        $id_group = $old_id_group;
    }
    // Yep, make sure it's unique, and no empties.
    foreach ($newAddGroups as $k => $v) {
        if (empty($v)) {
            unset($newAddGroups[$k]);
        }
    }
    $newAddGroups = array_unique($newAddGroups);
    $newAddGroups = implode(',', $newAddGroups);
    // Store the new settings.
    smf_db_query('
		UPDATE {db_prefix}members
		SET id_group = {int:primary_group}, additional_groups = {string:additional_groups}
		WHERE id_member = {int:current_member}', array('primary_group' => $id_group, 'current_member' => $id_member, 'additional_groups' => $newAddGroups));
    // Now log the subscription - maybe we have a dorment subscription we can restore?
    $request = smf_db_query('
		SELECT id_sublog, end_time, start_time
		FROM {db_prefix}log_subscribed
		WHERE id_subscribe = {int:current_subscription}
			AND id_member = {int:current_member}', array('current_subscription' => $id_subscribe, 'current_member' => $id_member));
    //!!! Don't really need to do this twice...
    if (mysql_num_rows($request) != 0) {
        list($id_sublog, $endtime, $starttime) = mysql_fetch_row($request);
        // If this has already expired but is active, extension means the period from now.
        if ($endtime < time()) {
            $endtime = time();
        }
        if ($starttime == 0) {
            $starttime = time();
        }
        // Work out the new expiry date.
        $endtime += $duration;
        if ($forceEndTime != 0) {
            $endtime = $forceEndTime;
        }
        // As everything else should be good, just update!
        smf_db_query('
			UPDATE {db_prefix}log_subscribed
			SET start_time = {int:start_time}, end_time = {int:end_time}, old_id_group = {int:old_id_group}, status = {int:is_active},
				reminder_sent = {int:no_reminder_sent}
			WHERE id_sublog = {int:current_subscription_item}', array('start_time' => $starttime, 'end_time' => $endtime, 'old_id_group' => $old_id_group, 'is_active' => 1, 'no_reminder_sent' => 0, 'current_subscription_item' => $id_sublog));
        return;
    }
    mysql_free_result($request);
    // Otherwise a very simple insert.
    $endtime = time() + $duration;
    if ($forceEndTime != 0) {
        $endtime = $forceEndTime;
    }
    if ($forceStartTime == 0) {
        $starttime = time();
    } else {
        $starttime = $forceStartTime;
    }
    smf_db_insert('', '{db_prefix}log_subscribed', array('id_subscribe' => 'int', 'id_member' => 'int', 'old_id_group' => 'int', 'start_time' => 'int', 'end_time' => 'int', 'status' => 'int', 'pending_details' => 'string'), array($id_subscribe, $id_member, $old_id_group, $starttime, $endtime, 1, ''), array('id_sublog'));
}
Example #14
0
function SetJavaScript()
{
    global $settings, $user_info, $smcFunc, $options;
    // Check the session id.
    checkSession('get');
    // This good-for-nothing pixel is being used to keep the session alive.
    if (empty($_GET['var']) || !isset($_GET['val'])) {
        redirectexit($settings['images_url'] . '/blank.gif');
    }
    // Sorry, guests can't go any further than this..
    if ($user_info['is_guest'] || $user_info['id'] == 0) {
        obExit(false);
    }
    $reservedVars = array('actual_theme_url', 'actual_images_url', 'base_theme_dir', 'base_theme_url', 'default_images_url', 'default_theme_dir', 'default_theme_url', 'default_template', 'images_url', 'number_recent_posts', 'smiley_sets_default', 'theme_dir', 'theme_id', 'theme_layers', 'theme_templates', 'theme_url', 'name');
    // Can't change reserved vars.
    if (in_array(strtolower($_GET['var']), $reservedVars)) {
        redirectexit($settings['images_url'] . '/blank.gif');
    }
    // Use a specific theme?
    if (isset($_GET['th']) || isset($_GET['id'])) {
        // Invalidate the current themes cache too.
        CacheAPI::putCache('theme_settings-' . $settings['theme_id'] . ':' . $user_info['id'], null, 60);
        $settings['theme_id'] = isset($_GET['th']) ? (int) $_GET['th'] : (int) $_GET['id'];
    }
    // If this is the admin preferences the passed value will just be an element of it.
    if ($_GET['var'] == 'admin_preferences') {
        $options['admin_preferences'] = !empty($options['admin_preferences']) ? unserialize($options['admin_preferences']) : array();
        // New thingy...
        if (isset($_GET['admin_key']) && strlen($_GET['admin_key']) < 5) {
            $options['admin_preferences'][$_GET['admin_key']] = $_GET['val'];
        }
        // Change the value to be something nice,
        $_GET['val'] = serialize($options['admin_preferences']);
    }
    // Update the option.
    smf_db_insert('replace', '{db_prefix}themes', array('id_theme' => 'int', 'id_member' => 'int', 'variable' => 'string-255', 'value' => 'string-65534'), array($settings['theme_id'], $user_info['id'], $_GET['var'], is_array($_GET['val']) ? implode(',', $_GET['val']) : $_GET['val']), array('id_theme', 'id_member', 'variable'));
    CacheAPI::putCache('theme_settings-' . $settings['theme_id'] . ':' . $user_info['id'], null, 60);
    // Don't output anything...
    redirectexit($settings['images_url'] . '/blank.gif');
}
Example #15
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']);
}
Example #16
0
function AdminApprove()
{
    global $txt, $context, $scripturl, $modSettings, $sourcedir, $language, $user_info, $smcFunc;
    // First, check our session.
    checkSession();
    require_once $sourcedir . '/lib/Subs-Post.php';
    // We also need to the login languages here - for emails.
    loadLanguage('Login');
    // Sort out where we are going...
    $browse_type = isset($_REQUEST['type']) ? $_REQUEST['type'] : (!empty($modSettings['registration_method']) && $modSettings['registration_method'] == 1 ? 'activate' : 'approve');
    $current_filter = (int) $_REQUEST['orig_filter'];
    // If we are applying a filter do just that - then redirect.
    if (isset($_REQUEST['filter']) && $_REQUEST['filter'] != $_REQUEST['orig_filter']) {
        redirectexit('action=admin;area=viewmembers;sa=browse;type=' . $_REQUEST['type'] . ';sort=' . $_REQUEST['sort'] . ';filter=' . $_REQUEST['filter'] . ';start=' . $_REQUEST['start']);
    }
    // Nothing to do?
    if (!isset($_POST['todoAction']) && !isset($_POST['time_passed'])) {
        redirectexit('action=admin;area=viewmembers;sa=browse;type=' . $_REQUEST['type'] . ';sort=' . $_REQUEST['sort'] . ';filter=' . $current_filter . ';start=' . $_REQUEST['start']);
    }
    // Are we dealing with members who have been waiting for > set amount of time?
    if (isset($_POST['time_passed'])) {
        $timeBefore = time() - 86400 * (int) $_POST['time_passed'];
        $condition = '
			AND date_registered < {int:time_before}';
    } else {
        $members = array();
        foreach ($_POST['todoAction'] as $id) {
            $members[] = (int) $id;
        }
        $condition = '
			AND id_member IN ({array_int:members})';
    }
    // Get information on each of the members, things that are important to us, like email address...
    $request = smf_db_query('
		SELECT id_member, member_name, real_name, email_address, validation_code, lngfile
		FROM {db_prefix}members
		WHERE is_activated = {int:activated_status}' . $condition . '
		ORDER BY lngfile', array('activated_status' => $current_filter, 'time_before' => empty($timeBefore) ? 0 : $timeBefore, 'members' => empty($members) ? array() : $members));
    $member_count = mysql_num_rows($request);
    // If no results then just return!
    if ($member_count == 0) {
        redirectexit('action=admin;area=viewmembers;sa=browse;type=' . $_REQUEST['type'] . ';sort=' . $_REQUEST['sort'] . ';filter=' . $current_filter . ';start=' . $_REQUEST['start']);
    }
    $member_info = array();
    $members = array();
    // Fill the info array.
    while ($row = mysql_fetch_assoc($request)) {
        $members[] = $row['id_member'];
        $member_info[] = array('id' => $row['id_member'], 'username' => $row['member_name'], 'name' => $row['real_name'], 'email' => $row['email_address'], 'language' => empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile'], 'code' => $row['validation_code']);
    }
    mysql_free_result($request);
    // Are we activating or approving the members?
    if ($_POST['todo'] == 'ok' || $_POST['todo'] == 'okemail') {
        // Approve/activate this member.
        smf_db_query('
			UPDATE {db_prefix}members
			SET validation_code = {string:blank_string}, is_activated = {int:is_activated}
			WHERE is_activated = {int:activated_status}' . $condition, array('is_activated' => 1, 'time_before' => empty($timeBefore) ? 0 : $timeBefore, 'members' => empty($members) ? array() : $members, 'activated_status' => $current_filter, 'blank_string' => ''));
        // Do we have to let the integration code know about the activations?
        if (!empty($modSettings['integrate_activate'])) {
            foreach ($member_info as $member) {
                HookAPI::callHook('integrate_activate', array($member['username']));
            }
        }
        // Check for email.
        if ($_POST['todo'] == 'okemail') {
            foreach ($member_info as $member) {
                $replacements = array('NAME' => $member['name'], 'USERNAME' => $member['username'], 'PROFILELINK' => $scripturl . '?action=profile;u=' . $member['id'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder');
                $emaildata = loadEmailTemplate('admin_approve_accept', $replacements, $member['language']);
                sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0);
            }
        }
    } elseif ($_POST['todo'] == 'require_activation') {
        require_once $sourcedir . '/lib/Subs-Members.php';
        // We have to do this for each member I'm afraid.
        foreach ($member_info as $member) {
            // Generate a random activation code.
            $validation_code = generateValidationCode();
            // Set these members for activation - I know this includes two id_member checks but it's safer than bodging $condition ;).
            smf_db_query('
				UPDATE {db_prefix}members
				SET validation_code = {string:validation_code}, is_activated = {int:not_activated}
				WHERE is_activated = {int:activated_status}
					' . $condition . '
					AND id_member = {int:selected_member}', array('not_activated' => 0, 'activated_status' => $current_filter, 'selected_member' => $member['id'], 'validation_code' => $validation_code, 'time_before' => empty($timeBefore) ? 0 : $timeBefore, 'members' => empty($members) ? array() : $members));
            $replacements = array('USERNAME' => $member['name'], 'ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $member['id'] . ';code=' . $validation_code, 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $member['id'], 'ACTIVATIONCODE' => $validation_code);
            $emaildata = loadEmailTemplate('admin_approve_activation', $replacements, $member['language']);
            sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0);
        }
    } elseif ($_POST['todo'] == 'reject' || $_POST['todo'] == 'rejectemail') {
        require_once $sourcedir . '/lib/Subs-Members.php';
        deleteMembers($members);
        // Send email telling them they aren't welcome?
        if ($_POST['todo'] == 'rejectemail') {
            foreach ($member_info as $member) {
                $replacements = array('USERNAME' => $member['name']);
                $emaildata = loadEmailTemplate('admin_approve_reject', $replacements, $member['language']);
                sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 1);
            }
        }
    } elseif ($_POST['todo'] == 'delete' || $_POST['todo'] == 'deleteemail') {
        require_once $sourcedir . '/lib/Subs-Members.php';
        deleteMembers($members);
        // Send email telling them they aren't welcome?
        if ($_POST['todo'] == 'deleteemail') {
            foreach ($member_info as $member) {
                $replacements = array('USERNAME' => $member['name']);
                $emaildata = loadEmailTemplate('admin_approve_delete', $replacements, $member['language']);
                sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 1);
            }
        }
    } elseif ($_POST['todo'] == 'remind') {
        foreach ($member_info as $member) {
            $replacements = array('USERNAME' => $member['name'], 'ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $member['id'] . ';code=' . $member['code'], 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $member['id'], 'ACTIVATIONCODE' => $member['code']);
            $emaildata = loadEmailTemplate('admin_approve_remind', $replacements, $member['language']);
            sendmail($member['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 1);
        }
    }
    // Back to the user's language!
    if (isset($current_language) && $current_language != $user_info['language']) {
        loadLanguage('index');
        loadLanguage('ManageMembers');
    }
    // Log what we did?
    if (!empty($modSettings['modlog_enabled']) && in_array($_POST['todo'], array('ok', 'okemail', 'require_activation', 'remind'))) {
        $log_action = $_POST['todo'] == 'remind' ? 'remind_member' : 'approve_member';
        $log_inserts = array();
        foreach ($member_info as $member) {
            $log_inserts[] = array(time(), 3, $user_info['id'], $user_info['ip'], $log_action, 0, 0, 0, serialize(array('member' => $member['id'])));
        }
        smf_db_insert('', '{db_prefix}log_actions', array('log_time' => 'int', 'id_log' => 'int', 'id_member' => 'int', 'ip' => 'string-16', 'action' => 'string', 'id_board' => 'int', 'id_topic' => 'int', 'id_msg' => 'int', 'extra' => 'string-65534'), $log_inserts, array('id_action'));
    }
    // Although updateStats *may* catch this, best to do it manually just in case (Doesn't always sort out unapprovedMembers).
    if (in_array($current_filter, array(3, 4))) {
        updateSettings(array('unapprovedMembers' => $modSettings['unapprovedMembers'] > $member_count ? $modSettings['unapprovedMembers'] - $member_count : 0));
    }
    // Update the member's stats. (but, we know the member didn't change their name.)
    updateStats('member', false);
    // If they haven't been deleted, update the post group statistics on them...
    if (!in_array($_POST['todo'], array('delete', 'deleteemail', 'reject', 'rejectemail', 'remind'))) {
        updateStats('postgroups', $members);
    }
    redirectexit('action=admin;area=viewmembers;sa=browse;type=' . $_REQUEST['type'] . ';sort=' . $_REQUEST['sort'] . ';filter=' . $current_filter . ';start=' . $_REQUEST['start']);
}
Example #17
0
function BoardNotify()
{
    global $scripturl, $txt, $board, $user_info, $context, $smcFunc;
    // Permissions are an important part of anything ;).
    is_not_guest();
    isAllowedTo('mark_notify');
    // You have to specify a board to turn notifications on!
    if (empty($board)) {
        fatal_lang_error('no_board', false);
    }
    // No subaction: find out what to do.
    if (empty($_GET['sa'])) {
        // We're gonna need the notify template...
        Eos_Smarty::loadTemplate('generic_skeleton');
        EoS_Smarty::getConfigInstance()->registerHookTemplate('generic_content_area', 'notify/notify_board');
        // Find out if they have notification set for this topic already.
        $request = smf_db_query('
			SELECT id_member
			FROM {db_prefix}log_notify
			WHERE id_member = {int:current_member}
				AND id_board = {int:current_board}
			LIMIT 1', array('current_board' => $board, 'current_member' => $user_info['id']));
        $context['notification_set'] = mysql_num_rows($request) != 0;
        mysql_free_result($request);
        // Set the template variables...
        $context['board_href'] = $scripturl . '?board=' . $board . '.' . $_REQUEST['start'];
        $context['start'] = $_REQUEST['start'];
        $context['page_title'] = $txt['notification'];
        return;
    } elseif ($_GET['sa'] == 'on') {
        checkSession('get');
        // Turn notification on.  (note this just blows smoke if it's already on.)
        smf_db_insert('ignore', '{db_prefix}log_notify', array('id_member' => 'int', 'id_board' => 'int'), array($user_info['id'], $board), array('id_member', 'id_board'));
    } else {
        checkSession('get');
        // Turn notification off for this board.
        smf_db_query('
			DELETE FROM {db_prefix}log_notify
			WHERE id_member = {int:current_member}
				AND id_board = {int:current_board}', array('current_board' => $board, 'current_member' => $user_info['id']));
    }
    // Back to the board!
    redirectexit('board=' . $board . '.' . $_REQUEST['start']);
}
Example #18
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']));
}
Example #19
0
function log_error($error_message, $error_type = 'general', $file = null, $line = null)
{
    global $txt, $modSettings, $sc, $user_info, $smcFunc, $scripturl, $last_error;
    // Check if error logging is actually on.
    if (empty($modSettings['enableErrorLogging'])) {
        return $error_message;
    }
    // Basically, htmlspecialchars it minus &. (for entities!)
    $error_message = strtr($error_message, array('<' => '&lt;', '>' => '&gt;', '"' => '&quot;'));
    $error_message = strtr($error_message, array('&lt;br /&gt;' => '<br />', '&lt;b&gt;' => '<strong>', '&lt;/b&gt;' => '</strong>', "\n" => '<br />'));
    // Add a file and line to the error message?
    // Don't use the actual txt entries for file and line but instead use %1$s for file and %2$s for line
    if ($file == null) {
        $file = '';
    } else {
        // Window style slashes don't play well, lets convert them to the unix style.
        $file = str_replace('\\', '/', $file);
    }
    if ($line == null) {
        $line = 0;
    } else {
        $line = (int) $line;
    }
    // Just in case there's no id_member or IP set yet.
    if (empty($user_info['id'])) {
        $user_info['id'] = 0;
    }
    if (empty($user_info['ip'])) {
        $user_info['ip'] = '';
    }
    // Find the best query string we can...
    $query_string = empty($_SERVER['QUERY_STRING']) ? empty($_SERVER['REQUEST_URL']) ? '' : str_replace($scripturl, '', $_SERVER['REQUEST_URL']) : $_SERVER['QUERY_STRING'];
    // Don't log the session hash in the url twice, it's a waste.
    $query_string = htmlspecialchars((SMF == 'SSI' ? '' : '?') . preg_replace(array('~;sesc=[^&;]+~', '~' . session_name() . '=' . session_id() . '[&;]~'), array(';sesc', ''), $query_string));
    // Just so we know what board error messages are from.
    if (isset($_POST['board']) && !isset($_GET['board'])) {
        $query_string .= ($query_string == '' ? 'board=' : ';board=') . $_POST['board'];
    }
    // What types of categories do we have?
    $known_error_types = array('general', 'critical', 'database', 'undefined_vars', 'user', 'template', 'debug');
    // Make sure the category that was specified is a valid one
    $error_type = in_array($error_type, $known_error_types) && $error_type !== true ? $error_type : 'general';
    // Don't log the same error countless times, as we can get in a cycle of depression...
    $error_info = array($user_info['id'], time(), $user_info['ip'], $query_string, $error_message, (string) $sc, $error_type, $file, $line);
    if (empty($last_error) || $last_error != $error_info) {
        // Insert the error into the database.
        smf_db_insert('', '{db_prefix}log_errors', array('id_member' => 'int', 'log_time' => 'int', 'ip' => 'string-16', 'url' => 'string-65534', 'message' => 'string-65534', 'session' => 'string', 'error_type' => 'string', 'file' => 'string-255', 'line' => 'int'), $error_info, array('id_error'));
        $last_error = $error_info;
    }
    // Return the message to make things simpler.
    return $error_message;
}
Example #20
0
function moveTopics($topics, $toBoard)
{
    global $sourcedir, $user_info, $modSettings, $smcFunc;
    // Empty array?
    if (empty($topics)) {
        return;
    } elseif (is_numeric($topics)) {
        $topics = array($topics);
    }
    $num_topics = count($topics);
    $fromBoards = array();
    // Destination board empty or equal to 0?
    if (empty($toBoard)) {
        return;
    }
    // Are we moving to the recycle board?
    $isRecycleDest = !empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] == $toBoard;
    // Determine the source boards...
    $request = smf_db_query('
		SELECT id_board, approved, COUNT(*) AS num_topics, SUM(unapproved_posts) AS unapproved_posts,
			SUM(num_replies) AS num_replies
		FROM {db_prefix}topics
		WHERE id_topic IN ({array_int:topics})
		GROUP BY id_board, approved', array('topics' => $topics));
    // Num of rows = 0 -> no topics found. Num of rows > 1 -> topics are on multiple boards.
    if (mysql_num_rows($request) == 0) {
        return;
    }
    while ($row = mysql_fetch_assoc($request)) {
        if (!isset($fromBoards[$row['id_board']]['num_posts'])) {
            $fromBoards[$row['id_board']] = array('num_posts' => 0, 'num_topics' => 0, 'unapproved_posts' => 0, 'unapproved_topics' => 0, 'id_board' => $row['id_board']);
        }
        // Posts = (num_replies + 1) for each approved topic.
        $fromBoards[$row['id_board']]['num_posts'] += $row['num_replies'] + ($row['approved'] ? $row['num_topics'] : 0);
        $fromBoards[$row['id_board']]['unapproved_posts'] += $row['unapproved_posts'];
        // Add the topics to the right type.
        if ($row['approved']) {
            $fromBoards[$row['id_board']]['num_topics'] += $row['num_topics'];
        } else {
            $fromBoards[$row['id_board']]['unapproved_topics'] += $row['num_topics'];
        }
    }
    mysql_free_result($request);
    // Move over the mark_read data. (because it may be read and now not by some!)
    $SaveAServer = max(0, $modSettings['maxMsgID'] - 50000);
    $request = smf_db_query('
		SELECT lmr.id_member, lmr.id_msg, t.id_topic
		FROM {db_prefix}topics AS t
			INNER JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board
				AND lmr.id_msg > t.id_first_msg AND lmr.id_msg > {int:protect_lmr_msg})
			LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = lmr.id_member)
		WHERE t.id_topic IN ({array_int:topics})
			AND lmr.id_msg > IFNULL(lt.id_msg, 0)', array('protect_lmr_msg' => $SaveAServer, 'topics' => $topics));
    $log_topics = array();
    while ($row = mysql_fetch_assoc($request)) {
        $log_topics[] = array($row['id_topic'], $row['id_member'], $row['id_msg']);
        // Prevent queries from getting too big. Taking some steam off.
        if (count($log_topics) > 500) {
            smf_db_insert('replace', '{db_prefix}log_topics', array('id_topic' => 'int', 'id_member' => 'int', 'id_msg' => 'int'), $log_topics, array('id_topic', 'id_member'));
            $log_topics = array();
        }
    }
    mysql_free_result($request);
    // Now that we have all the topics that *should* be marked read, and by which members...
    if (!empty($log_topics)) {
        // Insert that information into the database!
        smf_db_insert('replace', '{db_prefix}log_topics', array('id_topic' => 'int', 'id_member' => 'int', 'id_msg' => 'int'), $log_topics, array('id_topic', 'id_member'));
    }
    // Update the number of posts on each board.
    $totalTopics = 0;
    $totalPosts = 0;
    $totalUnapprovedTopics = 0;
    $totalUnapprovedPosts = 0;
    foreach ($fromBoards as $stats) {
        smf_db_query('
			UPDATE {db_prefix}boards
			SET
				num_posts = CASE WHEN {int:num_posts} > num_posts THEN 0 ELSE num_posts - {int:num_posts} END,
				num_topics = CASE WHEN {int:num_topics} > num_topics THEN 0 ELSE num_topics - {int:num_topics} END,
				unapproved_posts = CASE WHEN {int:unapproved_posts} > unapproved_posts THEN 0 ELSE unapproved_posts - {int:unapproved_posts} END,
				unapproved_topics = CASE WHEN {int:unapproved_topics} > unapproved_topics THEN 0 ELSE unapproved_topics - {int:unapproved_topics} END
			WHERE id_board = {int:id_board}', array('id_board' => $stats['id_board'], 'num_posts' => $stats['num_posts'], 'num_topics' => $stats['num_topics'], 'unapproved_posts' => $stats['unapproved_posts'], 'unapproved_topics' => $stats['unapproved_topics']));
        $totalTopics += $stats['num_topics'];
        $totalPosts += $stats['num_posts'];
        $totalUnapprovedTopics += $stats['unapproved_topics'];
        $totalUnapprovedPosts += $stats['unapproved_posts'];
    }
    smf_db_query('
		UPDATE {db_prefix}boards
		SET
			num_topics = num_topics + {int:total_topics},
			num_posts = num_posts + {int:total_posts},' . ($isRecycleDest ? '
			unapproved_posts = {int:no_unapproved}, unapproved_topics = {int:no_unapproved}' : '
			unapproved_posts = unapproved_posts + {int:total_unapproved_posts},
			unapproved_topics = unapproved_topics + {int:total_unapproved_topics}') . '
		WHERE id_board = {int:id_board}', array('id_board' => $toBoard, 'total_topics' => $totalTopics, 'total_posts' => $totalPosts, 'total_unapproved_topics' => $totalUnapprovedTopics, 'total_unapproved_posts' => $totalUnapprovedPosts, 'no_unapproved' => 0));
    // Move the topic.  Done.  :P
    smf_db_query('
		UPDATE {db_prefix}topics
		SET id_board = {int:id_board}' . ($isRecycleDest ? ',
			unapproved_posts = {int:no_unapproved}, approved = {int:is_approved}' : '') . '
		WHERE id_topic IN ({array_int:topics})', array('id_board' => $toBoard, 'topics' => $topics, 'is_approved' => 1, 'no_unapproved' => 0));
    // If this was going to the recycle bin, check what messages are being recycled, and remove them from the queue.
    if ($isRecycleDest && ($totalUnapprovedTopics || $totalUnapprovedPosts)) {
        $request = smf_db_query('
			SELECT id_msg
			FROM {db_prefix}messages
			WHERE id_topic IN ({array_int:topics})
				and approved = {int:not_approved}', array('topics' => $topics, 'not_approved' => 0));
        $approval_msgs = array();
        while ($row = mysql_fetch_assoc($request)) {
            $approval_msgs[] = $row['id_msg'];
        }
        mysql_free_result($request);
        // Empty the approval queue for these, as we're going to approve them next.
        if (!empty($approval_msgs)) {
            smf_db_query('
				DELETE FROM {db_prefix}approval_queue
				WHERE id_msg IN ({array_int:message_list})
					AND id_attach = {int:id_attach}', array('message_list' => $approval_msgs, 'id_attach' => 0));
        }
        // Get all the current max and mins.
        $request = smf_db_query('
			SELECT id_topic, id_first_msg, id_last_msg
			FROM {db_prefix}topics
			WHERE id_topic IN ({array_int:topics})', array('topics' => $topics));
        $topicMaxMin = array();
        while ($row = mysql_fetch_assoc($request)) {
            $topicMaxMin[$row['id_topic']] = array('min' => $row['id_first_msg'], 'max' => $row['id_last_msg']);
        }
        mysql_free_result($request);
        // Check the MAX and MIN are correct.
        $request = smf_db_query('
			SELECT id_topic, MIN(id_msg) AS first_msg, MAX(id_msg) AS last_msg
			FROM {db_prefix}messages
			WHERE id_topic IN ({array_int:topics})
			GROUP BY id_topic', array('topics' => $topics));
        while ($row = mysql_fetch_assoc($request)) {
            // If not, update.
            if ($row['first_msg'] != $topicMaxMin[$row['id_topic']]['min'] || $row['last_msg'] != $topicMaxMin[$row['id_topic']]['max']) {
                smf_db_query('
					UPDATE {db_prefix}topics
					SET id_first_msg = {int:first_msg}, id_last_msg = {int:last_msg}
					WHERE id_topic = {int:selected_topic}', array('first_msg' => $row['first_msg'], 'last_msg' => $row['last_msg'], 'selected_topic' => $row['id_topic']));
            }
        }
        mysql_free_result($request);
    }
    smf_db_query('
		UPDATE {db_prefix}messages
		SET id_board = {int:id_board}' . ($isRecycleDest ? ',approved = {int:is_approved}' : '') . '
		WHERE id_topic IN ({array_int:topics})', array('id_board' => $toBoard, 'topics' => $topics, 'is_approved' => 1));
    smf_db_query('
		UPDATE {db_prefix}log_reported
		SET id_board = {int:id_board}
		WHERE id_topic IN ({array_int:topics})', array('id_board' => $toBoard, 'topics' => $topics));
    smf_db_query('
		UPDATE {db_prefix}calendar
		SET id_board = {int:id_board}
		WHERE id_topic IN ({array_int:topics})', array('id_board' => $toBoard, 'topics' => $topics));
    // Mark target board as seen, if it was already marked as seen before.
    $request = smf_db_query('
		SELECT (IFNULL(lb.id_msg, 0) >= b.id_msg_updated) AS isSeen
		FROM {db_prefix}boards AS b
			LEFT JOIN {db_prefix}log_boards AS lb ON (lb.id_board = b.id_board AND lb.id_member = {int:current_member})
		WHERE b.id_board = {int:id_board}', array('current_member' => $user_info['id'], 'id_board' => $toBoard));
    list($isSeen) = mysql_fetch_row($request);
    mysql_free_result($request);
    if (!empty($isSeen) && !$user_info['is_guest']) {
        smf_db_insert('replace', '{db_prefix}log_boards', array('id_board' => 'int', 'id_member' => 'int', 'id_msg' => 'int'), array($toBoard, $user_info['id'], $modSettings['maxMsgID']), array('id_board', 'id_member'));
    }
    // Update the cache?
    if (!empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 3) {
        foreach ($topics as $topic_id) {
            CacheAPI::putCache('topic_board-' . $topic_id, null, 120);
        }
    }
    require_once $sourcedir . '/lib/Subs-Post.php';
    $updates = array_keys($fromBoards);
    $updates[] = $toBoard;
    updateLastMessages(array_unique($updates));
    // Update 'em pesky stats.
    updateStats('topic');
    updateStats('message');
    updateSettings(array('calendar_updated' => time()));
}
Example #21
0
function collapseCategories($categories, $new_status, $members = null, $check_collapsable = true)
{
    global $smcFunc;
    // Collapse or expand the categories.
    if ($new_status === 'collapse' || $new_status === 'expand') {
        smf_db_query('
			DELETE FROM {db_prefix}collapsed_categories
			WHERE id_cat IN ({array_int:category_list})' . ($members === null ? '' : '
				AND id_member IN ({array_int:member_list})'), array('category_list' => $categories, 'member_list' => $members));
        if ($new_status === 'collapse') {
            smf_db_query('
				INSERT INTO {db_prefix}collapsed_categories
					(id_cat, id_member)
				SELECT c.id_cat, mem.id_member
				FROM {db_prefix}categories AS c
					INNER JOIN {db_prefix}members AS mem ON (' . ($members === null ? '1=1' : '
						mem.id_member IN ({array_int:member_list})') . ')
				WHERE c.id_cat IN ({array_int:category_list})' . ($check_collapsable ? '
					AND c.can_collapse = {int:is_collapsible}' : ''), array('member_list' => $members, 'category_list' => $categories, 'is_collapsible' => 1));
        }
    } elseif ($new_status === 'toggle') {
        // Get the current state of the categories.
        $updates = array('insert' => array(), 'remove' => array());
        $request = smf_db_query('
			SELECT mem.id_member, c.id_cat, IFNULL(cc.id_cat, 0) AS is_collapsed, c.can_collapse
			FROM {db_prefix}members AS mem
				INNER JOIN {db_prefix}categories AS c ON (c.id_cat IN ({array_int:category_list}))
				LEFT JOIN {db_prefix}collapsed_categories AS cc ON (cc.id_cat = c.id_cat AND cc.id_member = mem.id_member)
			' . ($members === null ? '' : '
				WHERE mem.id_member IN ({array_int:member_list})'), array('category_list' => $categories, 'member_list' => $members));
        while ($row = mysql_fetch_assoc($request)) {
            if (empty($row['is_collapsed']) && (!empty($row['can_collapse']) || !$check_collapsable)) {
                $updates['insert'][] = array($row['id_member'], $row['id_cat']);
            } elseif (!empty($row['is_collapsed'])) {
                $updates['remove'][] = '(id_member = ' . $row['id_member'] . ' AND id_cat = ' . $row['id_cat'] . ')';
            }
        }
        mysql_free_result($request);
        // Collapse the ones that were originally expanded...
        if (!empty($updates['insert'])) {
            smf_db_insert('replace', '{db_prefix}collapsed_categories', array('id_cat' => 'int', 'id_member' => 'int'), $updates['insert'], array('id_cat', 'id_member'));
        }
        // And expand the ones that were originally collapsed.
        if (!empty($updates['remove'])) {
            smf_db_query('
				DELETE FROM {db_prefix}collapsed_categories
				WHERE ' . implode(' OR ', $updates['remove']), array());
        }
    }
}
Example #22
0
function loadAttachmentContext($id_msg)
{
    global $attachments, $modSettings, $txt, $scripturl, $topic, $sourcedir, $backend_subdir;
    // Set up the attachment info - based on code by Meriadoc.
    $attachmentData = array();
    $have_unapproved = false;
    if (isset($attachments[$id_msg]) && !empty($modSettings['attachmentEnable'])) {
        foreach ($attachments[$id_msg] as $i => $attachment) {
            $attachmentData[$i] = array('id' => $attachment['id_attach'], 'name' => preg_replace('~&amp;#(\\d{1,7}|x[0-9a-fA-F]{1,6});~', '&#\\1;', htmlspecialchars($attachment['filename'])), 'downloads' => $attachment['downloads'], 'size' => round($attachment['filesize'] / 1024, 2) . ' ' . $txt['kilobyte'], 'byte_size' => $attachment['filesize'], 'href' => $scripturl . '?action=dlattach;topic=' . $topic . '.0;attach=' . $attachment['id_attach'], 'link' => '<a href="' . $scripturl . '?action=dlattach;topic=' . $topic . '.0;attach=' . $attachment['id_attach'] . '">' . htmlspecialchars($attachment['filename']) . '</a>', 'is_image' => !empty($attachment['width']) && !empty($attachment['height']) && !empty($modSettings['attachmentShowImages']), 'is_approved' => $attachment['approved']);
            // If something is unapproved we'll note it so we can sort them.
            if (!$attachment['approved']) {
                $have_unapproved = true;
            }
            if (!$attachmentData[$i]['is_image']) {
                continue;
            }
            $attachmentData[$i]['real_width'] = $attachment['width'];
            $attachmentData[$i]['width'] = $attachment['width'];
            $attachmentData[$i]['real_height'] = $attachment['height'];
            $attachmentData[$i]['height'] = $attachment['height'];
            // Let's see, do we want thumbs?
            if (!empty($modSettings['attachmentThumbnails']) && !empty($modSettings['attachmentThumbWidth']) && !empty($modSettings['attachmentThumbHeight']) && ($attachment['width'] > $modSettings['attachmentThumbWidth'] || $attachment['height'] > $modSettings['attachmentThumbHeight']) && strlen($attachment['filename']) < 249) {
                // A proper thumb doesn't exist yet? Create one!
                if (empty($attachment['id_thumb']) || $attachment['thumb_width'] > $modSettings['attachmentThumbWidth'] || $attachment['thumb_height'] > $modSettings['attachmentThumbHeight'] || $attachment['thumb_width'] < $modSettings['attachmentThumbWidth'] && $attachment['thumb_height'] < $modSettings['attachmentThumbHeight']) {
                    $filename = getAttachmentFilename($attachment['filename'], $attachment['id_attach'], $attachment['id_folder']);
                    require_once $sourcedir . '/lib/Subs-Graphics.php';
                    if (createThumbnail($filename, $modSettings['attachmentThumbWidth'], $modSettings['attachmentThumbHeight'])) {
                        // So what folder are we putting this image in?
                        if (!empty($modSettings['currentAttachmentUploadDir'])) {
                            if (!is_array($modSettings['attachmentUploadDir'])) {
                                $modSettings['attachmentUploadDir'] = @unserialize($modSettings['attachmentUploadDir']);
                            }
                            $path = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']];
                            $id_folder_thumb = $modSettings['currentAttachmentUploadDir'];
                        } else {
                            $path = $modSettings['attachmentUploadDir'];
                            $id_folder_thumb = 1;
                        }
                        // Calculate the size of the created thumbnail.
                        $size = @getimagesize($filename . '_thumb');
                        list($attachment['thumb_width'], $attachment['thumb_height']) = $size;
                        $thumb_size = filesize($filename . '_thumb');
                        // These are the only valid image types for SMF.
                        $validImageTypes = array(1 => 'gif', 2 => 'jpeg', 3 => 'png', 5 => 'psd', 6 => 'bmp', 7 => 'tiff', 8 => 'tiff', 9 => 'jpeg', 14 => 'iff');
                        // What about the extension?
                        $thumb_ext = isset($validImageTypes[$size[2]]) ? $validImageTypes[$size[2]] : '';
                        // Figure out the mime type.
                        if (!empty($size['mime'])) {
                            $thumb_mime = $size['mime'];
                        } else {
                            $thumb_mime = 'image/' . $thumb_ext;
                        }
                        $thumb_filename = $attachment['filename'] . '_thumb';
                        $thumb_hash = getAttachmentFilename($thumb_filename, false, null, true);
                        // Add this beauty to the database.
                        smf_db_insert('', '{db_prefix}attachments', array('id_folder' => 'int', 'id_msg' => 'int', 'attachment_type' => 'int', 'filename' => 'string', 'file_hash' => 'string', 'size' => 'int', 'width' => 'int', 'height' => 'int', 'fileext' => 'string', 'mime_type' => 'string'), array($id_folder_thumb, $id_msg, 3, $thumb_filename, $thumb_hash, (int) $thumb_size, (int) $attachment['thumb_width'], (int) $attachment['thumb_height'], $thumb_ext, $thumb_mime), array('id_attach'));
                        $old_id_thumb = $attachment['id_thumb'];
                        $attachment['id_thumb'] = smf_db_insert_id('{db_prefix}attachments', 'id_attach');
                        if (!empty($attachment['id_thumb'])) {
                            smf_db_query('
								UPDATE {db_prefix}attachments
								SET id_thumb = {int:id_thumb}
								WHERE id_attach = {int:id_attach}', array('id_thumb' => $attachment['id_thumb'], 'id_attach' => $attachment['id_attach']));
                            $thumb_realname = getAttachmentFilename($thumb_filename, $attachment['id_thumb'], $id_folder_thumb, false, $thumb_hash);
                            rename($filename . '_thumb', $thumb_realname);
                            // Do we need to remove an old thumbnail?
                            if (!empty($old_id_thumb)) {
                                require_once $sourcedir . '/lib/Subs-ManageAttachments.php';
                                removeAttachments(array('id_attach' => $old_id_thumb), '', false, false);
                            }
                        }
                    }
                }
                // Only adjust dimensions on successful thumbnail creation.
                if (!empty($attachment['thumb_width']) && !empty($attachment['thumb_height'])) {
                    $attachmentData[$i]['width'] = $attachment['thumb_width'];
                    $attachmentData[$i]['height'] = $attachment['thumb_height'];
                }
            }
            if (!empty($attachment['id_thumb'])) {
                $attachmentData[$i]['thumbnail'] = array('id' => $attachment['id_thumb'], 'href' => $scripturl . '?action=dlattach;topic=' . $topic . '.0;attach=' . $attachment['id_thumb'] . ';image');
            }
            $attachmentData[$i]['thumbnail']['has_thumb'] = !empty($attachment['id_thumb']);
            // If thumbnails are disabled, check the maximum size of the image.
            if (!$attachmentData[$i]['thumbnail']['has_thumb'] && (!empty($modSettings['max_image_width']) && $attachment['width'] > $modSettings['max_image_width'] || !empty($modSettings['max_image_height']) && $attachment['height'] > $modSettings['max_image_height'])) {
                if (!empty($modSettings['max_image_width']) && (empty($modSettings['max_image_height']) || $attachment['height'] * $modSettings['max_image_width'] / $attachment['width'] <= $modSettings['max_image_height'])) {
                    $attachmentData[$i]['width'] = $modSettings['max_image_width'];
                    $attachmentData[$i]['height'] = floor($attachment['height'] * $modSettings['max_image_width'] / $attachment['width']);
                } elseif (!empty($modSettings['max_image_width'])) {
                    $attachmentData[$i]['width'] = floor($attachment['width'] * $modSettings['max_image_height'] / $attachment['height']);
                    $attachmentData[$i]['height'] = $modSettings['max_image_height'];
                }
            } elseif ($attachmentData[$i]['thumbnail']['has_thumb']) {
                // If the image is too large to show inline, make it a popup.
                if (!empty($modSettings['max_image_width']) && $attachmentData[$i]['real_width'] > $modSettings['max_image_width'] || !empty($modSettings['max_image_height']) && $attachmentData[$i]['real_height'] > $modSettings['max_image_height']) {
                    $attachmentData[$i]['thumbnail']['javascript'] = 'return reqWin(\'' . $attachmentData[$i]['href'] . ';image\', ' . ($attachment['width'] + 20) . ', ' . ($attachment['height'] + 20) . ', true);';
                } else {
                    $attachmentData[$i]['thumbnail']['javascript'] = 'return expandThumb(' . $attachment['id_attach'] . ');';
                }
            }
            if (!$attachmentData[$i]['thumbnail']['has_thumb']) {
                $attachmentData[$i]['downloads']++;
            }
        }
        // sort images to the top
        usort($attachmentData, 'sort_by_type');
    }
    // Do we need to instigate a sort?
    if ($have_unapproved) {
        usort($attachmentData, 'approved_attach_sort');
    }
    return $attachmentData;
}
Example #23
0
function registerMember(&$regOptions, $return_errors = false)
{
    global $scripturl, $txt, $modSettings, $context, $sourcedir;
    global $user_info, $options, $settings, $smcFunc;
    loadLanguage('Login');
    // We'll need some external functions.
    require_once $sourcedir . '/lib/Subs-Auth.php';
    require_once $sourcedir . '/lib/Subs-Post.php';
    // Put any errors in here.
    $reg_errors = array();
    // Registration from the admin center, let them sweat a little more.
    if ($regOptions['interface'] == 'admin') {
        is_not_guest();
        isAllowedTo('moderate_forum');
    } elseif ($regOptions['interface'] == 'guest') {
        // You cannot register twice...
        if (empty($user_info['is_guest'])) {
            redirectexit();
        }
        // Make sure they didn't just register with this session.
        if (!empty($_SESSION['just_registered']) && empty($modSettings['disableRegisterCheck'])) {
            fatal_lang_error('register_only_once', false);
        }
    }
    // What method of authorization are we going to use?
    if (empty($regOptions['auth_method']) || !in_array($regOptions['auth_method'], array('password', 'openid'))) {
        if (!empty($regOptions['openid'])) {
            $regOptions['auth_method'] = 'openid';
        } else {
            $regOptions['auth_method'] = 'password';
        }
    }
    // No name?!  How can you register with no name?
    if (empty($regOptions['username'])) {
        $reg_errors[] = array('lang', 'need_username');
    }
    // Spaces and other odd characters are evil...
    $regOptions['username'] = preg_replace('~[\\t\\n\\r\\x0B\\0' . ($context['server']['complex_preg_chars'] ? '\\x{A0}' : " ") . ']+~u', ' ', $regOptions['username']);
    // Don't use too long a name.
    if (commonAPI::strlen($regOptions['username']) > 25) {
        $reg_errors[] = array('lang', 'error_long_name');
    }
    // Only these characters are permitted.
    if (preg_match('~[<>&"\'=\\\\]~', preg_replace('~&#(?:\\d{1,7}|x[0-9a-fA-F]{1,6});~', '', $regOptions['username'])) != 0 || $regOptions['username'] == '_' || $regOptions['username'] == '|' || strpos($regOptions['username'], '[code') !== false || strpos($regOptions['username'], '[/code') !== false) {
        $reg_errors[] = array('lang', 'error_invalid_characters_username');
    }
    if (commonAPI::strtolower($regOptions['username']) === commonAPI::strtolower($txt['guest_title'])) {
        $reg_errors[] = array('lang', 'username_reserved', 'general', array($txt['guest_title']));
    }
    // !!! Separate the sprintf?
    if (empty($regOptions['email']) || preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', $regOptions['email']) === 0 || strlen($regOptions['email']) > 255) {
        $reg_errors[] = array('done', sprintf($txt['valid_email_needed'], commonAPI::htmlspecialchars($regOptions['username'])));
    }
    if (!empty($regOptions['check_reserved_name']) && isReservedName($regOptions['username'], 0, false)) {
        if ($regOptions['password'] == 'chocolate cake') {
            $reg_errors[] = array('done', 'Sorry, I don\'t take bribes... you\'ll need to come up with a different name.');
        }
        $reg_errors[] = array('done', '(' . htmlspecialchars($regOptions['username']) . ') ' . $txt['name_in_use']);
    }
    // Generate a validation code if it's supposed to be emailed.
    $validation_code = '';
    if ($regOptions['require'] == 'activation') {
        $validation_code = generateValidationCode();
    }
    // If you haven't put in a password generate one.
    if ($regOptions['interface'] == 'admin' && $regOptions['password'] == '' && $regOptions['auth_method'] == 'password') {
        mt_srand(time() + 1277);
        $regOptions['password'] = generateValidationCode();
        $regOptions['password_check'] = $regOptions['password'];
    } elseif ($regOptions['password'] != $regOptions['password_check'] && $regOptions['auth_method'] == 'password') {
        $reg_errors[] = array('lang', 'passwords_dont_match');
    }
    // That's kind of easy to guess...
    if ($regOptions['password'] == '') {
        if ($regOptions['auth_method'] == 'password') {
            $reg_errors[] = array('lang', 'no_password');
        } else {
            $regOptions['password'] = sha1(mt_rand());
        }
    }
    // Now perform hard password validation as required.
    if (!empty($regOptions['check_password_strength'])) {
        $passwordError = validatePassword($regOptions['password'], $regOptions['username'], array($regOptions['email']));
        // Password isn't legal?
        if ($passwordError != null) {
            $reg_errors[] = array('lang', 'profile_error_password_' . $passwordError);
        }
    }
    // If they are using an OpenID that hasn't been verified yet error out.
    // !!! Change this so they can register without having to attempt a login first
    if ($regOptions['auth_method'] == 'openid' && (empty($_SESSION['openid']['verified']) || $_SESSION['openid']['openid_uri'] != $regOptions['openid'])) {
        $reg_errors[] = array('lang', 'openid_not_verified');
    }
    // You may not be allowed to register this email.
    if (!empty($regOptions['check_email_ban'])) {
        isBannedEmail($regOptions['email'], 'cannot_register', $txt['ban_register_prohibited']);
    }
    // Check if the email address is in use.
    $request = smf_db_query('
		SELECT id_member
		FROM {db_prefix}members
		WHERE email_address = {string:email_address}
			OR email_address = {string:username}
		LIMIT 1', array('email_address' => $regOptions['email'], 'username' => $regOptions['username']));
    // !!! Separate the sprintf?
    if (mysql_num_rows($request) != 0) {
        $reg_errors[] = array('lang', 'email_in_use', false, array(htmlspecialchars($regOptions['email'])));
    }
    mysql_free_result($request);
    // If we found any errors we need to do something about it right away!
    foreach ($reg_errors as $key => $error) {
        /* Note for each error:
        			0 = 'lang' if it's an index, 'done' if it's clear text.
        			1 = The text/index.
        			2 = Whether to log.
        			3 = sprintf data if necessary. */
        if ($error[0] == 'lang') {
            loadLanguage('Errors');
        }
        $message = $error[0] == 'lang' ? empty($error[3]) ? $txt[$error[1]] : vsprintf($txt[$error[1]], $error[3]) : $error[1];
        // What to do, what to do, what to do.
        if ($return_errors) {
            if (!empty($error[2])) {
                log_error($message, $error[2]);
            }
            $reg_errors[$key] = $message;
        } else {
            fatal_error($message, empty($error[2]) ? false : $error[2]);
        }
    }
    // If there's any errors left return them at once!
    if (!empty($reg_errors)) {
        return $reg_errors;
    }
    $reservedVars = array('actual_theme_url', 'actual_images_url', 'base_theme_dir', 'base_theme_url', 'default_images_url', 'default_theme_dir', 'default_theme_url', 'default_template', 'images_url', 'number_recent_posts', 'smiley_sets_default', 'theme_dir', 'theme_id', 'theme_layers', 'theme_templates', 'theme_url');
    // Can't change reserved vars.
    if (isset($regOptions['theme_vars']) && array_intersect($regOptions['theme_vars'], $reservedVars) != array()) {
        fatal_lang_error('no_theme');
    }
    // Some of these might be overwritten. (the lower ones that are in the arrays below.)
    $regOptions['register_vars'] = array('member_name' => $regOptions['username'], 'email_address' => $regOptions['email'], 'passwd' => sha1(strtolower($regOptions['username']) . $regOptions['password']), 'password_salt' => substr(md5(mt_rand()), 0, 4), 'posts' => 0, 'date_registered' => time(), 'member_ip' => $regOptions['interface'] == 'admin' ? '127.0.0.1' : $user_info['ip'], 'member_ip2' => $regOptions['interface'] == 'admin' ? '127.0.0.1' : $_SERVER['BAN_CHECK_IP'], 'validation_code' => $validation_code, 'real_name' => $regOptions['username'], 'personal_text' => $modSettings['default_personal_text'], 'pm_email_notify' => 1, 'id_theme' => 0, 'id_post_group' => 4, 'lngfile' => '', 'buddy_list' => '', 'pm_ignore_list' => '', 'message_labels' => '', 'location' => '', 'time_format' => '', 'signature' => '', 'avatar' => '', 'usertitle' => '', 'secret_question' => '', 'secret_answer' => '', 'additional_groups' => '', 'ignore_boards' => '', 'smiley_set' => '', 'openid_uri' => !empty($regOptions['openid']) ? $regOptions['openid'] : '');
    // Setup the activation status on this new account so it is correct - firstly is it an under age account?
    if ($regOptions['require'] == 'coppa') {
        $regOptions['register_vars']['is_activated'] = 5;
        // !!! This should be changed.  To what should be it be changed??
        $regOptions['register_vars']['validation_code'] = '';
    } elseif ($regOptions['require'] == 'nothing') {
        $regOptions['register_vars']['is_activated'] = 1;
    } elseif ($regOptions['require'] == 'activation') {
        $regOptions['register_vars']['is_activated'] = 0;
    } else {
        $regOptions['register_vars']['is_activated'] = 3;
    }
    if (isset($regOptions['memberGroup'])) {
        // Make sure the id_group will be valid, if this is an administator.
        $regOptions['register_vars']['id_group'] = $regOptions['memberGroup'] == 1 && !allowedTo('admin_forum') ? 0 : $regOptions['memberGroup'];
        // Check if this group is assignable.
        $unassignableGroups = array(-1, 3);
        $request = smf_db_query('
			SELECT id_group
			FROM {db_prefix}membergroups
			WHERE min_posts != {int:min_posts}' . (allowedTo('admin_forum') ? '' : '
				OR group_type = {int:is_protected}'), array('min_posts' => -1, 'is_protected' => 1));
        while ($row = mysql_fetch_assoc($request)) {
            $unassignableGroups[] = $row['id_group'];
        }
        mysql_free_result($request);
        if (in_array($regOptions['register_vars']['id_group'], $unassignableGroups)) {
            $regOptions['register_vars']['id_group'] = 0;
        }
    }
    // Integrate optional member settings to be set.
    if (!empty($regOptions['extra_register_vars'])) {
        foreach ($regOptions['extra_register_vars'] as $var => $value) {
            $regOptions['register_vars'][$var] = $value;
        }
    }
    // Integrate optional user theme options to be set.
    $theme_vars = array();
    if (!empty($regOptions['theme_vars'])) {
        foreach ($regOptions['theme_vars'] as $var => $value) {
            $theme_vars[$var] = $value;
        }
    }
    // Call an optional function to validate the users' input.
    HookAPI::callHook('integrate_register', array(&$regOptions, &$theme_vars));
    // Right, now let's prepare for insertion.
    $knownInts = array('date_registered', 'posts', 'id_group', 'last_login', 'instant_messages', 'unread_messages', 'new_pm', 'pm_prefs', 'gender', 'hide_email', 'show_online', 'pm_email_notify', 'karma_good', 'karma_bad', 'notify_announcements', 'notify_send_body', 'notify_regularity', 'notify_types', 'id_theme', 'is_activated', 'id_msg_last_visit', 'id_post_group', 'total_time_logged_in', 'warning');
    $knownFloats = array('time_offset');
    $column_names = array();
    $values = array();
    foreach ($regOptions['register_vars'] as $var => $val) {
        $type = 'string';
        if (in_array($var, $knownInts)) {
            $type = 'int';
        } elseif (in_array($var, $knownFloats)) {
            $type = 'float';
        } elseif ($var == 'birthdate') {
            $type = 'date';
        }
        $column_names[$var] = $type;
        $values[$var] = $val;
    }
    // Register them into the database.
    smf_db_insert('', '{db_prefix}members', $column_names, $values, array('id_member'));
    $memberID = smf_db_insert_id('{db_prefix}members', 'id_member');
    // Update the number of members and latest member's info - and pass the name, but remove the 's.
    if ($regOptions['register_vars']['is_activated'] == 1) {
        updateStats('member', $memberID, $regOptions['register_vars']['real_name']);
    } else {
        updateStats('member');
    }
    // Theme variables too?
    if (!empty($theme_vars)) {
        $inserts = array();
        foreach ($theme_vars as $var => $val) {
            $inserts[] = array($memberID, $var, $val);
        }
        smf_db_insert('insert', '{db_prefix}themes', array('id_member' => 'int', 'variable' => 'string-255', 'value' => 'string-65534'), $inserts, array('id_member', 'variable'));
    }
    // If it's enabled, increase the registrations for today.
    trackStats(array('registers' => '+'));
    // Administrative registrations are a bit different...
    if ($regOptions['interface'] == 'admin') {
        if ($regOptions['require'] == 'activation') {
            $email_message = 'admin_register_activate';
        } elseif (!empty($regOptions['send_welcome_email'])) {
            $email_message = 'admin_register_immediate';
        }
        if (isset($email_message)) {
            $replacements = array('REALNAME' => $regOptions['register_vars']['real_name'], 'USERNAME' => $regOptions['username'], 'PASSWORD' => $regOptions['password'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', 'ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $memberID . ';code=' . $validation_code, 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $memberID, 'ACTIVATIONCODE' => $validation_code);
            $emaildata = loadEmailTemplate($email_message, $replacements);
            sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0);
        }
        // All admins are finished here.
        return $memberID;
    }
    // Can post straight away - welcome them to your fantastic community...
    if ($regOptions['require'] == 'nothing') {
        if (!empty($regOptions['send_welcome_email'])) {
            $replacements = array('REALNAME' => $regOptions['register_vars']['real_name'], 'USERNAME' => $regOptions['username'], 'PASSWORD' => $regOptions['password'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', 'OPENID' => !empty($regOptions['openid']) ? $regOptions['openid'] : '');
            $emaildata = loadEmailTemplate('register_' . ($regOptions['auth_method'] == 'openid' ? 'openid_' : '') . 'immediate', $replacements);
            sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0);
        }
        // Send admin their notification.
        adminNotify('standard', $memberID, $regOptions['username']);
    } elseif ($regOptions['require'] == 'activation' || $regOptions['require'] == 'coppa') {
        $replacements = array('REALNAME' => $regOptions['register_vars']['real_name'], 'USERNAME' => $regOptions['username'], 'PASSWORD' => $regOptions['password'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', 'OPENID' => !empty($regOptions['openid']) ? $regOptions['openid'] : '');
        if ($regOptions['require'] == 'activation') {
            $replacements += array('ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $memberID . ';code=' . $validation_code, 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $memberID, 'ACTIVATIONCODE' => $validation_code);
        } else {
            $replacements += array('COPPALINK' => $scripturl . '?action=coppa;u=' . $memberID);
        }
        $emaildata = loadEmailTemplate('register_' . ($regOptions['auth_method'] == 'openid' ? 'openid_' : '') . ($regOptions['require'] == 'activation' ? 'activate' : 'coppa'), $replacements);
        sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0);
    } else {
        $replacements = array('REALNAME' => $regOptions['register_vars']['real_name'], 'USERNAME' => $regOptions['username'], 'PASSWORD' => $regOptions['password'], 'FORGOTPASSWORDLINK' => $scripturl . '?action=reminder', 'OPENID' => !empty($regOptions['openid']) ? $regOptions['openid'] : '');
        $emaildata = loadEmailTemplate('register_' . ($regOptions['auth_method'] == 'openid' ? 'openid_' : '') . 'pending', $replacements);
        sendmail($regOptions['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 0);
        // Admin gets informed here...
        adminNotify('approval', $memberID, $regOptions['username']);
    }
    // Okay, they're for sure registered... make sure the session is aware of this for security. (Just married :P!)
    $_SESSION['just_registered'] = 1;
    return $memberID;
}
Example #24
0
function createBoard($boardOptions)
{
    global $boards, $modSettings, $smcFunc;
    // Trigger an error if one of the required values is not set.
    if (!isset($boardOptions['board_name']) || trim($boardOptions['board_name']) == '' || !isset($boardOptions['move_to']) || !isset($boardOptions['target_category'])) {
        trigger_error('createBoard(): One or more of the required options is not set', E_USER_ERROR);
    }
    if (in_array($boardOptions['move_to'], array('child', 'before', 'after')) && !isset($boardOptions['target_board'])) {
        trigger_error('createBoard(): Target board is not set', E_USER_ERROR);
    }
    // Set every optional value to its default value.
    $boardOptions += array('posts_count' => true, 'override_theme' => false, 'board_theme' => 0, 'access_groups' => array(), 'board_description' => '', 'profile' => 1, 'moderators' => '', 'inherit_permissions' => true, 'dont_log' => true, 'allow_topics' => 1, 'automerge' => 0, 'boardicon' => '');
    // Insert a board, the settings are dealt with later.
    smf_db_insert('', '{db_prefix}boards', array('id_cat' => 'int', 'name' => 'string-255', 'description' => 'string', 'board_order' => 'int', 'member_groups' => 'string', 'redirect' => 'string'), array($boardOptions['target_category'], $boardOptions['board_name'], '', 0, '-1,0', ''), array('id_board'));
    $board_id = smf_db_insert_id('{db_prefix}boards', 'id_board');
    if (empty($board_id)) {
        return 0;
    }
    // Change the board according to the given specifications.
    modifyBoard($board_id, $boardOptions);
    // Do we want the parent permissions to be inherited?
    if ($boardOptions['inherit_permissions']) {
        getBoardTree();
        if (!empty($boards[$board_id]['parent'])) {
            $request = smf_db_query('
				SELECT id_profile
				FROM {db_prefix}boards
				WHERE id_board = {int:board_parent}
				LIMIT 1', array('board_parent' => (int) $boards[$board_id]['parent']));
            list($boardOptions['profile']) = mysql_fetch_row($request);
            mysql_free_result($request);
            smf_db_query('
				UPDATE {db_prefix}boards
				SET id_profile = {int:new_profile}
				WHERE id_board = {int:current_board}', array('new_profile' => $boardOptions['profile'], 'current_board' => $board_id));
        }
    }
    // Clean the data cache.
    clean_cache('data');
    // Created it.
    logAction('add_board', array('board' => $board_id), 'admin');
    // Here you are, a new board, ready to be spammed.
    return $board_id;
}
Example #25
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');
}
Example #26
0
function notifyMembersBoard(&$topicData)
{
    global $txt, $scripturl, $language, $user_info;
    global $modSettings, $sourcedir;
    require_once $sourcedir . '/lib/Subs-Post.php';
    // Do we have one or lots of topics?
    if (isset($topicData['body'])) {
        $topicData = array($topicData);
    }
    // Find out what boards we have... and clear out any rubbish!
    $boards = array();
    foreach ($topicData as $key => $topic) {
        if (!empty($topic['board'])) {
            $boards[$topic['board']][] = $key;
        } else {
            unset($topic[$key]);
            continue;
        }
        // Censor the subject and body...
        censorText($topicData[$key]['subject']);
        censorText($topicData[$key]['body']);
        $topicData[$key]['subject'] = un_htmlspecialchars($topicData[$key]['subject']);
        $topicData[$key]['body'] = trim(un_htmlspecialchars(strip_tags(strtr(parse_bbc($topicData[$key]['body'], false), array('<br />' => "\n", '</div>' => "\n", '</li>' => "\n", '&#91;' => '[', '&#93;' => ']')))));
    }
    // Just the board numbers.
    $board_index = array_unique(array_keys($boards));
    if (empty($board_index)) {
        return;
    }
    // Yea, we need to add this to the digest queue.
    $digest_insert = array();
    foreach ($topicData as $id => $data) {
        $digest_insert[] = array($data['topic'], $data['msg'], 'topic', $user_info['id']);
    }
    smf_db_insert('', '{db_prefix}log_digest', array('id_topic' => 'int', 'id_msg' => 'int', 'note_type' => 'string', 'exclude' => 'int'), $digest_insert, array());
    // Find the members with notification on for these boards.
    $members = smf_db_query('
		SELECT
			mem.id_member, mem.email_address, mem.notify_regularity, mem.notify_send_body, mem.lngfile,
			ln.sent, ln.id_board, mem.id_group, mem.additional_groups, b.member_groups,
			mem.id_post_group
		FROM {db_prefix}log_notify AS ln
			INNER JOIN {db_prefix}boards AS b ON (b.id_board = ln.id_board)
			INNER JOIN {db_prefix}members AS mem ON (mem.id_member = ln.id_member)
		WHERE ln.id_board IN ({array_int:board_list})
			AND mem.id_member != {int:current_member}
			AND mem.is_activated = {int:is_activated}
			AND mem.notify_types != {int:notify_types}
			AND mem.notify_regularity < {int:notify_regularity}
		ORDER BY mem.lngfile', array('current_member' => $user_info['id'], 'board_list' => $board_index, 'is_activated' => 1, 'notify_types' => 4, 'notify_regularity' => 2));
    while ($rowmember = mysql_fetch_assoc($members)) {
        if ($rowmember['id_group'] != 1) {
            $allowed = explode(',', $rowmember['member_groups']);
            $rowmember['additional_groups'] = explode(',', $rowmember['additional_groups']);
            $rowmember['additional_groups'][] = $rowmember['id_group'];
            $rowmember['additional_groups'][] = $rowmember['id_post_group'];
            if (count(array_intersect($allowed, $rowmember['additional_groups'])) == 0) {
                continue;
            }
        }
        $langloaded = loadLanguage('EmailTemplates', empty($rowmember['lngfile']) || empty($modSettings['userLanguage']) ? $language : $rowmember['lngfile'], false);
        // Now loop through all the notifications to send for this board.
        if (empty($boards[$rowmember['id_board']])) {
            continue;
        }
        $sentOnceAlready = 0;
        foreach ($boards[$rowmember['id_board']] as $key) {
            // Don't notify the guy who started the topic!
            //!!! In this case actually send them a "it's approved hooray" email
            if ($topicData[$key]['poster'] == $rowmember['id_member']) {
                continue;
            }
            // Setup the string for adding the body to the message, if a user wants it.
            $send_body = empty($modSettings['disallow_sendBody']) && !empty($rowmember['notify_send_body']);
            $replacements = array('TOPICSUBJECT' => $topicData[$key]['subject'], 'TOPICLINK' => $scripturl . '?topic=' . $topicData[$key]['topic'] . '.new#new', 'MESSAGE' => $topicData[$key]['body'], 'UNSUBSCRIBELINK' => $scripturl . '?action=notifyboard;board=' . $topicData[$key]['board'] . '.0');
            if (!$send_body) {
                unset($replacements['MESSAGE']);
            }
            // Figure out which email to send off
            $emailtype = '';
            // Send only if once is off or it's on and it hasn't been sent.
            if (!empty($rowmember['notify_regularity']) && !$sentOnceAlready && empty($rowmember['sent'])) {
                $emailtype = 'notify_boards_once';
            } elseif (empty($rowmember['notify_regularity'])) {
                $emailtype = 'notify_boards';
            }
            if (!empty($emailtype)) {
                $emailtype .= $send_body ? '_body' : '';
                $emaildata = loadEmailTemplate($emailtype, $replacements, $langloaded);
                sendmail($rowmember['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 3);
            }
            $sentOnceAlready = 1;
        }
    }
    mysql_free_result($members);
    // Sent!
    smf_db_query('
		UPDATE {db_prefix}log_notify
		SET sent = {int:is_sent}
		WHERE id_board IN ({array_int:board_list})
			AND id_member != {int:current_member}', array('current_member' => $user_info['id'], 'board_list' => $board_index, 'is_sent' => 1));
}
Example #27
0
function DeleteInstall()
{
    global $txt, $HTTP_SESSION_VARS, $incontext;
    global $current_smf_version, $sourcedir, $forum_version, $modSettings, $user_info, $db_type;
    $incontext['page_title'] = $txt['congratulations'];
    $incontext['sub_template'] = 'delete_install';
    $incontext['continue'] = 0;
    require dirname(__FILE__) . '/Settings.php';
    load_database();
    chdir(dirname(__FILE__));
    require_once $sourcedir . '/Errors.php';
    require_once $sourcedir . '/lib/Subs.php';
    require_once $sourcedir . '/CommonAPI.php';
    require_once $sourcedir . '/Load.php';
    require_once $sourcedir . '/Security.php';
    require_once $sourcedir . '/lib/Subs-Auth.php';
    // Bring a warning over.
    if (!empty($incontext['account_existed'])) {
        $incontext['warning'] = $incontext['account_existed'];
    }
    smf_db_query('
		SET NAMES utf8', array());
    // As track stats is by default enabled let's add some activity.
    smf_db_insert('ignore', '{db_prefix}log_activity', array('date' => 'date', 'topics' => 'int', 'posts' => 'int', 'registers' => 'int'), array(strftime('%Y-%m-%d', time()), 1, 1, !empty($incontext['member_id']) ? 1 : 0), array('date'));
    // Automatically log them in ;)
    if (isset($incontext['member_id']) && isset($incontext['member_salt'])) {
        setLoginCookie(3153600 * 60, $incontext['member_id'], sha1(sha1(strtolower($_POST['username']) . $_POST['password1']) . $incontext['member_salt']));
    }
    $result = smf_db_query('
		SELECT value
		FROM {db_prefix}settings
		WHERE variable = {string:db_sessions}', array('db_sessions' => 'databaseSession_enable', 'db_error_skip' => true));
    if (mysql_num_rows($result) != 0) {
        list($db_sessions) = mysql_fetch_row($result);
    }
    mysql_free_result($result);
    if (empty($db_sessions)) {
        if (@version_compare(PHP_VERSION, '4.2.0') == -1) {
            $HTTP_SESSION_VARS['php_412_bugfix'] = true;
        }
        $_SESSION['admin_time'] = time();
    } else {
        $_SERVER['HTTP_USER_AGENT'] = substr($_SERVER['HTTP_USER_AGENT'], 0, 211);
        smf_db_insert('replace', '{db_prefix}sessions', array('session_id' => 'string', 'last_update' => 'int', 'data' => 'string'), array(session_id(), time(), 'USER_AGENT|s:' . strlen($_SERVER['HTTP_USER_AGENT']) . ':"' . $_SERVER['HTTP_USER_AGENT'] . '";admin_time|i:' . time() . ';'), array('session_id'));
    }
    // We're going to want our lovely $modSettings now.
    $request = smf_db_query('
		SELECT variable, value
		FROM {db_prefix}settings', array('db_error_skip' => true));
    // Only proceed if we can load the data.
    if ($request) {
        while ($row = mysql_fetch_row($request)) {
            $modSettings[$row[0]] = $row[1];
        }
        mysql_free_result($request);
    }
    updateStats('member');
    updateStats('message');
    updateStats('topic');
    $request = smf_db_query('
		SELECT id_msg
		FROM {db_prefix}messages
		WHERE id_msg = 1
			AND modified_time = 0
		LIMIT 1', array('db_error_skip' => true));
    if (mysql_num_rows($request) > 0) {
        updateStats('subject', 1, htmlspecialchars($txt['default_topic_subject']));
    }
    mysql_free_result($request);
    // Now is the perfect time to fetch the SM files.
    require_once $sourcedir . '/ScheduledTasks.php';
    // Sanity check that they loaded earlier!
    if (isset($modSettings['recycle_board'])) {
        $forum_version = $current_smf_version;
        // The variable is usually defined in index.php so lets just use our variable to do it for us.
        scheduled_fetchSMfiles();
        // Now go get those files!
        // We've just installed!
        $user_info['ip'] = $_SERVER['REMOTE_ADDR'];
        $user_info['id'] = isset($incontext['member_id']) ? $incontext['member_id'] : 0;
        logAction('install', array('version' => $forum_version), 'admin');
    }
    // Check if we need some stupid MySQL fix.
    $server_version = smf_db_get_version();
    if ($db_type == 'mysql' && in_array(substr($server_version, 0, 6), array('5.0.50', '5.0.51'))) {
        updateSettings(array('db_mysql_group_by_fix' => '1'));
    }
    // Some final context for the template.
    $incontext['dir_still_writable'] = is_writable(dirname(__FILE__)) && substr(__FILE__, 1, 2) != ':\\';
    $incontext['probably_delete_install'] = isset($_SESSION['installer_temp_ftp']) || is_writable(dirname(__FILE__)) || is_writable(__FILE__);
    return false;
}
Example #28
0
function subscriptions($memID)
{
    global $context, $txt, $sourcedir, $modSettings, $smcFunc, $scripturl;
    // Load the paid template anyway.
    loadTemplate('ManagePaid');
    loadLanguage('ManagePaid');
    // Load all of the subscriptions.
    require_once $sourcedir . '/ManagePaid.php';
    loadSubscriptions();
    $context['member']['id'] = $memID;
    // Remove any invalid ones.
    foreach ($context['subscriptions'] as $id => $sub) {
        // Work out the costs.
        $costs = @unserialize($sub['real_cost']);
        $cost_array = array();
        if ($sub['real_length'] == 'F') {
            foreach ($costs as $duration => $cost) {
                if ($cost != 0) {
                    $cost_array[$duration] = $cost;
                }
            }
        } else {
            $cost_array['fixed'] = $costs['fixed'];
        }
        if (empty($cost_array)) {
            unset($context['subscriptions'][$id]);
        } else {
            $context['subscriptions'][$id]['member'] = 0;
            $context['subscriptions'][$id]['subscribed'] = false;
            $context['subscriptions'][$id]['costs'] = $cost_array;
        }
    }
    // Work out what gateways are enabled.
    $gateways = loadPaymentGateways();
    foreach ($gateways as $id => $gateway) {
        $gateways[$id] = new $gateway['display_class']();
        if (!$gateways[$id]->gatewayEnabled()) {
            unset($gateways[$id]);
        }
    }
    // No gateways yet?
    if (empty($gateways)) {
        fatal_error($txt['paid_admin_not_setup_gateway']);
    }
    // Get the current subscriptions.
    $request = smf_db_query('
		SELECT id_sublog, id_subscribe, start_time, end_time, status, payments_pending, pending_details
		FROM {db_prefix}log_subscribed
		WHERE id_member = {int:selected_member}', array('selected_member' => $memID));
    $context['current'] = array();
    while ($row = mysql_fetch_assoc($request)) {
        // The subscription must exist!
        if (!isset($context['subscriptions'][$row['id_subscribe']])) {
            continue;
        }
        $context['current'][$row['id_subscribe']] = array('id' => $row['id_sublog'], 'sub_id' => $row['id_subscribe'], 'hide' => $row['status'] == 0 && $row['end_time'] == 0 && $row['payments_pending'] == 0, 'name' => $context['subscriptions'][$row['id_subscribe']]['name'], 'start' => timeformat($row['start_time'], false), 'end' => $row['end_time'] == 0 ? $txt['not_applicable'] : timeformat($row['end_time'], false), 'pending_details' => $row['pending_details'], 'status' => $row['status'], 'status_text' => $row['status'] == 0 ? $row['payments_pending'] ? $txt['paid_pending'] : $txt['paid_finished'] : $txt['paid_active']);
        if ($row['status'] == 1) {
            $context['subscriptions'][$row['id_subscribe']]['subscribed'] = true;
        }
    }
    mysql_free_result($request);
    // Simple "done"?
    if (isset($_GET['done'])) {
        $_GET['sub_id'] = (int) $_GET['sub_id'];
        // Must exist but let's be sure...
        if (isset($context['current'][$_GET['sub_id']])) {
            // What are the details like?
            $current_pending = @unserialize($context['current'][$_GET['sub_id']]['pending_details']);
            if (!empty($current_pending)) {
                $current_pending = array_reverse($current_pending);
                foreach ($current_pending as $id => $sub) {
                    // Just find one and change it.
                    if ($sub[0] == $_GET['sub_id'] && $sub[3] == 'prepay') {
                        $current_pending[$id][3] = 'payback';
                        break;
                    }
                }
                // Save the details back.
                $pending_details = serialize($current_pending);
                smf_db_query('
					UPDATE {db_prefix}log_subscribed
					SET payments_pending = payments_pending + 1, pending_details = {string:pending_details}
					WHERE id_sublog = {int:current_subscription_id}
						AND id_member = {int:selected_member}', array('current_subscription_id' => $context['current'][$_GET['sub_id']]['id'], 'selected_member' => $memID, 'pending_details' => $pending_details));
            }
        }
        $context['sub_template'] = 'paid_done';
        return;
    }
    // If this is confirmation then it's simpler...
    if (isset($_GET['confirm']) && isset($_POST['sub_id']) && is_array($_POST['sub_id'])) {
        // Hopefully just one.
        foreach ($_POST['sub_id'] as $k => $v) {
            $ID_SUB = (int) $k;
        }
        if (!isset($context['subscriptions'][$ID_SUB]) || $context['subscriptions'][$ID_SUB]['active'] == 0) {
            fatal_lang_error('paid_sub_not_active');
        }
        // Simplify...
        $context['sub'] = $context['subscriptions'][$ID_SUB];
        $period = 'xx';
        if ($context['sub']['flexible']) {
            $period = isset($_POST['cur'][$ID_SUB]) && isset($context['sub']['costs'][$_POST['cur'][$ID_SUB]]) ? $_POST['cur'][$ID_SUB] : 'xx';
        }
        // Check we have a valid cost.
        if ($context['sub']['flexible'] && $period == 'xx') {
            fatal_lang_error('paid_sub_not_active');
        }
        // Sort out the cost/currency.
        $context['currency'] = $modSettings['paid_currency_code'];
        $context['recur'] = $context['sub']['repeatable'];
        if ($context['sub']['flexible']) {
            // Real cost...
            $context['value'] = $context['sub']['costs'][$_POST['cur'][$ID_SUB]];
            $context['cost'] = sprintf($modSettings['paid_currency_symbol'], $context['value']) . '/' . $txt[$_POST['cur'][$ID_SUB]];
            // The period value for paypal.
            $context['paypal_period'] = strtoupper(substr($_POST['cur'][$ID_SUB], 0, 1));
        } else {
            // Real cost...
            $context['value'] = $context['sub']['costs']['fixed'];
            $context['cost'] = sprintf($modSettings['paid_currency_symbol'], $context['value']);
            // Recur?
            preg_match('~(\\d*)(\\w)~', $context['sub']['real_length'], $match);
            $context['paypal_unit'] = $match[1];
            $context['paypal_period'] = $match[2];
        }
        // Setup the gateway context.
        $context['gateways'] = array();
        foreach ($gateways as $id => $gateway) {
            $fields = $gateways[$id]->fetchGatewayFields($context['sub']['id'] . '+' . $memID, $context['sub'], $context['value'], $period, $scripturl . '?action=profile;u=' . $memID . ';area=subscriptions;sub_id=' . $context['sub']['id'] . ';done');
            if (!empty($fields['form'])) {
                $context['gateways'][] = $fields;
            }
        }
        // Bugger?!
        if (empty($context['gateways'])) {
            fatal_error($txt['paid_admin_not_setup_gateway']);
        }
        // Now we are going to assume they want to take this out ;)
        $new_data = array($context['sub']['id'], $context['value'], $period, 'prepay');
        if (isset($context['current'][$context['sub']['id']])) {
            // What are the details like?
            $current_pending = array();
            if ($context['current'][$context['sub']['id']]['pending_details'] != '') {
                $current_pending = @unserialize($context['current'][$context['sub']['id']]['pending_details']);
            }
            // Don't get silly.
            if (count($current_pending) > 9) {
                $current_pending = array();
            }
            $pending_count = 0;
            // Only record real pending payments as will otherwise confuse the admin!
            foreach ($current_pending as $pending) {
                if ($pending[3] == 'payback') {
                    $pending_count++;
                }
            }
            if (!in_array($new_data, $current_pending)) {
                $current_pending[] = $new_data;
                $pending_details = serialize($current_pending);
                smf_db_query('
					UPDATE {db_prefix}log_subscribed
					SET payments_pending = {int:pending_count}, pending_details = {string:pending_details}
					WHERE id_sublog = {int:current_subscription_item}
						AND id_member = {int:selected_member}', array('pending_count' => $pending_count, 'current_subscription_item' => $context['current'][$context['sub']['id']]['id'], 'selected_member' => $memID, 'pending_details' => $pending_details));
            }
        } else {
            $pending_details = serialize(array($new_data));
            smf_db_insert('', '{db_prefix}log_subscribed', array('id_subscribe' => 'int', 'id_member' => 'int', 'status' => 'int', 'payments_pending' => 'int', 'pending_details' => 'string-65534', 'start_time' => 'int', 'vendor_ref' => 'string-255'), array($context['sub']['id'], $memID, 0, 0, $pending_details, time(), ''), array('id_sublog'));
        }
        // Change the template.
        $context['sub_template'] = 'choose_payment';
        // Quit.
        return;
    } else {
        $context['sub_template'] = 'user_subscription';
    }
}
Example #29
0
function logSpider()
{
    global $modSettings, $context;
    if (empty($modSettings['spider_mode']) || empty($_SESSION['id_robot'])) {
        return;
    }
    // Attempt to update today's entry.
    if ($modSettings['spider_mode'] == 1) {
        $date = strftime('%Y-%m-%d', forum_time(false));
        smf_db_query('
			UPDATE {db_prefix}log_spider_stats
			SET last_seen = {int:current_time}, page_hits = page_hits + 1
			WHERE id_spider = {int:current_spider}
				AND stat_date = {date:current_date}', array('current_date' => $date, 'current_time' => time(), 'current_spider' => $_SESSION['id_robot']));
        // Nothing updated?
        if (smf_db_affected_rows() == 0) {
            smf_db_insert('ignore', '{db_prefix}log_spider_stats', array('id_spider' => 'int', 'last_seen' => 'int', 'stat_date' => 'date', 'page_hits' => 'int'), array($_SESSION['id_robot'], time(), $date, 1), array('id_spider', 'stat_date'));
        }
    } else {
        if ($modSettings['spider_mode'] > 2) {
            $url = $_GET + array('USER_AGENT' => $_SERVER['HTTP_USER_AGENT']);
            unset($url['sesc'], $url[$context['session_var']]);
            $url = serialize($url);
        } else {
            $url = '';
        }
        smf_db_insert('insert', '{db_prefix}log_spider_hits', array('id_spider' => 'int', 'log_time' => 'int', 'url' => 'string'), array($_SESSION['id_robot'], time(), $url), array());
    }
}
Example #30
0
function PlushSearch2()
{
    global $scripturl, $modSettings, $sourcedir, $txt;
    global $user_info, $context, $options, $messages_request, $boards_can;
    global $excludedWords, $participants, $search_versions, $searchAPI;
    if (!empty($context['load_average']) && !empty($modSettings['loadavg_search']) && $context['load_average'] >= $modSettings['loadavg_search']) {
        fatal_lang_error('loadavg_search_disabled', false);
    }
    $_ctx = new SearchContext();
    // No, no, no... this is a bit hard on the server, so don't you go prefetching it!
    if (isset($_SERVER['HTTP_X_MOZ']) && $_SERVER['HTTP_X_MOZ'] == 'prefetch') {
        ob_end_clean();
        header('HTTP/1.1 403 Forbidden');
        die;
    }
    $weight_factors = array('frequency', 'age', 'length', 'subject', 'first_message', 'sticky');
    $weight = array();
    $weight_total = 0;
    foreach ($weight_factors as $weight_factor) {
        $weight[$weight_factor] = empty($modSettings['search_weight_' . $weight_factor]) ? 0 : (int) $modSettings['search_weight_' . $weight_factor];
        $weight_total += $weight[$weight_factor];
    }
    // Zero weight.  Weightless :P.
    if (empty($weight_total)) {
        fatal_lang_error('search_invalid_weights');
    }
    // These vars don't require an interface, they're just here for tweaking.
    $recentPercentage = 0.3;
    $humungousTopicPosts = 200;
    $maxMembersToSearch = 500;
    $maxMessageResults = empty($modSettings['search_max_results']) ? 0 : $modSettings['search_max_results'] * 5;
    // Start with no errors.
    $context['search_errors'] = array();
    // Number of pages hard maximum - normally not set at all.
    $modSettings['search_max_results'] = empty($modSettings['search_max_results']) ? 200 * $modSettings['search_results_per_page'] : (int) $modSettings['search_max_results'];
    // Maximum length of the string.
    $context['search_string_limit'] = 100;
    loadLanguage('Search');
    // Are you allowed?
    isAllowedTo('search_posts');
    require_once $sourcedir . '/Display.php';
    require_once $sourcedir . '/lib/Subs-Package.php';
    // Search has a special database set.
    db_extend('search');
    // Load up the search API we are going to use.
    $modSettings['search_index'] = empty($modSettings['search_index']) ? 'standard' : $modSettings['search_index'];
    if (!file_exists($sourcedir . '/SearchAPI-' . ucwords($modSettings['search_index']) . '.php')) {
        fatal_lang_error('search_api_missing');
    }
    loadClassFile('SearchAPI-' . ucwords($modSettings['search_index']) . '.php');
    // Create an instance of the search API and check it is valid for this version of SMF.
    $search_class_name = $modSettings['search_index'] . '_search';
    $searchAPI = new $search_class_name();
    if (!$searchAPI || $searchAPI->supportsMethod('isValid') && !$searchAPI->isValid() || !matchPackageVersion($search_versions['forum_version'], $searchAPI->min_smf_version . '-' . $searchAPI->version_compatible)) {
        // Log the error.
        loadLanguage('Errors');
        log_error(sprintf($txt['search_api_not_compatible'], 'SearchAPI-' . ucwords($modSettings['search_index']) . '.php'), 'critical');
        loadClassFile('SearchAPI-Standard.php');
        $searchAPI = new standard_search();
    }
    // $search_params will carry all settings that differ from the default search parameters.
    // That way, the URLs involved in a search page will be kept as short as possible.
    $search_params = array();
    if (isset($_REQUEST['params'])) {
        // Due to IE's 2083 character limit, we have to compress long search strings
        $temp_params = base64_decode(str_replace(array('-', '_', '.'), array('+', '/', '='), $_REQUEST['params']));
        // Test for gzuncompress failing
        $temp_params2 = @gzuncompress($temp_params);
        $temp_params = explode('|"|', !empty($temp_params2) ? $temp_params2 : $temp_params);
        foreach ($temp_params as $i => $data) {
            @(list($k, $v) = explode('|\'|', $data));
            $search_params[$k] = $v;
        }
        if (isset($search_params['brd'])) {
            $search_params['brd'] = empty($search_params['brd']) ? array() : explode(',', $search_params['brd']);
        }
    }
    // Store whether simple search was used (needed if the user wants to do another query).
    if (!isset($search_params['advanced'])) {
        $search_params['advanced'] = empty($_REQUEST['advanced']) ? 0 : 1;
    }
    // 1 => 'allwords' (default, don't set as param) / 2 => 'anywords'.
    if (!empty($search_params['searchtype']) || !empty($_REQUEST['searchtype']) && $_REQUEST['searchtype'] == 2) {
        $search_params['searchtype'] = 2;
    }
    // Minimum age of messages. Default to zero (don't set param in that case).
    if (!empty($search_params['minage']) || !empty($_REQUEST['minage']) && $_REQUEST['minage'] > 0) {
        $search_params['minage'] = !empty($search_params['minage']) ? (int) $search_params['minage'] : (int) $_REQUEST['minage'];
    }
    // Maximum age of messages. Default to infinite (9999 days: param not set).
    if (!empty($search_params['maxage']) || !empty($_REQUEST['maxage']) && $_REQUEST['maxage'] < 9999) {
        $search_params['maxage'] = !empty($search_params['maxage']) ? (int) $search_params['maxage'] : (int) $_REQUEST['maxage'];
    }
    // Searching a specific topic?
    if (!empty($_REQUEST['topic'])) {
        $search_params['topic'] = (int) $_REQUEST['topic'];
        $search_params['show_complete'] = true;
    } elseif (!empty($search_params['topic'])) {
        $search_params['topic'] = (int) $search_params['topic'];
    }
    if (!empty($search_params['minage']) || !empty($search_params['maxage'])) {
        $request = smf_db_query('
			SELECT ' . (empty($search_params['maxage']) ? '0, ' : 'IFNULL(MIN(id_msg), -1), ') . (empty($search_params['minage']) ? '0' : 'IFNULL(MAX(id_msg), -1)') . '
			FROM {db_prefix}messages
			WHERE 1=1' . ($modSettings['postmod_active'] ? '
				AND approved = {int:is_approved_true}' : '') . (empty($search_params['minage']) ? '' : '
				AND poster_time <= {int:timestamp_minimum_age}') . (empty($search_params['maxage']) ? '' : '
				AND poster_time >= {int:timestamp_maximum_age}'), array('timestamp_minimum_age' => empty($search_params['minage']) ? 0 : time() - 86400 * $search_params['minage'], 'timestamp_maximum_age' => empty($search_params['maxage']) ? 0 : time() - 86400 * $search_params['maxage'], 'is_approved_true' => 1));
        list($minMsgID, $maxMsgID) = mysql_fetch_row($request);
        if ($minMsgID < 0 || $maxMsgID < 0) {
            $context['search_errors']['no_messages_in_time_frame'] = true;
        }
        mysql_free_result($request);
    }
    // Default the user name to a wildcard matching every user (*).
    if (!empty($search_params['userspec']) || !empty($_REQUEST['userspec']) && $_REQUEST['userspec'] != '*') {
        $search_params['userspec'] = isset($search_params['userspec']) ? $search_params['userspec'] : $_REQUEST['userspec'];
    }
    // If there's no specific user, then don't mention it in the main query.
    if (empty($search_params['userspec'])) {
        $userQuery = '';
    } else {
        $userString = strtr(commonAPI::htmlspecialchars($search_params['userspec'], ENT_QUOTES), array('&quot;' => '"'));
        $userString = strtr($userString, array('%' => '\\%', '_' => '\\_', '*' => '%', '?' => '_'));
        preg_match_all('~"([^"]+)"~', $userString, $matches);
        $possible_users = array_merge($matches[1], explode(',', preg_replace('~"[^"]+"~', '', $userString)));
        for ($k = 0, $n = count($possible_users); $k < $n; $k++) {
            $possible_users[$k] = trim($possible_users[$k]);
            if (strlen($possible_users[$k]) == 0) {
                unset($possible_users[$k]);
            }
        }
        // Create a list of database-escaped search names.
        $realNameMatches = array();
        foreach ($possible_users as $possible_user) {
            $realNameMatches[] = smf_db_quote('{string:possible_user}', array('possible_user' => $possible_user));
        }
        // Retrieve a list of possible members.
        $request = smf_db_query('
			SELECT id_member
			FROM {db_prefix}members
			WHERE {raw:match_possible_users}', array('match_possible_users' => 'real_name LIKE ' . implode(' OR real_name LIKE ', $realNameMatches)));
        // Simply do nothing if there're too many members matching the criteria.
        if (mysql_num_rows($request) > $maxMembersToSearch) {
            $userQuery = '';
        } elseif (mysql_num_rows($request) == 0) {
            $userQuery = smf_db_quote('m.id_member = {int:id_member_guest} AND ({raw:match_possible_guest_names})', array('id_member_guest' => 0, 'match_possible_guest_names' => 'm.poster_name LIKE ' . implode(' OR m.poster_name LIKE ', $realNameMatches)));
        } else {
            $memberlist = array();
            while ($row = mysql_fetch_assoc($request)) {
                $memberlist[] = $row['id_member'];
            }
            $userQuery = smf_db_quote('(m.id_member IN ({array_int:matched_members}) OR (m.id_member = {int:id_member_guest} AND ({raw:match_possible_guest_names})))', array('matched_members' => $memberlist, 'id_member_guest' => 0, 'match_possible_guest_names' => 'm.poster_name LIKE ' . implode(' OR m.poster_name LIKE ', $realNameMatches)));
        }
        mysql_free_result($request);
    }
    // If the boards were passed by URL (params=), temporarily put them back in $_REQUEST.
    if (!empty($search_params['brd']) && is_array($search_params['brd'])) {
        $_REQUEST['brd'] = $search_params['brd'];
    }
    // Ensure that brd is an array.
    if (!empty($_REQUEST['brd']) && !is_array($_REQUEST['brd'])) {
        $_REQUEST['brd'] = strpos($_REQUEST['brd'], ',') !== false ? explode(',', $_REQUEST['brd']) : array($_REQUEST['brd']);
    }
    // Make sure all boards are integers.
    if (!empty($_REQUEST['brd'])) {
        foreach ($_REQUEST['brd'] as $id => $brd) {
            $_REQUEST['brd'][$id] = (int) $brd;
        }
    }
    // Special case for boards: searching just one topic?
    if (!empty($search_params['topic'])) {
        $request = smf_db_query('
			SELECT b.id_board
			FROM {db_prefix}topics AS t
				INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board)
			WHERE t.id_topic = {int:search_topic_id}
				AND {query_see_board}' . ($modSettings['postmod_active'] ? '
				AND t.approved = {int:is_approved_true}' : '') . '
			LIMIT 1', array('search_topic_id' => $search_params['topic'], 'is_approved_true' => 1));
        if (mysql_num_rows($request) == 0) {
            fatal_lang_error('topic_gone', false);
        }
        $search_params['brd'] = array();
        list($search_params['brd'][0]) = mysql_fetch_row($request);
        mysql_free_result($request);
    } elseif ($user_info['is_admin'] && (!empty($search_params['advanced']) || !empty($_REQUEST['brd']))) {
        $search_params['brd'] = empty($_REQUEST['brd']) ? array() : $_REQUEST['brd'];
    } else {
        $see_board = empty($search_params['advanced']) ? 'query_wanna_see_board' : 'query_see_board';
        $request = smf_db_query('
			SELECT b.id_board
			FROM {db_prefix}boards AS b
			WHERE {raw:boards_allowed_to_see}
				AND redirect = {string:empty_string}' . (empty($_REQUEST['brd']) ? !empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? '
				AND b.id_board != {int:recycle_board_id}' : '' : '
				AND b.id_board IN ({array_int:selected_search_boards})'), array('boards_allowed_to_see' => $user_info[$see_board], 'empty_string' => '', 'selected_search_boards' => empty($_REQUEST['brd']) ? array() : $_REQUEST['brd'], 'recycle_board_id' => $modSettings['recycle_board']));
        $search_params['brd'] = array();
        while ($row = mysql_fetch_assoc($request)) {
            $search_params['brd'][] = $row['id_board'];
        }
        mysql_free_result($request);
        // This error should pro'bly only happen for hackers.
        if (empty($search_params['brd'])) {
            $context['search_errors']['no_boards_selected'] = true;
        }
    }
    if (count($search_params['brd']) != 0) {
        foreach ($search_params['brd'] as $k => $v) {
            $search_params['brd'][$k] = (int) $v;
        }
        // If we've selected all boards, this parameter can be left empty.
        $request = smf_db_query('
			SELECT COUNT(*)
			FROM {db_prefix}boards
			WHERE redirect = {string:empty_string}', array('empty_string' => ''));
        list($num_boards) = mysql_fetch_row($request);
        mysql_free_result($request);
        if (count($search_params['brd']) == $num_boards) {
            $boardQuery = '';
        } elseif (count($search_params['brd']) == $num_boards - 1 && !empty($modSettings['recycle_board']) && !in_array($modSettings['recycle_board'], $search_params['brd'])) {
            $boardQuery = '!= ' . $modSettings['recycle_board'];
        } else {
            $boardQuery = 'IN (' . implode(', ', $search_params['brd']) . ')';
        }
    } else {
        $boardQuery = '';
    }
    $search_params['show_complete'] = !empty($search_params['show_complete']) || !empty($_REQUEST['show_complete']);
    $search_params['subject_only'] = !empty($search_params['subject_only']) || !empty($_REQUEST['subject_only']);
    $context['compact'] = !$search_params['show_complete'];
    EoS_Smarty::loadTemplate('search/base');
    if (!isset($_REQUEST['xml'])) {
        EoS_Smarty::getConfigInstance()->registerHookTemplate('search_content_area', $context['compact'] ? 'search/results_compact' : 'search/results_as_messages');
    } else {
        EoS_Smarty::getConfigInstance()->registerHookTemplate('search_content_area', 'search/results_xml');
    }
    // Get the sorting parameters right. Default to sort by relevance descending.
    $sort_columns = array('relevance', 'num_replies', 'id_msg');
    if (empty($search_params['sort']) && !empty($_REQUEST['sort'])) {
        list($search_params['sort'], $search_params['sort_dir']) = array_pad(explode('|', $_REQUEST['sort']), 2, '');
    }
    $search_params['sort'] = !empty($search_params['sort']) && in_array($search_params['sort'], $sort_columns) ? $search_params['sort'] : 'relevance';
    if (!empty($search_params['topic']) && $search_params['sort'] === 'num_replies') {
        $search_params['sort'] = 'id_msg';
    }
    // Sorting direction: descending unless stated otherwise.
    $search_params['sort_dir'] = !empty($search_params['sort_dir']) && $search_params['sort_dir'] == 'asc' ? 'asc' : 'desc';
    // Determine some values needed to calculate the relevance.
    $minMsg = (int) ((1 - $recentPercentage) * $modSettings['maxMsgID']);
    $recentMsg = $modSettings['maxMsgID'] - $minMsg;
    // *** Parse the search query
    // Unfortunately, searching for words like this is going to be slow, so we're blacklisting them.
    // !!! Setting to add more here?
    // !!! Maybe only blacklist if they are the only word, or "any" is used?
    $blacklisted_words = array('img', 'url', 'quote', 'www', 'http', 'the', 'is', 'it', 'are', 'if');
    // What are we searching for?
    if (empty($search_params['search'])) {
        if (isset($_GET['search'])) {
            $search_params['search'] = un_htmlspecialchars($_GET['search']);
        } elseif (isset($_POST['search'])) {
            $search_params['search'] = $_POST['search'];
        } else {
            $search_params['search'] = '';
        }
    }
    // Nothing??
    if (!isset($search_params['search']) || $search_params['search'] == '') {
        $context['search_errors']['invalid_search_string'] = true;
    } elseif (commonAPI::strlen($search_params['search']) > $context['search_string_limit']) {
        $context['search_errors']['string_too_long'] = true;
        $txt['error_string_too_long'] = sprintf($txt['error_string_too_long'], $context['search_string_limit']);
    }
    // Change non-word characters into spaces.
    $stripped_query = preg_replace('~(?:[\\x0B\\0' . ($context['server']['complex_preg_chars'] ? '\\x{A0}' : " ") . '\\t\\r\\s\\n(){}\\[\\]<>!@$%^*.,:+=`\\~\\?/\\\\]+|&(?:amp|lt|gt|quot);)+~u', ' ', $search_params['search']);
    // Make the query lower case. It's gonna be case insensitive anyway.
    $stripped_query = un_htmlspecialchars(commonAPI::strtolower($stripped_query));
    // This (hidden) setting will do fulltext searching in the most basic way.
    if (!empty($modSettings['search_simple_fulltext'])) {
        $stripped_query = strtr($stripped_query, array('"' => ''));
    }
    $no_regexp = preg_match('~&#(?:\\d{1,7}|x[0-9a-fA-F]{1,6});~', $stripped_query) === 1;
    // Extract phrase parts first (e.g. some words "this is a phrase" some more words.)
    preg_match_all('/(?:^|\\s)([-]?)"([^"]+)"(?:$|\\s)/', $stripped_query, $matches, PREG_PATTERN_ORDER);
    $phraseArray = $matches[2];
    // Remove the phrase parts and extract the words.
    $wordArray = explode(' ', preg_replace('~(?:^|\\s)(?:[-]?)"(?:[^"]+)"(?:$|\\s)~u', ' ', $search_params['search']));
    // A minus sign in front of a word excludes the word.... so...
    $excludedWords = array();
    $excludedIndexWords = array();
    $excludedSubjectWords = array();
    $excludedPhrases = array();
    // .. first, we check for things like -"some words", but not "-some words".
    foreach ($matches[1] as $index => $word) {
        if ($word === '-') {
            if (($word = trim($phraseArray[$index], '-_\' ')) !== '' && !in_array($word, $blacklisted_words)) {
                $excludedWords[] = $word;
            }
            unset($phraseArray[$index]);
        }
    }
    // Now we look for -test, etc.... normaller.
    foreach ($wordArray as $index => $word) {
        if (strpos(trim($word), '-') === 0) {
            if (($word = trim($word, '-_\' ')) !== '' && !in_array($word, $blacklisted_words)) {
                $excludedWords[] = $word;
            }
            unset($wordArray[$index]);
        }
    }
    // The remaining words and phrases are all included.
    $searchArray = array_merge($phraseArray, $wordArray);
    // Trim everything and make sure there are no words that are the same.
    foreach ($searchArray as $index => $value) {
        // Skip anything practically empty.
        if (($searchArray[$index] = trim($value, '-_\' ')) === '') {
            unset($searchArray[$index]);
        } elseif (in_array($searchArray[$index], $blacklisted_words)) {
            $foundBlackListedWords = true;
            unset($searchArray[$index]);
        } elseif (commonAPI::strlen($value) < 2) {
            $context['search_errors']['search_string_small_words'] = true;
            unset($searchArray[$index]);
        } else {
            $searchArray[$index] = $searchArray[$index];
        }
    }
    $searchArray = array_slice(array_unique($searchArray), 0, 10);
    // Create an array of replacements for highlighting.
    $context['mark'] = array();
    foreach ($searchArray as $word) {
        $context['mark'][$word] = '<strong class="highlight">' . $word . '</strong>';
    }
    // Initialize two arrays storing the words that have to be searched for.
    $orParts = array();
    $searchWords = array();
    // Make sure at least one word is being searched for.
    if (empty($searchArray)) {
        $context['search_errors']['invalid_search_string' . (!empty($foundBlackListedWords) ? '_blacklist' : '')] = true;
    } elseif (empty($search_params['searchtype'])) {
        $orParts[0] = $searchArray;
    } else {
        foreach ($searchArray as $index => $value) {
            $orParts[$index] = array($value);
        }
    }
    // Don't allow duplicate error messages if one string is too short.
    if (isset($context['search_errors']['search_string_small_words'], $context['search_errors']['invalid_search_string'])) {
        unset($context['search_errors']['invalid_search_string']);
    }
    // Make sure the excluded words are in all or-branches.
    foreach ($orParts as $orIndex => $andParts) {
        foreach ($excludedWords as $word) {
            $orParts[$orIndex][] = $word;
        }
    }
    // Determine the or-branches and the fulltext search words.
    foreach ($orParts as $orIndex => $andParts) {
        $searchWords[$orIndex] = array('indexed_words' => array(), 'words' => array(), 'subject_words' => array(), 'all_words' => array());
        // Sort the indexed words (large words -> small words -> excluded words).
        if ($searchAPI->supportsMethod('searchSort')) {
            usort($orParts[$orIndex], 'searchSort');
        }
        foreach ($orParts[$orIndex] as $word) {
            $is_excluded = in_array($word, $excludedWords);
            $searchWords[$orIndex]['all_words'][] = $word;
            $subjectWords = text2words($word);
            if (!$is_excluded || count($subjectWords) === 1) {
                $searchWords[$orIndex]['subject_words'] = array_merge($searchWords[$orIndex]['subject_words'], $subjectWords);
                if ($is_excluded) {
                    $excludedSubjectWords = array_merge($excludedSubjectWords, $subjectWords);
                }
            } else {
                $excludedPhrases[] = $word;
            }
            // Have we got indexes to prepare?
            if ($searchAPI->supportsMethod('prepareIndexes')) {
                $searchAPI->prepareIndexes($word, $searchWords[$orIndex], $excludedIndexWords, $is_excluded);
            }
        }
        // Search_force_index requires all AND parts to have at least one fulltext word.
        if (!empty($modSettings['search_force_index']) && empty($searchWords[$orIndex]['indexed_words'])) {
            $context['search_errors']['query_not_specific_enough'] = true;
            break;
        } elseif ($search_params['subject_only'] && empty($searchWords[$orIndex]['subject_words']) && empty($excludedSubjectWords)) {
            $context['search_errors']['query_not_specific_enough'] = true;
            break;
        } else {
            $searchWords[$orIndex]['indexed_words'] = array_slice($searchWords[$orIndex]['indexed_words'], 0, 7);
            $searchWords[$orIndex]['subject_words'] = array_slice($searchWords[$orIndex]['subject_words'], 0, 7);
        }
    }
    // Let the user adjust the search query, should they wish?
    $context['search_params'] = $search_params;
    if (isset($context['search_params']['search'])) {
        $context['search_params']['search'] = commonAPI::htmlspecialchars($context['search_params']['search']);
    }
    if (isset($context['search_params']['userspec'])) {
        $context['search_params']['userspec'] = commonAPI::htmlspecialchars($context['search_params']['userspec']);
    }
    // Do we have captcha enabled?
    if ($user_info['is_guest'] && !empty($modSettings['search_enable_captcha']) && empty($_SESSION['ss_vv_passed']) && (empty($_SESSION['last_ss']) || $_SESSION['last_ss'] != $search_params['search'])) {
        // If we come from another search box tone down the error...
        if (!isset($_REQUEST['search_vv'])) {
            $context['search_errors']['need_verification_code'] = true;
        } else {
            require_once $sourcedir . '/lib/Subs-Editor.php';
            $verificationOptions = array('id' => 'search', 'skip_template' => true);
            $context['require_verification'] = create_control_verification($verificationOptions, true);
            if (is_array($context['require_verification'])) {
                foreach ($context['require_verification'] as $error) {
                    $context['search_errors'][$error] = true;
                }
            } else {
                $_SESSION['ss_vv_passed'] = true;
            }
        }
    }
    // *** Encode all search params
    // All search params have been checked, let's compile them to a single string... made less simple by PHP 4.3.9 and below.
    $temp_params = $search_params;
    if (isset($temp_params['brd'])) {
        $temp_params['brd'] = implode(',', $temp_params['brd']);
    }
    $context['params'] = array();
    foreach ($temp_params as $k => $v) {
        $context['params'][] = $k . '|\'|' . $v;
    }
    if (!empty($context['params'])) {
        // Due to old IE's 2083 character limit, we have to compress long search strings
        $params = @gzcompress(implode('|"|', $context['params']));
        // Gzcompress failed, use try non-gz
        if (empty($params)) {
            $params = implode('|"|', $context['params']);
        }
        // Base64 encode, then replace +/= with uri safe ones that can be reverted
        $context['params'] = str_replace(array('+', '/', '='), array('-', '_', '.'), base64_encode($params));
    }
    // ... and add the links to the link tree.
    $context['linktree'][] = array('url' => $scripturl . '?action=search;params=' . $context['params'], 'name' => $txt['search']);
    $context['linktree'][] = array('url' => $scripturl . '?action=search2;params=' . $context['params'], 'name' => $txt['search_results']);
    // *** A last error check
    // One or more search errors? Go back to the first search screen.
    if (!empty($context['search_errors'])) {
        $_REQUEST['params'] = $context['params'];
        EoS_Smarty::resetTemplates();
        return PlushSearch1();
    }
    // Spam me not, Spam-a-lot?
    if (empty($_SESSION['last_ss']) || $_SESSION['last_ss'] != $search_params['search']) {
        spamProtection('search');
    }
    // Store the last search string to allow pages of results to be browsed.
    $_SESSION['last_ss'] = $search_params['search'];
    // *** Reserve an ID for caching the search results.
    $query_params = array_merge($search_params, array('min_msg_id' => isset($minMsgID) ? (int) $minMsgID : 0, 'max_msg_id' => isset($maxMsgID) ? (int) $maxMsgID : 0, 'memberlist' => !empty($memberlist) ? $memberlist : array()));
    // Can this search rely on the API given the parameters?
    if ($searchAPI->supportsMethod('searchQuery', $query_params)) {
        $participants = array();
        $searchArray = array();
        $num_results = $searchAPI->searchQuery($query_params, $searchWords, $excludedIndexWords, $participants, $searchArray);
    } else {
        log_error('update cache');
        $update_cache = empty($_SESSION['search_cache']) || $_SESSION['search_cache']['params'] != $context['params'];
        if ($update_cache) {
            // Increase the pointer...
            $modSettings['search_pointer'] = empty($modSettings['search_pointer']) ? 0 : (int) $modSettings['search_pointer'];
            // ...and store it right off.
            updateSettings(array('search_pointer' => $modSettings['search_pointer'] >= 255 ? 0 : $modSettings['search_pointer'] + 1));
            // As long as you don't change the parameters, the cache result is yours.
            $_SESSION['search_cache'] = array('id_search' => $modSettings['search_pointer'], 'num_results' => -1, 'params' => $context['params']);
            // Clear the previous cache of the final results cache.
            smf_db_query('
				DELETE FROM {db_prefix}log_search_results
				WHERE id_search = {int:search_id}', array('search_id' => $_SESSION['search_cache']['id_search']));
            if ($search_params['subject_only']) {
                // We do this to try and avoid duplicate keys on databases not supporting INSERT IGNORE.
                $inserts = array();
                foreach ($searchWords as $orIndex => $words) {
                    $subject_query_params = array();
                    $subject_query = array('from' => '{db_prefix}topics AS t', 'inner_join' => array(), 'left_join' => array(), 'where' => array());
                    if ($modSettings['postmod_active']) {
                        $subject_query['where'][] = 't.approved = {int:is_approved}';
                    }
                    $numTables = 0;
                    $prev_join = 0;
                    $numSubjectResults = 0;
                    foreach ($words['subject_words'] as $subjectWord) {
                        $numTables++;
                        if (in_array($subjectWord, $excludedSubjectWords)) {
                            $subject_query['left_join'][] = '{db_prefix}log_search_subjects AS subj' . $numTables . ' ON (subj' . $numTables . '.word ' . (empty($modSettings['search_match_words']) ? 'LIKE {string:subject_words_' . $numTables . '_wild}' : '= {string:subject_words_' . $numTables . '}') . ' AND subj' . $numTables . '.id_topic = t.id_topic)';
                            $subject_query['where'][] = '(subj' . $numTables . '.word IS NULL)';
                        } else {
                            $subject_query['inner_join'][] = '{db_prefix}log_search_subjects AS subj' . $numTables . ' ON (subj' . $numTables . '.id_topic = ' . ($prev_join === 0 ? 't' : 'subj' . $prev_join) . '.id_topic)';
                            $subject_query['where'][] = 'subj' . $numTables . '.word ' . (empty($modSettings['search_match_words']) ? 'LIKE {string:subject_words_' . $numTables . '_wild}' : '= {string:subject_words_' . $numTables . '}');
                            $prev_join = $numTables;
                        }
                        $subject_query_params['subject_words_' . $numTables] = $subjectWord;
                        $subject_query_params['subject_words_' . $numTables . '_wild'] = '%' . $subjectWord . '%';
                    }
                    if (!empty($userQuery)) {
                        if ($subject_query['from'] != '{db_prefix}messages AS m') {
                            $subject_query['inner_join'][] = '{db_prefix}messages AS m ON (m.id_topic = t.id_topic)';
                        }
                        $subject_query['where'][] = $userQuery;
                    }
                    if (!empty($search_params['topic'])) {
                        $subject_query['where'][] = 't.id_topic = ' . $search_params['topic'];
                    }
                    if (!empty($minMsgID)) {
                        $subject_query['where'][] = 't.id_first_msg >= ' . $minMsgID;
                    }
                    if (!empty($maxMsgID)) {
                        $subject_query['where'][] = 't.id_last_msg <= ' . $maxMsgID;
                    }
                    if (!empty($boardQuery)) {
                        $subject_query['where'][] = 't.id_board ' . $boardQuery;
                    }
                    if (!empty($excludedPhrases)) {
                        if ($subject_query['from'] != '{db_prefix}messages AS m') {
                            $subject_query['inner_join'][] = '{db_prefix}messages AS m ON (m.id_msg = t.id_first_msg)';
                        }
                        $count = 0;
                        foreach ($excludedPhrases as $phrase) {
                            $subject_query['where'][] = 'm.subject NOT ' . (empty($modSettings['search_match_words']) || $no_regexp ? ' LIKE ' : ' RLIKE ') . '{string:excluded_phrases_' . $count . '}';
                            $subject_query_params['excluded_phrases_' . $count++] = empty($modSettings['search_match_words']) || $no_regexp ? '%' . strtr($phrase, array('_' => '\\_', '%' => '\\%')) . '%' : '[[:<:]]' . addcslashes(preg_replace(array('/([\\[\\]$.+*?|{}()])/'), array('[$1]'), $phrase), '\\\'') . '[[:>:]]';
                        }
                    }
                    $ignoreRequest = smf_db_query((1 ? '
						INSERT IGNORE INTO {db_prefix}log_search_results
							(id_search, id_topic, relevance, id_msg, num_matches)' : '') . '
						SELECT
							{int:id_search},
							t.id_topic,
							1000 * (
								{int:weight_frequency} / (t.num_replies + 1) +
								{int:weight_age} * CASE WHEN t.id_first_msg < {int:min_msg} THEN 0 ELSE (t.id_first_msg - {int:min_msg}) / {int:recent_message} END +
								{int:weight_length} * CASE WHEN t.num_replies < {int:huge_topic_posts} THEN t.num_replies / {int:huge_topic_posts} ELSE 1 END +
								{int:weight_subject} +
								{int:weight_sticky} * t.is_sticky
							) / {int:weight_total} AS relevance,
							' . (empty($userQuery) ? 't.id_first_msg' : 'm.id_msg') . ',
							1
						FROM ' . $subject_query['from'] . (empty($subject_query['inner_join']) ? '' : '
							INNER JOIN ' . implode('
							INNER JOIN ', $subject_query['inner_join'])) . (empty($subject_query['left_join']) ? '' : '
							LEFT JOIN ' . implode('
							LEFT JOIN ', $subject_query['left_join'])) . '
						WHERE ' . implode('
							AND ', $subject_query['where']) . (empty($modSettings['search_max_results']) ? '' : '
						LIMIT ' . ($modSettings['search_max_results'] - $numSubjectResults)), array_merge($subject_query_params, array('id_search' => $_SESSION['search_cache']['id_search'], 'weight_age' => $weight['age'], 'weight_frequency' => $weight['frequency'], 'weight_length' => $weight['length'], 'weight_sticky' => $weight['sticky'], 'weight_subject' => $weight['subject'], 'weight_total' => $weight_total, 'min_msg' => $minMsg, 'recent_message' => $recentMsg, 'huge_topic_posts' => $humungousTopicPosts, 'is_approved' => 1)));
                    $numSubjectResults += smf_db_affected_rows();
                    if (!empty($modSettings['search_max_results']) && $numSubjectResults >= $modSettings['search_max_results']) {
                        break;
                    }
                }
                // If there's data to be inserted for non-IGNORE databases do it here!
                if (!empty($inserts)) {
                    smf_db_insert('', '{db_prefix}log_search_results', array('id_search' => 'int', 'id_topic' => 'int', 'relevance' => 'int', 'id_msg' => 'int', 'num_matches' => 'int'), $inserts, array('id_search', 'id_topic'));
                }
                $_SESSION['search_cache']['num_results'] = $numSubjectResults;
            } else {
                $main_query = array('select' => array('id_search' => $_SESSION['search_cache']['id_search'], 'relevance' => '0'), 'weights' => array(), 'from' => '{db_prefix}topics AS t', 'inner_join' => array('{db_prefix}messages AS m ON (m.id_topic = t.id_topic)'), 'left_join' => array(), 'where' => array(), 'group_by' => array(), 'parameters' => array('min_msg' => $minMsg, 'recent_message' => $recentMsg, 'huge_topic_posts' => $humungousTopicPosts, 'is_approved' => 1));
                if (empty($search_params['topic']) && empty($search_params['show_complete'])) {
                    $main_query['select']['id_topic'] = 't.id_topic';
                    $main_query['select']['id_msg'] = 'MAX(m.id_msg) AS id_msg';
                    $main_query['select']['num_matches'] = 'COUNT(*) AS num_matches';
                    $main_query['weights'] = array('frequency' => 'COUNT(*) / (MAX(t.num_replies) + 1)', 'age' => 'CASE WHEN MAX(m.id_msg) < {int:min_msg} THEN 0 ELSE (MAX(m.id_msg) - {int:min_msg}) / {int:recent_message} END', 'length' => 'CASE WHEN MAX(t.num_replies) < {int:huge_topic_posts} THEN MAX(t.num_replies) / {int:huge_topic_posts} ELSE 1 END', 'subject' => '0', 'first_message' => 'CASE WHEN MIN(m.id_msg) = MAX(t.id_first_msg) THEN 1 ELSE 0 END', 'sticky' => 'MAX(t.is_sticky)');
                    $main_query['group_by'][] = 't.id_topic';
                } else {
                    // This is outrageous!
                    $main_query['select']['id_topic'] = 'm.id_msg AS id_topic';
                    $main_query['select']['id_msg'] = 'm.id_msg';
                    $main_query['select']['num_matches'] = '1 AS num_matches';
                    $main_query['weights'] = array('age' => '((m.id_msg - t.id_first_msg) / CASE WHEN t.id_last_msg = t.id_first_msg THEN 1 ELSE t.id_last_msg - t.id_first_msg END)', 'first_message' => 'CASE WHEN m.id_msg = t.id_first_msg THEN 1 ELSE 0 END');
                    if (!empty($search_params['topic'])) {
                        $main_query['where'][] = 't.id_topic = {int:topic}';
                        $main_query['parameters']['topic'] = $search_params['topic'];
                    }
                    if (!empty($search_params['show_complete'])) {
                        $main_query['group_by'][] = 'm.id_msg, t.id_first_msg, t.id_last_msg';
                    }
                }
                // *** Get the subject results.
                $numSubjectResults = 0;
                if (empty($search_params['topic'])) {
                    $inserts = array();
                    // Create a temporary table to store some preliminary results in.
                    smf_db_query('
						DROP TABLE IF EXISTS {db_prefix}tmp_log_search_topics', array('db_error_skip' => true));
                    $createTemporary = smf_db_query('
						CREATE TEMPORARY TABLE {db_prefix}tmp_log_search_topics (
							id_topic mediumint(8) unsigned NOT NULL default {string:string_zero},
							PRIMARY KEY (id_topic)
						) TYPE=HEAP', array('string_zero' => '0', 'db_error_skip' => true)) !== false;
                    // Clean up some previous cache.
                    if (!$createTemporary) {
                        smf_db_query('
							DELETE FROM {db_prefix}log_search_topics
							WHERE id_search = {int:search_id}', array('search_id' => $_SESSION['search_cache']['id_search']));
                    }
                    foreach ($searchWords as $orIndex => $words) {
                        $subject_query = array('from' => '{db_prefix}topics AS t', 'inner_join' => array(), 'left_join' => array(), 'where' => array(), 'params' => array());
                        $numTables = 0;
                        $prev_join = 0;
                        $count = 0;
                        foreach ($words['subject_words'] as $subjectWord) {
                            $numTables++;
                            if (in_array($subjectWord, $excludedSubjectWords)) {
                                if ($subject_query['from'] != '{db_prefix}messages AS m') {
                                    $subject_query['inner_join'][] = '{db_prefix}messages AS m ON (m.id_msg = t.id_first_msg)';
                                }
                                $subject_query['left_join'][] = '{db_prefix}log_search_subjects AS subj' . $numTables . ' ON (subj' . $numTables . '.word ' . (empty($modSettings['search_match_words']) ? 'LIKE {string:subject_not_' . $count . '}' : '= {string:subject_not_' . $count . '}') . ' AND subj' . $numTables . '.id_topic = t.id_topic)';
                                $subject_query['params']['subject_not_' . $count] = empty($modSettings['search_match_words']) ? '%' . $subjectWord . '%' : $subjectWord;
                                $subject_query['where'][] = '(subj' . $numTables . '.word IS NULL)';
                                $subject_query['where'][] = 'm.body NOT ' . (empty($modSettings['search_match_words']) || $no_regexp ? ' LIKE ' : ' RLIKE ') . '{string:body_not_' . $count . '}';
                                $subject_query['params']['body_not_' . $count++] = empty($modSettings['search_match_words']) || $no_regexp ? '%' . strtr($subjectWord, array('_' => '\\_', '%' => '\\%')) . '%' : '[[:<:]]' . addcslashes(preg_replace(array('/([\\[\\]$.+*?|{}()])/'), array('[$1]'), $subjectWord), '\\\'') . '[[:>:]]';
                            } else {
                                $subject_query['inner_join'][] = '{db_prefix}log_search_subjects AS subj' . $numTables . ' ON (subj' . $numTables . '.id_topic = ' . ($prev_join === 0 ? 't' : 'subj' . $prev_join) . '.id_topic)';
                                $subject_query['where'][] = 'subj' . $numTables . '.word LIKE {string:subject_like_' . $count . '}';
                                $subject_query['params']['subject_like_' . $count++] = empty($modSettings['search_match_words']) ? '%' . $subjectWord . '%' : $subjectWord;
                                $prev_join = $numTables;
                            }
                        }
                        if (!empty($userQuery)) {
                            if ($subject_query['from'] != '{db_prefix}messages AS m') {
                                $subject_query['inner_join'][] = '{db_prefix}messages AS m ON (m.id_msg = t.id_first_msg)';
                            }
                            $subject_query['where'][] = '{raw:user_query}';
                            $subject_query['params']['user_query'] = $userQuery;
                        }
                        if (!empty($search_params['topic'])) {
                            $subject_query['where'][] = 't.id_topic = {int:topic}';
                            $subject_query['params']['topic'] = $search_params['topic'];
                        }
                        if (!empty($minMsgID)) {
                            $subject_query['where'][] = 't.id_first_msg >= {int:min_msg_id}';
                            $subject_query['params']['min_msg_id'] = $minMsgID;
                        }
                        if (!empty($maxMsgID)) {
                            $subject_query['where'][] = 't.id_last_msg <= {int:max_msg_id}';
                            $subject_query['params']['max_msg_id'] = $maxMsgID;
                        }
                        if (!empty($boardQuery)) {
                            $subject_query['where'][] = 't.id_board {raw:board_query}';
                            $subject_query['params']['board_query'] = $boardQuery;
                        }
                        if (!empty($excludedPhrases)) {
                            if ($subject_query['from'] != '{db_prefix}messages AS m') {
                                $subject_query['inner_join'][] = '{db_prefix}messages AS m ON (m.id_msg = t.id_first_msg)';
                            }
                            $count = 0;
                            foreach ($excludedPhrases as $phrase) {
                                $subject_query['where'][] = 'm.subject NOT ' . (empty($modSettings['search_match_words']) || $no_regexp ? ' LIKE ' : ' RLIKE ') . '{string:exclude_phrase_' . $count . '}';
                                $subject_query['where'][] = 'm.body NOT ' . (empty($modSettings['search_match_words']) || $no_regexp ? ' LIKE ' : ' RLIKE ') . '{string:exclude_phrase_' . $count . '}';
                                $subject_query['params']['exclude_phrase_' . $count++] = empty($modSettings['search_match_words']) || $no_regexp ? '%' . strtr($phrase, array('_' => '\\_', '%' => '\\%')) . '%' : '[[:<:]]' . addcslashes(preg_replace(array('/([\\[\\]$.+*?|{}()])/'), array('[$1]'), $phrase), '\\\'') . '[[:>:]]';
                            }
                        }
                        // Nothing to search for?
                        if (empty($subject_query['where'])) {
                            continue;
                        }
                        $ignoreRequest = smf_db_query((1 ? '
							INSERT IGNORE INTO {db_prefix}' . ($createTemporary ? 'tmp_' : '') . 'log_search_topics
								(' . ($createTemporary ? '' : 'id_search, ') . 'id_topic)' : '') . '
							SELECT ' . ($createTemporary ? '' : $_SESSION['search_cache']['id_search'] . ', ') . 't.id_topic
							FROM ' . $subject_query['from'] . (empty($subject_query['inner_join']) ? '' : '
								INNER JOIN ' . implode('
								INNER JOIN ', $subject_query['inner_join'])) . (empty($subject_query['left_join']) ? '' : '
								LEFT JOIN ' . implode('
								LEFT JOIN ', $subject_query['left_join'])) . '
							WHERE ' . implode('
								AND ', $subject_query['where']) . (empty($modSettings['search_max_results']) ? '' : '
							LIMIT ' . ($modSettings['search_max_results'] - $numSubjectResults)), $subject_query['params']);
                        // Don't do INSERT IGNORE? Manually fix this up!
                        $numSubjectResults += smf_db_affected_rows();
                        if (!empty($modSettings['search_max_results']) && $numSubjectResults >= $modSettings['search_max_results']) {
                            break;
                        }
                    }
                    // Got some non-MySQL data to plonk in?
                    if (!empty($inserts)) {
                        smf_db_insert('', '{db_prefix}' . ($createTemporary ? 'tmp_' : '') . 'log_search_topics', $createTemporary ? array('id_topic' => 'int') : array('id_search' => 'int', 'id_topic' => 'int'), $inserts, $createTemporary ? array('id_topic') : array('id_search', 'id_topic'));
                    }
                    if ($numSubjectResults !== 0) {
                        $main_query['weights']['subject'] = 'CASE WHEN MAX(lst.id_topic) IS NULL THEN 0 ELSE 1 END';
                        $main_query['left_join'][] = '{db_prefix}' . ($createTemporary ? 'tmp_' : '') . 'log_search_topics AS lst ON (' . ($createTemporary ? '' : 'lst.id_search = {int:id_search} AND ') . 'lst.id_topic = t.id_topic)';
                        if (!$createTemporary) {
                            $main_query['parameters']['id_search'] = $_SESSION['search_cache']['id_search'];
                        }
                    }
                }
                $indexedResults = 0;
                // We building an index?
                if ($searchAPI->supportsMethod('indexedWordQuery', $query_params)) {
                    $inserts = array();
                    smf_db_query('
						DROP TABLE IF EXISTS {db_prefix}tmp_log_search_messages', array('db_error_skip' => true));
                    $createTemporary = smf_db_query('
						CREATE TEMPORARY TABLE {db_prefix}tmp_log_search_messages (
							id_msg int(10) unsigned NOT NULL default {string:string_zero},
							PRIMARY KEY (id_msg)
						) TYPE=HEAP', array('string_zero' => '0', 'db_error_skip' => true)) !== false;
                    // Clear, all clear!
                    if (!$createTemporary) {
                        smf_db_query('
							DELETE FROM {db_prefix}log_search_messages
							WHERE id_search = {int:id_search}', array('id_search' => $_SESSION['search_cache']['id_search']));
                    }
                    foreach ($searchWords as $orIndex => $words) {
                        // Search for this word, assuming we have some words!
                        if (!empty($words['indexed_words'])) {
                            // Variables required for the search.
                            $search_data = array('insert_into' => ($createTemporary ? 'tmp_' : '') . 'log_search_messages', 'no_regexp' => $no_regexp, 'max_results' => $maxMessageResults, 'indexed_results' => $indexedResults, 'params' => array('id_search' => !$createTemporary ? $_SESSION['search_cache']['id_search'] : 0, 'excluded_words' => $excludedWords, 'user_query' => !empty($userQuery) ? $userQuery : '', 'board_query' => !empty($boardQuery) ? $boardQuery : '', 'topic' => !empty($search_params['topic']) ? $search_params['topic'] : 0, 'min_msg_id' => !empty($minMsgID) ? $minMsgID : 0, 'max_msg_id' => !empty($maxMsgID) ? $maxMsgID : 0, 'excluded_phrases' => !empty($excludedPhrases) ? $excludedPhrases : array(), 'excluded_index_words' => !empty($excludedIndexWords) ? $excludedIndexWords : array(), 'excluded_subject_words' => !empty($excludedSubjectWords) ? $excludedSubjectWords : array()));
                            $ignoreRequest = $searchAPI->indexedWordQuery($words, $search_data);
                            $indexedResults += smf_db_affected_rows();
                            if (!empty($maxMessageResults) && $indexedResults >= $maxMessageResults) {
                                break;
                            }
                        }
                    }
                    // More non-MySQL stuff needed?
                    if (!empty($inserts)) {
                        smf_db_insert('', '{db_prefix}' . ($createTemporary ? 'tmp_' : '') . 'log_search_messages', $createTemporary ? array('id_msg' => 'int') : array('id_msg' => 'int', 'id_search' => 'int'), $inserts, $createTemporary ? array('id_msg') : array('id_msg', 'id_search'));
                    }
                    if (empty($indexedResults) && empty($numSubjectResults) && !empty($modSettings['search_force_index'])) {
                        $context['search_errors']['query_not_specific_enough'] = true;
                        $_REQUEST['params'] = $context['params'];
                        EoS_Smarty::resetTemplates();
                        return PlushSearch1();
                    } elseif (!empty($indexedResults)) {
                        $main_query['inner_join'][] = '{db_prefix}' . ($createTemporary ? 'tmp_' : '') . 'log_search_messages AS lsm ON (lsm.id_msg = m.id_msg)';
                        if (!$createTemporary) {
                            $main_query['where'][] = 'lsm.id_search = {int:id_search}';
                            $main_query['parameters']['id_search'] = $_SESSION['search_cache']['id_search'];
                        }
                    }
                } else {
                    $orWhere = array();
                    $count = 0;
                    foreach ($searchWords as $orIndex => $words) {
                        $where = array();
                        foreach ($words['all_words'] as $regularWord) {
                            $where[] = 'm.body' . (in_array($regularWord, $excludedWords) ? ' NOT' : '') . (empty($modSettings['search_match_words']) || $no_regexp ? ' LIKE ' : ' RLIKE ') . '{string:all_word_body_' . $count . '}';
                            if (in_array($regularWord, $excludedWords)) {
                                $where[] = 'm.subject NOT' . (empty($modSettings['search_match_words']) || $no_regexp ? ' LIKE ' : ' RLIKE ') . '{string:all_word_body_' . $count . '}';
                            }
                            $main_query['parameters']['all_word_body_' . $count++] = empty($modSettings['search_match_words']) || $no_regexp ? '%' . strtr($regularWord, array('_' => '\\_', '%' => '\\%')) . '%' : '[[:<:]]' . addcslashes(preg_replace(array('/([\\[\\]$.+*?|{}()])/'), array('[$1]'), $regularWord), '\\\'') . '[[:>:]]';
                        }
                        if (!empty($where)) {
                            $orWhere[] = count($where) > 1 ? '(' . implode(' AND ', $where) . ')' : $where[0];
                        }
                    }
                    if (!empty($orWhere)) {
                        $main_query['where'][] = count($orWhere) > 1 ? '(' . implode(' OR ', $orWhere) . ')' : $orWhere[0];
                    }
                    if (!empty($userQuery)) {
                        $main_query['where'][] = '{raw:user_query}';
                        $main_query['parameters']['user_query'] = $userQuery;
                    }
                    if (!empty($search_params['topic'])) {
                        $main_query['where'][] = 'm.id_topic = {int:topic}';
                        $main_query['parameters']['topic'] = $search_params['topic'];
                    }
                    if (!empty($minMsgID)) {
                        $main_query['where'][] = 'm.id_msg >= {int:min_msg_id}';
                        $main_query['parameters']['min_msg_id'] = $minMsgID;
                    }
                    if (!empty($maxMsgID)) {
                        $main_query['where'][] = 'm.id_msg <= {int:max_msg_id}';
                        $main_query['parameters']['max_msg_id'] = $maxMsgID;
                    }
                    if (!empty($boardQuery)) {
                        $main_query['where'][] = 'm.id_board {raw:board_query}';
                        $main_query['parameters']['board_query'] = $boardQuery;
                    }
                }
                // Did we either get some indexed results, or otherwise did not do an indexed query?
                if (!empty($indexedResults) || !$searchAPI->supportsMethod('indexedWordQuery', $query_params)) {
                    $relevance = '1000 * (';
                    $new_weight_total = 0;
                    foreach ($main_query['weights'] as $type => $value) {
                        $relevance .= $weight[$type] . ' * ' . $value . ' + ';
                        $new_weight_total += $weight[$type];
                    }
                    $main_query['select']['relevance'] = substr($relevance, 0, -3) . ') / ' . $new_weight_total . ' AS relevance';
                    $ignoreRequest = smf_db_query((1 ? '
						INSERT IGNORE INTO ' . '{db_prefix}log_search_results
							(' . implode(', ', array_keys($main_query['select'])) . ')' : '') . '
						SELECT
							' . implode(',
							', $main_query['select']) . '
						FROM ' . $main_query['from'] . (empty($main_query['inner_join']) ? '' : '
							INNER JOIN ' . implode('
							INNER JOIN ', $main_query['inner_join'])) . (empty($main_query['left_join']) ? '' : '
							LEFT JOIN ' . implode('
							LEFT JOIN ', $main_query['left_join'])) . (!empty($main_query['where']) ? '
						WHERE ' : '') . implode('
							AND ', $main_query['where']) . (empty($main_query['group_by']) ? '' : '
						GROUP BY ' . implode(', ', $main_query['group_by'])) . (empty($modSettings['search_max_results']) ? '' : '
						LIMIT ' . $modSettings['search_max_results']), $main_query['parameters']);
                    $_SESSION['search_cache']['num_results'] = smf_db_affected_rows();
                }
                // Insert subject-only matches.
                if ($_SESSION['search_cache']['num_results'] < $modSettings['search_max_results'] && $numSubjectResults !== 0) {
                    $usedIDs = array_flip(empty($inserts) ? array() : array_keys($inserts));
                    $ignoreRequest = smf_db_query((1 ? '
						INSERT IGNORE INTO {db_prefix}log_search_results
							(id_search, id_topic, relevance, id_msg, num_matches)' : '') . '
						SELECT
							{int:id_search},
							t.id_topic,
							1000 * (
								{int:weight_frequency} / (t.num_replies + 1) +
								{int:weight_age} * CASE WHEN t.id_first_msg < {int:min_msg} THEN 0 ELSE (t.id_first_msg - {int:min_msg}) / {int:recent_message} END +
								{int:weight_length} * CASE WHEN t.num_replies < {int:huge_topic_posts} THEN t.num_replies / {int:huge_topic_posts} ELSE 1 END +
								{int:weight_subject} +
								{int:weight_sticky} * t.is_sticky
							) / {int:weight_total} AS relevance,
							t.id_first_msg,
							1
						FROM {db_prefix}topics AS t
							INNER JOIN {db_prefix}' . ($createTemporary ? 'tmp_' : '') . 'log_search_topics AS lst ON (lst.id_topic = t.id_topic)' . ($createTemporary ? '' : 'WHERE lst.id_search = {int:id_search}') . (empty($modSettings['search_max_results']) ? '' : '
						LIMIT ' . ($modSettings['search_max_results'] - $_SESSION['search_cache']['num_results'])), array('id_search' => $_SESSION['search_cache']['id_search'], 'weight_age' => $weight['age'], 'weight_frequency' => $weight['frequency'], 'weight_length' => $weight['frequency'], 'weight_sticky' => $weight['frequency'], 'weight_subject' => $weight['frequency'], 'weight_total' => $weight_total, 'min_msg' => $minMsg, 'recent_message' => $recentMsg, 'huge_topic_posts' => $humungousTopicPosts));
                    // Once again need to do the inserts if the database don't support ignore!
                    $_SESSION['search_cache']['num_results'] += smf_db_affected_rows();
                } else {
                    $_SESSION['search_cache']['num_results'] = 0;
                }
            }
        }
        // *** Retrieve the results to be shown on the page
        $participants = array();
        $request = smf_db_query('
			SELECT ' . (empty($search_params['topic']) ? 'lsr.id_topic' : $search_params['topic'] . ' AS id_topic') . ', lsr.id_msg, lsr.relevance, lsr.num_matches
			FROM {db_prefix}log_search_results AS lsr' . ($search_params['sort'] == 'num_replies' ? '
				INNER JOIN {db_prefix}topics AS t ON (t.id_topic = lsr.id_topic)' : '') . '
			WHERE lsr.id_search = {int:id_search}
			ORDER BY ' . $search_params['sort'] . ' ' . $search_params['sort_dir'] . '
			LIMIT ' . (int) $_REQUEST['start'] . ', ' . $modSettings['search_results_per_page'], array('id_search' => $_SESSION['search_cache']['id_search']));
        while ($row = mysql_fetch_assoc($request)) {
            $context['topics'][$row['id_msg']] = array('relevance' => round($row['relevance'] / 10, 1) . '%', 'num_matches' => $row['num_matches'], 'matches' => array());
            // By default they didn't participate in the topic!
            $participants[$row['id_topic']] = false;
        }
        mysql_free_result($request);
        $num_results = $_SESSION['search_cache']['num_results'];
    }
    if (!empty($context['topics'])) {
        // Create an array for the permissions.
        $boards_can = array('post_reply_own' => boardsAllowedTo('post_reply_own'), 'post_reply_any' => boardsAllowedTo('post_reply_any'), 'mark_any_notify' => boardsAllowedTo('mark_any_notify'));
        // How's about some quick moderation?
        if (!empty($options['display_quick_mod'])) {
            $boards_can['lock_any'] = boardsAllowedTo('lock_any');
            $boards_can['lock_own'] = boardsAllowedTo('lock_own');
            $boards_can['make_sticky'] = boardsAllowedTo('make_sticky');
            $boards_can['move_any'] = boardsAllowedTo('move_any');
            $boards_can['move_own'] = boardsAllowedTo('move_own');
            $boards_can['remove_any'] = boardsAllowedTo('remove_any');
            $boards_can['remove_own'] = boardsAllowedTo('remove_own');
            $boards_can['merge_any'] = boardsAllowedTo('merge_any');
            $context['can_lock'] = in_array(0, $boards_can['lock_any']);
            $context['can_sticky'] = in_array(0, $boards_can['make_sticky']) && !empty($modSettings['enableStickyTopics']);
            $context['can_move'] = in_array(0, $boards_can['move_any']);
            $context['can_remove'] = in_array(0, $boards_can['remove_any']);
            $context['can_merge'] = in_array(0, $boards_can['merge_any']);
        }
        // What messages are we using?
        $msg_list = array_keys($context['topics']);
        // Load the posters...
        $request = smf_db_query('
			SELECT id_member
			FROM {db_prefix}messages
			WHERE id_member != {int:no_member}
				AND id_msg IN ({array_int:message_list})
			LIMIT ' . count($context['topics']), array('message_list' => $msg_list, 'no_member' => 0));
        $posters = array();
        while ($row = mysql_fetch_assoc($request)) {
            $posters[] = $row['id_member'];
        }
        mysql_free_result($request);
        if (!empty($posters)) {
            loadMemberData(array_unique($posters));
        }
        // Get the messages out for the callback - select enough that it can be made to look just like Display.
        $messages_request = smf_db_query('
			SELECT
				m.id_msg, m.subject, m.poster_name, m.poster_email, m.poster_time, m.id_member,
				m.icon, m.poster_ip, m.body, m.smileys_enabled, m.modified_time, m.modified_name,
				first_m.id_msg AS first_msg, first_m.subject AS first_subject, first_m.icon AS first_icon, first_m.poster_time AS first_poster_time,
				first_mem.id_member AS first_member_id, IFNULL(first_mem.real_name, first_m.poster_name) AS first_member_name,
				last_m.id_msg AS last_msg, last_m.poster_time AS last_poster_time, last_mem.id_member AS last_member_id,
				IFNULL(last_mem.real_name, last_m.poster_name) AS last_member_name, last_m.icon AS last_icon, last_m.subject AS last_subject,
				t.id_topic, t.is_sticky, t.locked, t.id_poll, t.num_replies, t.num_views,
				b.id_board, b.name AS board_name, c.id_cat, c.name AS cat_name
			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}categories AS c ON (c.id_cat = b.id_cat)
				INNER JOIN {db_prefix}messages AS first_m ON (first_m.id_msg = t.id_first_msg)
				INNER JOIN {db_prefix}messages AS last_m ON (last_m.id_msg = t.id_last_msg)
				LEFT JOIN {db_prefix}members AS first_mem ON (first_mem.id_member = first_m.id_member)
				LEFT JOIN {db_prefix}members AS last_mem ON (last_mem.id_member = first_m.id_member)
			WHERE m.id_msg IN ({array_int:message_list})' . ($modSettings['postmod_active'] ? '
				AND m.approved = {int:is_approved}' : '') . '
			ORDER BY FIND_IN_SET(m.id_msg, {string:message_list_in_set})
			LIMIT {int:limit}', array('message_list' => $msg_list, 'is_approved' => 1, 'message_list_in_set' => implode(',', $msg_list), 'limit' => count($context['topics'])));
        // If there are no results that means the things in the cache got deleted, so pretend we have no topics anymore.
        if (mysql_num_rows($messages_request) == 0) {
            $context['topics'] = array();
        }
        // If we want to know who participated in what then load this now.
        if (!empty($modSettings['enableParticipation']) && !$user_info['is_guest']) {
            $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($participants), array('current_member' => $user_info['id'], 'topic_list' => array_keys($participants)));
            while ($row = mysql_fetch_assoc($result)) {
                $participants[$row['id_topic']] = true;
            }
            mysql_free_result($result);
        }
    }
    // Now that we know how many results to expect we can start calculating the page numbers.
    $context['page_index'] = constructPageIndex($scripturl . '?action=search2;params=' . $context['params'], $_REQUEST['start'], $num_results, $modSettings['search_results_per_page'], false);
    // Consider the search complete!
    if (!empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 2) {
        CacheAPI::putCache('search_start:' . ($user_info['is_guest'] ? $user_info['ip'] : $user_info['id']), null, 90);
    }
    $context['key_words'] =& $searchArray;
    if (empty($context['compact'])) {
        $context['need_synhlt'] = 1;
    }
    $context['sub_template'] = 'results';
    $context['page_title'] = $txt['search_results'];
    $context['get_topics'] = 'prepareSearchContext';
    $context['can_send_pm'] = allowedTo('pm_send');
    $context['jump_to'] = array('label' => addslashes(un_htmlspecialchars($txt['jump_to'])), 'board_name' => addslashes(un_htmlspecialchars($txt['select_destination'])));
}