function AdminAccount() { global $txt, $db_type, $db_connection, $incontext, $db_prefix, $db_passwd, $sourcedir; $incontext['sub_template'] = 'admin_account'; $incontext['page_title'] = $txt['user_settings']; $incontext['continue'] = 1; // Skipping? if (!empty($_POST['skip'])) { return true; } // Need this to check whether we need the database password. require dirname(__FILE__) . '/Settings.php'; load_database(); if (!isset($_POST['username'])) { $_POST['username'] = ''; } if (!isset($_POST['email'])) { $_POST['email'] = ''; } $incontext['username'] = htmlspecialchars(stripslashes($_POST['username'])); $incontext['email'] = htmlspecialchars(stripslashes($_POST['email'])); $incontext['require_db_confirm'] = empty($db_type) || $db_type != 'sqlite'; // Only allow skipping if we think they already have an account setup. $request = smf_db_query(' SELECT id_member FROM {db_prefix}members WHERE id_group = {int:admin_group} OR FIND_IN_SET({int:admin_group}, additional_groups) != 0 LIMIT 1', array('db_error_skip' => true, 'admin_group' => 1)); if (mysql_num_rows($request) != 0) { $incontext['skip'] = 1; } mysql_free_result($request); // Trying to create an account? if (isset($_POST['password1']) && !empty($_POST['contbutt'])) { // Wrong password? if ($incontext['require_db_confirm'] && $_POST['password3'] != $db_passwd) { $incontext['error'] = $txt['error_db_connect']; return false; } // Not matching passwords? if ($_POST['password1'] != $_POST['password2']) { $incontext['error'] = $txt['error_user_settings_again_match']; return false; } // No password? if (strlen($_POST['password1']) < 4) { $incontext['error'] = $txt['error_user_settings_no_password']; return false; } if (!file_exists($sourcedir . '/lib/Subs.php')) { $incontext['error'] = $txt['error_subs_missing']; return false; } // Update the main contact email? if (!empty($_POST['email']) && (empty($webmaster_email) || $webmaster_email == '*****@*****.**')) { updateSettingsFile(array('webmaster_email' => $_POST['email'])); } // Work out whether we're going to have dodgy characters and remove them. $invalid_characters = preg_match('~[<>&"\'=\\\\]~', $_POST['username']) != 0; $_POST['username'] = preg_replace('~[<>&"\'=\\\\]~', '', $_POST['username']); $result = smf_db_query(' SELECT id_member, password_salt FROM {db_prefix}members WHERE member_name = {string:username} OR email_address = {string:email} LIMIT 1', array('username' => stripslashes($_POST['username']), 'email' => stripslashes($_POST['email']), 'db_error_skip' => true)); if (mysql_num_rows($result) != 0) { list($incontext['member_id'], $incontext['member_salt']) = mysql_fetch_row($result); mysql_free_result($result); $incontext['account_existed'] = $txt['error_user_settings_taken']; } elseif ($_POST['username'] == '' || strlen($_POST['username']) > 25) { // Try the previous step again. $incontext['error'] = $_POST['username'] == '' ? $txt['error_username_left_empty'] : $txt['error_username_too_long']; return false; } elseif ($invalid_characters || $_POST['username'] == '_' || $_POST['username'] == '|' || strpos($_POST['username'], '[code') !== false || strpos($_POST['username'], '[/code') !== false) { // Try the previous step again. $incontext['error'] = $txt['error_invalid_characters_username']; return false; } elseif (empty($_POST['email']) || preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', stripslashes($_POST['email'])) === 0 || strlen(stripslashes($_POST['email'])) > 255) { // One step back, this time fill out a proper email address. $incontext['error'] = sprintf($txt['error_valid_email_needed'], $_POST['username']); return false; } elseif ($_POST['username'] != '') { $incontext['member_salt'] = substr(md5(mt_rand()), 0, 4); // Format the username properly. $_POST['username'] = preg_replace('~[\\t\\n\\r\\x0B\\0\\xA0]+~', ' ', $_POST['username']); $ip = isset($_SERVER['REMOTE_ADDR']) ? substr($_SERVER['REMOTE_ADDR'], 0, 255) : ''; $request = smf_db_insert('insert', $db_prefix . 'members', array('member_name' => 'string-25', 'real_name' => 'string-25', 'passwd' => 'string', 'email_address' => 'string', 'id_group' => 'int', 'posts' => 'int', 'date_registered' => 'int', 'hide_email' => 'int', 'password_salt' => 'string', 'lngfile' => 'string', 'personal_text' => 'string', 'avatar' => 'string', 'member_ip' => 'string', 'member_ip2' => 'string', 'buddy_list' => 'string', 'pm_ignore_list' => 'string', 'message_labels' => 'string', 'location' => 'string', 'signature' => 'string', 'usertitle' => 'string', 'secret_question' => 'string', 'additional_groups' => 'string', 'ignore_boards' => 'string', 'openid_uri' => 'string'), array(stripslashes($_POST['username']), stripslashes($_POST['username']), sha1(strtolower(stripslashes($_POST['username'])) . stripslashes($_POST['password1'])), stripslashes($_POST['email']), 1, 0, time(), 0, $incontext['member_salt'], '', '', '', $ip, $ip, '', '', '', '', '', '', '', '', '', ''), array('id_member')); // Awww, crud! if ($request === false) { $incontext['error'] = $txt['error_user_settings_query'] . '<br /> <div style="margin: 2ex;">' . nl2br(htmlspecialchars(mysql_error($db_connection))) . '</div>'; return false; } $incontext['member_id'] = smf_db_insert_id("{$db_prefix}members", 'id_member'); } // If we're here we're good. return true; } return false; }
function smf_db_error($db_string, $connection = null) { global $txt, $context, $sourcedir, $webmaster_email, $modSettings; global $forum_version, $db_connection, $db_last_error, $db_persist; global $db_server, $db_user, $db_passwd, $db_name, $db_show_debug, $ssi_db_user, $ssi_db_passwd; global $smcFunc; // Get the file and line numbers. list($file, $line) = smf_db_error_backtrace('', '', 'return', __FILE__, __LINE__); // Decide which connection to use $connection = $connection == null ? $db_connection : $connection; // This is the error message... $query_error = mysql_error($connection); $query_errno = mysql_errno($connection); // Error numbers: // 1016: Can't open file '....MYI' // 1030: Got error ??? from table handler. // 1034: Incorrect key file for table. // 1035: Old key file for table. // 1205: Lock wait timeout exceeded. // 1213: Deadlock found. // 2006: Server has gone away. // 2013: Lost connection to server during query. // Log the error. if ($query_errno != 1213 && $query_errno != 1205 && function_exists('log_error')) { log_error($txt['database_error'] . ': ' . $query_error . (!empty($modSettings['enableErrorQueryLogging']) ? "\n\n{$db_string}" : ''), 'database', $file, $line); } // Database error auto fixing ;). if (function_exists('cache_get_data') && (!isset($modSettings['autoFixDatabase']) || $modSettings['autoFixDatabase'] == '1')) { // Force caching on, just for the error checking. $old_cache = @$modSettings['cache_enable']; $modSettings['cache_enable'] = '1'; if (($temp = cache_get_data('db_last_error', 600)) !== null) { $db_last_error = max(@$db_last_error, $temp); } if (@$db_last_error < time() - 3600 * 24 * 3) { // We know there's a problem... but what? Try to auto detect. if ($query_errno == 1030 && strpos($query_error, ' 127 ') !== false) { preg_match_all('~(?:[\\n\\r]|^)[^\']+?(?:FROM|JOIN|UPDATE|TABLE) ((?:[^\\n\\r(]+?(?:, )?)*)~s', $db_string, $matches); $fix_tables = array(); foreach ($matches[1] as $tables) { $tables = array_unique(explode(',', $tables)); foreach ($tables as $table) { // Now, it's still theoretically possible this could be an injection. So backtick it! if (trim($table) != '') { $fix_tables[] = '`' . strtr(trim($table), array('`' => '')) . '`'; } } } $fix_tables = array_unique($fix_tables); } elseif ($query_errno == 1016) { if (preg_match('~\'([^\\.\']+)~', $query_error, $match) != 0) { $fix_tables = array('`' . $match[1] . '`'); } } elseif ($query_errno == 1034 || $query_errno == 1035) { preg_match('~\'([^\']+?)\'~', $query_error, $match); $fix_tables = array('`' . $match[1] . '`'); } } // Check for errors like 145... only fix it once every three days, and send an email. (can't use empty because it might not be set yet...) if (!empty($fix_tables)) { // Subs-Admin.php for updateSettingsFile(), Subs-Post.php for sendmail(). require_once $sourcedir . '/Subs-Admin.php'; require_once $sourcedir . '/Subs-Post.php'; // Make a note of the REPAIR... cache_put_data('db_last_error', time(), 600); if (($temp = cache_get_data('db_last_error', 600)) === null) { updateSettingsFile(array('db_last_error' => time())); } // Attempt to find and repair the broken table. foreach ($fix_tables as $table) { $smcFunc['db_query']('', "\r\n\t\t\t\t\tREPAIR TABLE {$table}", false, false); } // And send off an email! sendmail($webmaster_email, $txt['database_error'], $txt['tried_to_repair']); $modSettings['cache_enable'] = $old_cache; // Try the query again...? $ret = $smcFunc['db_query']('', $db_string, false, false); if ($ret !== false) { return $ret; } } else { $modSettings['cache_enable'] = $old_cache; } // Check for the "lost connection" or "deadlock found" errors - and try it just one more time. if (in_array($query_errno, array(1205, 1213, 2006, 2013))) { if (in_array($query_errno, array(2006, 2013)) && $db_connection == $connection) { // Are we in SSI mode? If so try that username and password first if (SMF == 'SSI' && !empty($ssi_db_user) && !empty($ssi_db_passwd)) { if (empty($db_persist)) { $db_connection = @mysql_connect($db_server, $ssi_db_user, $ssi_db_passwd); } else { $db_connection = @mysql_pconnect($db_server, $ssi_db_user, $ssi_db_passwd); } } // Fall back to the regular username and password if need be if (!$db_connection) { if (empty($db_persist)) { $db_connection = @mysql_connect($db_server, $db_user, $db_passwd); } else { $db_connection = @mysql_pconnect($db_server, $db_user, $db_passwd); } } if (!$db_connection || !@mysql_select_db($db_name, $db_connection)) { $db_connection = false; } } if ($db_connection) { // Try a deadlock more than once more. for ($n = 0; $n < 4; $n++) { $ret = $smcFunc['db_query']('', $db_string, false, false); $new_errno = mysql_errno($db_connection); if ($ret !== false || in_array($new_errno, array(1205, 1213))) { break; } } // If it failed again, shucks to be you... we're not trying it over and over. if ($ret !== false) { return $ret; } } } elseif ($query_errno == 1030 && (strpos($query_error, ' -1 ') !== false || strpos($query_error, ' 28 ') !== false || strpos($query_error, ' 12 ') !== false)) { if (!isset($txt)) { $query_error .= ' - check database storage space.'; } else { if (!isset($txt['mysql_error_space'])) { loadLanguage('Errors'); } $query_error .= !isset($txt['mysql_error_space']) ? ' - check database storage space.' : $txt['mysql_error_space']; } } } // Nothing's defined yet... just die with it. if (empty($context) || empty($txt)) { die($query_error); } // Show an error message, if possible. $context['error_title'] = $txt['database_error']; if (allowedTo('admin_forum')) { $context['error_message'] = nl2br($query_error) . '<br />' . $txt['file'] . ': ' . $file . '<br />' . $txt['line'] . ': ' . $line; } else { $context['error_message'] = $txt['try_again']; } // A database error is often the sign of a database in need of upgrade. Check forum versions, and if not identical suggest an upgrade... (not for Demo/CVS versions!) if (allowedTo('admin_forum') && !empty($forum_version) && $forum_version != 'SMF ' . @$modSettings['smfVersion'] && strpos($forum_version, 'Demo') === false && strpos($forum_version, 'CVS') === false) { $context['error_message'] .= '<br /><br />' . sprintf($txt['database_error_versions'], $forum_version, $modSettings['smfVersion']); } if (allowedTo('admin_forum') && isset($db_show_debug) && $db_show_debug === true) { $context['error_message'] .= '<br /><br />' . nl2br($db_string); } // It's already been logged... don't log it again. fatal_error($context['error_message'], false); }
function ConvertUtf8() { global $scripturl, $context, $txt, $language, $db_character_set; global $modSettings, $user_info, $sourcedir, $smcFunc, $db_prefix; // Show me your badge! isAllowedTo('admin_forum'); // The character sets used in SMF's language files with their db equivalent. $charsets = array('big5' => 'big5', 'gbk' => 'gbk', 'ISO-8859-1' => 'latin1', 'ISO-8859-2' => 'latin2', 'ISO-8859-9' => 'latin5', 'ISO-8859-15' => 'latin9', 'tis-620' => 'tis620', 'UTF-8' => 'utf8', 'windows-1251' => 'cp1251', 'windows-1253' => 'utf8', 'windows-1255' => 'utf8', 'windows-1256' => 'cp1256'); // Get a list of character sets supported by your MySQL server. $request = $smcFunc['db_query']('', ' SHOW CHARACTER SET', array()); $db_charsets = array(); while ($row = $smcFunc['db_fetch_assoc']($request)) { $db_charsets[] = $row['Charset']; } $smcFunc['db_free_result']($request); // Character sets supported by both MySQL and SMF's language files. $charsets = array_intersect($charsets, $db_charsets); // This is for the first screen telling backups is good. if (!isset($_POST['proceed'])) { // Character set conversions are only supported as of MySQL 4.1.2. if (version_compare('4.1.2', preg_replace('~\\-.+?$~', '', $smcFunc['db_server_info']())) > 0) { fatal_lang_error('utf8_db_version_too_low'); } // Use the messages.body column as indicator for the database charset. $request = $smcFunc['db_query']('', ' SHOW FULL COLUMNS FROM {db_prefix}messages LIKE {string:body_like}', array('body_like' => 'body')); $column_info = $smcFunc['db_fetch_assoc']($request); $smcFunc['db_free_result']($request); // A collation looks like latin1_swedish. We only need the character set. list($context['database_charset']) = explode('_', $column_info['Collation']); $context['database_charset'] = in_array($context['database_charset'], $charsets) ? array_search($context['database_charset'], $charsets) : $context['database_charset']; // No need to convert to UTF-8 if it already is. if ($db_character_set === 'utf8' && !empty($modSettings['global_character_set']) && $modSettings['global_character_set'] === 'UTF-8') { fatal_lang_error('utf8_already_utf8'); } // Cannot do conversion if using a fulltext index if (!empty($modSettings['search_index']) && $modSettings['search_index'] == 'fulltext') { fatal_lang_error('utf8_cannot_convert_fulltext'); } // Grab the character set from the default language file. loadLanguage('index', $language, true); $context['charset_detected'] = $txt['lang_character_set']; $context['charset_about_detected'] = sprintf($txt['utf8_detected_charset'], $language, $context['charset_detected']); // Go back to your own language. loadLanguage('index', $user_info['language'], true); // Show a warning if the character set seems not to be supported. if (!isset($charsets[strtr(strtolower($context['charset_detected']), array('utf' => 'UTF', 'iso' => 'ISO'))])) { $context['charset_warning'] = sprintf($txt['utf8_charset_not_supported'], $txt['lang_character_set']); // Default to ISO-8859-1. $context['charset_detected'] = 'ISO-8859-1'; } $context['charset_list'] = array_keys($charsets); $context['page_title'] = $txt['utf8_title']; $context['sub_template'] = 'convert_utf8'; return; } // After this point we're starting the conversion. But first: session check. checkSession(); // Translation table for the character sets not native for MySQL. $translation_tables = array('windows-1255' => array('0x81' => '\'\'', '0x8A' => '\'\'', '0x8C' => '\'\'', '0x8D' => '\'\'', '0x8E' => '\'\'', '0x8F' => '\'\'', '0x90' => '\'\'', '0x9A' => '\'\'', '0x9C' => '\'\'', '0x9D' => '\'\'', '0x9E' => '\'\'', '0x9F' => '\'\'', '0xCA' => '\'\'', '0xD9' => '\'\'', '0xDA' => '\'\'', '0xDB' => '\'\'', '0xDC' => '\'\'', '0xDD' => '\'\'', '0xDE' => '\'\'', '0xDF' => '\'\'', '0xFB' => '\'\'', '0xFC' => '\'\'', '0xFF' => '\'\'', '0xC2' => '0xFF', '0x80' => '0xFC', '0xE2' => '0xFB', '0xA0' => '0xC2A0', '0xA1' => '0xC2A1', '0xA2' => '0xC2A2', '0xA3' => '0xC2A3', '0xA5' => '0xC2A5', '0xA6' => '0xC2A6', '0xA7' => '0xC2A7', '0xA8' => '0xC2A8', '0xA9' => '0xC2A9', '0xAB' => '0xC2AB', '0xAC' => '0xC2AC', '0xAD' => '0xC2AD', '0xAE' => '0xC2AE', '0xAF' => '0xC2AF', '0xB0' => '0xC2B0', '0xB1' => '0xC2B1', '0xB2' => '0xC2B2', '0xB3' => '0xC2B3', '0xB4' => '0xC2B4', '0xB5' => '0xC2B5', '0xB6' => '0xC2B6', '0xB7' => '0xC2B7', '0xB8' => '0xC2B8', '0xB9' => '0xC2B9', '0xBB' => '0xC2BB', '0xBC' => '0xC2BC', '0xBD' => '0xC2BD', '0xBE' => '0xC2BE', '0xBF' => '0xC2BF', '0xD7' => '0xD7B3', '0xD1' => '0xD781', '0xD4' => '0xD7B0', '0xD5' => '0xD7B1', '0xD6' => '0xD7B2', '0xE0' => '0xD790', '0xEA' => '0xD79A', '0xEC' => '0xD79C', '0xED' => '0xD79D', '0xEE' => '0xD79E', '0xEF' => '0xD79F', '0xF0' => '0xD7A0', '0xF1' => '0xD7A1', '0xF2' => '0xD7A2', '0xF3' => '0xD7A3', '0xF5' => '0xD7A5', '0xF6' => '0xD7A6', '0xF7' => '0xD7A7', '0xF8' => '0xD7A8', '0xF9' => '0xD7A9', '0x82' => '0xE2809A', '0x84' => '0xE2809E', '0x85' => '0xE280A6', '0x86' => '0xE280A0', '0x87' => '0xE280A1', '0x89' => '0xE280B0', '0x8B' => '0xE280B9', '0x93' => '0xE2809C', '0x94' => '0xE2809D', '0x95' => '0xE280A2', '0x97' => '0xE28094', '0x99' => '0xE284A2', '0xC0' => '0xD6B0', '0xC1' => '0xD6B1', '0xC3' => '0xD6B3', '0xC4' => '0xD6B4', '0xC5' => '0xD6B5', '0xC6' => '0xD6B6', '0xC7' => '0xD6B7', '0xC8' => '0xD6B8', '0xC9' => '0xD6B9', '0xCB' => '0xD6BB', '0xCC' => '0xD6BC', '0xCD' => '0xD6BD', '0xCE' => '0xD6BE', '0xCF' => '0xD6BF', '0xD0' => '0xD780', '0xD2' => '0xD782', '0xE3' => '0xD793', '0xE4' => '0xD794', '0xE5' => '0xD795', '0xE7' => '0xD797', '0xE9' => '0xD799', '0xFD' => '0xE2808E', '0xFE' => '0xE2808F', '0x92' => '0xE28099', '0x83' => '0xC692', '0xD3' => '0xD783', '0x88' => '0xCB86', '0x98' => '0xCB9C', '0x91' => '0xE28098', '0x96' => '0xE28093', '0xBA' => '0xC3B7', '0x9B' => '0xE280BA', '0xAA' => '0xC397', '0xA4' => '0xE282AA', '0xE1' => '0xD791', '0xE6' => '0xD796', '0xE8' => '0xD798', '0xEB' => '0xD79B', '0xF4' => '0xD7A4', '0xFA' => '0xD7AA', '0xFF' => '0xD6B2', '0xFC' => '0xE282AC', '0xFB' => '0xD792'), 'windows-1253' => array('0x81' => '\'\'', '0x88' => '\'\'', '0x8A' => '\'\'', '0x8C' => '\'\'', '0x8D' => '\'\'', '0x8E' => '\'\'', '0x8F' => '\'\'', '0x90' => '\'\'', '0x98' => '\'\'', '0x9A' => '\'\'', '0x9C' => '\'\'', '0x9D' => '\'\'', '0x9E' => '\'\'', '0x9F' => '\'\'', '0xAA' => '\'\'', '0xD2' => '\'\'', '0xFF' => '\'\'', '0xCE' => '0xCE9E', '0xB8' => '0xCE88', '0xBA' => '0xCE8A', '0xBC' => '0xCE8C', '0xBE' => '0xCE8E', '0xBF' => '0xCE8F', '0xC0' => '0xCE90', '0xC8' => '0xCE98', '0xCA' => '0xCE9A', '0xCC' => '0xCE9C', '0xCD' => '0xCE9D', '0xCF' => '0xCE9F', '0xDA' => '0xCEAA', '0xE8' => '0xCEB8', '0xEA' => '0xCEBA', '0xEC' => '0xCEBC', '0xEE' => '0xCEBE', '0xEF' => '0xCEBF', '0xC2' => '0xFF', '0xBD' => '0xC2BD', '0xED' => '0xCEBD', '0xB2' => '0xC2B2', '0xA0' => '0xC2A0', '0xA3' => '0xC2A3', '0xA4' => '0xC2A4', '0xA5' => '0xC2A5', '0xA6' => '0xC2A6', '0xA7' => '0xC2A7', '0xA8' => '0xC2A8', '0xA9' => '0xC2A9', '0xAB' => '0xC2AB', '0xAC' => '0xC2AC', '0xAD' => '0xC2AD', '0xAE' => '0xC2AE', '0xB0' => '0xC2B0', '0xB1' => '0xC2B1', '0xB3' => '0xC2B3', '0xB5' => '0xC2B5', '0xB6' => '0xC2B6', '0xB7' => '0xC2B7', '0xBB' => '0xC2BB', '0xE2' => '0xCEB2', '0x80' => '0xD2', '0x82' => '0xE2809A', '0x84' => '0xE2809E', '0x85' => '0xE280A6', '0x86' => '0xE280A0', '0xA1' => '0xCE85', '0xA2' => '0xCE86', '0x87' => '0xE280A1', '0x89' => '0xE280B0', '0xB9' => '0xCE89', '0x8B' => '0xE280B9', '0x91' => '0xE28098', '0x99' => '0xE284A2', '0x92' => '0xE28099', '0x93' => '0xE2809C', '0x94' => '0xE2809D', '0x95' => '0xE280A2', '0x96' => '0xE28093', '0x97' => '0xE28094', '0x9B' => '0xE280BA', '0xAF' => '0xE28095', '0xB4' => '0xCE84', '0xC1' => '0xCE91', '0xC3' => '0xCE93', '0xC4' => '0xCE94', '0xC5' => '0xCE95', '0xC6' => '0xCE96', '0x83' => '0xC692', '0xC7' => '0xCE97', '0xC9' => '0xCE99', '0xCB' => '0xCE9B', '0xD0' => '0xCEA0', '0xD1' => '0xCEA1', '0xD3' => '0xCEA3', '0xD4' => '0xCEA4', '0xD5' => '0xCEA5', '0xD6' => '0xCEA6', '0xD7' => '0xCEA7', '0xD8' => '0xCEA8', '0xD9' => '0xCEA9', '0xDB' => '0xCEAB', '0xDC' => '0xCEAC', '0xDD' => '0xCEAD', '0xDE' => '0xCEAE', '0xDF' => '0xCEAF', '0xE0' => '0xCEB0', '0xE1' => '0xCEB1', '0xE3' => '0xCEB3', '0xE4' => '0xCEB4', '0xE5' => '0xCEB5', '0xE6' => '0xCEB6', '0xE7' => '0xCEB7', '0xE9' => '0xCEB9', '0xEB' => '0xCEBB', '0xF0' => '0xCF80', '0xF1' => '0xCF81', '0xF2' => '0xCF82', '0xF3' => '0xCF83', '0xF4' => '0xCF84', '0xF5' => '0xCF85', '0xF6' => '0xCF86', '0xF7' => '0xCF87', '0xF8' => '0xCF88', '0xF9' => '0xCF89', '0xFA' => '0xCF8A', '0xFB' => '0xCF8B', '0xFC' => '0xCF8C', '0xFD' => '0xCF8D', '0xFE' => '0xCF8E', '0xFF' => '0xCE92', '0xD2' => '0xE282AC')); // Make some preparations. if (isset($translation_tables[$_POST['src_charset']])) { $replace = '%field%'; foreach ($translation_tables[$_POST['src_charset']] as $from => $to) { $replace = 'REPLACE(' . $replace . ', ' . $from . ', ' . $to . ')'; } } // Grab a list of tables. if (preg_match('~^`(.+?)`\\.(.+?)$~', $db_prefix, $match) === 1) { $queryTables = $smcFunc['db_query']('', ' SHOW TABLE STATUS FROM `' . strtr($match[1], array('`' => '')) . '` LIKE {string:table_name}', array('table_name' => str_replace('_', '\\_', $match[2]) . '%')); } else { $queryTables = $smcFunc['db_query']('', ' SHOW TABLE STATUS LIKE {string:table_name}', array('table_name' => str_replace('_', '\\_', $db_prefix) . '%')); } while ($table_info = $smcFunc['db_fetch_assoc']($queryTables)) { // Just to make sure it doesn't time out. if (function_exists('apache_reset_timeout')) { @apache_reset_timeout(); } $table_charsets = array(); // Loop through each column. $queryColumns = $smcFunc['db_query']('', ' SHOW FULL COLUMNS FROM ' . $table_info['Name'], array()); while ($column_info = $smcFunc['db_fetch_assoc']($queryColumns)) { // Only text'ish columns have a character set and need converting. if (strpos($column_info['Type'], 'text') !== false || strpos($column_info['Type'], 'char') !== false) { $collation = empty($column_info['Collation']) || $column_info['Collation'] === 'NULL' ? $table_info['Collation'] : $column_info['Collation']; if (!empty($collation) && $collation !== 'NULL') { list($charset) = explode('_', $collation); if (!isset($table_charsets[$charset])) { $table_charsets[$charset] = array(); } $table_charsets[$charset][] = $column_info; } } } $smcFunc['db_free_result']($queryColumns); // Only change the column if the data doesn't match the current charset. if (count($table_charsets) === 1 && key($table_charsets) !== $charsets[$_POST['src_charset']] || count($table_charsets) > 1) { $updates_blob = ''; $updates_text = ''; foreach ($table_charsets as $charset => $columns) { if ($charset !== $charsets[$_POST['src_charset']]) { foreach ($columns as $column) { $updates_blob .= ' CHANGE COLUMN ' . $column['Field'] . ' ' . $column['Field'] . ' ' . strtr($column['Type'], array('text' => 'blob', 'char' => 'binary')) . ($column['Null'] === 'YES' ? ' NULL' : ' NOT NULL') . (strpos($column['Type'], 'char') === false ? '' : ' default \'' . $column['Default'] . '\'') . ','; $updates_text .= ' CHANGE COLUMN ' . $column['Field'] . ' ' . $column['Field'] . ' ' . $column['Type'] . ' CHARACTER SET ' . $charsets[$_POST['src_charset']] . ($column['Null'] === 'YES' ? '' : ' NOT NULL') . (strpos($column['Type'], 'char') === false ? '' : ' default \'' . $column['Default'] . '\'') . ','; } } } // Change the columns to binary form. $smcFunc['db_query']('', ' ALTER TABLE {raw:table_name}{raw:updates_blob}', array('table_name' => $table_info['Name'], 'updates_blob' => substr($updates_blob, 0, -1))); // Convert the character set if MySQL has no native support for it. if (isset($translation_tables[$_POST['src_charset']])) { $update = ''; foreach ($table_charsets as $charset => $columns) { foreach ($columns as $column) { $update .= ' ' . $column['Field'] . ' = ' . strtr($replace, array('%field%' => $column['Field'])) . ','; } } $smcFunc['db_query']('', ' UPDATE {raw:table_name} SET {raw:updates}', array('table_name' => $table_info['Name'], 'updates' => substr($update, 0, -1))); } // Change the columns back, but with the proper character set. $smcFunc['db_query']('', ' ALTER TABLE {raw:table_name}{raw:updates_text}', array('table_name' => $table_info['Name'], 'updates_text' => substr($updates_text, 0, -1))); } // Now do the actual conversion (if still needed). if ($charsets[$_POST['src_charset']] !== 'utf8') { $smcFunc['db_query']('', ' ALTER TABLE {raw:table_name} CONVERT TO CHARACTER SET utf8', array('table_name' => $table_info['Name'])); } } $smcFunc['db_free_result']($queryTables); // Let the settings know we have a new character set. updateSettings(array('global_character_set' => 'UTF-8', 'previousCharacterSet' => empty($translation_tables[$_POST['src_charset']]) ? $charsets[$_POST['src_charset']] : $translation_tables[$_POST['src_charset']])); // Store it in Settings.php too because it's needed before db connection. require_once $sourcedir . '/Subs-Admin.php'; updateSettingsFile(array('db_character_set' => '\'utf8\'')); // The conversion might have messed up some serialized strings. Fix them! require_once $sourcedir . '/Subs-Charset.php'; fix_serialized_columns(); redirectexit('action=admin;area=maintain;done=convertutf8'); }
/** * Ask for the administrator login information. */ function action_adminAccount() { global $txt, $db_type, $db_connection, $databases, $incontext, $db_prefix, $db_passwd; $incontext['sub_template'] = 'admin_account'; $incontext['page_title'] = $txt['user_settings']; $incontext['continue'] = 1; // Need this to check whether we need the database password. require dirname(__FILE__) . '/Settings.php'; if (!defined('ELK')) { define('ELK', 1); } definePaths(); // These files may be or may not be already included, better safe than sorry for now require_once SOURCEDIR . '/Subs.php'; require_once SUBSDIR . '/Util.class.php'; $db = load_database(); if (!isset($_POST['username'])) { $_POST['username'] = ''; } if (!isset($_POST['email'])) { $_POST['email'] = ''; } $incontext['username'] = htmlspecialchars(stripslashes($_POST['username']), ENT_COMPAT, 'UTF-8'); $incontext['email'] = htmlspecialchars(stripslashes($_POST['email']), ENT_COMPAT, 'UTF-8'); $incontext['require_db_confirm'] = empty($db_type) || !empty($databases[$db_type]['require_db_confirm']); // Only allow create an admin account if they don't have one already. $request = $db->query('', ' SELECT id_member FROM {db_prefix}members WHERE id_group = {int:admin_group} OR FIND_IN_SET({int:admin_group}, additional_groups) != 0 LIMIT 1', array('db_error_skip' => true, 'admin_group' => 1)); // Skip the step if an admin already exists if ($db->num_rows($request) != 0) { return true; } $db->free_result($request); // Trying to create an account? if (isset($_POST['password1']) && !empty($_POST['contbutt'])) { // Wrong password? if ($incontext['require_db_confirm'] && $_POST['password3'] != $db_passwd) { $incontext['error'] = $txt['error_db_connect']; return false; } // Not matching passwords? if ($_POST['password1'] != $_POST['password2']) { $incontext['error'] = $txt['error_user_settings_again_match']; return false; } // No password? if (strlen($_POST['password1']) < 4) { $incontext['error'] = $txt['error_user_settings_no_password']; return false; } if (!file_exists(SOURCEDIR . '/Subs.php')) { $incontext['error'] = $txt['error_subs_missing']; return false; } // Update the main contact email? if (!empty($_POST['email']) && (empty($webmaster_email) || $webmaster_email == '*****@*****.**')) { updateSettingsFile(array('webmaster_email' => $_POST['email'])); } // Work out whether we're going to have dodgy characters and remove them. $invalid_characters = preg_match('~[<>&"\'=\\\\]~', $_POST['username']) != 0; $_POST['username'] = preg_replace('~[<>&"\'=\\\\]~', '', $_POST['username']); $result = $db->query('', ' SELECT id_member, password_salt FROM {db_prefix}members WHERE member_name = {string:username} OR email_address = {string:email} LIMIT 1', array('username' => stripslashes($_POST['username']), 'email' => stripslashes($_POST['email']), 'db_error_skip' => true)); if ($db->num_rows($result) != 0) { list($incontext['member_id'], $incontext['member_salt']) = $db->fetch_row($result); $db->free_result($result); $incontext['account_existed'] = $txt['error_user_settings_taken']; } elseif ($_POST['username'] == '' || strlen($_POST['username']) > 25) { // Try the previous step again. $incontext['error'] = $_POST['username'] == '' ? $txt['error_username_left_empty'] : $txt['error_username_too_long']; return false; } elseif ($invalid_characters || $_POST['username'] == '_' || $_POST['username'] == '|' || strpos($_POST['username'], '[code') !== false || strpos($_POST['username'], '[/code') !== false) { // Try the previous step again. $incontext['error'] = $txt['error_invalid_characters_username']; return false; } elseif (empty($_POST['email']) || !filter_var(stripslashes($_POST['email']), FILTER_VALIDATE_EMAIL) || strlen(stripslashes($_POST['email'])) > 255) { // One step back, this time fill out a proper email address. $incontext['error'] = sprintf($txt['error_valid_email_needed'], $_POST['username']); return false; } elseif ($_POST['username'] != '') { require_once SUBSDIR . '/Auth.subs.php'; $incontext['member_salt'] = substr(md5(mt_rand()), 0, 4); // Format the username properly. $_POST['username'] = preg_replace('~[\\t\\n\\r\\x0B\\0\\xA0]+~', ' ', $_POST['username']); $ip = isset($_SERVER['REMOTE_ADDR']) ? substr($_SERVER['REMOTE_ADDR'], 0, 255) : ''; // Get a security hash for this combination $password = stripslashes($_POST['password1']); $incontext['passwd'] = validateLoginPassword($password, '', $_POST['username'], true); $request = $db->insert('', $db_prefix . 'members', array('member_name' => 'string-25', 'real_name' => 'string-25', 'passwd' => 'string', 'email_address' => 'string', 'id_group' => 'int', 'posts' => 'int', 'date_registered' => 'int', 'hide_email' => 'int', 'password_salt' => 'string', 'lngfile' => 'string', 'personal_text' => 'string', 'avatar' => 'string', 'member_ip' => 'string', 'member_ip2' => 'string', 'buddy_list' => 'string', 'pm_ignore_list' => 'string', 'message_labels' => 'string', 'website_title' => 'string', 'website_url' => 'string', 'location' => 'string', 'signature' => 'string', 'usertitle' => 'string', 'secret_question' => 'string', 'additional_groups' => 'string', 'ignore_boards' => 'string', 'openid_uri' => 'string'), array(stripslashes($_POST['username']), stripslashes($_POST['username']), $incontext['passwd'], stripslashes($_POST['email']), 1, 0, time(), 0, $incontext['member_salt'], '', '', '', $ip, $ip, '', '', '', '', '', '', '', '', '', '', '', ''), array('id_member')); // Awww, crud! if ($request === false) { $incontext['error'] = $txt['error_user_settings_query'] . '<br /> <div style="margin: 2ex;">' . nl2br(htmlspecialchars($db->last_error($db_connection), ENT_COMPAT, 'UTF-8')) . '</div>'; return false; } $incontext['member_id'] = $db->insert_id("{$db_prefix}members", 'id_member'); } // If we're here we're good. return true; } return false; }
function saveSettings(&$config_vars) { global $boarddir, $sc, $cookiename, $modSettings, $user_settings; global $sourcedir, $context, $cachedir; // Fix the darn stupid cookiename! (more may not be allowed, but these for sure!) if (isset($_POST['cookiename'])) { $_POST['cookiename'] = preg_replace('~[,;\\s\\.$]+~' . ($context['utf8'] ? 'u' : ''), '', $_POST['cookiename']); } // Fix the forum's URL if necessary. if (isset($_POST['boardurl'])) { if (substr($_POST['boardurl'], -10) == '/index.php') { $_POST['boardurl'] = substr($_POST['boardurl'], 0, -10); } elseif (substr($_POST['boardurl'], -1) == '/') { $_POST['boardurl'] = substr($_POST['boardurl'], 0, -1); } if (substr($_POST['boardurl'], 0, 7) != 'http://' && substr($_POST['boardurl'], 0, 7) != 'file://' && substr($_POST['boardurl'], 0, 8) != 'https://') { $_POST['boardurl'] = 'http://' . $_POST['boardurl']; } } // Any passwords? $config_passwords = array('db_passwd', 'ssi_db_passwd'); // All the strings to write. $config_strs = array('mtitle', 'mmessage', 'language', 'mbname', 'boardurl', 'cookiename', 'webmaster_email', 'db_name', 'db_user', 'db_server', 'db_prefix', 'ssi_db_user', 'boarddir', 'sourcedir', 'cachedir'); // All the numeric variables. $config_ints = array(); // All the checkboxes. $config_bools = array('db_persist', 'db_error_send', 'maintenance'); // Now sort everything into a big array, and figure out arrays and etc. $new_settings = array(); foreach ($config_passwords as $config_var) { if (isset($_POST[$config_var][1]) && $_POST[$config_var][0] == $_POST[$config_var][1]) { $new_settings[$config_var] = '\'' . addcslashes($_POST[$config_var][0], '\'\\') . '\''; } } foreach ($config_strs as $config_var) { if (isset($_POST[$config_var])) { $new_settings[$config_var] = '\'' . addcslashes($_POST[$config_var], '\'\\') . '\''; } } foreach ($config_ints as $config_var) { if (isset($_POST[$config_var])) { $new_settings[$config_var] = (int) $_POST[$config_var]; } } foreach ($config_bools as $key) { if (!empty($_POST[$key])) { $new_settings[$key] = '1'; } else { $new_settings[$key] = '0'; } } // Save the relevant settings in the Settings.php file. require_once $sourcedir . '/Subs-Admin.php'; updateSettingsFile($new_settings); // Now loopt through the remaining (database-based) settings. $new_settings = array(); foreach ($config_vars as $config_var) { // We just saved the file-based settings, so skip their definitions. if (!is_array($config_var) || $config_var[2] == 'file') { continue; } // Rewrite the definition a bit. $new_settings[] = array($config_var[3], $config_var[0]); } // Save the new database-based settings, if any. if (!empty($new_settings)) { saveDBSettings($new_settings); } }
function doStep2() { global $txt, $db_prefix, $db_connection, $HTTP_SESSION_VARS, $cookiename; global $func, $db_character_set, $mbname, $context, $scripturl, $boardurl; global $current_smf_version; // Load the SQL server login information. require_once dirname(__FILE__) . '/Settings.php'; if (!isset($_POST['password3'])) { return doStep2a(); } $db_connection = @mysql_connect($db_server, $db_user, $_POST['password3']); if (!$db_connection) { echo ' <div class="error_message"> <div style="color: red;">', $txt['error_mysql_connect'], '</div> </div>'; return doStep2a(); } if (!mysql_select_db($db_name, $db_connection)) { echo ' <div class="error_message"> <div style="color: red;">', sprintf($txt['error_mysql_database'], $db_name), '</div> </div> <br />'; return doStep2a(); } // Let them try again... if ($_POST['password1'] != $_POST['password2']) { echo ' <div class="error_message"> <div style="color: red;">', $txt['error_user_settings_again_match'], '</div> </div> <br />'; return doStep2a(); } if (!file_exists($sourcedir . '/Subs.php')) { echo ' <div class="error_message"> <div style="color: red;">', $txt['error_subs_missing'], '</div> </div> <br />'; return doStep2a(); } updateSettingsFile(array('webmaster_email' => $_POST['email'])); chdir(dirname(__FILE__)); define('SMF', 1); require_once $sourcedir . '/Subs.php'; require_once $sourcedir . '/Load.php'; require_once $sourcedir . '/Security.php'; require_once $sourcedir . '/Subs-Auth.php'; // Define the sha1 function, if it doesn't exist. if (!function_exists('sha1')) { require_once $sourcedir . '/Subs-Compat.php'; } if (isset($db_character_set)) { mysql_query("\n\t\t\tSET NAMES {$db_character_set}"); } $result = mysql_query("\n\t\tSELECT ID_MEMBER, passwordSalt\n\t\tFROM {$db_prefix}members\n\t\tWHERE memberName = '{$_POST['username']}' OR emailAddress = '{$_POST['email']}'\n\t\tLIMIT 1"); if (mysql_num_rows($result) != 0) { list($id, $salt) = mysql_fetch_row($result); mysql_free_result($result); echo ' <div class="error_message"> <div style="color: red;">', $txt['error_user_settings_taken'], '</div> </div> <br />'; } elseif (preg_match('~[<>&"\'=\\\\]~', $_POST['username']) != 0 || strlen($_POST['username']) > 25 || $_POST['username'] == '_' || $_POST['username'] == '|' || strpos($_POST['username'], '[code') !== false || strpos($_POST['username'], '[/code') !== false) { // Initialize some variables needed for the language file. $context = array('forum_name' => $mbname); $modSettings = array('lastActive' => '15', 'hotTopicPosts' => '15', 'hotTopicVeryPosts' => '25', 'smfVersion' => $current_smf_version); $scripturl = $boardurl . '/index.php'; require_once dirname(__FILE__) . '/Themes/default/languages/' . strtr($_SESSION['installer_temp_lang'], array('Install' => 'index')); echo ' <div class="error_message"> <div style="color: red;">', $txt[240], '</div> </div> <br />'; // Try the previous step again. return doStep2a(); } elseif (empty($_POST['email']) || preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', stripslashes($_POST['email'])) === 0 || strlen(stripslashes($_POST['email'])) > 255) { // Artificially fill some of the globals needed for the language files. $context = array('forum_name' => $mbname); $modSettings = array('lastActive' => '15', 'hotTopicPosts' => '15', 'hotTopicVeryPosts' => '25', 'smfVersion' => $current_smf_version); $scripturl = $boardurl . '/index.php'; require_once dirname(__FILE__) . '/Themes/default/languages/' . strtr($_SESSION['installer_temp_lang'], array('Install' => 'index')); require_once dirname(__FILE__) . '/Themes/default/languages/' . strtr($_SESSION['installer_temp_lang'], array('Install' => 'Login')); echo ' <div class="error_message"> <div style="color: red;">', sprintf($txt[500], $_POST['username']), '</div> </div> <br />'; // One step back, this time fill out a proper email address. return doStep2a(); } elseif ($_POST['username'] != '') { $salt = substr(md5(mt_rand()), 0, 4); // Format the username properly. $_POST['username'] = preg_replace('~[\\t\\n\\r\\x0B\\0\\xA0]+~', ' ', $_POST['username']); $ip = isset($_SERVER['REMOTE_ADDR']) ? addslashes(substr(stripslashes($_SERVER['REMOTE_ADDR']), 0, 255)) : ''; $request = mysql_query("\n\t\t\tINSERT INTO {$db_prefix}members\n\t\t\t\t(memberName, realName, passwd, emailAddress, ID_GROUP, posts, dateRegistered, hideEmail, passwordSalt, lngfile, personalText, avatar, memberIP, memberIP2, buddy_list, pm_ignore_list, messageLabels, websiteTitle, websiteUrl, location, ICQ, MSN, signature, usertitle, secretQuestion, additionalGroups)\n\t\t\tVALUES (SUBSTRING('{$_POST['username']}', 1, 25), SUBSTRING('{$_POST['username']}', 1, 25), '" . sha1(strtolower($_POST['username']) . $_POST['password1']) . "', '{$_POST['email']}', 1, '0', '" . time() . "', '0', '{$salt}', '', '', '', '{$ip}', '{$ip}', '', '', '', '', '', '', '', '', '', '', '', '')"); // Awww, crud! if ($request === false) { echo ' <div class="error_message"> <div style="color: red;">', $txt['error_user_settings_query'], '</div> <div style="margin: 2ex;">', nl2br(htmlspecialchars(mysql_error($db_connection))), '</div> <a href="', $_SERVER['PHP_SELF'], '?step=2">', $txt['error_message_click'], '</a> ', $txt['error_message_try_again'], ' </div>'; return false; } $id = mysql_insert_id(); } // Automatically log them in ;). if (isset($id) && isset($salt)) { setLoginCookie(3153600 * 60, $id, sha1(sha1(strtolower($_POST['username']) . $_POST['password1']) . $salt)); } $result = mysql_query("\n\t\tSELECT value\n\t\tFROM {$db_prefix}settings\n\t\tWHERE variable = 'databaseSession_enable'"); if (mysql_num_rows($result) != 0) { list($db_sessions) = mysql_fetch_row($result); } mysql_free_result($result); if (empty($db_sessions)) { if (@version_compare(PHP_VERSION, '4.2.0') == -1) { $HTTP_SESSION_VARS['php_412_bugfix'] = true; } $_SESSION['admin_time'] = time(); } else { $_SERVER['HTTP_USER_AGENT'] = addslashes(substr($_SERVER['HTTP_USER_AGENT'], 0, 211)); mysql_query("\n\t\t\tINSERT INTO {$db_prefix}sessions\n\t\t\t\t(session_id, last_update, data)\n\t\t\tVALUES ('" . session_id() . "', " . time() . ",\n\t\t\t\t'USER_AGENT|s:" . strlen(stripslashes($_SERVER['HTTP_USER_AGENT'])) . ":\"{$_SERVER['HTTP_USER_AGENT']}\";admin_time|i:" . time() . ";')"); } updateStats('member'); updateStats('message'); updateStats('topic'); // This function is needed to do the updateStats('subject') call. $func['strtolower'] = $db_character_set === 'utf8' || $txt['lang_character_set'] === 'UTF-8' ? create_function('$string', ' return $string;') : 'strtolower'; $request = mysql_query("\n\t\tSELECT ID_MSG\n\t\tFROM {$db_prefix}messages\n\t\tWHERE ID_MSG = 1\n\t\t\tAND modifiedTime = 0\n\t\tLIMIT 1"); if (mysql_num_rows($request) > 0) { updateStats('subject', 1, addslashes(htmlspecialchars($txt['default_topic_subject']))); } mysql_free_result($request); echo ' <div class="panel"> <h2>', $txt['congratulations'], '</h2> <br /> ', $txt['congratulations_help'], '<br /> <br />'; if (is_writable(dirname(__FILE__)) && substr(__FILE__, 1, 2) != ':\\') { echo ' <i>', $txt['still_writable'], '</i><br /> <br />'; } // Don't show the box if it's like 99% sure it won't work :P. if (isset($_SESSION['installer_temp_ftp']) || is_writable(dirname(__FILE__)) || is_writable(__FILE__)) { echo ' <div style="margin: 1ex; font-weight: bold;"> <label for="delete_self"><input type="checkbox" id="delete_self" onclick="doTheDelete();" /> ', $txt['delete_installer'], !isset($_SESSION['installer_temp_ftp']) ? ' ' . $txt['delete_installer_maybe'] : '', '</label> </div> <script language="JavaScript" type="text/javascript"><!-- // --><![CDATA[ function doTheDelete() { var theCheck = document.getElementById ? document.getElementById("delete_self") : document.all.delete_self; var tempImage = new Image(); tempImage.src = "', $_SERVER['PHP_SELF'], '?delete=1&ts=" + (new Date().getTime()); tempImage.width = 0; theCheck.disabled = true; } // ]]></script> <br />'; } echo ' ', sprintf($txt['go_to_your_forum'], $boardurl . '/index.php'), '<br /> <br /> ', $txt['good_luck'], ' </div>'; return true; }
<div style="margin: 2.5ex; font-family: monospace;"><b>', $mysql_error, '</b></div> <a href="', $_SERVER['PHP_SELF'], '?step=0&overphp=true">', $install_lang['error_message_click'], '</a> ', $install_lang['error_message_try_again'], ' </div>'; return false; } // Let's try that database on for size... if ($database != '') { mysql_query("\r\n CREATE DATABASE IF NOT EXISTS `{$database}`", $db_connection); } // Okay, let's try the prefix if it didn't work... if (!mysql_select_db($database, $db_connection) && $database != '') { mysql_query("\r\n CREATE DATABASE IF NOT EXISTS `{$TABLE_PREFIX}{$database}`", $db_connection); if (mysql_select_db($TABLE_PREFIX . $database, $db_connection)) { $db_name = $TABLE_PREFIX . $db_name; updateSettingsFile(array('database' => $database)); } } // Okay, now let's try to connect... if (!mysql_select_db($database, $db_connection)) { echo ' <div class="error_message"> <div style="color: red;">', sprintf($install_lang['error_mysql_database'], $database), '</div> <br /> <a href="', $_SERVER['PHP_SELF'], '?step=0&overphp=true">', $install_lang['error_message_click'], '</a> ', $install_lang['error_message_try_again'], ' </div>'; return false; } $replaces = array('{$db_prefix}' => $TABLE_PREFIX); foreach ($install_lang as $key => $value) { if (substr($key, 0, 8) == 'default_') {
function show_db_error($loadavg = false) { global $sourcedir, $mbname, $maintenance, $mtitle, $mmessage, $modSettings; global $db_connection, $webmaster_email, $db_last_error, $db_error_send, $smcFunc; // Don't cache this page! header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); header('Cache-Control: no-cache'); // Send the right error codes. header('HTTP/1.1 503 Service Temporarily Unavailable'); header('Status: 503 Service Temporarily Unavailable'); header('Retry-After: 3600'); if ($loadavg == false) { // For our purposes, we're gonna want this on if at all possible. $modSettings['cache_enable'] = '1'; if (($temp = cache_get_data('db_last_error', 600)) !== null) { $db_last_error = max($db_last_error, $temp); } if ($db_last_error < time() - 3600 * 24 * 3 && empty($maintenance) && !empty($db_error_send)) { require_once $sourcedir . '/Subs-Admin.php'; // Avoid writing to the Settings.php file if at all possible; use shared memory instead. cache_put_data('db_last_error', time(), 600); if (($temp = cache_get_data('db_last_error', 600)) === null) { updateSettingsFile(array('db_last_error' => time())); } // Language files aren't loaded yet :(. $db_error = @$smcFunc['db_error']($db_connection); @mail($webmaster_email, $mbname . ': SMF Database Error!', 'There has been a problem with the database!' . ($db_error == '' ? '' : "\n" . $smcFunc['db_title'] . ' reported:' . "\n" . $db_error) . "\n\n" . 'This is a notice email to let you know that SMF could not connect to the database, contact your host if this continues.'); } } if (!empty($maintenance)) { echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta name="robots" content="noindex" /> <title>', $mtitle, '</title> </head> <body> <h3>', $mtitle, '</h3> ', $mmessage, ' </body> </html>'; } elseif ($loadavg) { echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta name="robots" content="noindex" /> <title>Temporarily Unavailable</title> </head> <body> <h3>Temporarily Unavailable</h3> Due to high stress on the server the forum is temporarily unavailable. Please try again later. </body> </html>'; } else { echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta name="robots" content="noindex" /> <title>Connection Problems</title> </head> <body> <h3>Connection Problems</h3> Sorry, SMF was unable to connect to the database. This may be caused by the server being busy. Please try again later. </body> </html>'; } die; }
function ModifyCoreSettings2() { global $boarddir, $sc, $cookiename, $modSettings, $user_settings, $sourcedir; global $context; // Strip the slashes off of the post vars. foreach ($_POST as $key => $val) { $_POST[$key] = stripslashes__recursive($val); } // Fix the darn stupid cookiename! (more may not be allowed, but these for sure!) if (isset($_POST['cookiename'])) { $_POST['cookiename'] = preg_replace('~[,;\\s\\.$]+~' . ($context['utf8'] ? 'u' : ''), '', $_POST['cookiename']); } // Fix the forum's URL if necessary. if (substr($_POST['boardurl'], -10) == '/index.php') { $_POST['boardurl'] = substr($_POST['boardurl'], 0, -10); } elseif (substr($_POST['boardurl'], -1) == '/') { $_POST['boardurl'] = substr($_POST['boardurl'], 0, -1); } if (substr($_POST['boardurl'], 0, 7) != 'http://' && substr($_POST['boardurl'], 0, 7) != 'file://' && substr($_POST['boardurl'], 0, 8) != 'https://') { $_POST['boardurl'] = 'http://' . $_POST['boardurl']; } // Any passwords? $config_passwords = array('db_passwd'); // All the strings to write. $config_strs = array('mtitle', 'mmessage', 'language', 'mbname', 'boardurl', 'cookiename', 'webmaster_email', 'db_name', 'db_user', 'db_server', 'db_prefix', 'boarddir', 'sourcedir'); // All the numeric variables. $config_ints = array(); // All the checkboxes. $config_bools = array('db_persist', 'db_error_send', 'maintenance'); // Now sort everything into a big array, and figure out arrays and etc. $config_vars = array(); foreach ($config_passwords as $config_var) { if (isset($_POST[$config_var][1]) && $_POST[$config_var][0] == $_POST[$config_var][1]) { $config_vars[$config_var] = '\'' . addcslashes($_POST[$config_var][0], "'\\") . '\''; } } foreach ($config_strs as $config_var) { if (isset($_POST[$config_var])) { $config_vars[$config_var] = '\'' . addcslashes($_POST[$config_var], "'\\") . '\''; } } foreach ($config_ints as $config_var) { if (isset($_POST[$config_var])) { $config_vars[$config_var] = (int) $_POST[$config_var]; } } foreach ($config_bools as $key) { if (!empty($_POST[$key])) { $config_vars[$key] = '1'; } else { $config_vars[$key] = '0'; } } require_once $sourcedir . '/Admin.php'; updateSettingsFile($config_vars); // If the cookie name was changed, reset the cookie. if (isset($config_vars['cookiename']) && $cookiename != $_POST['cookiename']) { include_once $sourcedir . '/Subs-Auth.php'; $cookiename = $_POST['cookiename']; setLoginCookie(60 * $modSettings['cookieTime'], $user_settings['ID_MEMBER'], sha1($user_settings['passwd'] . $user_settings['passwordSalt'])); redirectexit('action=serversettings;sa=core;sesc=' . $sc, $context['server']['needs_login_fix']); } redirectexit('action=serversettings;sa=core;sesc=' . $sc); }
/** * Edit a particular set of language entries. */ function ModifyLanguage() { global $settings, $context, $smcFunc, $txt, $modSettings, $boarddir, $sourcedir, $language; loadLanguage('ManageSettings'); // Select the languages tab. $context['menu_data_' . $context['admin_menu_id']]['current_subsection'] = 'edit'; $context['page_title'] = $txt['edit_languages']; $context['sub_template'] = 'modify_language_entries'; $context['lang_id'] = $_GET['lid']; list($theme_id, $file_id) = empty($_REQUEST['tfid']) || strpos($_REQUEST['tfid'], '+') === false ? array(1, '') : explode('+', $_REQUEST['tfid']); // Clean the ID - just in case. preg_match('~([A-Za-z0-9_-]+)~', $context['lang_id'], $matches); $context['lang_id'] = $matches[1]; // Get all the theme data. $request = $smcFunc['db_query']('', ' SELECT id_theme, variable, value FROM {db_prefix}themes WHERE id_theme != {int:default_theme} AND id_member = {int:no_member} AND variable IN ({string:name}, {string:theme_dir})', array('default_theme' => 1, 'no_member' => 0, 'name' => 'name', 'theme_dir' => 'theme_dir')); $themes = array(1 => array('name' => $txt['dvc_default'], 'theme_dir' => $settings['default_theme_dir'])); while ($row = $smcFunc['db_fetch_assoc']($request)) { $themes[$row['id_theme']][$row['variable']] = $row['value']; } $smcFunc['db_free_result']($request); // This will be where we look $lang_dirs = array(); // Check we have themes with a path and a name - just in case - and add the path. foreach ($themes as $id => $data) { if (count($data) != 2) { unset($themes[$id]); } elseif (is_dir($data['theme_dir'] . '/languages')) { $lang_dirs[$id] = $data['theme_dir'] . '/languages'; } // How about image directories? if (is_dir($data['theme_dir'] . '/images/' . $context['lang_id'])) { $images_dirs[$id] = $data['theme_dir'] . '/images/' . $context['lang_id']; } } $current_file = $file_id ? $lang_dirs[$theme_id] . '/' . $file_id . '.' . $context['lang_id'] . '.php' : ''; // Now for every theme get all the files and stick them in context! $context['possible_files'] = array(); foreach ($lang_dirs as $theme => $theme_dir) { // Open it up. $dir = dir($theme_dir); while ($entry = $dir->read()) { // We're only after the files for this language. if (preg_match('~^([A-Za-z]+)\\.' . $context['lang_id'] . '\\.php$~', $entry, $matches) == 0) { continue; } if (!isset($context['possible_files'][$theme])) { $context['possible_files'][$theme] = array('id' => $theme, 'name' => $themes[$theme]['name'], 'files' => array()); } $context['possible_files'][$theme]['files'][] = array('id' => $matches[1], 'name' => isset($txt['lang_file_desc_' . $matches[1]]) ? $txt['lang_file_desc_' . $matches[1]] : $matches[1], 'selected' => $theme_id == $theme && $file_id == $matches[1]); } $dir->close(); usort($context['possible_files'][$theme]['files'], create_function('$val1, $val2', 'return strcmp($val1[\'name\'], $val2[\'name\']);')); } // We no longer wish to speak this language. if (!empty($_POST['delete_main']) && $context['lang_id'] != 'english') { checkSession(); validateToken('admin-mlang'); // @todo Todo: FTP Controls? require_once $sourcedir . '/Subs-Package.php'; // First, Make a backup? if (!empty($modSettings['package_make_backups']) && (!isset($_SESSION['last_backup_for']) || $_SESSION['last_backup_for'] != $context['lang_id'] . '$$$')) { $_SESSION['last_backup_for'] = $context['lang_id'] . '$$$'; package_create_backup('backup_lang_' . $context['lang_id']); } // Second, loop through the array to remove the files. foreach ($lang_dirs as $curPath) { foreach ($context['possible_files'][1]['files'] as $lang) { if (file_exists($curPath . '/' . $lang['id'] . '.' . $context['lang_id'] . '.php')) { unlink($curPath . '/' . $lang['id'] . '.' . $context['lang_id'] . '.php'); } } // Check for the email template. if (file_exists($curPath . '/EmailTemplates.' . $context['lang_id'] . '.php')) { unlink($curPath . '/EmailTemplates.' . $context['lang_id'] . '.php'); } } // Third, the agreement file. if (file_exists($boarddir . '/agreement.' . $context['lang_id'] . '.txt')) { unlink($boarddir . '/agreement.' . $context['lang_id'] . '.txt'); } // Fourth, a related images folder? foreach ($images_dirs as $curPath) { if (is_dir($curPath)) { deltree($curPath); } } // Members can no longer use this language. $smcFunc['db_query']('', ' UPDATE {db_prefix}members SET lngfile = {string:empty_string} WHERE lngfile = {string:current_language}', array('empty_string' => '', 'current_language' => $context['lang_id'])); // Fifth, update getLanguages() cache. if (!empty($modSettings['cache_enable'])) { cache_put_data('known_languages', null, !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600); cache_put_data('known_languages_all', null, !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600); } // Sixth, if we deleted the default language, set us back to english? if ($context['lang_id'] == $language) { require_once $sourcedir . '/Subs-Admin.php'; $language = 'english'; updateSettingsFile(array('language' => '\'' . $language . '\'')); } // Seventh, get out of here. redirectexit('action=admin;area=languages;sa=edit;' . $context['session_var'] . '=' . $context['session_id']); } // Saving primary settings? $madeSave = false; if (!empty($_POST['save_main']) && !$current_file) { checkSession(); validateToken('admin-mlang'); // Read in the current file. $current_data = implode('', file($settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php')); // These are the replacements. old => new $replace_array = array('~\\$txt\\[\'lang_character_set\'\\]\\s=\\s(\'|")[^\\r\\n]+~' => '$txt[\'lang_character_set\'] = \'' . addslashes($_POST['character_set']) . '\';', '~\\$txt\\[\'lang_locale\'\\]\\s=\\s(\'|")[^\\r\\n]+~' => '$txt[\'lang_locale\'] = \'' . addslashes($_POST['locale']) . '\';', '~\\$txt\\[\'lang_dictionary\'\\]\\s=\\s(\'|")[^\\r\\n]+~' => '$txt[\'lang_dictionary\'] = \'' . addslashes($_POST['dictionary']) . '\';', '~\\$txt\\[\'lang_spelling\'\\]\\s=\\s(\'|")[^\\r\\n]+~' => '$txt[\'lang_spelling\'] = \'' . addslashes($_POST['spelling']) . '\';', '~\\$txt\\[\'lang_rtl\'\\]\\s=\\s[A-Za-z0-9]+;~' => '$txt[\'lang_rtl\'] = ' . (!empty($_POST['rtl']) ? 'true' : 'false') . ';'); $current_data = preg_replace(array_keys($replace_array), array_values($replace_array), $current_data); $fp = fopen($settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php', 'w+'); fwrite($fp, $current_data); fclose($fp); $madeSave = true; } // Quickly load index language entries. $old_txt = $txt; require $settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php'; $context['lang_file_not_writable_message'] = is_writable($settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php') ? '' : sprintf($txt['lang_file_not_writable'], $settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php'); // Setup the primary settings context. $context['primary_settings'] = array('name' => $smcFunc['ucwords'](strtr($context['lang_id'], array('_' => ' ', '-utf8' => ''))), 'character_set' => $txt['lang_character_set'], 'locale' => $txt['lang_locale'], 'dictionary' => $txt['lang_dictionary'], 'spelling' => $txt['lang_spelling'], 'rtl' => $txt['lang_rtl']); // Restore normal service. $txt = $old_txt; // Are we saving? $save_strings = array(); if (isset($_POST['save_entries']) && !empty($_POST['entry'])) { checkSession(); validateToken('admin-mlang'); // Clean each entry! foreach ($_POST['entry'] as $k => $v) { // Only try to save if it's changed! if ($_POST['entry'][$k] != $_POST['comp'][$k]) { $save_strings[$k] = cleanLangString($v, false); } } } // If we are editing a file work away at that. if ($current_file) { $context['entries_not_writable_message'] = is_writable($current_file) ? '' : sprintf($txt['lang_entries_not_writable'], $current_file); $entries = array(); // We can't just require it I'm afraid - otherwise we pass in all kinds of variables! $multiline_cache = ''; foreach (file($current_file) as $line) { // Got a new entry? if ($line[0] == '$' && !empty($multiline_cache)) { preg_match('~\\$(helptxt|txt|editortxt)\\[\'(.+)\'\\]\\s?=\\s?(.+);~ms', strtr($multiline_cache, array("\r" => '')), $matches); if (!empty($matches[3])) { $entries[$matches[2]] = array('type' => $matches[1], 'full' => $matches[0], 'entry' => $matches[3]); $multiline_cache = ''; } } $multiline_cache .= $line; } // Last entry to add? if ($multiline_cache) { preg_match('~\\$(helptxt|txt|editortxt)\\[\'(.+)\'\\]\\s?=\\s?(.+);~ms', strtr($multiline_cache, array("\r" => '')), $matches); if (!empty($matches[3])) { $entries[$matches[2]] = array('type' => $matches[1], 'full' => $matches[0], 'entry' => $matches[3]); } } // These are the entries we can definitely save. $final_saves = array(); $context['file_entries'] = array(); foreach ($entries as $entryKey => $entryValue) { // Ignore some things we set separately. $ignore_files = array('lang_character_set', 'lang_locale', 'lang_dictionary', 'lang_spelling', 'lang_rtl'); if (in_array($entryKey, $ignore_files)) { continue; } // These are arrays that need breaking out. $arrays = array('days', 'days_short', 'months', 'months_titles', 'months_short', 'happy_birthday_author', 'karlbenson1_author', 'nite0859_author', 'zwaldowski_author', 'geezmo_author', 'karlbenson2_author'); if (in_array($entryKey, $arrays)) { // Get off the first bits. $entryValue['entry'] = substr($entryValue['entry'], strpos($entryValue['entry'], '(') + 1, strrpos($entryValue['entry'], ')') - strpos($entryValue['entry'], '(')); $entryValue['entry'] = explode(',', strtr($entryValue['entry'], array(' ' => ''))); // Now create an entry for each item. $cur_index = 0; $save_cache = array('enabled' => false, 'entries' => array()); foreach ($entryValue['entry'] as $id => $subValue) { // Is this a new index? if (preg_match('~^(\\d+)~', $subValue, $matches)) { $cur_index = $matches[1]; $subValue = substr($subValue, strpos($subValue, '\'')); } // Clean up some bits. $subValue = strtr($subValue, array('"' => '', '\'' => '', ')' => '')); // Can we save? if (isset($save_strings[$entryKey . '-+- ' . $cur_index])) { $save_cache['entries'][$cur_index] = strtr($save_strings[$entryKey . '-+- ' . $cur_index], array('\'' => '')); $save_cache['enabled'] = true; } else { $save_cache['entries'][$cur_index] = $subValue; } $context['file_entries'][] = array('key' => $entryKey . '-+- ' . $cur_index, 'value' => $subValue, 'rows' => 1); $cur_index++; } // Do we need to save? if ($save_cache['enabled']) { // Format the string, checking the indexes first. $items = array(); $cur_index = 0; foreach ($save_cache['entries'] as $k2 => $v2) { // Manually show the custom index. if ($k2 != $cur_index) { $items[] = $k2 . ' => \'' . $v2 . '\''; $cur_index = $k2; } else { $items[] = '\'' . $v2 . '\''; } $cur_index++; } // Now create the string! $final_saves[$entryKey] = array('find' => $entryValue['full'], 'replace' => '$' . $entryValue['type'] . '[\'' . $entryKey . '\'] = array(' . implode(', ', $items) . ');'); } } else { // Saving? if (isset($save_strings[$entryKey]) && $save_strings[$entryKey] != $entryValue['entry']) { // @todo Fix this properly. if ($save_strings[$entryKey] == '') { $save_strings[$entryKey] = '\'\''; } // Set the new value. $entryValue['entry'] = $save_strings[$entryKey]; // And we know what to save now! $final_saves[$entryKey] = array('find' => $entryValue['full'], 'replace' => '$' . $entryValue['type'] . '[\'' . $entryKey . '\'] = ' . $save_strings[$entryKey] . ';'); } $editing_string = cleanLangString($entryValue['entry'], true); $context['file_entries'][] = array('key' => $entryKey, 'value' => $editing_string, 'rows' => (int) (strlen($editing_string) / 38) + substr_count($editing_string, "\n") + 1); } } // Any saves to make? if (!empty($final_saves)) { checkSession(); $file_contents = implode('', file($current_file)); foreach ($final_saves as $save) { $file_contents = strtr($file_contents, array($save['find'] => $save['replace'])); } // Save the actual changes. $fp = fopen($current_file, 'w+'); fwrite($fp, strtr($file_contents, array("\r" => ''))); fclose($fp); $madeSave = true; } // Another restore. $txt = $old_txt; } // If we saved, redirect. if ($madeSave) { redirectexit('action=admin;area=languages;sa=editlang;lid=' . $context['lang_id']); } createToken('admin-mlang'); }