Ejemplo n.º 1
0
function mobi_table_exist($table_name)
{
    global $smcFunc, $db_prefix, $db_name;
    $tb_prefix = preg_replace('/`' . $db_name . '`./', '', $db_prefix);
    db_extend();
    $tables = $smcFunc['db_list_tables'](false, $tb_prefix . "tapatalk_users");
    return !empty($tables);
}
Ejemplo n.º 2
0
/**
* file_source()
*
* - initialises all the basic context required for the database cleanup.
* - passes execution onto the relevant section.
* - if the passed action is not found it shows the main page.
*
* @return
*/
function file_source()
{
    global $smcFunc, $context, $table_prefix, $version;
    // You have to be allowed to do this
    isAllowedTo('admin_forum');
    // SMF 1 or 2 ?
    if (isset($smcFunc)) {
        db_extend('packages');
        $version = 2;
        $table_prefix = '{db_prefix}';
    } else {
        db_compat();
        $version = 1;
        $table_prefix = '';
    }
    $actions = array('examine' => 'examine', 'execute' => 'execute');
    $titles = array('examine' => 'Examine Database', 'execute' => 'Execute Changes');
    // Set a default action if none or an unsupported one is given
    if (!isset($_GET['action']) || !isset($actions[$_GET['action']])) {
        $current_action = 'examine';
    } else {
        $current_action = $actions[$_GET['action']];
    }
    // Set up the template information and language
    loadtext();
    $context['sub_template'] = $current_action;
    $context['page_title'] = $titles[$current_action];
    $context['page_title_html_safe'] = $titles[$current_action];
    $context['robot_no_index'] = true;
    $context['html_headers'] .= '
	<style type="text/css">
		.normallist li
		{
			list-style: circle;
			line-height: 1.5em;
		}
		.submit_button
		{
			text-align: center;
		}
		.error
		{
			background-color: #FFECEC;
		}
		.success
		{
			color: #00CC00;
		}
		.fail
		{
			color: #EE0000;
		}
	</style>';
    $current_action();
}
Ejemplo n.º 3
0
function db_packages_init()
{
    global $reservedTables, $db_package_log, $db_prefix;
    $db_package_log = array();
    // We setup an array of SMF tables we can't do auto-remove on - in case a mod writer cocks it up!
    $reservedTables = array('admin_info_files', 'approval_queue', 'attachments', 'ban_groups', 'ban_items', 'board_permissions', 'boards', 'calendar', 'calendar_holidays', 'categories', 'collapsed_categories', 'custom_fields', 'group_moderators', 'log_actions', 'log_activity', 'log_banned', 'log_boards', 'log_digest', 'log_errors', 'log_floodcontrol', 'log_group_requests', 'log_karma', 'log_mark_read', 'log_notify', 'log_online', 'log_packages', 'log_polls', 'log_reported', 'log_reported_comments', 'log_scheduled_tasks', 'log_search_messages', 'log_search_results', 'log_search_subjects', 'log_search_topics', 'log_topics', 'mail_queue', 'membergroups', 'members', 'message_icons', 'messages', 'moderators', 'package_servers', 'permission_profiles', 'permissions', 'personal_messages', 'pm_recipients', 'poll_choices', 'polls', 'scheduled_tasks', 'sessions', 'settings', 'smileys', 'themes', 'topics');
    foreach ($reservedTables as $k => $table_name) {
        $reservedTables[$k] = strtolower($db_prefix . $table_name);
    }
    // We in turn may need the extra stuff.
    db_extend('extra');
}
Ejemplo n.º 4
0
function getServerVersions($checkFor)
{
    global $txt, $db_connection, $_PHPA, $smcFunc, $memcached, $modSettings;
    loadLanguage('Admin');
    $versions = array();
    // Is GD available?  If it is, we should show version information for it too.
    if (in_array('gd', $checkFor) && function_exists('gd_info')) {
        $temp = gd_info();
        $versions['gd'] = array('title' => $txt['support_versions_gd'], 'version' => $temp['GD Version']);
    }
    // Now lets check for the Database.
    if (in_array('db_server', $checkFor)) {
        db_extend();
        if (!isset($db_connection) || $db_connection === false) {
            trigger_error('getServerVersions(): you need to be connected to the database in order to get its server version', E_USER_NOTICE);
        } else {
            $versions['db_server'] = array('title' => sprintf($txt['support_versions_db'], $smcFunc['db_title']), 'version' => '');
            $versions['db_server']['version'] = $smcFunc['db_get_version']();
        }
    }
    // If we're using memcache we need the server info.
    if (empty($memcached) && function_exists('memcache_get') && isset($modSettings['cache_memcached']) && trim($modSettings['cache_memcached']) != '') {
        get_memcached_server();
    }
    // Check to see if we have any accelerators installed...
    if (in_array('mmcache', $checkFor) && defined('MMCACHE_VERSION')) {
        $versions['mmcache'] = array('title' => 'Turck MMCache', 'version' => MMCACHE_VERSION);
    }
    if (in_array('eaccelerator', $checkFor) && defined('EACCELERATOR_VERSION')) {
        $versions['eaccelerator'] = array('title' => 'eAccelerator', 'version' => EACCELERATOR_VERSION);
    }
    if (in_array('phpa', $checkFor) && isset($_PHPA)) {
        $versions['phpa'] = array('title' => 'ionCube PHP-Accelerator', 'version' => $_PHPA['VERSION']);
    }
    if (in_array('apc', $checkFor) && extension_loaded('apc')) {
        $versions['apc'] = array('title' => 'Alternative PHP Cache', 'version' => phpversion('apc'));
    }
    if (in_array('memcache', $checkFor) && function_exists('memcache_set')) {
        $versions['memcache'] = array('title' => 'Memcached', 'version' => empty($memcached) ? '???' : memcache_get_version($memcached));
    }
    if (in_array('xcache', $checkFor) && function_exists('xcache_set')) {
        $versions['xcache'] = array('title' => 'XCache', 'version' => XCACHE_VERSION);
    }
    if (in_array('php', $checkFor)) {
        $versions['php'] = array('title' => 'PHP', 'version' => PHP_VERSION);
    }
    if (in_array('server', $checkFor)) {
        $versions['server'] = array('title' => $txt['support_versions_server'], 'version' => $_SERVER['SERVER_SOFTWARE']);
    }
    return $versions;
}
Ejemplo n.º 5
0
function protected_alter($change, $substep, $is_test = false)
{
    global $db_prefix, $smcFunc;
    db_extend('packages');
    // Firstly, check whether the current index/column exists.
    $found = false;
    if ($change['type'] === 'column') {
        $columns = $smcFunc['db_list_columns']('{db_prefix}' . $change['table'], true);
        foreach ($columns as $column) {
            // Found it?
            if ($column['name'] === $change['name']) {
                $found |= 1;
                // Do some checks on the data if we have it set.
                if (isset($change['col_type'])) {
                    $found &= $change['col_type'] === $column['type'];
                }
                if (isset($change['null_allowed'])) {
                    $found &= $column['null'] == $change['null_allowed'];
                }
                if (isset($change['default'])) {
                    $found &= $change['default'] === $column['default'];
                }
            }
        }
    } elseif ($change['type'] === 'index') {
        $request = upgrade_query('
			SHOW INDEX
			FROM ' . $db_prefix . $change['table']);
        if ($request !== false) {
            $cur_index = array();
            while ($row = $smcFunc['db_fetch_assoc']($request)) {
                if ($row['Key_name'] === $change['name']) {
                    $cur_index[(int) $row['Seq_in_index']] = $row['Column_name'];
                }
            }
            ksort($cur_index, SORT_NUMERIC);
            $found = array_values($cur_index) === $change['target_columns'];
            $smcFunc['db_free_result']($request);
        }
    }
    // If we're trying to add and it's added, we're done.
    if ($found && in_array($change['method'], array('add', 'change'))) {
        return true;
    } elseif (!$found && in_array($change['method'], array('remove', 'change_remove'))) {
        return true;
    } elseif ($is_test) {
        return false;
    }
    // Not found it yet? Bummer! How about we see if we're currently doing it?
    $running = false;
    $found = false;
    while (1 == 1) {
        $request = upgrade_query('
			SHOW FULL PROCESSLIST');
        while ($row = $smcFunc['db_fetch_assoc']($request)) {
            if (strpos($row['Info'], 'ALTER TABLE ' . $db_prefix . $change['table']) !== false && strpos($row['Info'], $change['text']) !== false) {
                $found = true;
            }
        }
        // Can't find it? Then we need to run it fools!
        if (!$found && !$running) {
            $smcFunc['db_free_result']($request);
            $success = upgrade_query('
				ALTER TABLE ' . $db_prefix . $change['table'] . '
				' . $change['text'], true) !== false;
            if (!$success) {
                return false;
            }
            // Return
            $running = true;
        } elseif (!$found) {
            $smcFunc['db_free_result']($request);
            return true;
        }
        // Pause execution for a sec or three.
        sleep(3);
        // Can never be too well protected.
        nextSubstep($substep);
    }
    // Protect it.
    nextSubstep($substep);
}
Ejemplo n.º 6
0
/**
 * Creates a search API and returns the object.
 *
 */
function findSearchAPI()
{
    global $sourcedir, $modSettings, $search_versions, $searchAPI, $txt;
    require_once $sourcedir . '/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');
    }
    require_once $sourcedir . '/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();
    // An invalid Search API.
    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');
        require_once $sourcedir . '/SearchAPI-Standard.php';
        $searchAPI = new standard_search();
    }
    return $searchAPI;
}
Ejemplo n.º 7
0
function OptimizeTables()
{
    global $db_type, $db_name, $db_prefix, $txt, $context, $scripturl, $sourcedir, $smcFunc;
    isAllowedTo('admin_forum');
    checkSession('post');
    ignore_user_abort(true);
    db_extend();
    // Start with no tables optimized.
    $opttab = 0;
    $context['page_title'] = $txt['database_optimize'];
    $context['sub_template'] = 'optimize';
    // Only optimize the tables related to this smf install, not all the tables in the db
    $real_prefix = preg_match('~^(`?)(.+?)\\1\\.(.*?)$~', $db_prefix, $match) === 1 ? $match[3] : $db_prefix;
    // Get a list of tables, as well as how many there are.
    $temp_tables = $smcFunc['db_list_tables'](false, $real_prefix . '%');
    $tables = array();
    foreach ($temp_tables as $table) {
        $tables[] = array('table_name' => $table);
    }
    // If there aren't any tables then I believe that would mean the world has exploded...
    $context['num_tables'] = count($tables);
    if ($context['num_tables'] == 0) {
        fatal_error('You appear to be running SMF in a flat file mode... fantastic!', false);
    }
    // For each table....
    $context['optimized_tables'] = array();
    foreach ($tables as $table) {
        // Optimize the table!  We use backticks here because it might be a custom table.
        $data_freed = $smcFunc['db_optimize_table']($table['table_name']);
        // Optimizing one sqlite table optimizes them all.
        if ($db_type == 'sqlite') {
            break;
        }
        if ($data_freed > 0) {
            $context['optimized_tables'][] = array('name' => $table['table_name'], 'data_freed' => $data_freed);
        }
    }
    // Number of tables, etc....
    $txt['database_numb_tables'] = sprintf($txt['database_numb_tables'], $context['num_tables']);
    $context['num_tables_optimized'] = count($context['optimized_tables']);
    // Check that we don't auto optimise again too soon!
    require_once $sourcedir . '/ScheduledTasks.php';
    CalculateNextTrigger('auto_optimize', true);
}
Ejemplo n.º 8
0
* under the terms of the provided license as published by Lewis Media.        *
*                                                                             *
* This program is distributed in the hope that it is and will be useful,      *
* but WITHOUT ANY WARRANTIES; without even any implied warranty of            *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                        *
*                                                                             *
* See the "license.txt" file for details of the Simple Machines license.      *
* The latest version can always be found at http://www.simplemachines.org.    *
******************************************************************************/
// If SSI.php is in the same place as this file, and SMF isn't defined, this is being run standalone.
if (file_exists(dirname(__FILE__) . '/SSI.php') && !defined('SMF')) {
    require_once dirname(__FILE__) . '/SSI.php';
} elseif (!defined('SMF')) {
    die('<b>Error:</b> Cannot install - please verify you put this in the same place as SMF\'s index.php.');
}
db_extend('packages');
$smcFunc['db_add_column']('{db_prefix}polls', array('name' => 'id_topic', 'type' => 'mediumint', 'size' => 8, 'null' => false, 'default' => 0, 'auto' => false, 'unsigned' => true));
$smcFunc['db_change_column']('{db_prefix}polls', 'id_topic', array('unsigned' => true));
// Let's get all our indexes.
$indexes = $smcFunc['db_list_indexes']('{db_prefix}polls', true);
// Do we already have it?
foreach ($indexes as $index) {
    if ($index['name'] == 'id_topic') {
        // If we want to overwrite simply remove the current one then continue.
        $smcFunc['db_remove_index']('{db_prefix}polls', 'id_topic');
    }
}
$smcFunc['db_add_index']('{db_prefix}polls', array('columns' => array('id_topic')));
$request = $smcFunc['db_query']('', '
	SELECT p.id_poll
	FROM {db_prefix}polls AS p
Ejemplo n.º 9
0
function KB_ImportSMFarticle()
{
    global $smcFunc, $context, $txt, $db_prefix;
    $context['import_results'] = '';
    $context['sub_template'] = 'kbimportasmfa';
    $dbresult = $smcFunc['db_query']('', "\n\t    SELECT \n\t\t\tc.kbid, c.name\n\t\tFROM {db_prefix}kb_category AS c \n\t\tORDER BY c.name ASC");
    $context['kb_cat'] = array();
    while ($row = $smcFunc['db_fetch_assoc']($dbresult)) {
        $context['kb_cat'][] = $row;
    }
    $smcFunc['db_free_result']($dbresult);
    if (isset($_REQUEST['doimport'])) {
        checkSession();
        $cat = (int) $_REQUEST['catid'];
        db_extend();
        $articles_tables = $smcFunc['db_list_tables'](false, $db_prefix . 'articles');
        if (empty($articles_tables)) {
            fatal_lang_error('kb_importytp4', false);
        }
        if (empty($cat)) {
            fatal_lang_error('kb_importtp1');
        }
        $result = $smcFunc['db_query']('', '
		    SELECT 
			a.ID_MEMBER, a.title, p.pagetext, a.views, a.approved, a.date
		    FROM {db_prefix}articles AS a
			LEFT JOIN {db_prefix}articles_page AS p ON (a.ID_ARTICLE = p.ID_ARTICLE)', array());
        while ($row = $smcFunc['db_fetch_assoc']($result)) {
            $smcFunc['db_insert']('', '{db_prefix}kb_articles', array('id_member' => 'int', 'title' => 'string', 'content' => 'string', 'views' => 'int', 'approved' => 'int', 'date' => 'int'), array($row['ID_MEMBER'], $row['title'], $row['pagetext'], $row['views'], $row['approved'], $row['date']), array());
        }
        $smcFunc['db_free_result']($result);
        KB_cleanCache();
        $result = $smcFunc['db_query']('', '
		    SELECT 
			k.kbnid, k.title 
		    FROM {db_prefix}kb_articles AS k, {db_prefix}articles AS a
		    WHERE a.ID_MEMBER = k.id_member AND k.date = a.date AND a.title = k.title', array());
        $context['import_results'] = '<strong>' . $txt['kb_import1'] . '</strong><br />';
        while ($row = $smcFunc['db_fetch_assoc']($result)) {
            $context['import_results'] .= $row['title'] . '<br />';
            $smcFunc['db_query']('', '
				UPDATE {db_prefix}kb_articles
				SET
				id_cat = {int:cat}
				WHERE kbnid = {int:kbid}', array('kbid' => (int) $row['kbnid'], 'cat' => $cat));
        }
        $smcFunc['db_free_result']($result);
    }
}
Ejemplo n.º 10
0
function PlushSearch2()
{
    global $scripturl, $modSettings, $sourcedir, $txt, $db_connection;
    global $user_info, $context, $options, $messages_request, $boards_can;
    global $excludedWords, $participants, $smcFunc, $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);
    }
    // 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');
    if (!isset($_REQUEST['xml'])) {
        loadTemplate('Search');
    } else {
        $context['sub_template'] = 'results';
    }
    // Are you allowed?
    isAllowedTo('search_posts');
    require_once $sourcedir . '/Display.php';
    require_once $sourcedir . '/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 = $smcFunc['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) = $smcFunc['db_fetch_row']($request);
        if ($minMsgID < 0 || $maxMsgID < 0) {
            $context['search_errors']['no_messages_in_time_frame'] = true;
        }
        $smcFunc['db_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($smcFunc['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[] = $smcFunc['db_quote']('{string:possible_user}', array('possible_user' => $possible_user));
        }
        // Retrieve a list of possible members.
        $request = $smcFunc['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 ($smcFunc['db_num_rows']($request) > $maxMembersToSearch) {
            $userQuery = '';
        } elseif ($smcFunc['db_num_rows']($request) == 0) {
            $userQuery = $smcFunc['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 = $smcFunc['db_fetch_assoc']($request)) {
                $memberlist[] = $row['id_member'];
            }
            $userQuery = $smcFunc['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)));
        }
        $smcFunc['db_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 = $smcFunc['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 ($smcFunc['db_num_rows']($request) == 0) {
            fatal_lang_error('topic_gone', false);
        }
        $search_params['brd'] = array();
        list($search_params['brd'][0]) = $smcFunc['db_fetch_row']($request);
        $smcFunc['db_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 = $smcFunc['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 = $smcFunc['db_fetch_assoc']($request)) {
            $search_params['brd'][] = $row['id_board'];
        }
        $smcFunc['db_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 = $smcFunc['db_query']('', '
			SELECT COUNT(*)
			FROM {db_prefix}boards
			WHERE redirect = {string:empty_string}', array('empty_string' => ''));
        list($num_boards) = $smcFunc['db_fetch_row']($request);
        $smcFunc['db_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'];
    // 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 ($smcFunc['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['utf8'] ? $context['server']['complex_preg_chars'] ? '\\x{A0}' : " " : '\\xA0') . '\\t\\r\\s\\n(){}\\[\\]<>!@$%^*.,:+=`\\~\\?/\\\\]+|&(?:amp|lt|gt|quot);)+~' . ($context['utf8'] ? 'u' : ''), ' ', $search_params['search']);
    // Make the query lower case. It's gonna be case insensitive anyway.
    $stripped_query = un_htmlspecialchars($smcFunc['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)~' . ($context['utf8'] ? '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 ($smcFunc['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);
        }
    }
    // *** Spell checking
    $context['show_spellchecking'] = !empty($modSettings['enableSpellChecking']) && function_exists('pspell_new');
    if ($context['show_spellchecking']) {
        // Windows fix.
        ob_start();
        $old = error_reporting(0);
        pspell_new('en');
        $pspell_link = pspell_new($txt['lang_dictionary'], $txt['lang_spelling'], '', strtr($txt['lang_character_set'], array('iso-' => 'iso', 'ISO-' => 'iso')), PSPELL_FAST | PSPELL_RUN_TOGETHER);
        if (!$pspell_link) {
            $pspell_link = pspell_new('en', '', '', '', PSPELL_FAST | PSPELL_RUN_TOGETHER);
        }
        error_reporting($old);
        ob_end_clean();
        $did_you_mean = array('search' => array(), 'display' => array());
        $found_misspelling = false;
        foreach ($searchArray as $word) {
            if (empty($pspell_link)) {
                continue;
            }
            $word = $word;
            // Don't check phrases.
            if (preg_match('~^\\w+$~', $word) === 0) {
                $did_you_mean['search'][] = '"' . $word . '"';
                $did_you_mean['display'][] = '&quot;' . $smcFunc['htmlspecialchars']($word) . '&quot;';
                continue;
            } elseif (preg_match('~\\d~', $word) === 1) {
                $did_you_mean['search'][] = $word;
                $did_you_mean['display'][] = $smcFunc['htmlspecialchars']($word);
                continue;
            } elseif (pspell_check($pspell_link, $word)) {
                $did_you_mean['search'][] = $word;
                $did_you_mean['display'][] = $smcFunc['htmlspecialchars']($word);
                continue;
            }
            $suggestions = pspell_suggest($pspell_link, $word);
            foreach ($suggestions as $i => $s) {
                // Search is case insensitive.
                if ($smcFunc['strtolower']($s) == $smcFunc['strtolower']($word)) {
                    unset($suggestions[$i]);
                } elseif ($suggestions[$i] != censorText($s)) {
                    unset($suggestions[$i]);
                }
            }
            // Anything found?  If so, correct it!
            if (!empty($suggestions)) {
                $suggestions = array_values($suggestions);
                $did_you_mean['search'][] = $suggestions[0];
                $did_you_mean['display'][] = '<em><strong>' . $smcFunc['htmlspecialchars']($suggestions[0]) . '</strong></em>';
                $found_misspelling = true;
            } else {
                $did_you_mean['search'][] = $word;
                $did_you_mean['display'][] = $smcFunc['htmlspecialchars']($word);
            }
        }
        if ($found_misspelling) {
            // Don't spell check excluded words, but add them still...
            $temp_excluded = array('search' => array(), 'display' => array());
            foreach ($excludedWords as $word) {
                $word = $word;
                if (preg_match('~^\\w+$~', $word) == 0) {
                    $temp_excluded['search'][] = '-"' . $word . '"';
                    $temp_excluded['display'][] = '-&quot;' . $smcFunc['htmlspecialchars']($word) . '&quot;';
                } else {
                    $temp_excluded['search'][] = '-' . $word;
                    $temp_excluded['display'][] = '-' . $smcFunc['htmlspecialchars']($word);
                }
            }
            $did_you_mean['search'] = array_merge($did_you_mean['search'], $temp_excluded['search']);
            $did_you_mean['display'] = array_merge($did_you_mean['display'], $temp_excluded['display']);
            $temp_params = $search_params;
            $temp_params['search'] = implode(' ', $did_you_mean['search']);
            if (isset($temp_params['brd'])) {
                $temp_params['brd'] = implode(',', $temp_params['brd']);
            }
            $context['params'] = array();
            foreach ($temp_params as $k => $v) {
                $context['did_you_mean_params'][] = $k . '|\'|' . $v;
            }
            $context['did_you_mean_params'] = base64_encode(implode('|"|', $context['did_you_mean_params']));
            $context['did_you_mean'] = implode(' ', $did_you_mean['display']);
        }
    }
    // 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'] = $smcFunc['htmlspecialchars']($context['search_params']['search']);
    }
    if (isset($context['search_params']['userspec'])) {
        $context['search_params']['userspec'] = $smcFunc['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 . '/Subs-Editor.php';
            $verificationOptions = array('id' => 'search');
            $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'];
        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 {
        $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.
            $smcFunc['db_search_query']('delete_log_search_results', '
				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 = $smcFunc['db_search_query']('insert_log_search_results_subject', ($smcFunc['db_support_ignore'] ? '
						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)));
                    // If the database doesn't support IGNORE to make this fast we need to do some tracking.
                    if (!$smcFunc['db_support_ignore']) {
                        while ($row = $smcFunc['db_fetch_row']($ignoreRequest)) {
                            // No duplicates!
                            if (isset($inserts[$row[1]])) {
                                continue;
                            }
                            foreach ($row as $key => $value) {
                                $inserts[$row[1]][] = (int) $row[$key];
                            }
                        }
                        $smcFunc['db_free_result']($ignoreRequest);
                        $numSubjectResults = count($inserts);
                    } else {
                        $numSubjectResults += $smcFunc['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)) {
                    $smcFunc['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.
                    $smcFunc['db_search_query']('drop_tmp_log_search_topics', '
						DROP TABLE IF EXISTS {db_prefix}tmp_log_search_topics', array('db_error_skip' => true));
                    $createTemporary = $smcFunc['db_search_query']('create_tmp_log_search_topics', '
						CREATE TEMPORARY TABLE {db_prefix}tmp_log_search_topics (
							id_topic mediumint(8) unsigned NOT NULL default {string:string_zero},
							PRIMARY KEY (id_topic)
						) ENGINE=MEMORY', array('string_zero' => '0', 'db_error_skip' => true)) !== false;
                    // Clean up some previous cache.
                    if (!$createTemporary) {
                        $smcFunc['db_search_query']('delete_log_search_topics', '
							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 = $smcFunc['db_search_query']('insert_log_search_topics', ($smcFunc['db_support_ignore'] ? '
							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!
                        if (!$smcFunc['db_support_ignore']) {
                            while ($row = $smcFunc['db_fetch_row']($ignoreRequest)) {
                                $ind = $createTemporary ? 0 : 1;
                                // No duplicates!
                                if (isset($inserts[$row[$ind]])) {
                                    continue;
                                }
                                $inserts[$row[$ind]] = $row;
                            }
                            $smcFunc['db_free_result']($ignoreRequest);
                            $numSubjectResults = count($inserts);
                        } else {
                            $numSubjectResults += $smcFunc['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)) {
                        $smcFunc['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();
                    $smcFunc['db_search_query']('drop_tmp_log_search_messages', '
						DROP TABLE IF EXISTS {db_prefix}tmp_log_search_messages', array('db_error_skip' => true));
                    $createTemporary = $smcFunc['db_search_query']('create_tmp_log_search_messages', '
						CREATE TEMPORARY TABLE {db_prefix}tmp_log_search_messages (
							id_msg int(10) unsigned NOT NULL default {string:string_zero},
							PRIMARY KEY (id_msg)
						) ENGINE=MEMORY', array('string_zero' => '0', 'db_error_skip' => true)) !== false;
                    // Clear, all clear!
                    if (!$createTemporary) {
                        $smcFunc['db_search_query']('delete_log_search_messages', '
							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);
                            if (!$smcFunc['db_support_ignore']) {
                                while ($row = $smcFunc['db_fetch_row']($ignoreRequest)) {
                                    // No duplicates!
                                    if (isset($inserts[$row[0]])) {
                                        continue;
                                    }
                                    $inserts[$row[0]] = $row;
                                }
                                $smcFunc['db_free_result']($ignoreRequest);
                                $indexedResults = count($inserts);
                            } else {
                                $indexedResults += $smcFunc['db_affected_rows']();
                            }
                            if (!empty($maxMessageResults) && $indexedResults >= $maxMessageResults) {
                                break;
                            }
                        }
                    }
                    // More non-MySQL stuff needed?
                    if (!empty($inserts)) {
                        $smcFunc['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'];
                        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 = $smcFunc['db_search_query']('insert_log_search_results_no_index', ($smcFunc['db_support_ignore'] ? '
						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']);
                    // We love to handle non-good databases that don't support our ignore!
                    if (!$smcFunc['db_support_ignore']) {
                        $inserts = array();
                        while ($row = $smcFunc['db_fetch_row']($ignoreRequest)) {
                            // No duplicates!
                            if (isset($inserts[$row[2]])) {
                                continue;
                            }
                            foreach ($row as $key => $value) {
                                $inserts[$row[2]][] = (int) $row[$key];
                            }
                        }
                        $smcFunc['db_free_result']($ignoreRequest);
                        // Now put them in!
                        if (!empty($inserts)) {
                            $query_columns = array();
                            foreach ($main_query['select'] as $k => $v) {
                                $query_columns[$k] = 'int';
                            }
                            $smcFunc['db_insert']('', '{db_prefix}log_search_results', $query_columns, $inserts, array('id_search', 'id_topic'));
                        }
                        $_SESSION['search_cache']['num_results'] += count($inserts);
                    } else {
                        $_SESSION['search_cache']['num_results'] = $smcFunc['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 = $smcFunc['db_search_query']('insert_log_search_results_sub_only', ($smcFunc['db_support_ignore'] ? '
						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!
                    if (!$smcFunc['db_support_ignore']) {
                        $inserts = array();
                        while ($row = $smcFunc['db_fetch_row']($ignoreRequest)) {
                            // No duplicates!
                            if (isset($usedIDs[$row[1]])) {
                                continue;
                            }
                            $usedIDs[$row[1]] = true;
                            $inserts[] = $row;
                        }
                        $smcFunc['db_free_result']($ignoreRequest);
                        // Now put them in!
                        if (!empty($inserts)) {
                            $smcFunc['db_insert']('', '{db_prefix}log_search_results', array('id_search' => 'int', 'id_topic' => 'int', 'relevance' => 'float', 'id_msg' => 'int', 'num_matches' => 'int'), $inserts, array('id_search', 'id_topic'));
                        }
                        $_SESSION['search_cache']['num_results'] += count($inserts);
                    } else {
                        $_SESSION['search_cache']['num_results'] += $smcFunc['db_affected_rows']();
                    }
                } else {
                    $_SESSION['search_cache']['num_results'] = 0;
                }
            }
        }
        // *** Retrieve the results to be shown on the page
        $participants = array();
        $request = $smcFunc['db_search_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 = $smcFunc['db_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;
        }
        $smcFunc['db_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 = $smcFunc['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 = $smcFunc['db_fetch_assoc']($request)) {
            $posters[] = $row['id_member'];
        }
        $smcFunc['db_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 = $smcFunc['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 ($smcFunc['db_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 = $smcFunc['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 = $smcFunc['db_fetch_assoc']($result)) {
                $participants[$row['id_topic']] = true;
            }
            $smcFunc['db_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) {
        cache_put_data('search_start:' . ($user_info['is_guest'] ? $user_info['ip'] : $user_info['id']), null, 90);
    }
    $context['key_words'] =& $searchArray;
    // Setup the default topic icons... for checking they exist and the like!
    $stable_icons = array('xx', 'thumbup', 'thumbdown', 'exclamation', 'question', 'lamp', 'smiley', 'angry', 'cheesy', 'grin', 'sad', 'wink', 'moved', 'recycled', 'wireless', 'clip');
    $context['icon_sources'] = array();
    foreach ($stable_icons as $icon) {
        $context['icon_sources'][$icon] = 'images_url';
    }
    $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'])));
}
Ejemplo n.º 11
0
function alterTable($tableName, $knownKeys = '', $knownColumns = '', $alterColumns = '', $reverseKeys = false, $reverseColumns = false)
{
    global $smcFunc, $to_prefix;
    // Ok, you old scripts. Get off it!
    print_error('alterTable is deprecated in convert.php. Please consider using proper \\$smcFuncs.' . var_dump(function_exists('debug_backtrace') ? debug_backtrace() : 'Unable to backtrace'));
    // Shorten this up
    $to_table = $to_prefix . $tableName;
    // Get Packing!
    db_extend('packages');
    // Get the keys
    if (!empty($knownKeys)) {
        $availableKeys = array_flip($smcFunc['db_list_indexes']());
    } else {
        $knownKeys = array();
    }
    // Are we dealing with columns also?
    if (!empty($knownColumns)) {
        $availableColumns = array_flip($smcFunc['db_list_columns']("{$tableName}", true));
    } else {
        $knownColumns = array();
    }
    // Column to alter
    if (!empty($alterColumns) && is_array($alterColumns)) {
        $alterColumns = $alterColumns;
    } else {
        $alterColumns = array();
    }
    // Check indexes
    foreach ($knownKeys as $key => $value) {
        // If we are dropping keys then it should unset the known keys if it's NOT available
        if ($reverseKeys == false && !in_array($key, $availableKeys)) {
            unset($knownKeys[$key], $knownKeys[$key]);
        } elseif ($reverseKeys == true && in_array($key, $availableKeys)) {
            unset($knownKeys[$key], $knownKeys[$key]);
        }
    }
    // Check columns
    foreach ($knownColumns as $column => $value) {
        // Here we reverse things.  If the column is not in then we must add it.
        if ($reverseColumns == false && in_array($column, $availableColumns)) {
            unset($knownColumns[$column], $knownColumns[$column]);
        } elseif ($reverseColumns == true && !in_array($column, $availableColumns)) {
            unset($knownColumns[$column], $knownColumns[$column]);
        }
    }
    // Now merge the three
    $alter = array_merge($alterColumns, $knownKeys, $knownColumns);
    // Now lets see what we want to do with them
    $clause = '';
    foreach ($alter as $key) {
        $clause .= "\n\t\t{$key},";
    }
    // Lets do some altering
    convert_query("\n\t\tALTER TABLE {$to_table}" . substr($clause, 0, -1));
}
Ejemplo n.º 12
0
/**
 * Determine a few things about the database
 * - collation
 * - name
 * - version
 */
function get_database_version()
{
    global $db_type, $context, $db_name, $txt, $db_prefix;
    $db = database();
    if (empty($db_type) || !empty($db_type) && $db_type == 'mysql') {
        $temp_prefix = (strpos($db_prefix, $db_name) === false ? '`' . $db_name . '`.' : '') . $db_prefix;
        // Get the collation of the 'body' field of the messages table
        $query = ' SHOW FULL COLUMNS FROM ' . $temp_prefix . 'messages WHERE Field = \'body\'';
        $request = $db->query('', $query);
        $row = $db->fetch_assoc($request);
        if (!empty($row)) {
            $collation = $row['Collation'];
        }
    }
    $context['character_set'] = !empty($collation) ? $collation : $txt['unknown_db_version'];
    db_extend();
    $context['database_version'] = $db->db_title() . ' ' . $db->db_server_version();
}
Ejemplo n.º 13
0
function mobi_table_exist($table_name)
{
    global $smcFunc, $db_prefix;
    db_extend();
    $tables = $smcFunc['db_list_tables'](false, $db_prefix . $table_name);
    return !empty($tables);
}
Ejemplo n.º 14
0
function sortSmileyTable()
{
    global $smcFunc;
    db_extend('packages');
    // Add a sorting column.
    smf_db_add_column('{db_prefix}smileys', array('name' => 'temp_order', 'size' => 8, 'type' => 'mediumint', 'null' => false));
    // Set the contents of this column.
    smf_db_query('
		UPDATE {db_prefix}smileys
		SET temp_order = LENGTH(code)', array());
    // Order the table by this column.
    smf_db_query('
		ALTER TABLE {db_prefix}smileys
		ORDER BY temp_order DESC', array('db_error_skip' => true));
    // Remove the sorting column.
    smf_db_remove_column('{db_prefix}smileys', 'temp_order');
}
Ejemplo n.º 15
0
 * wayne Mankertz.
 * Portions created by the Initial Developer are Copyright (C) 2011
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */
if (file_exists(dirname(__FILE__) . '/SSI.php') && !defined('SMF')) {
    require_once dirname(__FILE__) . '/SSI.php';
} elseif (!defined('SMF')) {
    die('<strong>Error:</strong> Cannot install - please verify you put this in the same place as SMF\'s index.php.');
}
global $db_prefix, $modSettings, $smcFunc;
// First load the SMF 2's Extra DB Functions
db_extend('packages');
db_extend('extra');
pre_installCheck();
$GplusHooks = array('integrate_pre_include' => '$sourcedir/GPlus/GPlusHooks.php', 'integrate_buffer' => 'ob_gplus', 'integrate_actions' => 'gplus_actions', 'integrate_profile_areas' => 'gplus_profile_areas', 'integrate_admin_areas' => 'gplus_admin_areas', 'integrate_login' => 'gplus_integrate_login', 'integrate_logout' => 'gplus_integrate_logout', 'integrate_load_theme' => 'gplus_loadTheme');
foreach ($GplusHooks as $hook => $function) {
    add_integration_function($hook, $function);
}
db_add_col('members', 'gpname', 'varchar', 255);
db_add_col('members', 'gpid', 'varchar', 255);
function pre_installCheck()
{
    if (version_compare(PHP_VERSION, '5.2.0', '<')) {
        fatal_error('<strong>PHP 5 or geater is required to install SA Google+.  Please advise your host that PHP4 is no longer maintained and ask that they upgrade you to PHP5.</strong><br />');
    }
}
function db_add_col($table, $col, $type, $size)
{
Ejemplo n.º 16
0
/**
 * Create a custom search index for the messages table.
 * Called by ?action=admin;area=managesearch;sa=createmsgindex.
 * Linked from the EditSearchMethod screen.
 * Requires the admin_forum permission.
 * Depending on the size of the message table, the process is divided in steps.
 *
 * @uses ManageSearch template, 'create_index', 'create_index_progress', and 'create_index_done'
 *  sub-templates.
 */
function CreateMessageIndex()
{
    global $modSettings, $context, $smcFunc, $db_prefix, $txt;
    // Scotty, we need more time...
    @set_time_limit(600);
    if (function_exists('apache_reset_timeout')) {
        @apache_reset_timeout();
    }
    $context[$context['admin_menu_name']]['current_subsection'] = 'method';
    $context['page_title'] = $txt['search_index_custom'];
    $messages_per_batch = 50;
    $index_properties = array(2 => array('column_definition' => 'small', 'step_size' => 1000000), 4 => array('column_definition' => 'medium', 'step_size' => 1000000, 'max_size' => 16777215), 5 => array('column_definition' => 'large', 'step_size' => 100000000, 'max_size' => 2000000000));
    if (isset($_REQUEST['resume']) && !empty($modSettings['search_custom_index_resume'])) {
        $context['index_settings'] = unserialize($modSettings['search_custom_index_resume']);
        $context['start'] = (int) $context['index_settings']['resume_at'];
        unset($context['index_settings']['resume_at']);
        $context['step'] = 1;
    } else {
        $context['index_settings'] = array('bytes_per_word' => isset($_REQUEST['bytes_per_word']) && isset($index_properties[$_REQUEST['bytes_per_word']]) ? (int) $_REQUEST['bytes_per_word'] : 2);
        $context['start'] = isset($_REQUEST['start']) ? (int) $_REQUEST['start'] : 0;
        $context['step'] = isset($_REQUEST['step']) ? (int) $_REQUEST['step'] : 0;
        // admin timeouts are painful when building these long indexes
        if ($_SESSION['admin_time'] + 3300 < time() && $context['step'] >= 1) {
            $_SESSION['admin_time'] = time();
        }
    }
    if ($context['step'] !== 0) {
        checkSession('request');
    }
    // Step 0: let the user determine how they like their index.
    if ($context['step'] === 0) {
        $context['sub_template'] = 'create_index';
    }
    // Step 1: insert all the words.
    if ($context['step'] === 1) {
        $context['sub_template'] = 'create_index_progress';
        if ($context['start'] === 0) {
            db_extend();
            $tables = $smcFunc['db_list_tables'](false, $db_prefix . 'log_search_words');
            if (!empty($tables)) {
                $smcFunc['db_search_query']('drop_words_table', '
					DROP TABLE {db_prefix}log_search_words', array());
            }
            $smcFunc['db_create_word_search']($index_properties[$context['index_settings']['bytes_per_word']]['column_definition']);
            // Temporarily switch back to not using a search index.
            if (!empty($modSettings['search_index']) && $modSettings['search_index'] == 'custom') {
                updateSettings(array('search_index' => ''));
            }
            // Don't let simultanious processes be updating the search index.
            if (!empty($modSettings['search_custom_index_config'])) {
                updateSettings(array('search_custom_index_config' => ''));
            }
        }
        $num_messages = array('done' => 0, 'todo' => 0);
        $request = $smcFunc['db_query']('', '
			SELECT id_msg >= {int:starting_id} AS todo, COUNT(*) AS num_messages
			FROM {db_prefix}messages
			GROUP BY todo', array('starting_id' => $context['start']));
        while ($row = $smcFunc['db_fetch_assoc']($request)) {
            $num_messages[empty($row['todo']) ? 'done' : 'todo'] = $row['num_messages'];
        }
        if (empty($num_messages['todo'])) {
            $context['step'] = 2;
            $context['percentage'] = 80;
            $context['start'] = 0;
        } else {
            // Number of seconds before the next step.
            $stop = time() + 3;
            while (time() < $stop) {
                $inserts = array();
                $request = $smcFunc['db_query']('', '
					SELECT id_msg, body
					FROM {db_prefix}messages
					WHERE id_msg BETWEEN {int:starting_id} AND {int:ending_id}
					LIMIT {int:limit}', array('starting_id' => $context['start'], 'ending_id' => $context['start'] + $messages_per_batch - 1, 'limit' => $messages_per_batch));
                $forced_break = false;
                $number_processed = 0;
                while ($row = $smcFunc['db_fetch_assoc']($request)) {
                    // In theory it's possible for one of these to take friggin ages so add more timeout protection.
                    if ($stop < time()) {
                        $forced_break = true;
                        break;
                    }
                    $number_processed++;
                    foreach (text2words($row['body'], $context['index_settings']['bytes_per_word'], true) as $id_word) {
                        $inserts[] = array($id_word, $row['id_msg']);
                    }
                }
                $num_messages['done'] += $number_processed;
                $num_messages['todo'] -= $number_processed;
                $smcFunc['db_free_result']($request);
                $context['start'] += $forced_break ? $number_processed : $messages_per_batch;
                if (!empty($inserts)) {
                    $smcFunc['db_insert']('ignore', '{db_prefix}log_search_words', array('id_word' => 'int', 'id_msg' => 'int'), $inserts, array('id_word', 'id_msg'));
                }
                if ($num_messages['todo'] === 0) {
                    $context['step'] = 2;
                    $context['start'] = 0;
                    break;
                } else {
                    updateSettings(array('search_custom_index_resume' => serialize(array_merge($context['index_settings'], array('resume_at' => $context['start'])))));
                }
            }
            // Since there are still two steps to go, 80% is the maximum here.
            $context['percentage'] = round($num_messages['done'] / ($num_messages['done'] + $num_messages['todo']), 3) * 80;
        }
    } elseif ($context['step'] === 2) {
        if ($context['index_settings']['bytes_per_word'] < 4) {
            $context['step'] = 3;
        } else {
            $stop_words = $context['start'] === 0 || empty($modSettings['search_stopwords']) ? array() : explode(',', $modSettings['search_stopwords']);
            $stop = time() + 3;
            $context['sub_template'] = 'create_index_progress';
            $max_messages = ceil(60 * $modSettings['totalMessages'] / 100);
            while (time() < $stop) {
                $request = $smcFunc['db_query']('', '
					SELECT id_word, COUNT(id_word) AS num_words
					FROM {db_prefix}log_search_words
					WHERE id_word BETWEEN {int:starting_id} AND {int:ending_id}
					GROUP BY id_word
					HAVING COUNT(id_word) > {int:minimum_messages}', array('starting_id' => $context['start'], 'ending_id' => $context['start'] + $index_properties[$context['index_settings']['bytes_per_word']]['step_size'] - 1, 'minimum_messages' => $max_messages));
                while ($row = $smcFunc['db_fetch_assoc']($request)) {
                    $stop_words[] = $row['id_word'];
                }
                $smcFunc['db_free_result']($request);
                updateSettings(array('search_stopwords' => implode(',', $stop_words)));
                if (!empty($stop_words)) {
                    $smcFunc['db_query']('', '
						DELETE FROM {db_prefix}log_search_words
						WHERE id_word in ({array_int:stop_words})', array('stop_words' => $stop_words));
                }
                $context['start'] += $index_properties[$context['index_settings']['bytes_per_word']]['step_size'];
                if ($context['start'] > $index_properties[$context['index_settings']['bytes_per_word']]['max_size']) {
                    $context['step'] = 3;
                    break;
                }
            }
            $context['percentage'] = 80 + round($context['start'] / $index_properties[$context['index_settings']['bytes_per_word']]['max_size'], 3) * 20;
        }
    }
    // Step 3: remove words not distinctive enough.
    if ($context['step'] === 3) {
        $context['sub_template'] = 'create_index_done';
        updateSettings(array('search_index' => 'custom', 'search_custom_index_config' => serialize($context['index_settings'])));
        $smcFunc['db_query']('', '
			DELETE FROM {db_prefix}settings
			WHERE variable = {string:search_custom_index_resume}', array('search_custom_index_resume' => 'search_custom_index_resume'));
    }
}
Ejemplo n.º 17
0
/**
 * Dumps the database.
 * It writes all of the database to standard output.
 * It uses gzip compression if compress is set in the URL/post data.
 * It may possibly time out, and mess up badly if you were relying on it. :P
 * The data dumped depends on whether "struct" and "data" are passed.
 * It requires an administrator and the session hash by post.
 * It is called from ManageMaintenance.php.
 */
function DumpDatabase2()
{
    global $db_name, $scripturl, $context, $modSettings, $crlf, $smcFunc, $db_prefix, $db_show_debug;
    // Administrators only!
    if (!allowedTo('admin_forum')) {
        fatal_lang_error('no_dump_database', 'critical');
    }
    // We don't need debug when dumping the database
    $modSettings['disableQueryCheck'] = true;
    $db_show_debug = false;
    // You can't dump nothing!
    if (!isset($_REQUEST['struct']) && !isset($_REQUEST['data'])) {
        $_REQUEST['data'] = true;
    }
    checkSession('post');
    // We will need this, badly!
    db_extend();
    // Attempt to stop from dying...
    @set_time_limit(600);
    $time_limit = ini_get('max_execution_time');
    $start_time = time();
    // @todo ... fail on not getting the requested memory?
    setMemoryLimit('256M');
    $memory_limit = memoryReturnBytes(ini_get('memory_limit')) / 4;
    $current_used_memory = 0;
    $db_backup = '';
    $output_function = 'un_compressed';
    @ob_end_clean();
    // Start saving the output... (don't do it otherwise for memory reasons.)
    if (isset($_REQUEST['compress']) && function_exists('gzencode')) {
        $output_function = 'gzencode';
        // Send faked headers so it will just save the compressed output as a gzip.
        header('Content-Type: application/x-gzip');
        header('Accept-Ranges: bytes');
        header('Content-Encoding: none');
        // Gecko browsers... don't like this. (Mozilla, Firefox, etc.)
        if (!isBrowser('gecko')) {
            header('Content-Transfer-Encoding: binary');
        }
        // The file extension will include .gz...
        $extension = '.sql.gz';
    } else {
        // Get rid of the gzipping alreading being done.
        if (!empty($modSettings['enableCompressedOutput'])) {
            @ob_end_clean();
        } elseif (ob_get_length() != 0) {
            ob_clean();
        }
        // Tell the client to save this file, even though it's text.
        header('Content-Type: ' . (isBrowser('ie') || isBrowser('opera') ? 'application/octetstream' : 'application/octet-stream'));
        header('Content-Encoding: none');
        // This time the extension should just be .sql.
        $extension = '.sql';
    }
    // This should turn off the session URL parser.
    $scripturl = '';
    // If this database is flat file and has a handler function pass it to that.
    if (!empty($smcFunc['db_get_backup'])) {
        $smcFunc['db_get_backup']();
        exit;
    }
    // Send the proper headers to let them download this file.
    header('Content-Disposition: attachment; filename="' . $db_name . '-' . (empty($_REQUEST['struct']) ? 'data' : (empty($_REQUEST['data']) ? 'structure' : 'complete')) . '_' . strftime('%Y-%m-%d') . $extension . '"');
    header('Cache-Control: private');
    header('Connection: close');
    // This makes things simpler when using it so very very often.
    $crlf = "\r\n";
    // SQL Dump Header.
    $db_chunks = '-- ==========================================================' . $crlf . '--' . $crlf . '-- Database dump of tables in `' . $db_name . '`' . $crlf . '-- ' . timeformat(time(), false) . $crlf . '--' . $crlf . '-- ==========================================================' . $crlf . $crlf;
    // Get all tables in the database....
    if (preg_match('~^`(.+?)`\\.(.+?)$~', $db_prefix, $match) != 0) {
        $db = strtr($match[1], array('`' => ''));
        $dbp = str_replace('_', '\\_', $match[2]);
    } else {
        $db = false;
        $dbp = $db_prefix;
    }
    // Dump each table.
    $tables = $smcFunc['db_list_tables'](false, $db_prefix . '%');
    foreach ($tables as $tableName) {
        // Are we dumping the structures?
        if (isset($_REQUEST['struct'])) {
            $db_chunks .= $crlf . '--' . $crlf . '-- Table structure for table `' . $tableName . '`' . $crlf . '--' . $crlf . $crlf . $smcFunc['db_table_sql']($tableName) . ';' . $crlf;
        } else {
            // This is needed to speedup things later
            $smcFunc['db_table_sql']($tableName);
        }
        // How about the data?
        if (!isset($_REQUEST['data']) || substr($tableName, -10) == 'log_errors') {
            continue;
        }
        $first_round = true;
        $close_table = false;
        // Are there any rows in this table?
        while ($get_rows = $smcFunc['db_insert_sql']($tableName, $first_round)) {
            if (empty($get_rows)) {
                break;
            }
            // Time is what we need here!
            if (function_exists('apache_reset_timeout')) {
                @apache_reset_timeout();
            } elseif (!empty($time_limit) && $start_time + $time_limit - 20 > time()) {
                $start_time = time();
                @set_time_limit(150);
            }
            if ($first_round) {
                $db_chunks .= $crlf . '--' . $crlf . '-- Dumping data in `' . $tableName . '`' . $crlf . '--' . $crlf . $crlf;
                $first_round = false;
            }
            $db_chunks .= $get_rows;
            $current_used_memory += $smcFunc['strlen']($db_chunks);
            $db_backup .= $db_chunks;
            unset($db_chunks);
            $db_chunks = '';
            if ($current_used_memory > $memory_limit) {
                echo $output_function($db_backup);
                $current_used_memory = 0;
                // This is probably redundant
                unset($db_backup);
                $db_backup = '';
            }
            $close_table = true;
        }
        // No rows to get - skip it.
        if ($close_table) {
            $db_backup .= '-- --------------------------------------------------------' . $crlf;
        }
    }
    $db_backup .= $crlf . '-- Done' . $crlf;
    echo $output_function($db_backup);
    exit;
}
Ejemplo n.º 18
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);
}
Ejemplo n.º 19
0
function store_as_alert($push_data)
{
    global $smcFunc, $db_prefix, $modSettings;
    db_extend();
    $matched_tables = $smcFunc['db_list_tables'](false, $db_prefix . "tapatalk_push");
    if (!empty($matched_tables)) {
        $push_data['title'] = $smcFunc['db_escape_string']($push_data['title']);
        $push_data['author'] = $smcFunc['db_escape_string']($push_data['author']);
        $request = $smcFunc['db_insert']('ignore', '{db_prefix}tapatalk_push', array('userid' => 'int', 'type' => 'string', 'id' => 'int', 'subid' => 'int', 'subfid' => 'int', 'mid' => 'int', 'title' => 'string', 'author' => 'string', 'authorid' => 'int', 'dateline' => 'int'), array($push_data['userid'], $push_data['type'], $push_data['id'], isset($push_data['subid']) ? $push_data['subid'] : 0, isset($push_data['subfid']) ? $push_data['subfid'] : 0, isset($push_data['mid']) ? $push_data['mid'] : 0, $push_data['title'], $push_data['author'], $push_data['authorid'], $push_data['dateline']), array('userid'));
        $affected_rows = $smcFunc['db_affected_rows']($request);
    }
    $current_time = time();
    // Check outdated push data and clean
    if (isset($modSettings['tp_alert_clean_time']) && !empty($modSettings['tp_alert_clean_time'])) {
        $last_clean_time = $modSettings['tp_alert_clean_time'];
        $clean_period = 1 * 24 * 60 * 60;
        if ($current_time - $last_clean_time > $clean_period) {
            $d_request = $smcFunc['db_query']('', '
                DELETE
                FROM {db_prefix}tapatalk_push
                    WHERE dateline < {int:outdateTime}', array('outdateTime' => $current_time - 30 * 24 * 60 * 60));
            updateSettings(array('tp_alert_clean_time' => $current_time), true);
        }
    } else {
        updateSettings(array('tp_alert_clean_time' => $current_time));
    }
}
Ejemplo n.º 20
0
function sortSpiderTable()
{
    global $smcFunc;
    db_extend('packages');
    // Add a sorting column.
    $smcFunc['db_add_column']('{db_prefix}spiders', array('name' => 'temp_order', 'size' => 8, 'type' => 'mediumint', 'null' => false));
    // Set the contents of this column.
    $smcFunc['db_query']('set_spider_order', '
		UPDATE {db_prefix}spiders
		SET temp_order = LENGTH(user_agent)', array());
    // Order the table by this column.
    $smcFunc['db_query']('alter_table_spiders', '
		ALTER TABLE {db_prefix}spiders
		ORDER BY temp_order DESC', array('db_error_skip' => true));
    // Remove the sorting column.
    $smcFunc['db_remove_column']('{db_prefix}spiders', 'temp_order');
}
Ejemplo n.º 21
0
/**********************************************************************************
* Maximum profile                                                                 *
* =============================================================================== *
***********************************************************************************
*  snrj tarafından http://smf.konusal.com için editlenmiştir                      *
**********************************************************************************/
// Handle running this file by using SSI.php
if (file_exists(dirname(__FILE__) . '/SSI.php') && !defined('SMF')) {
    require_once dirname(__FILE__) . '/SSI.php';
} elseif (!defined('SMF')) {
    die('<b>Error:</b> Cannot install - please verify you put this in the same place as SMF\'s index.php.');
}
global $db_prefix, $smcFunc;
// Make sure that we have the package database functions.
if (!array_key_exists('db_add_column', $smcFunc)) {
    db_extend('Packages');
}
// Let's check for the UTF-8 support
// Sorry, this is only for MySQL; I don't know the other way :(
global $db_type, $db_prefix;
if ($db_type == 'mysql') {
    $request = mysql_query('
		SELECT variable, value 
		FROM ' . $db_prefix . 'settings 
		WHERE variable = "global_character_set" 
			AND value="UTF-8"');
    if (mysql_num_rows($request) > 0) {
        mysql_free_result($request);
        mysql_query('ALTER TABLE ' . $db_prefix . 'Maximum_comments DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci');
        mysql_query('ALTER TABLE ' . $db_prefix . 'Maximum_comments CHANGE `comment` `comment` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL');
        mysql_query('ALTER TABLE ' . $db_prefix . 'Maximum_pictures DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci');
Ejemplo n.º 22
0
function scheduled_auto_optimize()
{
    global $modSettings, $db_prefix, $db_type;
    // By default do it now!
    $delay = false;
    // As a kind of hack, if the server load is too great delay, but only by a bit!
    if (!empty($modSettings['load_average']) && !empty($modSettings['loadavg_auto_opt']) && $modSettings['load_average'] >= $modSettings['loadavg_auto_opt']) {
        $delay = true;
    }
    // Otherwise are we restricting the number of people online for this?
    if (!empty($modSettings['autoOptMaxOnline'])) {
        $request = smf_db_query('
			SELECT COUNT(*)
			FROM {db_prefix}log_online', array());
        list($dont_do_it) = mysql_fetch_row($request);
        mysql_free_result($request);
        if ($dont_do_it > $modSettings['autoOptMaxOnline']) {
            $delay = true;
        }
    }
    // If we are gonna delay, do so now!
    if ($delay) {
        return false;
    }
    db_extend();
    // Get all the tables.
    $tables = smf_db_list_tables(false, $db_prefix . '%');
    // Actually do the optimisation.
    if ($db_type == 'sqlite') {
        smf_db_optimize_table($table[0]);
    } else {
        foreach ($tables as $table) {
            smf_db_optimize_table($table);
        }
    }
    // Return for the log...
    return true;
}
Ejemplo n.º 23
0
function DumpDatabase2()
{
    global $db_name, $scripturl, $context, $modSettings, $crlf, $smcFunc, $db_prefix;
    // Administrators only!
    if (!allowedTo('admin_forum')) {
        fatal_lang_error('no_dump_database', 'critical');
    }
    // You can't dump nothing!
    if (!isset($_REQUEST['struct']) && !isset($_REQUEST['data'])) {
        $_REQUEST['data'] = true;
    }
    checkSession('post');
    // We will need this, badly!
    db_extend();
    // Attempt to stop from dying...
    @set_time_limit(600);
    if (@ini_get('memory_limit') < 256) {
        @ini_set('memory_limit', '256M');
    }
    // Start saving the output... (don't do it otherwise for memory reasons.)
    if (isset($_REQUEST['compress']) && function_exists('gzencode')) {
        // Make sure we're gzipping output, but then say we're not in the header ^_^.
        if (empty($modSettings['enableCompressedOutput'])) {
            @ob_start('ob_gzhandler');
        } elseif (ob_get_length() != 0) {
            ob_end_clean();
            @ob_start('ob_gzhandler');
        }
        // Send faked headers so it will just save the compressed output as a gzip.
        header('Content-Type: application/x-gzip');
        header('Accept-Ranges: bytes');
        header('Content-Encoding: none');
        // Gecko browsers... don't like this. (Mozilla, Firefox, etc.)
        if (!$context['browser']['is_gecko']) {
            header('Content-Transfer-Encoding: binary');
        }
        // The file extension will include .gz...
        $extension = '.sql.gz';
    } else {
        // Get rid of the gzipping alreading being done.
        if (!empty($modSettings['enableCompressedOutput'])) {
            @ob_end_clean();
        } elseif (function_exists('ob_clean') && ob_get_length() != 0) {
            ob_clean();
        }
        // Tell the client to save this file, even though it's text.
        header('Content-Type: ' . ($context['browser']['is_ie'] || $context['browser']['is_opera'] ? 'application/octetstream' : 'application/octet-stream'));
        header('Content-Encoding: none');
        // This time the extension should just be .sql.
        $extension = '.sql';
    }
    // This should turn off the session URL parser.
    $scripturl = '';
    // If this database is flat file and has a handler function pass it to that.
    if (!empty($smcFunc['db_get_backup'])) {
        $smcFunc['db_get_backup']();
        exit;
    }
    // Send the proper headers to let them download this file.
    header('Content-Disposition: filename="' . $db_name . '-' . (empty($_REQUEST['struct']) ? 'data' : (empty($_REQUEST['data']) ? 'structure' : 'complete')) . '_' . strftime('%Y-%m-%d') . $extension . '"');
    header('Cache-Control: private');
    header('Connection: close');
    // This makes things simpler when using it so very very often.
    $crlf = "\r\n";
    // SQL Dump Header.
    echo '-- ==========================================================', $crlf, '--', $crlf, '-- Database dump of tables in `', $db_name, '`', $crlf, '-- ', timeformat(time(), false), $crlf, '--', $crlf, '-- ==========================================================', $crlf, $crlf;
    // Get all tables in the database....
    if (preg_match('~^`(.+?)`\\.(.+?)$~', $db_prefix, $match) != 0) {
        $db = strtr($match[1], array('`' => ''));
        $dbp = str_replace('_', '\\_', $match[2]);
    } else {
        $db = false;
        $dbp = $db_prefix;
    }
    // Dump each table.
    $tables = $smcFunc['db_list_tables'](false, $db_prefix . '%');
    foreach ($tables as $tableName) {
        if (function_exists('apache_reset_timeout')) {
            @apache_reset_timeout();
        }
        // Are we dumping the structures?
        if (isset($_REQUEST['struct'])) {
            echo $crlf, '--', $crlf, '-- Table structure for table `', $tableName, '`', $crlf, '--', $crlf, $crlf, $smcFunc['db_table_sql']($tableName), ';', $crlf;
        }
        // How about the data?
        if (!isset($_REQUEST['data']) || substr($tableName, -10) == 'log_errors') {
            continue;
        }
        // Are there any rows in this table?
        $get_rows = $smcFunc['db_insert_sql']($tableName);
        // No rows to get - skip it.
        if (empty($get_rows)) {
            continue;
        }
        echo $crlf, '--', $crlf, '-- Dumping data in `', $tableName, '`', $crlf, '--', $crlf, $crlf, $get_rows, '-- --------------------------------------------------------', $crlf;
    }
    echo $crlf, '-- Done', $crlf;
    exit;
}
Ejemplo n.º 24
0
function DatabasePopulation()
{
    global $txt, $db_connection, $databases, $modSettings, $db_type, $db_prefix, $incontext, $db_name, $boardurl;
    $incontext['sub_template'] = 'populate_database';
    $incontext['page_title'] = $txt['db_populate'];
    $incontext['continue'] = 1;
    // Already done?
    if (isset($_POST['pop_done'])) {
        return true;
    }
    // Reload settings.
    require dirname(__FILE__) . '/Settings.php';
    load_database();
    // Before running any of the queries, let's make sure another version isn't already installed.
    $result = smf_db_query('
		SELECT variable, value
		FROM {db_prefix}settings', array('db_error_skip' => true));
    $modSettings = array();
    if ($result !== false) {
        while ($row = mysql_fetch_assoc($result)) {
            $modSettings[$row['variable']] = $row['value'];
        }
        mysql_free_result($result);
        // Do they match?  If so, this is just a refresh so charge on!
        if (!isset($modSettings['smfVersion']) || $modSettings['smfVersion'] != $GLOBALS['current_smf_version']) {
            $incontext['error'] = $txt['error_versions_do_not_match'];
            return false;
        }
    }
    smf_db_query('
		SET NAMES utf8', array());
    $boardurl = $_POST['boardurl'];
    echo $boardurl;
    $replaces = array('{$db_prefix}' => $db_prefix, '{$boarddir}' => mysql_real_escape_string(dirname(__FILE__)), '{$boardurl}' => $boardurl, '{$enableCompressedOutput}' => isset($_POST['compress']) ? '1' : '0', '{$databaseSession_enable}' => isset($_POST['dbsession']) ? '1' : '0', '{$smf_version}' => $GLOBALS['current_smf_version'], '{$current_time}' => time(), '{$sched_task_offset}' => 82800 + mt_rand(0, 86399));
    foreach ($txt as $key => $value) {
        if (substr($key, 0, 8) == 'default_') {
            $replaces['{$' . $key . '}'] = mysql_real_escape_string($value);
        }
    }
    $replaces['{$default_reserved_names}'] = strtr($replaces['{$default_reserved_names}'], array('\\\\n' => '\\n'));
    $replaces[') ENGINE=MyISAM;'] = ') ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;';
    // Read in the SQL.  Turn this on and that off... internationalize... etc.
    $sql_lines = explode("\n", strtr(implode(' ', file(dirname(__FILE__) . '/install_' . $GLOBALS['db_script_version'] . '_' . $db_type . '.sql')), $replaces));
    // Execute the SQL.
    $current_statement = '';
    $exists = array();
    $incontext['failures'] = array();
    $incontext['sql_results'] = array('tables' => 0, 'inserts' => 0, 'table_dups' => 0, 'insert_dups' => 0);
    foreach ($sql_lines as $count => $line) {
        // No comments allowed!
        if (substr(trim($line), 0, 1) != '#') {
            $current_statement .= "\n" . rtrim($line);
        }
        // Is this the end of the query string?
        if (empty($current_statement) || preg_match('~;[\\s]*$~s', $line) == 0 && $count != count($sql_lines)) {
            continue;
        }
        // Does this table already exist?  If so, don't insert more data into it!
        if (preg_match('~^\\s*INSERT INTO ([^\\s\\n\\r]+?)~', $current_statement, $match) != 0 && in_array($match[1], $exists)) {
            $incontext['sql_results']['insert_dups']++;
            $current_statement = '';
            continue;
        }
        if (smf_db_query($current_statement, array('security_override' => true, 'db_error_skip' => true), $db_connection) === false) {
            // Error 1050: Table already exists!
            //!!! Needs to be made better!
            if (($db_type != 'mysql' || mysql_errno($db_connection) === 1050) && preg_match('~^\\s*CREATE TABLE ([^\\s\\n\\r]+?)~', $current_statement, $match) == 1) {
                $exists[] = $match[1];
                $incontext['sql_results']['table_dups']++;
            } elseif (!preg_match('~^\\s*CREATE( UNIQUE)? INDEX ([^\\n\\r]+?)~', $current_statement, $match) && !($db_type == 'postgresql' && preg_match('~^\\s*CREATE OPERATOR (^\\n\\r]+?)~', $current_statement, $match))) {
                $incontext['failures'][$count] = mysql_error($db_connection);
            }
        } else {
            if (preg_match('~^\\s*CREATE TABLE ([^\\s\\n\\r]+?)~', $current_statement, $match) == 1) {
                $incontext['sql_results']['tables']++;
            } else {
                preg_match_all('~\\)[,;]~', $current_statement, $matches);
                if (!empty($matches[0])) {
                    $incontext['sql_results']['inserts'] += count($matches[0]);
                } else {
                    $incontext['sql_results']['inserts']++;
                }
            }
        }
        $current_statement = '';
    }
    // Sort out the context for the SQL.
    foreach ($incontext['sql_results'] as $key => $number) {
        if ($number == 0) {
            unset($incontext['sql_results'][$key]);
        } else {
            $incontext['sql_results'][$key] = sprintf($txt['db_populate_' . $key], $number);
        }
    }
    // Make sure UTF will be used globally.
    if (isset($_POST['utf8']) && !empty($databases[$db_type]['utf8_support'])) {
        smf_db_insert('replace', $db_prefix . 'settings', array('variable' => 'string-255', 'value' => 'string-65534'), array('global_character_set', 'UTF-8'), array('variable'));
    }
    // Maybe we can auto-detect better cookie settings?
    preg_match('~^http[s]?://([^\\.]+?)([^/]*?)(/.*)?$~', $boardurl, $matches);
    if (!empty($matches)) {
        // Default = both off.
        $localCookies = false;
        $globalCookies = false;
        // Okay... let's see.  Using a subdomain other than www.? (not a perfect check.)
        if ($matches[2] != '' && (strpos(substr($matches[2], 1), '.') === false || in_array($matches[1], array('forum', 'board', 'community', 'forums', 'support', 'chat', 'help', 'talk', 'boards', 'www')))) {
            $globalCookies = true;
        }
        // If there's a / in the middle of the path, or it starts with ~... we want local.
        if (isset($matches[3]) && strlen($matches[3]) > 3 && (substr($matches[3], 0, 2) == '/~' || strpos(substr($matches[3], 1), '/') !== false)) {
            $localCookies = true;
        }
        $rows = array();
        if ($globalCookies) {
            $rows[] = array('globalCookies', '1');
        }
        if ($localCookies) {
            $rows[] = array('localCookies', '1');
        }
        if (!empty($rows)) {
            smf_db_insert('replace', $db_prefix . 'settings', array('variable' => 'string-255', 'value' => 'string-65534'), $rows, array('variable'));
        }
    }
    // As of PHP 5.1, setting a timezone is required.
    if (!isset($modSettings['default_timezone'])) {
        $server_offset = mktime(0, 0, 0, 1, 1, 1970);
        $timezone_id = 'Etc/GMT' . ($server_offset > 0 ? '+' : '') . $server_offset / 3600;
        if (date_default_timezone_set($timezone_id)) {
            smf_db_insert('', $db_prefix . 'settings', array('variable' => 'string-255', 'value' => 'string-65534'), array('default_timezone', $timezone_id), array('variable'));
        }
    }
    // Let's optimize those new tables.
    db_extend();
    $tables = smf_db_list_tables($db_name, $db_prefix . '%');
    foreach ($tables as $table) {
        smf_db_optimize_table($table) != -1 or $db_messed = true;
        // Optimizing one sqlite table, optimizes them all
        if ($db_type == 'sqlite') {
            break;
        }
        if (!empty($db_messed)) {
            $incontext['failures'][-1] = mysql_error($db_connection);
            break;
        }
    }
    // Check for the ALTER privilege.
    if (!empty($databases[$db_type]['alter_support']) && smf_db_query("ALTER TABLE {$db_prefix}boards ORDER BY id_board", array('security_override' => true, 'db_error_skip' => true)) === false) {
        $incontext['error'] = $txt['error_db_alter_priv'];
        return false;
    }
    if (!empty($exists)) {
        $incontext['page_title'] = $txt['user_refresh_install'];
        $incontext['was_refresh'] = true;
    }
    return false;
}
Ejemplo n.º 25
0
function get_database_version()
{
    global $db_type, $smcFunc, $context, $db_name, $txt, $db_prefix;
    if (empty($db_type) || !empty($db_type) && $db_type == 'mysql') {
        $temp_prefix = (strpos($db_prefix, $db_name) === false ? '`' . $db_name . '`.' : '') . $db_prefix;
        // Get the collation of the 'body' field of the messages table
        $query = ' SHOW FULL COLUMNS FROM ' . $temp_prefix . 'messages WHERE Field = \'body\'';
        $request = mysql_query($query);
        $row = @mysql_fetch_assoc($request);
        if (!empty($row)) {
            $collation = $row['Collation'];
        }
    }
    if (!empty($collation)) {
        $context['character_set'] = $collation;
    } else {
        $context['character_set'] = $txt['unknown_db_version'];
    }
    if (empty($smcFunc)) {
        $context['database_version'] = 'MySQL ' . mysql_get_server_info();
    } else {
        db_extend();
        $context['database_version'] = $smcFunc['db_title'] . ' ' . $smcFunc['db_get_version']();
    }
}
Ejemplo n.º 26
0
function ModifyPostSettings($return_config = false)
{
    global $context, $txt, $modSettings, $scripturl, $sourcedir, $smcFunc, $db_prefix;
    // All the settings...
    $config_vars = array(array('check', 'removeNestedQuotes'), array('check', 'enableEmbeddedFlash', 'subtext' => $txt['enableEmbeddedFlash_warning']), array('check', 'enableSpellChecking', 'subtext' => function_exists('pspell_new') ? $txt['enableSpellChecking_warning'] : '<span class="alert">' . $txt['enableSpellChecking_warning'] . '</span>'), array('check', 'disable_wysiwyg'), '', array('int', 'max_messageLength', 'subtext' => $txt['max_messageLength_zero'], 'postinput' => $txt['manageposts_characters']), array('int', 'fixLongWords', 'subtext' => $txt['fixLongWords_zero'] . ($context['utf8'] ? ' <span class="alert">' . $txt['fixLongWords_warning'] . '</span>' : ''), 'postinput' => $txt['manageposts_characters']), array('int', 'topicSummaryPosts', 'postinput' => $txt['manageposts_posts']), '', array('int', 'spamWaitTime', 'postinput' => $txt['manageposts_seconds']), array('int', 'edit_wait_time', 'postinput' => $txt['manageposts_seconds']), array('int', 'edit_disable_time', 'subtext' => $txt['edit_disable_time_zero'], 'postinput' => $txt['manageposts_minutes']));
    if ($return_config) {
        return $config_vars;
    }
    // We'll want this for our easy save.
    require_once $sourcedir . '/ManageServer.php';
    // Setup the template.
    $context['page_title'] = $txt['manageposts_settings'];
    $context['sub_template'] = 'show_settings';
    // Are we saving them - are we??
    if (isset($_GET['save'])) {
        checkSession();
        // If we're changing the message length let's check the column is big enough.
        if (!empty($_POST['max_messageLength']) && $_POST['max_messageLength'] != $modSettings['max_messageLength']) {
            db_extend('packages');
            $colData = $smcFunc['db_list_columns']('{db_prefix}messages', true);
            foreach ($colData as $column) {
                if ($column['name'] == 'body') {
                    $body_type = $column['type'];
                }
            }
            $indData = $smcFunc['db_list_indexes']('{db_prefix}messages', true);
            foreach ($indData as $index) {
                foreach ($index['columns'] as $column) {
                    if ($column == 'body' && $index['type'] == 'fulltext') {
                        $fulltext = true;
                    }
                }
            }
            if (isset($body_type) && $_POST['max_messageLength'] > 65535 && $body_type == 'text') {
                // !!! Show an error message?!
                // MySQL only likes fulltext indexes on text columns... for now?
                if (!empty($fulltext)) {
                    $_POST['max_messageLength'] = 65535;
                } else {
                    // Make it longer so we can do their limit.
                    $smcFunc['db_change_column']('{db_prefix}messages', 'body', array('type' => 'mediumtext'));
                }
            } elseif (isset($body_type) && $_POST['max_messageLength'] <= 65535 && $body_type != 'text') {
                // Shorten the column so we can have the benefit of fulltext searching again!
                $smcFunc['db_change_column']('{db_prefix}messages', 'body', array('type' => 'text'));
            }
        }
        saveDBSettings($config_vars);
        redirectexit('action=admin;area=postsettings;sa=posts');
    }
    // Final settings...
    $context['post_url'] = $scripturl . '?action=admin;area=postsettings;save;sa=posts';
    $context['settings_title'] = $txt['manageposts_settings'];
    // Prepare the settings...
    prepareDBSettingContext($config_vars);
}
Ejemplo n.º 27
0
/**
 * Modify any setting related to posts and posting.
 * Requires the admin_forum permission.
 * Accessed from ?action=admin;area=postsettings;sa=posts.
 *
 * @param bool $return_config = false
 * @uses Admin template, edit_post_settings sub-template.
 */
function ModifyPostSettings($return_config = false)
{
    global $context, $txt, $modSettings, $scripturl, $sourcedir, $smcFunc, $db_prefix, $db_type;
    // All the settings...
    $config_vars = array(array('check', 'removeNestedQuotes'), array('check', 'enableEmbeddedFlash', 'subtext' => $txt['enableEmbeddedFlash_warning']), array('check', 'enableSpellChecking', 'subtext' => function_exists('pspell_new') ? $txt['enableSpellChecking_warning'] : '<span class="alert">' . $txt['enableSpellChecking_warning'] . '</span>'), array('check', 'disable_wysiwyg'), '', array('int', 'max_messageLength', 'subtext' => $txt['max_messageLength_zero'], 'postinput' => $txt['manageposts_characters']), array('int', 'fixLongWords', 'subtext' => $txt['fixLongWords_zero'] . ($context['utf8'] ? ' <span class="alert">' . $txt['fixLongWords_warning'] . '</span>' : ''), 'postinput' => $txt['manageposts_characters']), array('int', 'topicSummaryPosts', 'postinput' => $txt['manageposts_posts']), '', array('int', 'spamWaitTime', 'postinput' => $txt['manageposts_seconds']), array('int', 'edit_wait_time', 'postinput' => $txt['manageposts_seconds']), array('int', 'edit_disable_time', 'subtext' => $txt['edit_disable_time_zero'], 'postinput' => $txt['manageposts_minutes']), '', array('int', 'preview_characters', 'subtext' => $txt['preview_characters_zero'], 'postinput' => $txt['preview_characters_units']));
    call_integration_hook('integrate_modify_post_settings', array(&$config_vars));
    if ($return_config) {
        return $config_vars;
    }
    // We'll want this for our easy save.
    require_once $sourcedir . '/ManageServer.php';
    // Setup the template.
    $context['page_title'] = $txt['manageposts_settings'];
    $context['sub_template'] = 'show_settings';
    // Are we saving them - are we??
    if (isset($_GET['save'])) {
        checkSession();
        // If we're changing the message length (and we are using MySQL) let's check the column is big enough.
        if (isset($_POST['max_messageLength']) && $_POST['max_messageLength'] != $modSettings['max_messageLength'] && $db_type == 'mysql') {
            db_extend('packages');
            $colData = $smcFunc['db_list_columns']('{db_prefix}messages', true);
            foreach ($colData as $column) {
                if ($column['name'] == 'body') {
                    $body_type = $column['type'];
                }
            }
            if (isset($body_type) && ($_POST['max_messageLength'] > 65535 || $_POST['max_messageLength'] == 0) && $body_type == 'text') {
                fatal_lang_error('convert_to_mediumtext', false, array($scripturl . '?action=admin;area=maintain;sa=database'));
            }
        }
        // If we're changing the post preview length let's check its valid
        if (!empty($_POST['preview_characters'])) {
            $_POST['preview_characters'] = (int) min(max(0, $_POST['preview_characters']), 512);
        }
        call_integration_hook('integrate_save_post_settings');
        saveDBSettings($config_vars);
        redirectexit('action=admin;area=postsettings;sa=posts');
    }
    // Final settings...
    $context['post_url'] = $scripturl . '?action=admin;area=postsettings;save;sa=posts';
    $context['settings_title'] = $txt['manageposts_settings'];
    // Prepare the settings...
    prepareDBSettingContext($config_vars);
}