/** * Finds or repairs errors in the database to fix possible problems. * Requires the admin_forum permission. * Calls createSalvageArea() to create a new board, if necesary. * Accessed by ?action=admin;area=repairboards. * * @uses raw_data sub-template. */ function RepairBoards() { global $txt, $context, $sourcedir, $salvageBoardID; isAllowedTo('admin_forum'); // Try secure more memory. setMemoryLimit('128M'); // Print out the top of the webpage. $context['page_title'] = $txt['admin_repair']; $context['sub_template'] = 'repair_boards'; $context[$context['admin_menu_name']]['current_subsection'] = 'general'; // Load the language file. loadLanguage('ManageMaintenance'); // Make sure the tabs stay nice. $context[$context['admin_menu_name']]['tab_data'] = array('title' => $txt['maintain_title'], 'help' => '', 'description' => $txt['maintain_info'], 'tabs' => array()); // Start displaying errors without fixing them. if (isset($_GET['fixErrors'])) { checkSession('get'); } // Will want this. loadForumTests(); // Giant if/else. The first displays the forum errors if a variable is not set and asks // if you would like to continue, the other fixes the errors. if (!isset($_GET['fixErrors'])) { $context['error_search'] = true; $context['repair_errors'] = array(); $context['to_fix'] = findForumErrors(); if (!empty($context['to_fix'])) { $_SESSION['repairboards_to_fix'] = $context['to_fix']; $_SESSION['repairboards_to_fix2'] = null; if (empty($context['repair_errors'])) { $context['repair_errors'][] = '???'; } } } else { $context['error_search'] = false; $context['to_fix'] = isset($_SESSION['repairboards_to_fix']) ? $_SESSION['repairboards_to_fix'] : array(); require_once $sourcedir . '/Subs-Boards.php'; // Actually do the fix. findForumErrors(true); // Note that we've changed everything possible ;) updateSettings(array('settings_updated' => time())); updateStats('message'); updateStats('topic'); updateSettings(array('calendar_updated' => time())); if (!empty($salvageBoardID)) { $context['redirect_to_recount'] = true; } $_SESSION['repairboards_to_fix'] = null; $_SESSION['repairboards_to_fix2'] = null; } }
/** * Point d'entr�e de l'application * */ function init() { $c =& PmvConfig::getInstance(); $Lang =& Lang::getInstance(); // id used for caching define('SMARTY_CACHE_ID', md5(@$_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'] . serialize($_GET) . serialize($_POST) . (isset($_COOKIE[COOKIE_NAME_SESSION]) ? serialize($_COOKIE[COOKIE_NAME_SESSION]) : '') . $Lang->getFileName() . date("Y-m-d") . TIME_BEFORE_NEW_DAY_ARCHIVE . PHPMV_VERSION . INTERNAL_STATS)); setIncludePath(); $db =& Db::getInstance(); if (defined('DB_HOST')) { $db->connect(); } // try to set memory limit to MEMORY_LIMIT setMemoryLimit(); $controller =& ApplicationController::getInstance(); $controller->loadLang(); $controller->parseRequest(); $controller->loadModule(); $controller->executeAction(); }
/** * Constructor for the xml parser. * Example use: * $xml = new xmlArray(file('data.xml')); * @param string $data the xml data or an array of, unless is_clone is true. * @param bool $auto_trim, default false, used to automatically trim textual data. * @param int $level, default null, the debug level, specifies whether notices * should be generated for missing elements and attributes. * @param bool $is_clone, default false. If is_clone is true, the * xmlArray is cloned from another - used internally only. */ public function __construct($data, $auto_trim = false, $level = null, $is_clone = false) { // If we're using this try to get some more memory. setMemoryLimit('32M'); // Set the debug level. $this->debug_level = $level !== null ? $level : error_reporting(); $this->trim = $auto_trim; // Is the data already parsed? if ($is_clone) { $this->array = $data; return; } // Is the input an array? (ie. passed from file()?) if (is_array($data)) { $data = implode('', $data); } // Remove any xml declaration or doctype, and parse out comments and CDATA. $data = preg_replace('/<!--.*?-->/s', '', $this->_to_cdata(preg_replace(array('/^<\\?xml.+?\\?' . '>/is', '/<!DOCTYPE[^>]+?' . '>/s'), '', $data))); // Now parse the xml! $this->array = $this->_parse($data); }
/** * A complicated but relatively quick internal search. */ function AdminSearchInternal() { global $context, $txt, $helptxt, $scripturl, $sourcedir; // Try to get some more memory. setMemoryLimit('128M'); // Load a lot of language files. $language_files = array('Help', 'ManageMail', 'ManageSettings', 'ManageCalendar', 'ManageBoards', 'ManagePaid', 'ManagePermissions', 'Search', 'Login', 'ManageSmileys'); // All the files we need to include. $include_files = array('ManageSettings', 'ManageBoards', 'ManageNews', 'ManageAttachments', 'ManageCalendar', 'ManageMail', 'ManagePaid', 'ManagePermissions', 'ManagePosts', 'ManageRegistration', 'ManageSearch', 'ManageSearchEngines', 'ManageServer', 'ManageSmileys', 'ManageLanguages'); // This is a special array of functions that contain setting data - we query all these to simply pull all setting bits! $settings_search = array(array('ModifyCoreFeatures', 'area=corefeatures'), array('ModifyBasicSettings', 'area=featuresettings;sa=basic'), array('ModifyLayoutSettings', 'area=featuresettings;sa=layout'), array('ModifyKarmaSettings', 'area=featuresettings;sa=karma'), array('ModifySignatureSettings', 'area=featuresettings;sa=sig'), array('ModifyGeneralSecuritySettings', 'area=securitysettings;sa=general'), array('ModifySpamSettings', 'area=securitysettings;sa=spam'), array('ModifyModerationSettings', 'area=securitysettings;sa=moderation'), array('ModifyGeneralModSettings', 'area=modsettings;sa=general'), array('ManageAttachmentSettings', 'area=manageattachments;sa=attachments'), array('ManageAvatarSettings', 'area=manageattachments;sa=avatars'), array('ModifyCalendarSettings', 'area=managecalendar;sa=settings'), array('EditBoardSettings', 'area=manageboards;sa=settings'), array('ModifyMailSettings', 'area=mailqueue;sa=settings'), array('ModifyNewsSettings', 'area=news;sa=settings'), array('GeneralPermissionSettings', 'area=permissions;sa=settings'), array('ModifyPostSettings', 'area=postsettings;sa=posts'), array('ModifyBBCSettings', 'area=postsettings;sa=bbc'), array('ModifyTopicSettings', 'area=postsettings;sa=topics'), array('EditSearchSettings', 'area=managesearch;sa=settings'), array('EditSmileySettings', 'area=smileys;sa=settings'), array('ModifyGeneralSettings', 'area=serversettings;sa=general'), array('ModifyDatabaseSettings', 'area=serversettings;sa=database'), array('ModifyCookieSettings', 'area=serversettings;sa=cookie'), array('ModifyCacheSettings', 'area=serversettings;sa=cache'), array('ModifyLanguageSettings', 'area=languages;sa=settings'), array('ModifyRegistrationSettings', 'area=regcenter;sa=settings'), array('ManageSearchEngineSettings', 'area=sengines;sa=settings'), array('ModifySubscriptionSettings', 'area=paidsubscribe;sa=settings'), array('ModifyPruningSettings', 'area=logs;sa=pruning')); call_integration_hook('integrate_admin_search', array(&$language_files, &$include_files, &$settings_search)); loadLanguage(implode('+', $language_files)); foreach ($include_files as $file) { require_once $sourcedir . '/' . $file . '.php'; } /* This is the huge array that defines everything... it's a huge array of items formatted as follows: 0 = Language index (Can be array of indexes) to search through for this setting. 1 = URL for this indexes page. 2 = Help index for help associated with this item (If different from 0) */ $search_data = array('sections' => array(), 'settings' => array(array('COPPA', 'area=regcenter;sa=settings'), array('CAPTCHA', 'area=securitysettings;sa=spam'))); // Go through the admin menu structure trying to find suitably named areas! foreach ($context[$context['admin_menu_name']]['sections'] as $section) { foreach ($section['areas'] as $menu_key => $menu_item) { $search_data['sections'][] = array($menu_item['label'], 'area=' . $menu_key); if (!empty($menu_item['subsections'])) { foreach ($menu_item['subsections'] as $key => $sublabel) { if (isset($sublabel['label'])) { $search_data['sections'][] = array($sublabel['label'], 'area=' . $menu_key . ';sa=' . $key); } } } } } foreach ($settings_search as $setting_area) { // Get a list of their variables. $config_vars = $setting_area[0](true); foreach ($config_vars as $var) { if (!empty($var[1]) && !in_array($var[0], array('permissions', 'switch'))) { $search_data['settings'][] = array($var[isset($var[2]) && in_array($var[2], array('file', 'db')) ? 0 : 1], $setting_area[1]); } } } $context['page_title'] = $txt['admin_search_results']; $context['search_results'] = array(); $search_term = strtolower(un_htmlspecialchars($context['search_term'])); // Go through all the search data trying to find this text! foreach ($search_data as $section => $data) { foreach ($data as $item) { $found = false; if (!is_array($item[0])) { $item[0] = array($item[0]); } foreach ($item[0] as $term) { if (stripos($term, $search_term) !== false || isset($txt[$term]) && stripos($txt[$term], $search_term) !== false || isset($txt['setting_' . $term]) && stripos($txt['setting_' . $term], $search_term) !== false) { $found = $term; break; } } if ($found) { // Format the name - and remove any descriptions the entry may have. $name = isset($txt[$found]) ? $txt[$found] : (isset($txt['setting_' . $found]) ? $txt['setting_' . $found] : $found); $name = preg_replace('~<(?:div|span)\\sclass="smalltext">.+?</(?:div|span)>~', '', $name); $context['search_results'][] = array('url' => (substr($item[1], 0, 4) == 'area' ? $scripturl . '?action=admin;' . $item[1] : $item[1]) . ';' . $context['session_var'] . '=' . $context['session_id'] . (substr($item[1], 0, 4) == 'area' && $section == 'settings' ? '#' . $item[0][0] : ''), 'name' => $name, 'type' => $section, 'help' => shorten_subject(isset($item[2]) ? strip_tags($helptxt[$item[2]]) : (isset($helptxt[$found]) ? strip_tags($helptxt[$found]) : ''), 255)); } } } }
/** * Get admin information from the database. * Accessed by ?action=viewadminfile. */ public function action_viewadminfile() { global $modSettings; require_once SUBSDIR . '/AdminDebug.subs.php'; // Don't allow non-administrators. isAllowedTo('admin_forum'); setMemoryLimit('128M'); if (empty($_REQUEST['filename']) || !is_string($_REQUEST['filename'])) { fatal_lang_error('no_access', false); } $file = adminInfoFile($_REQUEST['filename']); // @todo Temp // Figure out if sesc is still being used. if (strpos($file['file_data'], ';sesc=') !== false) { $file['file_data'] = ' if (!(\'elkForum_sessionvar\' in window)) window.elkForum_sessionvar = \'sesc\'; ' . strtr($file['file_data'], array(';sesc=' => ';\' + window.elkForum_sessionvar + \'=')); } Template_Layers::getInstance()->removeAll(); // Lets make sure we aren't going to output anything nasty. @ob_end_clean(); if (!empty($modSettings['enableCompressedOutput'])) { ob_start('ob_gzhandler'); } else { ob_start(); } // Make sure they know what type of file we are. header('Content-Type: ' . $file['filetype']); echo $file['file_data']; obExit(false); }
/** * A complicated but relatively quick internal search. */ public function action_search_internal() { global $context, $txt, $helptxt, $scripturl; // Try to get some more memory. setMemoryLimit('128M'); // Load a lot of language files. $language_files = array('Help', 'ManageMail', 'ManageSettings', 'ManageCalendar', 'ManageBoards', 'ManagePaid', 'ManagePermissions', 'Search', 'Login', 'ManageSmileys', 'Maillist'); // All the files we need to include. $include_files = array('AddonSettings.controller', 'AdminLog.controller', 'CoreFeatures.controller', 'ManageAttachments.controller', 'ManageAvatars.controller', 'ManageBBC.controller', 'ManageBoards.controller', 'ManageCalendar.controller', 'ManageDrafts.controller', 'ManageFeatures.controller', 'ManageLanguages.controller', 'ManageMail.controller', 'ManageNews.controller', 'ManagePaid.controller', 'ManagePermissions.controller', 'ManagePosts.controller', 'ManageRegistration.controller', 'ManageSearch.controller', 'ManageSearchEngines.controller', 'ManageSecurity.controller', 'ManageServer.controller', 'ManageSmileys.controller', 'ManageTopics.controller', 'ManageMaillist.controller', 'ManageMembergroups.controller'); // This is a special array of functions that contain setting data // - we query all these to simply pull all setting bits! $settings_search = array(array('settings_search', 'area=logs;sa=pruning', 'AdminLog_Controller'), array('config_vars', 'area=corefeatures', 'CoreFeatures_Controller'), array('basicSettings_search', 'area=featuresettings;sa=basic', 'ManageFeatures_Controller'), array('layoutSettings_search', 'area=featuresettings;sa=layout', 'ManageFeatures_Controller'), array('karmaSettings_search', 'area=featuresettings;sa=karma', 'ManageFeatures_Controller'), array('likesSettings_search', 'area=featuresettings;sa=likes', 'ManageFeatures_Controller'), array('mentionSettings_search', 'area=featuresettings;sa=mention', 'ManageFeatures_Controller'), array('signatureSettings_search', 'area=featuresettings;sa=sig', 'ManageFeatures_Controller'), array('settings_search', 'area=addonsettings;sa=general', 'AddonSettings_Controller'), array('settings_search', 'area=manageattachments;sa=attachments', 'ManageAttachments_Controller'), array('settings_search', 'area=manageattachments;sa=avatars', 'ManageAvatars_Controller'), array('settings_search', 'area=postsettings;sa=bbc', 'ManageBBC_Controller'), array('settings_search', 'area=manageboards;sa=settings', 'ManageBoards_Controller'), array('settings_search', 'area=managecalendar;sa=settings', 'ManageCalendar_Controller'), array('settings_search', 'area=managedrafts', 'ManageDrafts_Controller'), array('settings_search', 'area=languages;sa=settings', 'ManageLanguages_Controller'), array('settings_search', 'area=mailqueue;sa=settings', 'ManageMail_Controller'), array('settings_search', 'area=maillist;sa=emailsettings', 'ManageMaillist_Controller'), array('settings_search', 'area=membergroups;sa=settings', 'ManageMembergroups_Controller'), array('settings_search', 'area=news;sa=settings', 'ManageNews_Controller'), array('settings_search', 'area=paidsubscribe;sa=settings', 'ManagePaid_Controller'), array('settings_search', 'area=permissions;sa=settings', 'ManagePermissions_Controller'), array('settings_search', 'area=postsettings;sa=posts', 'ManagePosts_Controller'), array('settings_search', 'area=regcenter;sa=settings', 'ManageRegistration_Controller'), array('settings_search', 'area=managesearch;sa=settings', 'ManageSearch_Controller'), array('settings_search', 'area=sengines;sa=settings', 'ManageSearchEngines_Controller'), array('securitySettings_search', 'area=securitysettings;sa=general', 'ManageSecurity_Controller'), array('spamSettings_search', 'area=securitysettings;sa=spam', 'ManageSecurity_Controller'), array('moderationSettings_search', 'area=securitysettings;sa=moderation', 'ManageSecurity_Controller'), array('bbSettings_search', 'area=securitysettings;sa=badbehavior', 'ManageSecurity_Controller'), array('generalSettings_search', 'area=serversettings;sa=general', 'ManageServer_Controller'), array('databaseSettings_search', 'area=serversettings;sa=database', 'ManageServer_Controller'), array('cookieSettings_search', 'area=serversettings;sa=cookie', 'ManageServer_Controller'), array('cacheSettings_search', 'area=serversettings;sa=cache', 'ManageServer_Controller'), array('balancingSettings_search', 'area=serversettings;sa=loads', 'ManageServer_Controller'), array('settings_search', 'area=smileys;sa=settings', 'ManageSmileys_Controller'), array('settings_search', 'area=postsettings;sa=topics', 'ManageTopics_Controller')); call_integration_hook('integrate_admin_search', array(&$language_files, &$include_files, &$settings_search)); loadLanguage(implode('+', $language_files)); foreach ($include_files as $file) { require_once ADMINDIR . '/' . $file . '.php'; } /* This is the huge array that defines everything ... it's items are formatted as follows: 0 = Language index (Can be array of indexes) to search through for this setting. 1 = URL for this indexes page. 2 = Help index for help associated with this item (If different from 0) */ $search_data = array('sections' => array(), 'settings' => array(array('COPPA', 'area=regcenter;sa=settings'), array('CAPTCHA', 'area=securitysettings;sa=spam'))); // Go through the admin menu structure trying to find suitably named areas! foreach ($context[$context['admin_menu_name']]['sections'] as $section) { foreach ($section['areas'] as $menu_key => $menu_item) { $search_data['sections'][] = array($menu_item['label'], 'area=' . $menu_key); if (!empty($menu_item['subsections'])) { foreach ($menu_item['subsections'] as $key => $sublabel) { if (isset($sublabel['label'])) { $search_data['sections'][] = array($sublabel['label'], 'area=' . $menu_key . ';sa=' . $key); } } } } } foreach ($settings_search as $setting_area) { // Get a list of their variables. if (isset($setting_area[2])) { // an OOP controller: get the settings from the settings method. $controller = new $setting_area[2](); $config_vars = $controller->{$setting_area[0]}(); } else { // a good ole' procedural controller: get the settings from the function. $config_vars = $setting_area[0](true); } foreach ($config_vars as $var) { if (!empty($var[1]) && !in_array($var[0], array('permissions', 'switch', 'warning'))) { $search_data['settings'][] = array($var[isset($var[2]) && in_array($var[2], array('file', 'db')) ? 0 : 1], $setting_area[1]); } } } $context['page_title'] = $txt['admin_search_results']; $context['search_results'] = array(); // Go through all the search data trying to find this text! $search_term = strtolower(un_htmlspecialchars($context['search_term'])); foreach ($search_data as $section => $data) { foreach ($data as $item) { $found = false; if (!is_array($item[0])) { $item[0] = array($item[0]); } foreach ($item[0] as $term) { if (stripos($term, $search_term) !== false || isset($txt[$term]) && stripos($txt[$term], $search_term) !== false || isset($txt['setting_' . $term]) && stripos($txt['setting_' . $term], $search_term) !== false) { $found = $term; break; } } if ($found) { // Format the name - and remove any descriptions the entry may have. $name = isset($txt[$found]) ? $txt[$found] : (isset($txt['setting_' . $found]) ? $txt['setting_' . $found] : $found); $name = preg_replace('~<(?:div|span)\\sclass="smalltext">.+?</(?:div|span)>~', '', $name); if (!empty($name)) { $context['search_results'][] = array('url' => (substr($item[1], 0, 4) == 'area' ? $scripturl . '?action=admin;' . $item[1] : $item[1]) . ';' . $context['session_var'] . '=' . $context['session_id'] . (substr($item[1], 0, 4) == 'area' && $section == 'settings' ? '#' . $item[0][0] : ''), 'name' => $name, 'type' => $section, 'help' => Util::shorten_text(isset($item[2]) ? strip_tags($helptxt[$item[2]]) : (isset($helptxt[$found]) ? strip_tags($helptxt[$found]) : ''), 255)); } } } } }
/** * Dumps the database. * * What it does: * - It writes all of the database to standard output. * - It uses gzip compression if compress is set in the URL/post data. * - It may possibly time out, and mess up badly if you were relying on it. :P * - The data dumped depends on whether "struct" and "data" are passed. * - It is called from ManageMaintenance.controller.php. */ function DumpDatabase2() { global $db_name, $scripturl, $modSettings, $db_prefix, $db_show_debug; // We'll need a db to dump :P $database = database(); // We don't need debug when dumping the database $modSettings['disableQueryCheck'] = true; $db_show_debug = false; // You can't dump nothing! if (!isset($_REQUEST['struct']) && !isset($_REQUEST['data'])) { $_REQUEST['data'] = true; } // Attempt to stop from dying... @set_time_limit(600); $time_limit = ini_get('max_execution_time'); $start_time = time(); // @todo ... fail on not getting the requested memory? setMemoryLimit('256M'); $memory_limit = memoryReturnBytes(ini_get('memory_limit')) / 4; $current_used_memory = 0; $db_backup = ''; $output_function = 'un_compressed'; @ob_end_clean(); // Start saving the output... (don't do it otherwise for memory reasons.) if (isset($_REQUEST['compress']) && function_exists('gzencode')) { $output_function = 'gzencode'; // Send faked headers so it will just save the compressed output as a gzip. header('Content-Type: application/x-gzip'); header('Accept-Ranges: bytes'); header('Content-Encoding: none'); // Gecko browsers... don't like this. (Mozilla, Firefox, etc.) if (!isBrowser('gecko')) { header('Content-Transfer-Encoding: binary'); } // The file extension will include .gz... $extension = '.sql.gz'; } else { // Get rid of the gzipping alreading being done. if (!empty($modSettings['enableCompressedOutput'])) { @ob_end_clean(); } elseif (ob_get_length() != 0) { ob_clean(); } // Tell the client to save this file, even though it's text. header('Content-Type: ' . (isBrowser('ie') || isBrowser('opera') ? 'application/octetstream' : 'application/octet-stream')); header('Content-Encoding: none'); // This time the extension should just be .sql. $extension = '.sql'; } // This should turn off the session URL parser. $scripturl = ''; // Send the proper headers to let them download this file. header('Content-Disposition: attachment; filename="' . $db_name . '-' . (empty($_REQUEST['struct']) ? 'data' : (empty($_REQUEST['data']) ? 'structure' : 'complete')) . '_' . strftime('%Y-%m-%d') . $extension . '"'); header('Cache-Control: private'); header('Connection: close'); // This makes things simpler when using it so very very often. $crlf = "\r\n"; // SQL Dump Header. $db_chunks = '-- ==========================================================' . $crlf . '--' . $crlf . '-- Database dump of tables in `' . $db_name . '`' . $crlf . '-- ' . standardTime(time(), false) . $crlf . '--' . $crlf . '-- ==========================================================' . $crlf . $crlf; // Get all tables in the database....for our installation $real_prefix = preg_match('~^(`?)(.+?)\\1\\.(.*?)$~', $db_prefix, $match) === 1 ? $match[3] : $db_prefix; $tables = $database->db_list_tables(false, $real_prefix . '%'); // Dump each table. foreach ($tables as $tableName) { // Are we dumping the structures? if (isset($_REQUEST['struct'])) { $db_chunks .= $crlf . '--' . $crlf . '-- Table structure for table `' . $tableName . '`' . $crlf . '--' . $crlf . $crlf . $database->db_table_sql($tableName) . ';' . $crlf; } else { // This is needed to speedup things later $database->db_table_sql($tableName); } // How about the data? if (!isset($_REQUEST['data']) || substr($tableName, -10) == 'log_errors') { continue; } $first_round = true; $close_table = false; // Are there any rows in this table? while ($get_rows = $database->insert_sql($tableName, $first_round)) { if (empty($get_rows)) { break; } // Time is what we need here! if (function_exists('apache_reset_timeout')) { @apache_reset_timeout(); } elseif (!empty($time_limit) && $start_time + $time_limit - 20 > time()) { $start_time = time(); @set_time_limit(150); } // for the first pass, start the output with a custom line... if ($first_round) { $db_chunks .= $crlf . '--' . $crlf . '-- Dumping data in `' . $tableName . '`' . $crlf . '--' . $crlf . $crlf; $first_round = false; } $db_chunks .= $get_rows; $current_used_memory += Util::strlen($db_chunks); $db_backup .= $db_chunks; unset($db_chunks); $db_chunks = ''; if ($current_used_memory > $memory_limit) { echo $output_function($db_backup); $current_used_memory = 0; // This is probably redundant unset($db_backup); $db_backup = ''; } $close_table = true; } // No rows to get - skip it. if ($close_table) { $db_backup .= '-- --------------------------------------------------------' . $crlf; } } // write the last line $db_backup .= $crlf . '-- Done' . $crlf; echo $output_function($db_backup); exit; }
/** * Writes data to a file, almost exactly like the file_put_contents() function. * * - uses FTP to create/chmod the file when necessary and available. * - uses text mode for text mode file extensions. * - returns the number of bytes written. * * @package Packages * @param string $filename * @param string $data * @param bool $testing * @return int */ function package_put_contents($filename, $data, $testing = false) { global $package_ftp, $package_cache, $modSettings; static $text_filetypes = array('php', 'txt', '.js', 'css', 'vbs', 'tml', 'htm'); if (!isset($package_cache)) { // Try to increase the memory limit - we don't want to run out of ram! $mem_check = setMemoryLimit('128M'); if (!empty($modSettings['package_disable_cache']) || $mem_check || stripos(PHP_OS, 'win') !== false) { $package_cache = array(); } else { $package_cache = false; } } if (isset($package_ftp)) { $ftp_file = strtr($filename, array($_SESSION['pack_ftp']['root'] => '')); } if (!file_exists($filename) && isset($package_ftp)) { $package_ftp->create_file($ftp_file); } elseif (!file_exists($filename)) { @touch($filename); } package_chmod($filename); if (!$testing && (strpos($filename, 'packages/') !== false || $package_cache === false)) { $fp = @fopen($filename, in_array(substr($filename, -3), $text_filetypes) ? 'w' : 'wb'); // We should show an error message or attempt a rollback, no? if (!$fp) { return false; } fwrite($fp, $data); fclose($fp); } elseif (strpos($filename, 'packages/') !== false || $package_cache === false) { return strlen($data); } else { $package_cache[$filename] = $data; // Permission denied, eh? $fp = @fopen($filename, 'r+'); if (!$fp) { return false; } fclose($fp); } return strlen($data); }
/** * Supporting function for the database maintenance area. */ public function action_database() { global $context, $modSettings, $maintenance, $iknowitmaybeunsafe; // We need this, really.. require_once SUBSDIR . '/Maintenance.subs.php'; // Set up the sub-template $context['sub_template'] = 'maintain_database'; if (DB_TYPE == 'MySQL') { $body_type = fetchBodyType(); $context['convert_to'] = $body_type == 'text' ? 'mediumtext' : 'text'; $context['convert_to_suggest'] = $body_type != 'text' && !empty($modSettings['max_messageLength']) && $modSettings['max_messageLength'] < 65536; } // Check few things to give advices before make a backup // If safe mod is enable the external tool is *always* the best (and probably the only) solution $context['safe_mode_enable'] = @ini_get('safe_mode'); // This is just a...guess $messages = countMessages(); // 256 is what we use in the backup script setMemoryLimit('256M'); $memory_limit = memoryReturnBytes(ini_get('memory_limit')) / (1024 * 1024); // Zip limit is set to more or less 1/4th the size of the available memory * 1500 // 1500 is an estimate of the number of messages that generates a database of 1 MB (yeah I know IT'S AN ESTIMATION!!!) // Why that? Because the only reliable zip package is the one sent out the first time, // so when the backup takes 1/5th (just to stay on the safe side) of the memory available $zip_limit = $memory_limit * 1500 / 5; // Here is more tricky: it depends on many factors, but the main idea is that // if it takes "too long" the backup is not reliable. So, I know that on my computer it take // 20 minutes to backup 2.5 GB, of course my computer is not representative, so I'll multiply by 4 the time. // I would consider "too long" 5 minutes (I know it can be a long time, but let's start with that): // 80 minutes for a 2.5 GB and a 5 minutes limit means 160 MB approx $plain_limit = 240000; // Last thing: are we able to gain time? $current_time_limit = ini_get('max_execution_time'); @set_time_limit(159); //something strange just to be sure $new_time_limit = ini_get('max_execution_time'); @set_time_limit($current_time_limit); $context['use_maintenance'] = 0; // External tool if: // * safe_mode enable OR // * cannot change the execution time OR // * cannot reset timeout if ($context['safe_mode_enable'] || empty($new_time_limit) || $current_time_limit == $new_time_limit && !function_exists('apache_reset_timeout')) { $context['suggested_method'] = 'use_external_tool'; } elseif ($zip_limit < $plain_limit && $messages < $zip_limit) { $context['suggested_method'] = 'zipped_file'; } elseif ($zip_limit > $plain_limit || $zip_limit < $plain_limit && $plain_limit < $messages) { $context['suggested_method'] = 'use_external_tool'; $context['use_maintenance'] = empty($maintenance) ? 2 : 0; } else { $context['use_maintenance'] = 1; $context['suggested_method'] = 'plain_text'; } loadTemplate('Packages'); loadLanguage('Packages'); // $context['package_ftp'] may be set action_backup_display when an error occur if (!isset($context['package_ftp'])) { $context['package_ftp'] = array('form_elements_only' => true, 'server' => '', 'port' => '', 'username' => '', 'path' => '', 'error' => ''); } $context['skip_security'] = !empty($iknowitmaybeunsafe); }
/** * Generate a report on the current permissions by board and membergroup. * functions ending with "Report" are responsible for generating data * for reporting. * they are all called from ReportsMain. * never access the context directly, but use the data handling * functions to do so. */ function BoardPermissionsReport() { global $context, $txt, $modSettings, $smcFunc; // Get as much memory as possible as this can be big. setMemoryLimit('256M'); if (isset($_REQUEST['boards'])) { if (!is_array($_REQUEST['boards'])) { $_REQUEST['boards'] = explode(',', $_REQUEST['boards']); } foreach ($_REQUEST['boards'] as $k => $dummy) { $_REQUEST['boards'][$k] = (int) $dummy; } $board_clause = 'id_board IN ({array_int:boards})'; } else { $board_clause = '1=1'; } if (isset($_REQUEST['groups'])) { if (!is_array($_REQUEST['groups'])) { $_REQUEST['groups'] = explode(',', $_REQUEST['groups']); } foreach ($_REQUEST['groups'] as $k => $dummy) { $_REQUEST['groups'][$k] = (int) $dummy; } $group_clause = 'id_group IN ({array_int:groups})'; } else { $group_clause = '1=1'; } // Fetch all the board names. $request = $smcFunc['db_query']('', ' SELECT id_board, name, id_profile FROM {db_prefix}boards WHERE ' . $board_clause . ' ORDER BY id_board', array('boards' => isset($_REQUEST['boards']) ? $_REQUEST['boards'] : array())); $profiles = array(); while ($row = $smcFunc['db_fetch_assoc']($request)) { $boards[$row['id_board']] = array('name' => $row['name'], 'profile' => $row['id_profile']); $profiles[] = $row['id_profile']; } $smcFunc['db_free_result']($request); // Get all the possible membergroups, except admin! $request = $smcFunc['db_query']('', ' SELECT id_group, group_name FROM {db_prefix}membergroups WHERE ' . $group_clause . ' AND id_group != {int:admin_group}' . (empty($modSettings['permission_enable_postgroups']) ? ' AND min_posts = {int:min_posts}' : '') . ' ORDER BY min_posts, CASE WHEN id_group < {int:newbie_group} THEN id_group ELSE 4 END, group_name', array('admin_group' => 1, 'min_posts' => -1, 'newbie_group' => 4, 'groups' => isset($_REQUEST['groups']) ? $_REQUEST['groups'] : array())); if (!isset($_REQUEST['groups']) || in_array(-1, $_REQUEST['groups']) || in_array(0, $_REQUEST['groups'])) { $member_groups = array('col' => '', -1 => $txt['membergroups_guests'], 0 => $txt['membergroups_members']); } else { $member_groups = array('col' => ''); } while ($row = $smcFunc['db_fetch_assoc']($request)) { $member_groups[$row['id_group']] = $row['group_name']; } $smcFunc['db_free_result']($request); // Make sure that every group is represented - plus in rows! setKeys('rows', $member_groups); // Cache every permission setting, to make sure we don't miss any allows. $permissions = array(); $board_permissions = array(); $request = $smcFunc['db_query']('', ' SELECT id_profile, id_group, add_deny, permission FROM {db_prefix}board_permissions WHERE id_profile IN ({array_int:profile_list}) AND ' . $group_clause . (empty($modSettings['permission_enable_deny']) ? ' AND add_deny = {int:not_deny}' : '') . ' ORDER BY id_profile, permission', array('profile_list' => $profiles, 'not_deny' => 1, 'groups' => isset($_REQUEST['groups']) ? $_REQUEST['groups'] : array())); while ($row = $smcFunc['db_fetch_assoc']($request)) { foreach ($boards as $id => $board) { if ($board['profile'] == $row['id_profile']) { $board_permissions[$id][$row['id_group']][$row['permission']] = $row['add_deny']; } } // Make sure we get every permission. if (!isset($permissions[$row['permission']])) { // This will be reused on other boards. $permissions[$row['permission']] = array('title' => isset($txt['board_perms_name_' . $row['permission']]) ? $txt['board_perms_name_' . $row['permission']] : $row['permission']); } } $smcFunc['db_free_result']($request); // Now cycle through the board permissions array... lots to do ;) foreach ($board_permissions as $board => $groups) { // Create the table for this board first. newTable($boards[$board]['name'], 'x', 'all', 100, 'center', 200, 'left'); // Add the header row - shows all the membergroups. addData($member_groups); // Add the separator. addSeparator($txt['board_perms_permission']); // Here cycle through all the detected permissions. foreach ($permissions as $ID_PERM => $perm_info) { // Is this identical to the global? $identicalGlobal = $board == 0 ? false : true; // Default data for this row. $curData = array('col' => $perm_info['title']); // Now cycle each membergroup in this set of permissions. foreach ($member_groups as $id_group => $name) { // Don't overwrite the key column! if ($id_group === 'col') { continue; } $group_permissions = isset($groups[$id_group]) ? $groups[$id_group] : array(); // Do we have any data for this group? if (isset($group_permissions[$ID_PERM])) { // Set the data for this group to be the local permission. $curData[$id_group] = $group_permissions[$ID_PERM]; } else { $curData[$id_group] = 'x'; } // Now actually make the data for the group look right. if (empty($curData[$id_group])) { $curData[$id_group] = '<span style="color: red;">' . $txt['board_perms_deny'] . '</span>'; } elseif ($curData[$id_group] == 1) { $curData[$id_group] = '<span style="color: darkgreen;">' . $txt['board_perms_allow'] . '</span>'; } else { $curData[$id_group] = 'x'; } // Embolden those permissions different from global (makes it a lot easier!) if (@$board_permissions[0][$id_group][$ID_PERM] != @$group_permissions[$ID_PERM]) { $curData[$id_group] = '<strong>' . $curData[$id_group] . '</strong>'; } } // Now add the data for this permission. addData($curData); } } }
function getSystemInformation(&$tpl) { $infos = array(); // directory to write $infos['dirs'] = checkDirWritable(); // php version $infos['php_version'] = phpversion(); $infos['php_ok'] = version_compare(PHP_VERSION_NEEDED, $infos['php_version']) === -1; $extensions = @get_loaded_extensions(); // Gd version if (in_array('gd', $extensions)) { $gdInfo = gd_info(); $infos['gd_version'] = $gdInfo['GD Version']; ereg("([0-9]{1})", $gdInfo['GD Version'], $gdVersion); $gdVersion[0] >= 2 ? $infos['gd_ok'] = true : ($infos['gd_ok'] = false); // Freetype $gdInfo['FreeType Support'] === true && function_exists('imagettfbbox') ? $infos['freetype_ok'] = true : ($infos['freetype_ok'] = false); } // Mysql + version if (in_array('mysql', $extensions)) { $infos['mysql_ok'] = true; $infos['mysql_version'] = getMysqlVersion(); } // server version $infos['server_version'] = addslashes($_SERVER['SERVER_SOFTWARE']); // server os (linux) $infos['server_os'] = @php_uname(); // servert time $infos['server_time'] = date('H:i:s'); /* //Tous ce qui est relatif a XML if (in_array('xml', $extensions) && function_exists('utf8_decode') && function_exists('utf8_encode') ) { $infos['xml_ok'] = true; } */ if (function_exists('set_time_limit')) { $infos['set_time_limit_ok'] = true; } if (function_exists('utf8_encode') && function_exists('utf8_decode')) { $infos['php_xml'] = true; } if (function_exists('mail')) { $infos['mail_ok'] = true; } //Registre global $infos['register_globals'] = ini_get('register_globals') != 0; if ($memoryValue = getMemoryValue()) { $infos['memory'] = $memoryValue . "M"; if ($memoryValue < MEMORY_LIMIT) { $tpl->assign("memory_limit", "PHP's memory_limit is " . $infos['memory'] . ". If this is too low, phpMyVisites may not work correctly on high traffic websites! Attempting to raise limit to " . MEMORY_LIMIT . "M..."); if (setMemoryLimit()) { $tpl->assign("memory_limit_ok", "Memory set to " . MEMORY_LIMIT . "M!"); $infos['memory_ok'] = true; } else { $tpl->assign("memory_limit", "Failed to set memory_limit to 20M. If phpMyVisites doesn't work correctly, try to raise this limit to at least 20M, look in the php.ini file or ask your server administrator."); } $infos['memory'] = @ini_get('memory_limit'); } else { $infos['memory_ok'] = true; } } // server uptime from mysql uptime $res = query('SHOW STATUS'); if ($res) { while ($row = mysql_fetch_array($res)) { $serverStatus[$row[0]] = $row[1]; } $infos['server_uptime'] = date("r", time() - $serverStatus['Uptime']); } return $infos; }
/** * Delete one or more members. * * What it does: * - Requires profile_remove_own or profile_remove_any permission for * respectively removing your own account or any account. * - Non-admins cannot delete admins. * * The function: * - changes author of messages, topics and polls to guest authors. * - removes all log entries concerning the deleted members, except the * error logs, ban logs and moderation logs. * - removes these members' personal messages (only the inbox) * - rmoves avatars, ban entries, theme settings, moderator positions, poll votes, * drafts, likes, mentions, notifications * - removes custom field data associated with them * - updates member statistics afterwards. * * @package Members * @param int[]|int $users * @param bool $check_not_admin = false */ function deleteMembers($users, $check_not_admin = false) { global $modSettings, $user_info; $db = database(); // Try give us a while to sort this out... @set_time_limit(600); // Try to get some more memory. setMemoryLimit('128M'); // If it's not an array, make it so! if (!is_array($users)) { $users = array($users); } else { $users = array_unique($users); } // Make sure there's no void user in here. $users = array_diff($users, array(0)); // How many are they deleting? if (empty($users)) { return; } elseif (count($users) == 1) { list($user) = $users; if ($user == $user_info['id']) { isAllowedTo('profile_remove_own'); } else { isAllowedTo('profile_remove_any'); } } else { foreach ($users as $k => $v) { $users[$k] = (int) $v; } // Deleting more than one? You can't have more than one account... isAllowedTo('profile_remove_any'); } // Get their names for logging purposes. $request = $db->query('', ' SELECT id_member, member_name, email_address, CASE WHEN id_group = {int:admin_group} OR FIND_IN_SET({int:admin_group}, additional_groups) != 0 THEN 1 ELSE 0 END AS is_admin FROM {db_prefix}members WHERE id_member IN ({array_int:user_list}) LIMIT ' . count($users), array('user_list' => $users, 'admin_group' => 1)); $admins = array(); $emails = array(); $user_log_details = array(); while ($row = $db->fetch_assoc($request)) { if ($row['is_admin']) { $admins[] = $row['id_member']; } $user_log_details[$row['id_member']] = array($row['id_member'], $row['member_name']); $emails[] = $row['email_address']; } $db->free_result($request); if (empty($user_log_details)) { return; } // Make sure they aren't trying to delete administrators if they aren't one. But don't bother checking if it's just themself. if (!empty($admins) && ($check_not_admin || !allowedTo('admin_forum') && (count($users) != 1 || $users[0] != $user_info['id']))) { $users = array_diff($users, $admins); foreach ($admins as $id) { unset($user_log_details[$id]); } } // No one left? if (empty($users)) { return; } // Log the action - regardless of who is deleting it. $log_changes = array(); foreach ($user_log_details as $user) { $log_changes[] = array('action' => 'delete_member', 'log_type' => 'admin', 'extra' => array('member' => $user[0], 'name' => $user[1], 'member_acted' => $user_info['name'])); // Remove any cached data if enabled. if (!empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 2) { cache_put_data('user_settings-' . $user[0], null, 60); } } // Make these peoples' posts guest posts. $db->query('', ' UPDATE {db_prefix}messages SET id_member = {int:guest_id}' . (!empty($modSettings['deleteMembersRemovesEmail']) ? ', poster_email = {string:blank_email}' : '') . ' WHERE id_member IN ({array_int:users})', array('guest_id' => 0, 'blank_email' => '', 'users' => $users)); $db->query('', ' UPDATE {db_prefix}polls SET id_member = {int:guest_id} WHERE id_member IN ({array_int:users})', array('guest_id' => 0, 'users' => $users)); // Make these peoples' posts guest first posts and last posts. $db->query('', ' UPDATE {db_prefix}topics SET id_member_started = {int:guest_id} WHERE id_member_started IN ({array_int:users})', array('guest_id' => 0, 'users' => $users)); $db->query('', ' UPDATE {db_prefix}topics SET id_member_updated = {int:guest_id} WHERE id_member_updated IN ({array_int:users})', array('guest_id' => 0, 'users' => $users)); $db->query('', ' UPDATE {db_prefix}log_actions SET id_member = {int:guest_id} WHERE id_member IN ({array_int:users})', array('guest_id' => 0, 'users' => $users)); $db->query('', ' UPDATE {db_prefix}log_banned SET id_member = {int:guest_id} WHERE id_member IN ({array_int:users})', array('guest_id' => 0, 'users' => $users)); $db->query('', ' UPDATE {db_prefix}log_errors SET id_member = {int:guest_id} WHERE id_member IN ({array_int:users})', array('guest_id' => 0, 'users' => $users)); // Delete the member. $db->query('', ' DELETE FROM {db_prefix}members WHERE id_member IN ({array_int:users})', array('users' => $users)); // Delete any drafts... $db->query('', ' DELETE FROM {db_prefix}user_drafts WHERE id_member IN ({array_int:users})', array('users' => $users)); // Delete any likes... $db->query('', ' DELETE FROM {db_prefix}message_likes WHERE id_member IN ({array_int:users})', array('users' => $users)); // Delete any custom field data... $db->query('', ' DELETE FROM {db_prefix}custom_fields_data WHERE id_member IN ({array_int:users})', array('users' => $users)); // Delete any post by email keys... $db->query('', ' DELETE FROM {db_prefix}postby_emails WHERE email_to IN ({array_string:emails})', array('emails' => $emails)); // Delete the logs... $db->query('', ' DELETE FROM {db_prefix}log_actions WHERE id_log = {int:log_type} AND id_member IN ({array_int:users})', array('log_type' => 2, 'users' => $users)); $db->query('', ' DELETE FROM {db_prefix}log_boards WHERE id_member IN ({array_int:users})', array('users' => $users)); $db->query('', ' DELETE FROM {db_prefix}log_comments WHERE id_recipient IN ({array_int:users}) AND comment_type = {string:warntpl}', array('users' => $users, 'warntpl' => 'warntpl')); $db->query('', ' DELETE FROM {db_prefix}log_group_requests WHERE id_member IN ({array_int:users})', array('users' => $users)); $db->query('', ' DELETE FROM {db_prefix}log_karma WHERE id_target IN ({array_int:users}) OR id_executor IN ({array_int:users})', array('users' => $users)); $db->query('', ' DELETE FROM {db_prefix}log_mark_read WHERE id_member IN ({array_int:users})', array('users' => $users)); $db->query('', ' DELETE FROM {db_prefix}log_notify WHERE id_member IN ({array_int:users})', array('users' => $users)); $db->query('', ' DELETE FROM {db_prefix}log_online WHERE id_member IN ({array_int:users})', array('users' => $users)); $db->query('', ' DELETE FROM {db_prefix}log_subscribed WHERE id_member IN ({array_int:users})', array('users' => $users)); $db->query('', ' DELETE FROM {db_prefix}log_topics WHERE id_member IN ({array_int:users})', array('users' => $users)); $db->query('', ' DELETE FROM {db_prefix}collapsed_categories WHERE id_member IN ({array_int:users})', array('users' => $users)); // Make their votes appear as guest votes - at least it keeps the totals right. // @todo Consider adding back in cookie protection. $db->query('', ' UPDATE {db_prefix}log_polls SET id_member = {int:guest_id} WHERE id_member IN ({array_int:users})', array('guest_id' => 0, 'users' => $users)); // Remove the mentions $db->query('', ' DELETE FROM {db_prefix}log_mentions WHERE id_member IN ({array_int:users})', array('users' => $users)); // Delete personal messages. require_once SUBSDIR . '/PersonalMessage.subs.php'; deleteMessages(null, null, $users); $db->query('', ' UPDATE {db_prefix}personal_messages SET id_member_from = {int:guest_id} WHERE id_member_from IN ({array_int:users})', array('guest_id' => 0, 'users' => $users)); // They no longer exist, so we don't know who it was sent to. $db->query('', ' DELETE FROM {db_prefix}pm_recipients WHERE id_member IN ({array_int:users})', array('users' => $users)); // Delete avatar. require_once SUBSDIR . '/ManageAttachments.subs.php'; removeAttachments(array('id_member' => $users)); // It's over, no more moderation for you. $db->query('', ' DELETE FROM {db_prefix}moderators WHERE id_member IN ({array_int:users})', array('users' => $users)); $db->query('', ' DELETE FROM {db_prefix}group_moderators WHERE id_member IN ({array_int:users})', array('users' => $users)); // If you don't exist we can't ban you. $db->query('', ' DELETE FROM {db_prefix}ban_items WHERE id_member IN ({array_int:users})', array('users' => $users)); // Remove individual theme settings. $db->query('', ' DELETE FROM {db_prefix}themes WHERE id_member IN ({array_int:users})', array('users' => $users)); // These users are nobody's buddy nomore. $request = $db->query('', ' SELECT id_member, pm_ignore_list, buddy_list FROM {db_prefix}members WHERE FIND_IN_SET({raw:pm_ignore_list}, pm_ignore_list) != 0 OR FIND_IN_SET({raw:buddy_list}, buddy_list) != 0', array('pm_ignore_list' => implode(', pm_ignore_list) != 0 OR FIND_IN_SET(', $users), 'buddy_list' => implode(', buddy_list) != 0 OR FIND_IN_SET(', $users))); while ($row = $db->fetch_assoc($request)) { updateMemberData($row['id_member'], array('pm_ignore_list' => implode(',', array_diff(explode(',', $row['pm_ignore_list']), $users)), 'buddy_list' => implode(',', array_diff(explode(',', $row['buddy_list']), $users)))); } $db->free_result($request); // Make sure no member's birthday is still sticking in the calendar... updateSettings(array('calendar_updated' => time())); // Integration rocks! call_integration_hook('integrate_delete_members', array($users)); updateMemberStats(); logActions($log_changes); }
/** * New Topic posting controller, reads, parses, checks and posts a new topic * * What it does: * - New topics do not have security keys in them so they are subject to spoofing * - It must be from the email of a registered user * - It must have been sent to an email ID that has been set to post new topics * - Accessed through emailtopic. * * @param string|null $data used to supply a full body+headers email */ public function action_pbe_topic($data = null) { global $modSettings, $user_info, $maintenance; // The function is not even on ... if (empty($modSettings['maillist_enabled'])) { return; } // Our mail parser and our main subs require_once SUBSDIR . '/EmailParse.class.php'; require_once SUBSDIR . '/Emailpost.subs.php'; // Init loadLanguage('Maillist'); setMemoryLimit('256M'); // Get the data from one of our sources $email_message = new Email_Parse(); $email_message->read_data($data, BOARDDIR); if (!$email_message->raw_message) { return false; } // Parse the header and some needed details $email_message->read_email(true, $email_message->raw_message); $email_message->load_address(); // No key for this, so set some blanks for the error function (if needed) $email_message->message_type = 'x'; $email_message->message_key_id = ''; $email_message->message_id = 0; // If the feature is on but the post/pm function is not enabled, just log the message. if (empty($modSettings['pbe_post_enabled'])) { return pbe_emailError('error_email_notenabled', $email_message); } // Load the user from the database based on the sending email address $email_message->email['from'] = !empty($email_message->email['from']) ? strtolower($email_message->email['from']) : ''; $pbe = query_load_user_info($email_message->email['from']); // Can't find this email as one of our users? if (empty($pbe)) { return pbe_emailError('error_not_find_member', $email_message); } // Getting hammy with it? if ($email_message->load_spam()) { return pbe_emailError('error_found_spam', $email_message); } // The board that this email address corresponds to $board_number = pbe_find_board_number($email_message); if (empty($board_number)) { return pbe_emailError('error_not_find_board', $email_message); } // In maintenance mode so just save it for the moderators to deal with if (!empty($maintenance) && $maintenance !== 2 && !$pbe['user_info']['is_admin'] && !$user_info['is_admin']) { return pbe_emailError('error_in_maintenance_mode', $email_message); } // Any additional spam / security checking call_integration_hook('integrate_mailist_checks_before', array($email_message, $pbe)); // To post a NEW topic, we need some board details for where it goes $board_info = query_load_board_details($board_number, $pbe); if (empty($board_info)) { return pbe_emailError('error_board_gone', $email_message); } // Load up this users permissions for that board query_load_permissions('board', $pbe, $board_info); // Account for any moderation they may be under pbe_check_moderation($pbe); // Create the topic, send notifications return pbe_create_topic($pbe, $email_message, $board_info); }
* This software is a derived product, based on: * * Simple Machines Forum (SMF) * copyright: 2011 Simple Machines (http://www.simplemachines.org) * license: BSD, See included LICENSE.TXT for terms and conditions. * * This file resets a database back to Elkarte defaults by removing * rows / cols / tables / indexes and modsettings that addons added * */ if (!file_exists(dirname(__FILE__) . '/SSI.php')) { exit('Please verify you put this in the same place as SSI.php file.'); } require_once dirname(__FILE__) . '/SSI.php'; // Memory is always good setMemoryLimit('128M'); // Now get to work ... file_source(); obExit(true); /** * file_source() * * - initialises all the basic context required for the database cleanup. * - passes execution onto the relevant section. * - if the passed action is not found it shows the main page. * * @return */ function file_source() { global $context, $table_prefix;
/** * Generate a report on the current permissions by board and membergroup. * functions ending with "Report" are responsible for generating data * for reporting. * they are all called from action_index. * never access the context directly, but use the data handling * functions to do so. */ public function action_board_perms() { global $txt; // Get as much memory as possible as this can be big. setMemoryLimit('256M'); // Boards, first. require_once SUBSDIR . '/Boards.subs.php'; require_once SUBSDIR . '/Membergroups.subs.php'; // Lets get started $query_boards = array(); if (isset($_REQUEST['boards'])) { if (!is_array($_REQUEST['boards'])) { $query_boards['boards'] = array_map('intval', explode(',', $_REQUEST['boards'])); } else { $query_boards['boards'] = array_map('intval', $_REQUEST['boards']); } } else { $query_boards = 'all'; } // Fetch the board names and profiles. // This returns id_board, name, id_profile keys $boards = fetchBoardsInfo($query_boards, array('sort_by' => 'id_board', 'selects' => 'permissions')); $profiles = array(); foreach ($boards as $b) { $profiles[] = $b['id_profile']; } // Groups, next. $query_groups = array(); if (isset($_REQUEST['groups'])) { if (!is_array($_REQUEST['groups'])) { $query_groups = array_map('intval', explode(',', $_REQUEST['groups'])); } else { $query_groups = array_map('intval', $_REQUEST['groups']); } $group_clause = 'id_group IN ({array_int:groups})'; } else { $group_clause = '1=1'; } // Get all the possible membergroups, except admin! require_once SUBSDIR . '/Reports.subs.php'; $all_groups = allMembergroups($group_clause, $query_groups); if (empty($query_groups) || in_array(-1, $query_groups) || in_array(0, $query_groups)) { $member_groups = array('col' => '', -1 => $txt['membergroups_guests'], 0 => $txt['membergroups_members']) + $all_groups; } else { $member_groups = array('col' => '') + $all_groups; } // Make sure that every group is represented - plus in rows! setKeys('rows', $member_groups); // Permissions, last! $boardPermissions = boardPermissions($profiles, $group_clause, $query_groups); $permissions = array(); $board_permissions = array(); foreach ($boardPermissions as $row) { foreach ($boards as $id => $board) { if ($board['id_profile'] == $row['id_profile']) { $board_permissions[$id][$row['id_group']][$row['permission']] = $row['add_deny']; } } // Make sure we get every permission. if (!isset($permissions[$row['permission']])) { // This will be reused on other boards. $permissions[$row['permission']] = array('title' => isset($txt['board_perms_name_' . $row['permission']]) ? $txt['board_perms_name_' . $row['permission']] : $row['permission']); } } // Now cycle through the board permissions array... lots to do ;) foreach ($board_permissions as $board => $groups) { // Create the table for this board first. newTable($boards[$board]['name'], 'x', 'all', 100, 'center', 200, 'left'); // Add the header row - shows all the membergroups. addData($member_groups); // Add the separator. addSeparator($txt['board_perms_permission']); // Here cycle through all the detected permissions. foreach ($permissions as $ID_PERM => $perm_info) { // Default data for this row. $curData = array('col' => $perm_info['title']); // Now cycle each membergroup in this set of permissions. foreach ($member_groups as $id_group => $name) { // Don't overwrite the key column! if ($id_group === 'col') { continue; } $group_permissions = isset($groups[$id_group]) ? $groups[$id_group] : array(); // Do we have any data for this group? if (isset($group_permissions[$ID_PERM])) { // Set the data for this group to be the local permission. $curData[$id_group] = $group_permissions[$ID_PERM]; } else { $curData[$id_group] = 'x'; } // Now actually make the data for the group look right. if (empty($curData[$id_group])) { $curData[$id_group] = '<span class="alert">' . $txt['board_perms_deny'] . '</span>'; } elseif ($curData[$id_group] == 1) { $curData[$id_group] = '<span class="success">' . $txt['board_perms_allow'] . '</span>'; } else { $curData[$id_group] = 'x'; } } // Now add the data for this permission. addData($curData); } } }
/** * See if we have enough memory to thumbnail an image * * @package Graphics * @param int[] $sizes image size */ function imageMemoryCheck($sizes) { global $modSettings; // Doing the old 'set it and hope' way? if (empty($modSettings['attachment_thumb_memory'])) { setMemoryLimit('128M'); return true; } // Determine the memory requirements for this image, note: if you want to use an image formula // W x H x bits/8 x channels x Overhead factor // You will need to account for single bit images as GD expands them to an 8 bit and will greatly // overun the calculated value. // The 5 below is simply a shortcut of 8bpp, 3 channels, 1.66 overhead $needed_memory = $sizes[0] * $sizes[1] * 5; // If we need more, lets try to get it return setMemoryLimit($needed_memory, true); }
/** * Allow the admin to reset permissions on files. */ public function action_perms() { global $context, $txt, $modSettings, $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 time and memory eating ... setMemoryLimit('128M'); @set_time_limit(600); // Load up some FTP stuff. create_chmod_control(); if (empty($package_ftp) && !isset($_POST['skip_ftp'])) { require_once SUBSDIR . '/FtpConnection.class.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']); } // @todo 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. require_once SUBSDIR . '/Themes.subs.php'; $themes = getCustomThemes(); foreach ($themes as $id => $theme) { // Skip the default if ($id == 1) { continue; } if (substr(strtolower(strtr($theme['theme_dir'], array('\\' => '/'))), 0, strlen(BOARDDIR) + 7) === strtolower(strtr(BOARDDIR, array('\\' => '/')) . '/themes')) { $context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['themes']['contents'][substr($theme['theme_dir'], strlen(BOARDDIR) + 8)] = array('type' => 'dir_recursive', 'list_contents' => true, 'contents' => array('languages' => array('type' => 'dir', 'list_contents' => true))); } else { $context['file_tree'][strtr($theme['theme_dir'], array('\\' => '/'))] = array('type' => 'dir_recursive', 'list_contents' => true, 'contents' => array('languages' => array('type' => 'dir', 'list_contents' => true))); } } // If we're submitting then let's move on to another function to keep things cleaner.. if (isset($_POST['action_changes'])) { return $this->action_perms_save(); } $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'; Template_Layers::getInstance()->removeAll(); } }
/** * Supporting function for the database maintenance area. */ function MaintainDatabase() { global $context, $db_type, $db_character_set, $modSettings, $smcFunc, $txt, $maintenance; // Show some conversion options? $context['convert_utf8'] = $db_type == 'mysql' && (!isset($db_character_set) || $db_character_set !== 'utf8' || empty($modSettings['global_character_set']) || $modSettings['global_character_set'] !== 'UTF-8') && version_compare('4.1.2', preg_replace('~\\-.+?$~', '', $smcFunc['db_server_info']()), '<='); $context['convert_entities'] = $db_type == 'mysql' && isset($db_character_set, $modSettings['global_character_set']) && $db_character_set === 'utf8' && $modSettings['global_character_set'] === 'UTF-8'; if ($db_type == 'mysql') { db_extend('packages'); $colData = $smcFunc['db_list_columns']('{db_prefix}messages', true); foreach ($colData as $column) { if ($column['name'] == 'body') { $body_type = $column['type']; } } $context['convert_to'] = $body_type == 'text' ? 'mediumtext' : 'text'; $context['convert_to_suggest'] = $body_type != 'text' && !empty($modSettings['max_messageLength']) && $modSettings['max_messageLength'] < 65536; } // Check few things to give advices before make a backup // If safe mod is enable the external tool is *always* the best (and probably the only) solution $context['safe_mode_enable'] = @ini_get('safe_mode'); // This is just a...guess $result = $smcFunc['db_query']('', ' SELECT COUNT(*) FROM {db_prefix}messages', array()); list($messages) = $smcFunc['db_fetch_row']($result); $smcFunc['db_free_result']($result); // 256 is what we use in the backup script setMemoryLimit('256M'); $memory_limit = memoryReturnBytes(ini_get('memory_limit')) / (1024 * 1024); // Zip limit is set to more or less 1/4th the size of the available memory * 1500 // 1500 is an estimate of the number of messages that generates a database of 1 MB (yeah I know IT'S AN ESTIMATION!!!) // Why that? Because the only reliable zip package is the one sent out the first time, // so when the backup takes 1/5th (just to stay on the safe side) of the memory available $zip_limit = $memory_limit * 1500 / 5; // Here is more tricky: it depends on many factors, but the main idea is that // if it takes "too long" the backup is not reliable. So, I know that on my computer it take // 20 minutes to backup 2.5 GB, of course my computer is not representative, so I'll multiply by 4 the time. // I would consider "too long" 5 minutes (I know it can be a long time, but let's start with that): // 80 minutes for a 2.5 GB and a 5 minutes limit means 160 MB approx $plain_limit = 240000; // Last thing: are we able to gain time? $current_time_limit = ini_get('max_execution_time'); @set_time_limit(159); //something strange just to be sure $new_time_limit = ini_get('max_execution_time'); $context['use_maintenance'] = 0; // External tool if: // * safe_mode enable OR // * cannot change the execution time OR // * cannot reset timeout if ($context['safe_mode_enable'] || empty($new_time_limit) || $current_time_limit == $new_time_limit && !function_exists('apache_reset_timeout')) { $context['suggested_method'] = 'use_external_tool'; } elseif ($zip_limit < $plain_limit && $messages < $zip_limit) { $context['suggested_method'] = 'zipped_file'; } elseif ($zip_limit > $plain_limit || $zip_limit < $plain_limit && $plain_limit < $messages) { $context['suggested_method'] = 'use_external_tool'; $context['use_maintenance'] = empty($maintenance) ? 2 : 0; } else { $context['use_maintenance'] = 1; $context['suggested_method'] = 'plain_text'; } if (isset($_GET['done']) && $_GET['done'] == 'convertutf8') { $context['maintenance_finished'] = $txt['utf8_title']; } if (isset($_GET['done']) && $_GET['done'] == 'convertentities') { $context['maintenance_finished'] = $txt['entity_convert_title']; } }