function ManageGames() { global $scripturl, $txt, $context, $sourcedir, $smcFunc, $modSettings; require_once $sourcedir . '/Arcade.php'; require_once $sourcedir . '/Subs-ArcadeAdmin.php'; // Templates loadTemplate('ManageGames'); SMFArcade::loadArcade('admin', 'manage_games'); loadClassFile('Class-Package.php'); // Need to update files in database? if (!empty($modSettings['arcadeGamecacheUpdate']) && (empty($modSettings['arcadeDBUpdate']) || $modSettings['arcadeDBUpdate'] < max(filemtime($modSettings['gamesDirectory']), filemtime(__FILE__)))) { updateGameCache(); } if (isset($_REQUEST['uninstall_submit']) && !isset($_REQUEST['sa'])) { $_REQUEST['sa'] = 'uninstall'; } if (isset($_REQUEST['done']) && !empty($_SESSION['qaction'])) { $context['show_done'] = true; if ($_SESSION['qaction'] == 'install') { $context['qaction_title'] = $txt['arcade_install_complete']; $context['qaction_text'] = $txt['arcade_install_following_games']; } elseif ($_SESSION['qaction'] == 'uninstall') { $context['qaction_title'] = $txt['arcade_uninstall_complete']; $context['qaction_text'] = $txt['arcade_uninstall_following_games']; } if (isset($_SESSION['qaction_data']) && is_array($_SESSION['qaction_data'])) { $context['qaction_data'] = $_SESSION['qaction_data']; } unset($_SESSION['qaction_data']); unset($_SESSION['qaction']); } $subActions = array('list' => array('ManageGamesList', 'arcade_admin'), 'uninstall' => array('ManageGamesUninstall', 'arcade_admin'), 'uninstall2' => array('ManageGamesUninstall2', 'arcade_admin'), 'install' => array('ManageGamesInstall', 'arcade_admin'), 'install2' => array('ManageGamesInstall2', 'arcade_admin'), 'upload' => array('ManageGamesUpload', 'arcade_admin'), 'upload2' => array('ManageGamesUpload2', 'arcade_admin'), 'quickedit' => array('ManageGamesQuickEdit', 'arcade_admin'), 'edit' => array('EditGame', 'arcade_admin'), 'edit2' => array('EditGame2', 'arcade_admin'), 'export' => array('ExportGameinfo', 'arcade_admin')); // What user wants to do? $_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : 'list'; // Do we have reason to allow him/her to do it? isAllowedTo($subActions[$_REQUEST['sa']][1]); $context[$context['admin_menu_name']]['tab_data']['title'] = $txt['arcade_manage_games']; $context[$context['admin_menu_name']]['tab_data']['description'] = $txt['arcade_manage_games_desc']; $subActions[$_REQUEST['sa']][0](); }
function gif_loadFile($lpszFileName, $iIndex = 0) { // The classes needed are in this file. loadClassFile('Class-Graphics.php'); $gif = new gif_file(); if (!$gif->loadFile($lpszFileName, $iIndex)) { return false; } return $gif; }
function PackageGBrowse() { global $txt, $boardurl, $context, $scripturl, $boarddir, $sourcedir, $forum_version, $context, $smcFunc; if (isset($_GET['server'])) { if ($_GET['server'] == '') { redirectexit('action=admin;area=packages;get'); } $server = (int) $_GET['server']; // Query the server list to find the current server. $request = $smcFunc['db_query']('', ' SELECT name, url FROM {db_prefix}package_servers WHERE id_server = {int:current_server} LIMIT 1', array('current_server' => $server)); list($name, $url) = $smcFunc['db_fetch_row']($request); $smcFunc['db_free_result']($request); // If the server does not exist, dump out. if (empty($url)) { fatal_lang_error('couldnt_connect', false); } // If there is a relative link, append to the stored server url. if (isset($_GET['relative'])) { $url = $url . (substr($url, -1) == '/' ? '' : '/') . $_GET['relative']; } // Clear any "absolute" URL. Since "server" is present, "absolute" is garbage. unset($_GET['absolute']); } elseif (isset($_GET['absolute']) && $_GET['absolute'] != '') { // Initialize the requried variables. $server = ''; $url = $_GET['absolute']; $name = ''; $_GET['package'] = $url . '/packages.xml?language=' . $context['user']['language']; // Clear any "relative" URL. Since "server" is not present, "relative" is garbage. unset($_GET['relative']); $token = checkConfirm('get_absolute_url'); if ($token !== true) { $context['sub_template'] = 'package_confirm'; $context['page_title'] = $txt['package_servers']; $context['confirm_message'] = sprintf($txt['package_confirm_view_package_content'], htmlspecialchars($_GET['absolute'])); $context['proceed_href'] = $scripturl . '?action=admin;area=packages;get;sa=browse;absolute=' . urlencode($_GET['absolute']) . ';confirm=' . $token; return; } } else { fatal_lang_error('couldnt_connect', false); } // In safe mode or on lycos? Try this URL. (includes package-list for informational purposes ;).) //if (@ini_get('safe_mode')) // redirectexit($url . '/index.php?package-list&language=' . $context['user']['language'] . '&ref=' . $boardurl); // Attempt to connect. If unsuccessful... try the URL. if (!isset($_GET['package']) || file_exists($_GET['package'])) { $_GET['package'] = $url . '/packages.xml?language=' . $context['user']['language']; } // Check to be sure the packages.xml file actually exists where it is should be... or dump out. if ((isset($_GET['absolute']) || isset($_GET['relative'])) && !url_exists($_GET['package'])) { fatal_lang_error('packageget_unable', false, array($url . '/index.php')); } // Might take some time. @set_time_limit(600); // Read packages.xml and parse into xmlArray. (the true tells it to trim things ;).) loadClassFile('Class-Package.php'); $listing = new xmlArray(fetch_web_data($_GET['package']), true); // Errm.... empty file? Try the URL.... if (!$listing->exists('package-list')) { fatal_lang_error('packageget_unable', false, array($url . '/index.php')); } // List out the packages... $context['package_list'] = array(); $listing = $listing->path('package-list[0]'); // Use the package list's name if it exists. if ($listing->exists('list-title')) { $name = $listing->fetch('list-title'); } // Pick the correct template. $context['sub_template'] = 'package_list'; $context['page_title'] = $txt['package_servers'] . ($name != '' ? ' - ' . $name : ''); $context['package_server'] = $server; // By default we use an unordered list, unless there are no lists with more than one package. $context['list_type'] = 'ul'; $instmods = loadInstalledPackages(); $installed_mods = array(); // Look through the list of installed mods... foreach ($instmods as $installed_mod) { $installed_mods[$installed_mod['package_id']] = $installed_mod['version']; } // Get default author and email if they exist. if ($listing->exists('default-author')) { $default_author = $smcFunc['htmlspecialchars']($listing->fetch('default-author')); if ($listing->exists('default-author/@email')) { $default_email = $smcFunc['htmlspecialchars']($listing->fetch('default-author/@email')); } } // Get default web site if it exists. if ($listing->exists('default-website')) { $default_website = $smcFunc['htmlspecialchars']($listing->fetch('default-website')); if ($listing->exists('default-website/@title')) { $default_title = $smcFunc['htmlspecialchars']($listing->fetch('default-website/@title')); } } $the_version = strtr($forum_version, array('SMF ' => '')); if (!empty($_SESSION['version_emulate'])) { $the_version = $_SESSION['version_emulate']; } $packageNum = 0; $packageSection = 0; $sections = $listing->set('section'); foreach ($sections as $i => $section) { $context['package_list'][$packageSection] = array('title' => '', 'text' => '', 'items' => array()); $packages = $section->set('title|heading|text|remote|rule|modification|language|avatar-pack|theme|smiley-set'); foreach ($packages as $thisPackage) { $package = array('type' => $thisPackage->name()); if (in_array($package['type'], array('title', 'text'))) { $context['package_list'][$packageSection][$package['type']] = $smcFunc['htmlspecialchars']($thisPackage->fetch('.')); } elseif (in_array($package['type'], array('heading', 'rule'))) { $package['name'] = $smcFunc['htmlspecialchars']($thisPackage->fetch('.')); } elseif ($package['type'] == 'remote') { $remote_type = $thisPackage->exists('@type') ? $thisPackage->fetch('@type') : 'relative'; if ($remote_type == 'relative' && substr($thisPackage->fetch('@href'), 0, 7) != 'http://') { if (isset($_GET['absolute'])) { $current_url = $_GET['absolute'] . '/'; } elseif (isset($_GET['relative'])) { $current_url = $_GET['relative'] . '/'; } else { $current_url = ''; } $current_url .= $thisPackage->fetch('@href'); if (isset($_GET['absolute'])) { $package['href'] = $scripturl . '?action=admin;area=packages;get;sa=browse;absolute=' . $current_url; } else { $package['href'] = $scripturl . '?action=admin;area=packages;get;sa=browse;server=' . $context['package_server'] . ';relative=' . $current_url; } } else { $current_url = $thisPackage->fetch('@href'); $package['href'] = $scripturl . '?action=admin;area=packages;get;sa=browse;absolute=' . $current_url; } $package['name'] = $smcFunc['htmlspecialchars']($thisPackage->fetch('.')); $package['link'] = '<a href="' . $package['href'] . '">' . $package['name'] . '</a>'; } else { if (isset($_GET['absolute'])) { $current_url = $_GET['absolute'] . '/'; } elseif (isset($_GET['relative'])) { $current_url = $_GET['relative'] . '/'; } else { $current_url = ''; } $server_att = $server != '' ? ';server=' . $server : ''; $package += $thisPackage->to_array(); if (isset($package['website'])) { unset($package['website']); } $package['author'] = array(); if ($package['description'] == '') { $package['description'] = $txt['package_no_description']; } else { $package['description'] = parse_bbc(preg_replace('~\\[[/]?html\\]~i', '', $smcFunc['htmlspecialchars']($package['description']))); } $package['is_installed'] = isset($installed_mods[$package['id']]); $package['is_current'] = $package['is_installed'] && $installed_mods[$package['id']] == $package['version']; $package['is_newer'] = $package['is_installed'] && $installed_mods[$package['id']] > $package['version']; // This package is either not installed, or installed but old. Is it supported on this version of SMF? if (!$package['is_installed'] || !$package['is_current'] && !$package['is_newer']) { if ($thisPackage->exists('version/@for')) { $package['can_install'] = matchPackageVersion($the_version, $thisPackage->fetch('version/@for')); } } else { $package['can_install'] = false; } $already_exists = getPackageInfo(basename($package['filename'])); $package['download_conflict'] = is_array($already_exists) && $already_exists['id'] == $package['id'] && $already_exists['version'] != $package['version']; $package['href'] = $url . '/' . $package['filename']; $package['name'] = $smcFunc['htmlspecialchars']($package['name']); $package['link'] = '<a href="' . $package['href'] . '">' . $package['name'] . '</a>'; $package['download']['href'] = $scripturl . '?action=admin;area=packages;get;sa=download' . $server_att . ';package=' . $current_url . $package['filename'] . ($package['download_conflict'] ? ';conflict' : '') . ';' . $context['session_var'] . '=' . $context['session_id']; $package['download']['link'] = '<a href="' . $package['download']['href'] . '">' . $package['name'] . '</a>'; if ($thisPackage->exists('author') || isset($default_author)) { if ($thisPackage->exists('author/@email')) { $package['author']['email'] = $thisPackage->fetch('author/@email'); } elseif (isset($default_email)) { $package['author']['email'] = $default_email; } if ($thisPackage->exists('author') && $thisPackage->fetch('author') != '') { $package['author']['name'] = $smcFunc['htmlspecialchars']($thisPackage->fetch('author')); } else { $package['author']['name'] = $default_author; } if (!empty($package['author']['email'])) { // Only put the "mailto:" if it looks like a valid email address. Some may wish to put a link to an SMF IM Form or other web mail form. $package['author']['href'] = preg_match('~^[\\w\\.\\-]+@[\\w][\\w\\-\\.]+[\\w]$~', $package['author']['email']) != 0 ? 'mailto:' . $package['author']['email'] : $package['author']['email']; $package['author']['link'] = '<a href="' . $package['author']['href'] . '">' . $package['author']['name'] . '</a>'; } } if ($thisPackage->exists('website') || isset($default_website)) { if ($thisPackage->exists('website') && $thisPackage->exists('website/@title')) { $package['author']['website']['name'] = $smcFunc['htmlspecialchars']($thisPackage->fetch('website/@title')); } elseif (isset($default_title)) { $package['author']['website']['name'] = $default_title; } elseif ($thisPackage->exists('website')) { $package['author']['website']['name'] = $smcFunc['htmlspecialchars']($thisPackage->fetch('website')); } else { $package['author']['website']['name'] = $default_website; } if ($thisPackage->exists('website') && $thisPackage->fetch('website') != '') { $authorhompage = $thisPackage->fetch('website'); } else { $authorhompage = $default_website; } if (strpos(strtolower($authorhompage), 'a href') === false) { $package['author']['website']['href'] = $authorhompage; $package['author']['website']['link'] = '<a href="' . $authorhompage . '">' . $package['author']['website']['name'] . '</a>'; } else { if (preg_match('/a href="(.+?)"/', $authorhompage, $match) == 1) { $package['author']['website']['href'] = $match[1]; } else { $package['author']['website']['href'] = ''; } $package['author']['website']['link'] = $authorhompage; } } else { $package['author']['website']['href'] = ''; $package['author']['website']['link'] = ''; } } $package['is_remote'] = $package['type'] == 'remote'; $package['is_title'] = $package['type'] == 'title'; $package['is_heading'] = $package['type'] == 'heading'; $package['is_text'] = $package['type'] == 'text'; $package['is_line'] = $package['type'] == 'rule'; $packageNum = in_array($package['type'], array('title', 'heading', 'text', 'remote', 'rule')) ? 0 : $packageNum + 1; $package['count'] = $packageNum; if (!in_array($package['type'], array('title', 'text'))) { $context['package_list'][$packageSection]['items'][] = $package; } if ($package['count'] > 1) { $context['list_type'] = 'ol'; } } $packageSection++; } // Lets make sure we get a nice new spiffy clean $package to work with. Otherwise we get PAIN! unset($package); foreach ($context['package_list'] as $ps_id => $packageSection) { foreach ($packageSection['items'] as $i => $package) { if ($package['count'] == 0 || isset($package['can_install'])) { continue; } $context['package_list'][$ps_id]['items'][$i]['can_install'] = false; $packageInfo = getPackageInfo($url . '/' . $package['filename']); if (is_array($packageInfo) && $packageInfo['xml']->exists('install')) { $installs = $packageInfo['xml']->set('install'); foreach ($installs as $install) { if (!$install->exists('@for') || matchPackageVersion($the_version, $install->fetch('@for'))) { // Okay, this one is good to go. $context['package_list'][$ps_id]['items'][$i]['can_install'] = true; break; } } } } } }
function fetch_web_data($url, $post_data = '', $keep_alive = false, $redirection_level = 0) { global $webmaster_email; static $keep_alive_dom = null, $keep_alive_fp = null; preg_match('~^(http|ftp)(s)?://([^/:]+)(:(\\d+))?(.+)$~', $url, $match); // An FTP url. We should try connecting and RETRieving it... if (empty($match[1])) { return false; } elseif ($match[1] == 'ftp') { // Include the file containing the ftp_connection class. loadClassFile('Class-Package.php'); // Establish a connection and attempt to enable passive mode. $ftp = new ftp_connection(($match[2] ? 'ssl://' : '') . $match[3], empty($match[5]) ? 21 : $match[5], 'anonymous', $webmaster_email); if ($ftp->error !== false || !$ftp->passive()) { return false; } // I want that one *points*! fwrite($ftp->connection, 'RETR ' . $match[6] . "\r\n"); // Since passive mode worked (or we would have returned already!) open the connection. $fp = @fsockopen($ftp->pasv['ip'], $ftp->pasv['port'], $err, $err, 5); if (!$fp) { return false; } // The server should now say something in acknowledgement. $ftp->check_response(150); $data = ''; while (!feof($fp)) { $data .= fread($fp, 4096); } fclose($fp); // All done, right? Good. $ftp->check_response(226); $ftp->close(); } elseif (isset($match[1]) && $match[1] == 'http') { if ($keep_alive && $match[3] == $keep_alive_dom) { $fp = $keep_alive_fp; } if (empty($fp)) { // Open the socket on the port we want... $fp = @fsockopen(($match[2] ? 'ssl://' : '') . $match[3], empty($match[5]) ? $match[2] ? 443 : 80 : $match[5], $err, $err, 5); if (!$fp) { return false; } } if ($keep_alive) { $keep_alive_dom = $match[3]; $keep_alive_fp = $fp; } // I want this, from there, and I'm not going to be bothering you for more (probably.) if (empty($post_data)) { fwrite($fp, 'GET ' . $match[6] . ' HTTP/1.0' . "\r\n"); fwrite($fp, 'Host: ' . $match[3] . (empty($match[5]) ? $match[2] ? ':443' : '' : ':' . $match[5]) . "\r\n"); fwrite($fp, 'User-Agent: PHP/SMF' . "\r\n"); if ($keep_alive) { fwrite($fp, 'Connection: Keep-Alive' . "\r\n\r\n"); } else { fwrite($fp, 'Connection: close' . "\r\n\r\n"); } } else { fwrite($fp, 'POST ' . $match[6] . ' HTTP/1.0' . "\r\n"); fwrite($fp, 'Host: ' . $match[3] . (empty($match[5]) ? $match[2] ? ':443' : '' : ':' . $match[5]) . "\r\n"); fwrite($fp, 'User-Agent: PHP/SMF' . "\r\n"); if ($keep_alive) { fwrite($fp, 'Connection: Keep-Alive' . "\r\n"); } else { fwrite($fp, 'Connection: close' . "\r\n"); } fwrite($fp, 'Content-Type: application/x-www-form-urlencoded' . "\r\n"); fwrite($fp, 'Content-Length: ' . strlen($post_data) . "\r\n\r\n"); fwrite($fp, $post_data); } $response = fgets($fp, 768); // Redirect in case this location is permanently or temporarily moved. if ($redirection_level < 3 && preg_match('~^HTTP/\\S+\\s+30[127]~i', $response) === 1) { $header = ''; $location = ''; while (!feof($fp) && trim($header = fgets($fp, 4096)) != '') { if (strpos($header, 'Location:') !== false) { $location = trim(substr($header, strpos($header, ':') + 1)); } } if (empty($location)) { return false; } else { if (!$keep_alive) { fclose($fp); } return fetch_web_data($location, $post_data, $keep_alive, $redirection_level + 1); } } elseif (preg_match('~^HTTP/\\S+\\s+20[01]~i', $response) === 0) { return false; } // Skip the headers... while (!feof($fp) && trim($header = fgets($fp, 4096)) != '') { if (preg_match('~content-length:\\s*(\\d+)~i', $header, $match) != 0) { $content_length = $match[1]; } elseif (preg_match('~connection:\\s*close~i', $header) != 0) { $keep_alive_dom = null; $keep_alive = false; } continue; } $data = ''; if (isset($content_length)) { while (!feof($fp) && strlen($data) < $content_length) { $data .= fread($fp, $content_length - strlen($data)); } } else { while (!feof($fp)) { $data .= fread($fp, 4096); } } if (!$keep_alive) { fclose($fp); } } else { // Umm, this shouldn't happen? trigger_error('fetch_web_data(): Bad URL', E_USER_NOTICE); $data = false; } return $data; }
function AddLanguage() { global $context, $sourcedir, $forum_version, $boarddir, $txt, $smcFunc, $scripturl; // Are we searching for new languages courtesy of Simple Machines? if (!empty($_POST['smf_add_sub'])) { // Need fetch_web_data. require_once $sourcedir . '/Subs-Package.php'; $context['smf_search_term'] = htmlspecialchars(trim($_POST['smf_add'])); // We're going to use this URL. $url = 'http://download.simplemachines.org/fetch_language.php?version=' . urlencode(strtr($forum_version, array('SMF ' => ''))); // Load the class file and stick it into an array. loadClassFile('Class-Package.php'); $language_list = new xmlArray(fetch_web_data($url), true); // Check it exists. if (!$language_list->exists('languages')) { $context['smf_error'] = 'no_response'; } else { $language_list = $language_list->path('languages[0]'); $lang_files = $language_list->set('language'); $context['smf_languages'] = array(); foreach ($lang_files as $file) { // Were we searching? if (!empty($context['smf_search_term']) && strpos($file->fetch('name'), $smcFunc['strtolower']($context['smf_search_term'])) === false) { continue; } $context['smf_languages'][] = array('id' => $file->fetch('id'), 'name' => $smcFunc['ucwords']($file->fetch('name')), 'version' => $file->fetch('version'), 'utf8' => $file->fetch('utf8'), 'description' => $file->fetch('description'), 'link' => $scripturl . '?action=admin;area=languages;sa=downloadlang;did=' . $file->fetch('id') . ';' . $context['session_var'] . '=' . $context['session_id']); } if (empty($context['smf_languages'])) { $context['smf_error'] = 'no_files'; } } } $context['sub_template'] = 'add_language'; }
function PackagePermissions() { global $context, $txt, $modSettings, $boarddir, $sourcedir, $cachedir, $package_ftp; // Let's try and be good, yes? checkSession('get'); // If we're restoring permissions this is just a pass through really. if (isset($_GET['restore'])) { create_chmod_control(array(), array(), true); fatal_lang_error('no_access', false); } // This is a memory eat. @ini_set('memory_limit', '128M'); @set_time_limit(600); // Load up some FTP stuff. create_chmod_control(); if (empty($package_ftp) && !isset($_POST['skip_ftp'])) { loadClassFile('Class-Package.php'); $ftp = new ftp_connection(null); list($username, $detect_path, $found_path) = $ftp->detect_path($boarddir); $context['package_ftp'] = array('server' => isset($modSettings['package_server']) ? $modSettings['package_server'] : 'localhost', 'port' => isset($modSettings['package_port']) ? $modSettings['package_port'] : '21', 'username' => empty($username) ? isset($modSettings['package_username']) ? $modSettings['package_username'] : '' : $username, 'path' => $detect_path, 'form_elements_only' => true); } else { $context['ftp_connected'] = true; } // Define the template. $context['page_title'] = $txt['package_file_perms']; $context['sub_template'] = 'file_permissions'; // Define what files we're interested in, as a tree. $context['file_tree'] = array(strtr($boarddir, array('\\' => '/')) => array('type' => 'dir', 'contents' => array('agreement.txt' => array('type' => 'file', 'writable_on' => 'standard'), 'Settings.php' => array('type' => 'file', 'writable_on' => 'restrictive'), 'Settings_bak.php' => array('type' => 'file', 'writable_on' => 'restrictive'), 'attachments' => array('type' => 'dir', 'writable_on' => 'restrictive'), 'avatars' => array('type' => 'dir', 'writable_on' => 'standard'), 'cache' => array('type' => 'dir', 'writable_on' => 'restrictive'), 'custom_avatar_dir' => array('type' => 'dir', 'writable_on' => 'restrictive'), 'Smileys' => array('type' => 'dir_recursive', 'writable_on' => 'standard'), 'Sources' => array('type' => 'dir', 'list_contents' => true, 'writable_on' => 'standard'), 'Themes' => array('type' => 'dir_recursive', 'writable_on' => 'standard', 'contents' => array('default' => array('type' => 'dir_recursive', 'list_contents' => true, 'contents' => array('languages' => array('type' => 'dir', 'list_contents' => true))))), 'Packages' => array('type' => 'dir', 'writable_on' => 'standard', 'contents' => array('temp' => array('type' => 'dir'), 'backup' => array('type' => 'dir'), 'installed.list' => array('type' => 'file', 'writable_on' => 'standard')))))); // Directories that can move. if (substr($sourcedir, 0, strlen($boarddir)) != $boarddir) { unset($context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['Sources']); $context['file_tree'][strtr($sourcedir, array('\\' => '/'))] = array('type' => 'dir', 'list_contents' => true, 'writable_on' => 'standard'); } // Moved the cache? if (substr($cachedir, 0, strlen($boarddir)) != $boarddir) { unset($context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['cache']); $context['file_tree'][strtr($cachedir, array('\\' => '/'))] = array('type' => 'dir', 'list_contents' => false, 'writable_on' => 'restrictive'); } // Are we using multiple attachment directories? if (!empty($modSettings['currentAttachmentUploadDir'])) { unset($context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['attachments']); if (!is_array($modSettings['attachmentUploadDir'])) { $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']); } // !!! Should we suggest non-current directories be read only? foreach ($modSettings['attachmentUploadDir'] as $dir) { $context['file_tree'][strtr($dir, array('\\' => '/'))] = array('type' => 'dir', 'writable_on' => 'restrictive'); } } elseif (substr($modSettings['attachmentUploadDir'], 0, strlen($boarddir)) != $boarddir) { unset($context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['attachments']); $context['file_tree'][strtr($modSettings['attachmentUploadDir'], array('\\' => '/'))] = array('type' => 'dir', 'writable_on' => 'restrictive'); } if (substr($modSettings['smileys_dir'], 0, strlen($boarddir)) != $boarddir) { unset($context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['Smileys']); $context['file_tree'][strtr($modSettings['smileys_dir'], array('\\' => '/'))] = array('type' => 'dir_recursive', 'writable_on' => 'standard'); } if (substr($modSettings['avatar_directory'], 0, strlen($boarddir)) != $boarddir) { unset($context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['avatars']); $context['file_tree'][strtr($modSettings['avatar_directory'], array('\\' => '/'))] = array('type' => 'dir', 'writable_on' => 'standard'); } if (isset($modSettings['custom_avatar_dir']) && substr($modSettings['custom_avatar_dir'], 0, strlen($boarddir)) != $boarddir) { unset($context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['custom_avatar_dir']); $context['file_tree'][strtr($modSettings['custom_avatar_dir'], array('\\' => '/'))] = array('type' => 'dir', 'writable_on' => 'restrictive'); } // Load up any custom themes. $request = smf_db_query(' SELECT value FROM {db_prefix}themes WHERE id_theme > {int:default_theme_id} AND id_member = {int:guest_id} AND variable = {string:theme_dir} ORDER BY value ASC', array('default_theme_id' => 1, 'guest_id' => 0, 'theme_dir' => 'theme_dir')); while ($row = mysql_fetch_assoc($request)) { if (substr(strtolower(strtr($row['value'], array('\\' => '/'))), 0, strlen($boarddir) + 7) == strtolower(strtr($boarddir, array('\\' => '/')) . '/Themes')) { $context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['Themes']['contents'][substr($row['value'], strlen($boarddir) + 8)] = array('type' => 'dir_recursive', 'list_contents' => true, 'contents' => array('languages' => array('type' => 'dir', 'list_contents' => true))); } else { $context['file_tree'][strtr($row['value'], array('\\' => '/'))] = array('type' => 'dir_recursive', 'list_contents' => true, 'contents' => array('languages' => array('type' => 'dir', 'list_contents' => true))); } } mysql_free_result($request); // If we're submitting then let's move on to another function to keep things cleaner.. if (isset($_POST['action_changes'])) { return PackagePermissionsAction(); } $context['look_for'] = array(); // Are we looking for a particular tree - normally an expansion? if (!empty($_REQUEST['find'])) { $context['look_for'][] = base64_decode($_REQUEST['find']); } // Only that tree? $context['only_find'] = isset($_GET['xml']) && !empty($_REQUEST['onlyfind']) ? $_REQUEST['onlyfind'] : ''; if ($context['only_find']) { $context['look_for'][] = $context['only_find']; } // Have we got a load of back-catalogue trees to expand from a submit etc? if (!empty($_GET['back_look'])) { $potententialTrees = unserialize(base64_decode($_GET['back_look'])); foreach ($potententialTrees as $tree) { $context['look_for'][] = $tree; } } // ... maybe posted? if (!empty($_POST['back_look'])) { $context['only_find'] = array_merge($context['only_find'], $_POST['back_look']); } $context['back_look_data'] = base64_encode(serialize(array_slice($context['look_for'], 0, 15))); // Are we finding more files than first thought? $context['file_offset'] = !empty($_REQUEST['fileoffset']) ? (int) $_REQUEST['fileoffset'] : 0; // Don't list more than this many files in a directory. $context['file_limit'] = 150; // How many levels shall we show? $context['default_level'] = empty($context['only_find']) ? 2 : 25; // This will be used if we end up catching XML data. $context['xml_data'] = array('roots' => array('identifier' => 'root', 'children' => array(array('value' => preg_replace('~[^A-Za-z0-9_\\-=:]~', ':-:', $context['only_find'])))), 'folders' => array('identifier' => 'folder', 'children' => array())); foreach ($context['file_tree'] as $path => $data) { // Run this directory. if (file_exists($path) && (empty($context['only_find']) || substr($context['only_find'], 0, strlen($path)) == $path)) { // Get the first level down only. fetchPerms__recursive($path, $context['file_tree'][$path], 1); $context['file_tree'][$path]['perms'] = array('chmod' => @is_writable($path), 'perms' => @fileperms($path)); } else { unset($context['file_tree'][$path]); } } // Is this actually xml? if (isset($_GET['xml'])) { loadTemplate('Xml'); $context['sub_template'] = 'generic_xml'; $context['template_layers'] = array(); } }
function AdminSearchOM() { global $context, $sourcedir; $docsURL = 'docs.simplemachines.org'; $context['doc_scripturl'] = 'http://docs.simplemachines.org/index.php'; // Set all the parameters search might expect. $postVars = array('search' => $context['search_term']); // Encode the search data. foreach ($postVars as $k => $v) { $postVars[$k] = urlencode($k) . '=' . urlencode($v); } // This is what we will send. $postVars = implode('&', $postVars); // Get the results from the doc site. require_once $sourcedir . '/lib/Subs-Package.php'; $search_results = fetch_web_data($context['doc_scripturl'] . '?action=search2&xml', $postVars); // If we didn't get any xml back we are in trouble - perhaps the doc site is overloaded? if (!$search_results || preg_match('~<' . '\\?xml\\sversion="\\d+\\.\\d+"\\sencoding=".+?"\\?' . '>\\s*(<smf>.+?</smf>)~is', $search_results, $matches) != true) { fatal_lang_error('cannot_connect_doc_site'); } $search_results = $matches[1]; // Otherwise we simply walk through the XML and stick it in context for display. $context['search_results'] = array(); loadClassFile('Class-Package.php'); // Get the results loaded into an array for processing! $results = new xmlArray($search_results, false); // Move through the smf layer. if (!$results->exists('smf')) { fatal_lang_error('cannot_connect_doc_site'); } $results = $results->path('smf[0]'); // Are there actually some results? if (!$results->exists('noresults') && !$results->exists('results')) { fatal_lang_error('cannot_connect_doc_site'); } elseif ($results->exists('results')) { foreach ($results->set('results/result') as $result) { if (!$result->exists('messages')) { continue; } $context['search_results'][$result->fetch('id')] = array('topic_id' => $result->fetch('id'), 'relevance' => $result->fetch('relevance'), 'board' => array('id' => $result->fetch('board/id'), 'name' => $result->fetch('board/name'), 'href' => $result->fetch('board/href')), 'category' => array('id' => $result->fetch('category/id'), 'name' => $result->fetch('category/name'), 'href' => $result->fetch('category/href')), 'messages' => array()); // Add the messages. foreach ($result->set('messages/message') as $message) { $context['search_results'][$result->fetch('id')]['messages'][] = array('id' => $message->fetch('id'), 'subject' => $message->fetch('subject'), 'body' => $message->fetch('body'), 'time' => $message->fetch('time'), 'timestamp' => $message->fetch('timestamp'), 'start' => $message->fetch('start'), 'author' => array('id' => $message->fetch('author/id'), 'name' => $message->fetch('author/name'), 'href' => $message->fetch('author/href'))); } } } }
function loadPaymentGateways() { global $sourcedir; $gateways = array(); if ($dh = opendir($sourcedir)) { while (($file = readdir($dh)) !== false) { if (is_file($sourcedir . '/' . $file) && preg_match('~^Subscriptions-([A-Za-z\\d]+)\\.php$~', $file, $matches)) { // Check this is definitely a valid gateway! $fp = fopen($sourcedir . '/' . $file, 'rb'); $header = fread($fp, 4096); fclose($fp); if (strpos($header, '// SMF Payment Gateway: ' . strtolower($matches[1])) !== false) { loadClassFile($file); $gateways[] = array('filename' => $file, 'code' => strtolower($matches[1]), 'valid_version' => class_exists(strtolower($matches[1]) . '_payment') && class_exists(strtolower($matches[1]) . '_display'), 'payment_class' => strtolower($matches[1]) . '_payment', 'display_class' => strtolower($matches[1]) . '_display'); } } } } closedir($dh); return $gateways; }
function MaintenanceGameCache() { global $db_prefix, $modSettings, $smcFunc, $context; loadClassFile('Class-Package.php'); updateGameCache(); }
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('"' => '"')); $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'][] = '"' . $smcFunc['htmlspecialchars']($word) . '"'; 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'][] = '-"' . $smcFunc['htmlspecialchars']($word) . '"'; } 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']))); }
function loadSearchAPIs() { global $sourcedir, $txt; $apis = array(); if ($dh = opendir($sourcedir)) { while (($file = readdir($dh)) !== false) { if (is_file($sourcedir . '/' . $file) && preg_match('~SearchAPI-([A-Za-z\\d_]+)\\.php~', $file, $matches)) { // Check this is definitely a valid API! $fp = fopen($sourcedir . '/' . $file, 'rb'); $header = fread($fp, 4096); fclose($fp); if (strpos($header, '* SearchAPI-' . $matches[1] . '.php') !== false) { loadClassFile($file); $index_name = strtolower($matches[1]); $search_class_name = $index_name . '_search'; $searchAPI = new $search_class_name(); // No Support? NEXT! if (!$searchAPI->is_supported) { continue; } $apis[$index_name] = array('filename' => $file, 'setting_index' => $index_name, 'has_template' => in_array($index_name, array('custom', 'fulltext', 'standard')), 'label' => $index_name && isset($txt['search_index_' . $index_name]) ? $txt['search_index_' . $index_name] : '', 'desc' => $index_name && isset($txt['search_index_' . $index_name . '_desc']) ? $txt['search_index_' . $index_name . '_desc'] : ''); } } } } closedir($dh); return $apis; }
function updateGameCache() { global $scripturl, $txt, $db_prefix, $modSettings, $context, $sourcedir, $smcFunc, $boarddir; // Clear entries $smcFunc['db_query']('truncate_table', ' TRUNCATE {db_prefix}arcade_files'); require_once $sourcedir . '/Subs-Package.php'; loadClassFile('Class-Package.php'); // Try to get more memory @ini_set('memory_limit', '128M'); // Do actual update gameCacheInsertGames(getAvailableGames()); updateSettings(array('arcadeDBUpdate' => time())); }
/** * */ public static function loadArcade($mode = 'normal', $index = '') { global $db_prefix, $scripturl, $txt, $modSettings, $context, $settings, $sourcedir, $user_info; global $smcFunc, $boarddir; static $loaded = false; if (!empty($loaded)) { return; } spl_autoload_register(array('SMFArcade', 'autoload')); $loaded = true; $context['arcade'] = array(); require_once $sourcedir . '/Subs-Arcade.php'; // Load language loadLanguage('Arcade'); // Permission query arcadePermissionQuery(); // Normal mode if ($mode == 'normal' || $mode == 'arena') { if (empty($modSettings['arcadeEnabled'])) { return false; } loadTemplate('Arcade', array('forum', 'arcade')); $user_info['arcade_settings'] = loadArcadeSettings($user_info['id']); $context['games_per_page'] = !empty($user_info['arcade_settings']['gamesPerPage']) ? $user_info['arcade_settings']['gamesPerPage'] : $modSettings['gamesPerPage']; $context['scores_per_page'] = !empty($user_info['arcade_settings']['scoresPerPage']) ? $user_info['arcade_settings']['scoresPerPage'] : $modSettings['scoresPerPage']; if (!empty($modSettings['arcadeSkipJquery'])) { $context['html_headers'] .= '<script language="JavaScript" type="text/javascript" src="' . $settings['default_theme_url'] . '/scripts/arcade/jquery.js"></script>'; } // Arcade javascript $context['html_headers'] .= '<script language="JavaScript" type="text/javascript" src="' . $settings['default_theme_url'] . '/scripts/arcade/main.js"></script>'; // Add Arcade to link tree $context['linktree'][] = array('url' => $scripturl . '?action=arcade', 'name' => $txt['arcade']); // What I can do? $context['arcade']['can_play'] = allowedTo('arcade_play'); $context['arcade']['can_favorite'] = !empty($modSettings['arcadeEnableFavorites']) && !$user_info['is_guest']; $context['arcade']['can_rate'] = !empty($modSettings['arcadeEnableRatings']) && !$user_info['is_guest']; $context['arcade']['can_submit'] = allowedTo('arcade_submit'); $context['arcade']['can_comment_own'] = allowedTo('arcade_comment_own'); $context['arcade']['can_comment_any'] = allowedTo('arcade_comment_any'); $context['arcade']['can_admin_arcade'] = allowedTo('arcade_admin'); $context['arcade']['can_create_match'] = allowedTo('arcade_create_match'); $context['arcade']['can_join_match'] = allowedTo('arcade_join_match'); // Or can I (do I have enought posts etc.) PostPermissionCheck(); // Finally load Arcade Settings LoadArcadeSettings(); if (!isset($_REQUEST['xml'])) { $context['template_layers'][] = 'Arcade'; } } elseif ($mode == 'profile') { loadTemplate('ArcadeProfile', array('arcade', 'forum')); } elseif ($mode == 'admin') { loadTemplate('ArcadeAdmin'); loadLanguage('ArcadeAdmin'); $context['html_headers'] .= ' <script language="JavaScript" type="text/javascript" src="' . $settings['default_theme_url'] . '/scripts/arcade.js"></script>'; // Update games database? if (file_exists($boarddir . '/Games.xml')) { loadClassFile('Class-Package.php'); $games = new xmlArray(file_get_contents($boarddir . '/Games.xml')); $database = $games->path('smf/database'); $database = $database->to_array(); $xmlGames = $games->set('smf/game'); if (!empty($modSettings['arcadeGameDatabaseVersion']) && $modSettings['arcadeGameDatabaseVersion'] > $database['version']) { break; } $games = array(); foreach ($xmlGames as $game) { $games[] = array($game->fetch('id'), $game->fetch('name'), $game->fetch('description'), $game->fetch('url/info'), $game->fetch('url/download')); } $smcFunc['db_insert']('replace', '{db_prefix}arcade_game_info', array('internal_name' => 'string', 'game_name' => 'string', 'description' => 'string', 'info_url' => 'string', 'download_url' => 'string'), $games, array('internal_name')); updateSettings(array('arcadeGameDatabaseVersion' => $database['version'], 'arcadeGameDatabaseUpdate' => $database['update'])); @unlink($boarddir . '/Games.xml'); } $context['template_layers'][] = 'ArcadeAdmin'; $context['page_title'] = $txt['arcade_admin_title']; } }
function initRelated() { global $context, $modSettings; // Already initialized? if (isset($context['relatedClass'])) { return true; } $context['rt_ignore'] = empty($modSettings['relatedIgnoredboards']) ? array() : explode(',', $modSettings['relatedIgnoredboards']); // Recycle board should be ignored by default if (!empty($modSettings['recycle_enable']) && !empty($modSettings['recycle_board'])) { $context['rt_ignore'][] = $modSettings['recycle_board']; } // Make sure each board is only one time there $context['rt_ignore'] = array_unique($context['rt_ignore']); // No methods selected? No need to do this then if (empty($modSettings['relatedIndex'])) { return false; } $context['relatedClass'] = array(); $relatedIndexes = explode(',', $modSettings['relatedIndex']); foreach ($relatedIndexes as $indexType) { $indexType = ucwords($modSettings['relatedIndex']); $class = 'RelatedTopics' . $indexType; loadClassFile('Subs-Related' . $indexType . '.php'); $context['relatedClass'][] = new $class(); } if (empty($context['relatedClass'])) { return false; } return true; }