In some cases, FTP clients do not properly upload files with this many folders. Please double check to make sure you have uploaded all the files in the distribution.
If that doesn\'t help, please make sure this install.php file is in the same place as the Themes folder.
';
die;
}
// Override the language file?
if (isset($_GET['lang_file']))
$_SESSION['installer_temp_lang'] = $_GET['lang_file'];
elseif (isset($GLOBALS['HTTP_GET_VARS']['lang_file']))
$_SESSION['installer_temp_lang'] = $GLOBALS['HTTP_GET_VARS']['lang_file'];
// Make sure it exists, if it doesn't reset it.
if (!isset($_SESSION['installer_temp_lang']) || !file_exists(dirname(__FILE__) . '/Themes/default/languages/' . $_SESSION['installer_temp_lang']))
{
// Use the first one...
list ($_SESSION['installer_temp_lang']) = array_keys($incontext['detected_languages']);
// If we have english and some other language, use the other language. We Americans hate english :P.
if ($_SESSION['installer_temp_lang'] == 'Install.english.php' && count($incontext['detected_languages']) > 1)
list (, $_SESSION['installer_temp_lang']) = array_keys($incontext['detected_languages']);
}
// And now include the actual language file itself.
require_once(dirname(__FILE__) . '/Themes/default/languages/' . $_SESSION['installer_temp_lang']);
}
// This handy function loads some settings and the like.
function load_database()
{
global $db_prefix, $db_connection, $db_character_set, $sourcedir, $language;
global $smcFunc, $mbname, $scripturl, $boardurl, $modSettings, $db_type, $db_name, $db_user;
// Need this to check whether we need the database password.
require(dirname(__FILE__) . '/Settings.php');
if (!defined('SMF'))
define('SMF', 1);
if (empty($smcFunc))
$smcFunc = array();
$modSettings['disableQueryCheck'] = true;
// Connect the database.
if (!$db_connection)
{
require_once($sourcedir . '/Subs-Db-' . $db_type . '.php');
if (@version_compare(PHP_VERSION, '5') == -1)
require_once($sourcedir . '/Subs-Compat.php');
if (!$db_connection)
$db_connection = smf_db_initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix, array('persist' => $db_persist));
}
}
// This is called upon exiting the installer, for template etc.
function installExit($fallThrough = false)
{
global $incontext, $installurl, $txt;
// Send character set.
header('Content-Type: text/html; charset=' . (isset($txt['lang_character_set']) ? $txt['lang_character_set'] : 'ISO-8859-1'));
// We usually dump our templates out.
if (!$fallThrough)
{
// The top install bit.
template_install_above();
// Call the template.
if (isset($incontext['sub_template']))
{
$incontext['form_url'] = $installurl . '?step=' . $incontext['current_step'];
call_user_func('template_' . $incontext['sub_template']);
}
//!!! REMOVE THIS!!
else
{
if (function_exists('doStep' . $_GET['step']))
call_user_func('doStep' . $_GET['step']);
}
// Show the footer.
template_install_below();
}
// Bang - gone!
die();
}
function Welcome()
{
global $incontext, $txt, $databases, $installurl;
$incontext['page_title'] = $txt['install_welcome'];
$incontext['sub_template'] = 'welcome_message';
// Done the submission?
if (isset($_POST['contbutt']))
return true;
// Check the PHP version.
if ((!function_exists('version_compare') || version_compare($GLOBALS['required_php_version'], PHP_VERSION) > 0))
{
$incontext['warning'] = $txt['error_php_too_low'];
}
// See if we think they have already installed it?
if (file_exists(dirname(__FILE__) . '/Settings.php'))
{
$probably_installed = 0;
foreach (file(dirname(__FILE__) . '/Settings.php') as $line)
{
if (preg_match('~^\$db_passwd\s=\s\'([^\']+)\';$~', $line))
$probably_installed++;
if (preg_match('~^\$boardurl\s=\s\'([^\']+)\';~', $line) && !preg_match('~^\$boardurl\s=\s\'http://127\.0\.0\.1/smf\';~', $line))
$probably_installed++;
}
if ($probably_installed == 2)
$incontext['warning'] = $txt['error_already_installed'];
}
// Is some database support even compiled in?
$incontext['supported_databases'] = array();
foreach ($databases as $key => $db)
{
if ($db['supported'])
{
if (!file_exists(dirname(__FILE__) . '/install_' . $GLOBALS['db_script_version'] . '_' . $key . '.sql'))
{
$databases[$key]['supported'] = false;
$notFoundSQLFile = true;
$txt['error_db_script_missing'] = sprintf($txt['error_db_script_missing'], 'install_' . $GLOBALS['db_script_version'] . '_' . $key . '.sql');
}
else
{
$db_type = $key;
$incontext['supported_databases'][] = $db;
}
}
}
if (empty($incontext['supported_databases']))
$error = empty($notFoundSQLFile) ? 'error_db_missing' : 'error_db_script_missing';
// How about session support? Some crazy sysadmin remove it?
elseif (!function_exists('session_start'))
$error = 'error_session_missing';
// Make sure they uploaded all the files.
elseif (!file_exists(dirname(__FILE__) . '/index.php'))
$error = 'error_missing_files';
// Very simple check on the session.save_path for Windows.
// !!! Move this down later if they don't use database-driven sessions?
elseif (@ini_get('session.save_path') == '/tmp' && substr(__FILE__, 1, 2) == ':\\')
$error = 'error_session_save_path';
// Since each of the three messages would look the same, anyway...
if (isset($error))
$incontext['error'] = $txt[$error];
// Mod_security blocks everything that smells funny. Let SMF handle security.
if (!fixModSecurity() && !isset($_GET['overmodsecurity']))
$incontext['error'] = $txt['error_mod_security'] . '
' . $txt['error_message_click'] . ' ' . $txt['error_message_bad_try_again'];
return false;
}
function CheckFilesWritable()
{
global $txt, $incontext;
$incontext['page_title'] = $txt['ftp_checking_writable'];
$incontext['sub_template'] = 'chmod_files';
$writable_files = array(
'attachments',
'avatars',
'cache',
'Packages',
'Packages/installed.list',
'Smileys',
'Themes',
'agreement.txt',
'Settings.php',
'Settings_bak.php'
);
$extra_files = array(
'Themes/classic/index.template.php',
'Themes/classic/style.css'
);
foreach ($incontext['detected_languages'] as $lang => $temp)
$extra_files[] = 'Themes/default/languages/' . $lang;
$failure = false;
// With mod_security installed, we could attempt to fix it with .htaccess.
if (function_exists('apache_get_modules') && in_array('mod_security', apache_get_modules()))
$writable_files[] = file_exists(dirname(__FILE__) . '/.htaccess') ? '.htaccess' : '.';
// On linux, it's easy - just use is_writable!
if (substr(__FILE__, 1, 2) != ':\\')
{
foreach ($writable_files as $file)
{
if (!is_writable(dirname(__FILE__) . '/' . $file))
{
@chmod(dirname(__FILE__) . '/' . $file, 0755);
// Well, 755 hopefully worked... if not, try 777.
$failure |= !is_writable(dirname(__FILE__) . '/' . $file) && !@chmod(dirname(__FILE__) . '/' . $file, 0777);
}
}
foreach ($extra_files as $file)
@chmod(dirname(__FILE__) . (empty($file) ? '' : '/' . $file), 0777);
}
// Windows is trickier. Let's try opening for r+...
else
{
foreach ($writable_files as $file)
{
// Folders can't be opened for write... but the index.php in them can ;).
if (is_dir(dirname(__FILE__) . '/' . $file))
$file .= '/index.php';
// Funny enough, chmod actually does do something on windows - it removes the read only attribute.
@chmod(dirname(__FILE__) . '/' . $file, 0777);
$fp = @fopen(dirname(__FILE__) . '/' . $file, 'r+');
// Hmm, okay, try just for write in that case...
if (!$fp)
$fp = @fopen(dirname(__FILE__) . '/' . $file, 'w');
$failure |= !$fp;
@fclose($fp);
}
foreach ($extra_files as $file)
@chmod(dirname(__FILE__) . (empty($file) ? '' : '/' . $file), 0777);
}
if (!isset($_SERVER))
return !$failure;
// Put the list into context.
$incontext['writable_files'] = $writable_files;
// It's not going to be possible to use FTP on windows to solve the problem...
if ($failure && substr(__FILE__, 1, 2) == ':\\')
{
$incontext['error'] = $txt['error_windows_chmod'] . '
' . implode('
', $writable_files) . '
';
return false;
}
// We're going to have to use... FTP!
elseif ($failure)
{
// Load any session data we might have...
if (!isset($_POST['ftp_username']) && isset($_SESSION['installer_temp_ftp']))
{
$_POST['ftp_server'] = $_SESSION['installer_temp_ftp']['server'];
$_POST['ftp_port'] = $_SESSION['installer_temp_ftp']['port'];
$_POST['ftp_username'] = $_SESSION['installer_temp_ftp']['username'];
$_POST['ftp_password'] = $_SESSION['installer_temp_ftp']['password'];
$_POST['ftp_path'] = $_SESSION['installer_temp_ftp']['path'];
}
if (isset($_POST['ftp_username']))
{
$ftp = new ftp_connection($_POST['ftp_server'], $_POST['ftp_port'], $_POST['ftp_username'], $_POST['ftp_password']);
if ($ftp->error === false)
{
// Try it without /home/abc just in case they messed up.
if (!$ftp->chdir($_POST['ftp_path']))
{echo 'sddsgdsgs';
$incontext['ftp_error'] = $ftp->last_message;
$ftp->chdir(preg_replace('~^/home[2]?/[^/]+?~', '', $_POST['ftp_path']));
}
}
}
if (!isset($ftp) || $ftp->error !== false)
{
if (!isset($ftp))
$ftp = new ftp_connection(null);
// Save the error so we can mess with listing...
elseif ($ftp->error !== false && !isset($incontext['ftp_error']))
$incontext['ftp_error'] = $ftp->last_message === null ? '' : $ftp->last_message;
list ($username, $detect_path, $found_path) = $ftp->detect_path(dirname(__FILE__));
if ($found_path || !isset($_POST['ftp_path']))
$_POST['ftp_path'] = $detect_path;
if (!isset($_POST['ftp_username']))
$_POST['ftp_username'] = $username;
// Set the username etc, into context.
$incontext['ftp'] = array(
'server' => isset($_POST['ftp_server']) ? $_POST['ftp_server'] : 'localhost',
'port' => isset($_POST['ftp_port']) ? $_POST['ftp_port'] : '21',
'username' => isset($_POST['ftp_username']) ? $_POST['ftp_username'] : '',
'path' => $_POST['ftp_path'],
'path_msg' => !empty($found_path) ? $txt['ftp_path_found_info'] : $txt['ftp_path_info'],
);
return false;
}
else
{
$_SESSION['installer_temp_ftp'] = array(
'server' => $_POST['ftp_server'],
'port' => $_POST['ftp_port'],
'username' => $_POST['ftp_username'],
'password' => $_POST['ftp_password'],
'path' => $_POST['ftp_path']
);
foreach ($writable_files as $file)
{
if (!is_writable(dirname(__FILE__) . '/' . $file))
$ftp->chmod($file, 0755);
if (!is_writable(dirname(__FILE__) . '/' . $file))
$ftp->chmod($file, 0777);
}
$ftp->close();
}
}
return true;
}
function DatabaseSettings()
{
global $txt, $databases, $incontext, $smcFunc;
$incontext['sub_template'] = 'database_settings';
$incontext['page_title'] = $txt['db_settings'];
$incontext['continue'] = 1;
// Set up the defaults.
$incontext['db']['server'] = 'localhost';
$incontext['db']['user'] = '';
$incontext['db']['name'] = '';
$incontext['db']['pass'] = '';
$incontext['db']['type'] = '';
$incontext['supported_databases'] = array();
$foundOne = false;
foreach ($databases as $key => $db)
{
// Override with the defaults for this DB if appropriate.
if ($db['supported'])
{
$incontext['supported_databases'][$key] = $db;
if (!$foundOne)
{
if (isset($db['default_host']))
$incontext['db']['server'] = @ini_get($db['default_host']) or $incontext['db']['server'] = 'localhost';
if (isset($db['default_user']))
{
$incontext['db']['user'] = @ini_get($db['default_user']);
$incontext['db']['name'] = @ini_get($db['default_user']);
}
if (isset($db['default_password']))
$incontext['db']['pass'] = @ini_get($db['default_password']);
if (isset($db['default_port']))
$db_port = @ini_get($db['default_port']);
$incontext['db']['type'] = $key;
$foundOne = true;
}
}
}
// Override for repost.
if (isset($_POST['db_user']))
{
$incontext['db']['user'] = $_POST['db_user'];
$incontext['db']['name'] = $_POST['db_type'] == 'sqlite' && isset($_POST['db_filename']) ? $_POST['db_filename'] : $_POST['db_name'];
$incontext['db']['server'] = $_POST['db_server'];
$incontext['db']['prefix'] = $_POST['db_prefix'];
}
else
$incontext['db']['prefix'] = 'smf_';
// This is just because it makes it easier for people on Lycos/Tripod UK :P.
if (isset($_SERVER['SERVER_NAME']) && $_SERVER['SERVER_NAME'] == 'members.lycos.co.uk' && defined('LOGIN'))
{
$incontext['db']['user'] = LOGIN;
$incontext['db']['name'] = LOGIN . '_uk_db';
}
// Should we use a non standard port?
if (!empty($db_port))
$incontext['db']['server'] .= ':' . $db_port;
// Are we submitting?
if (isset($_POST['db_type']))
{
if (isset($_POST['db_filename']))
{
// You better enter enter a database name for SQLite.
if (trim($_POST['db_filename']) == '')
{
$incontext['error'] = $txt['error_db_filename'];
return false;
}
// Duplicate name in the same dir? Can't do that with SQLite. Weird things happen.
if (file_exists($_POST['db_filename'] . (substr($_POST['db_filename'], -3) != '.db' ? '.db' : '')))
{
$incontext['error'] = $txt['error_db_filename_exists'];
return false;
}
}
// What type are they trying?
$db_type = preg_replace('~[^A-Za-z0-9]~', '', $_POST['db_type']);
$db_prefix = $_POST['db_prefix'];
// Validate the prefix.
$valid_prefix = $databases[$db_type]['validate_prefix']($db_prefix);
if ($valid_prefix !== true)
{
$incontext['error'] = $valid_prefix;
return false;
}
// Take care of these variables...
$vars = array(
'db_type' => $db_type,
'db_name' => $_POST['db_type'] == 'sqlite' && isset($_POST['db_filename']) ? $_POST['db_filename'] : $_POST['db_name'],
'db_user' => $_POST['db_user'],
'db_passwd' => isset($_POST['db_passwd']) ? $_POST['db_passwd'] : '',
'db_server' => $_POST['db_server'],
'db_prefix' => $db_prefix,
// The cookiename is special; we want it to be the same if it ever needs to be reinstalled with the same info.
'cookiename' => 'SMFCookie' . abs(crc32($_POST['db_name'] . preg_replace('~[^A-Za-z0-9_$]~', '', $_POST['db_prefix'])) % 1000),
);
// God I hope it saved!
if (!updateSettingsFile($vars) && substr(__FILE__, 1, 2) == ':\\')
{
$incontext['error'] = $txt['error_windows_chmod'];
return false;
}
// Make sure it works.
require(dirname(__FILE__) . '/Settings.php');
if (empty($sourcedir))
$sourcedir = dirname(__FILE__) . '/Sources';
// Better find the database file!
if (!file_exists($sourcedir . '/Subs-Db-' . $db_type . '.php'))
{
$incontext['error'] = sprintf($txt['error_db_file'], 'Subs-Db-' . $db_type . '.php');
return false;
}
// Now include it for database functions!
define('SMF', 1);
$modSettings['disableQueryCheck'] = true;
if (empty($smcFunc))
$smcFunc = array();
require_once($sourcedir . '/Subs-Db-' . $db_type . '.php');
// What - running PHP4? The shame!
if (@version_compare(PHP_VERSION, '5') == -1)
require_once($sourcedir . '/Subs-Compat.php');
// Attempt a connection.
$needsDB = !empty($databases[$db_type]['always_has_db']);
$db_connection = smf_db_initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix, array('non_fatal' => true, 'dont_select_db' => !$needsDB));
// No dice? Let's try adding the prefix they specified, just in case they misread the instructions ;).
if ($db_connection == null)
{
$db_error = @$smcFunc['db_error']();
$db_connection = smf_db_initiate($db_server, $db_name, $_POST['db_prefix'] . $db_user, $db_passwd, $db_prefix, array('non_fatal' => true, 'dont_select_db' => !$needsDB));
if ($db_connection != null)
{
$db_user = $_POST['db_prefix'] . $db_user;
updateSettingsFile(array('db_user' => $db_user));
}
}
// Still no connection? Big fat error message :P.
if (!$db_connection)
{
$incontext['error'] = $txt['error_db_connect'] . '
' . $db_error . '
';
return false;
}
// Do they meet the install requirements?
// !!! Old client, new server?
if (version_compare($databases[$db_type]['version'], preg_replace('~^\D*|\-.+?$~', '', eval($databases[$db_type]['version_check']))) > 0)
{
$incontext['error'] = $txt['error_db_too_low'];
return false;
}
// Let's try that database on for size... assuming we haven't already lost the opportunity.
if ($db_name != '' && !$needsDB)
{
$smcFunc['db_query']('', "
CREATE DATABASE IF NOT EXISTS `$db_name`",
array(
'security_override' => true,
'db_error_skip' => true,
),
$db_connection
);
// Okay, let's try the prefix if it didn't work...
if (!$smcFunc['db_select_db']($db_name, $db_connection) && $db_name != '')
{
$smcFunc['db_query']('', "
CREATE DATABASE IF NOT EXISTS `$_POST[db_prefix]$db_name`",
array(
'security_override' => true,
'db_error_skip' => true,
),
$db_connection
);
if ($smcFunc['db_select_db']($_POST['db_prefix'] . $db_name, $db_connection))
{
$db_name = $_POST['db_prefix'] . $db_name;
updateSettingsFile(array('db_name' => $db_name));
}
}
// Okay, now let's try to connect...
if (!$smcFunc['db_select_db']($db_name, $db_connection))
{
$incontext['error'] = sprintf($txt['error_db_database'], $db_name);
return false;
}
}
return true;
}
return false;
}
// Let's start with basic forum type settings.
function ForumSettings()
{
global $txt, $incontext, $databases, $smcFunc, $db_connection, $db_type;
$incontext['sub_template'] = 'forum_settings';
$incontext['page_title'] = $txt['install_settings'];
// Let's see if we got the database type correct.
if (isset($_POST['db_type'], $databases[$_POST['db_type']]))
$db_type = $_POST['db_type'];
// Else we'd better be able to get the connection.
else
load_database();
$db_type = isset($_POST['db_type']) ? $_POST['db_type'] : $db_type;
// What host and port are we on?
$host = empty($_SERVER['HTTP_HOST']) ? $_SERVER['SERVER_NAME'] . (empty($_SERVER['SERVER_PORT']) || $_SERVER['SERVER_PORT'] == '80' ? '' : ':' . $_SERVER['SERVER_PORT']) : $_SERVER['HTTP_HOST'];
// Now, to put what we've learned together... and add a path.
$incontext['detected_url'] = 'http' . (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on' ? 's' : '') . '://' . $host . substr($_SERVER['PHP_SELF'], 0, strrpos($_SERVER['PHP_SELF'], '/'));
// Check if the database sessions will even work.
$incontext['test_dbsession'] = @ini_get('session.auto_start') != 1 && @version_compare(PHP_VERSION, '4.2.0') != -1;
$incontext['utf8_should_work'] = strpos(strtolower(PHP_OS), 'win') === false || @version_compare(PHP_VERSION, '4.2.3') != -1;
$incontext['utf8_default'] = $databases[$db_type]['utf8_default'];
$incontext['continue'] = 1;
// Submitting?
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'];
// Save these variables.
$vars = array(
'boardurl' => $_POST['boardurl'],
'boarddir' => addslashes(dirname(__FILE__)),
'sourcedir' => addslashes(dirname(__FILE__)) . '/Sources',
'cachedir' => addslashes(dirname(__FILE__)) . '/cache',
'mbname' => $_POST['mbname'],
'language' => substr($_SESSION['installer_temp_lang'], 8, -4),
);
// Must save!
if (!updateSettingsFile($vars) && substr(__FILE__, 1, 2) == ':\\')
{
$incontext['error'] = $txt['error_windows_chmod'];
return false;
}
// Make sure it works.
require(dirname(__FILE__) . '/Settings.php');
// UTF-8 requires a setting to override the language charset.
if (isset($_POST['utf8']) && !empty($databases[$db_type]['utf8_support']))
{
if (version_compare($databases[$db_type]['utf8_version'], preg_replace('~\-.+?$~', '', eval($databases[$db_type]['utf8_version_check']))) > 0)
{
$incontext['error'] = sprintf($txt['error_utf8_version'], $databases[$db_type]['utf8_version']);
return false;
}
else
// Set the character set here.
updateSettingsFile(array('db_character_set' => 'utf8'));
}
// Good, skip on.
return true;
}
return false;
}
// Step one: Do the SQL thang.
function DatabasePopulation()
{
global $txt, $db_connection, $smcFunc, $databases, $modSettings, $db_type, $sourcedir, $db_prefix, $incontext, $db_name, $boardurl;
$incontext['sub_template'] = 'populate_database';
$incontext['page_title'] = $txt['db_populate'];
$incontext['continue'] = 1;
// Already done?
if (isset($_POST['pop_done']))
return true;
// Reload settings.
require(dirname(__FILE__) . '/Settings.php');
load_database();
// Before running any of the queries, let's make sure another version isn't already installed.
$result = $smcFunc['db_query']('', '
SELECT variable, value
FROM {db_prefix}settings',
array(
'db_error_skip' => true,
)
);
$modSettings = array();
if ($result !== false)
{
while ($row = $smcFunc['db_fetch_assoc']($result))
$modSettings[$row['variable']] = $row['value'];
$smcFunc['db_free_result']($result);
// Do they match? If so, this is just a refresh so charge on!
if (!isset($modSettings['smfVersion']) || $modSettings['smfVersion'] != $GLOBALS['current_smf_version'])
{
$incontext['error'] = $txt['error_versions_do_not_match'];
return false;
}
}
// If doing UTF8, select it.
if (!empty($db_character_set) && $db_character_set == 'utf8' && !empty($databases[$db_type]['utf8_support']))
$smcFunc['db_query']('', '
SET NAMES utf8',
array(
'db_error_skip' => true,
)
);
$replaces = array(
'{$db_prefix}' => $db_prefix,
'{$boarddir}' => $smcFunc['db_escape_string'](dirname(__FILE__)),
'{$boardurl}' => $boardurl,
'{$enableCompressedOutput}' => isset($_POST['compress']) ? '1' : '0',
'{$databaseSession_enable}' => isset($_POST['dbsession']) ? '1' : '0',
'{$smf_version}' => $GLOBALS['current_smf_version'],
'{$current_time}' => time(),
'{$sched_task_offset}' => 82800 + mt_rand(0, 86399),
);
foreach ($txt as $key => $value)
{
if (substr($key, 0, 8) == 'default_')
$replaces['{$' . $key . '}'] = $smcFunc['db_escape_string']($value);
}
$replaces['{$default_reserved_names}'] = strtr($replaces['{$default_reserved_names}'], array('\\\\n' => '\\n'));
// MySQL users below v4 can't use engine.
if ($db_type == 'mysql' && version_compare('4', preg_replace('~\-.+?$~', '', eval($databases[$db_type]['version_check']))) > 0)
$replaces[') ENGINE='] = ') TYPE=';
// If the UTF-8 setting was enabled, add it to the table definitions.
//!!! Very MySQL specific still
if (isset($_POST['utf8']) && !empty($databases[$db_type]['utf8_support']))
$replaces[') ENGINE=MyISAM;'] = ') ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;';
// Read in the SQL. Turn this on and that off... internationalize... etc.
$sql_lines = explode("\n", strtr(implode(' ', file(dirname(__FILE__) . '/install_' . $GLOBALS['db_script_version'] . '_' . $db_type . '.sql')), $replaces));
// Execute the SQL.
$current_statement = '';
$exists = array();
$incontext['failures'] = array();
$incontext['sql_results'] = array(
'tables' => 0,
'inserts' => 0,
'table_dups' => 0,
'insert_dups' => 0,
);
foreach ($sql_lines as $count => $line)
{
// No comments allowed!
if (substr(trim($line), 0, 1) != '#')
$current_statement .= "\n" . rtrim($line);
// Is this the end of the query string?
if (empty($current_statement) || (preg_match('~;[\s]*$~s', $line) == 0 && $count != count($sql_lines)))
continue;
// Does this table already exist? If so, don't insert more data into it!
if (preg_match('~^\s*INSERT INTO ([^\s\n\r]+?)~', $current_statement, $match) != 0 && in_array($match[1], $exists))
{
$incontext['sql_results']['insert_dups']++;
$current_statement = '';
continue;
}
if ($smcFunc['db_query']('', $current_statement, array('security_override' => true, 'db_error_skip' => true), $db_connection) === false)
{
// Error 1050: Table already exists!
//!!! Needs to be made better!
if (($db_type != 'mysql' || mysql_errno($db_connection) === 1050) && preg_match('~^\s*CREATE TABLE ([^\s\n\r]+?)~', $current_statement, $match) == 1)
{
$exists[] = $match[1];
$incontext['sql_results']['table_dups']++;
}
// Don't error on duplicate indexes.
elseif (!preg_match('~^\s*CREATE INDEX ([^\n\r]+?)~', $current_statement, $match))
{
$incontext['failures'][$count] = $smcFunc['db_error']();
}
}
else
{
if (preg_match('~^\s*CREATE TABLE ([^\s\n\r]+?)~', $current_statement, $match) == 1)
$incontext['sql_results']['tables']++;
else
{
preg_match_all('~\)[,;]~', $current_statement, $matches);
if (!empty($matches[0]))
$incontext['sql_results']['inserts'] += count($matches[0]);
else
$incontext['sql_results']['inserts']++;
}
}
$current_statement = '';
}
// Sort out the context for the SQL.
foreach ($incontext['sql_results'] as $key => $number)
{
if ($number == 0)
unset($incontext['sql_results'][$key]);
else
$incontext['sql_results'][$key] = sprintf($txt['db_populate_' . $key], $number);
}
// Make sure UTF will be used globally.
if (isset($_POST['utf8']) && !empty($databases[$db_type]['utf8_support']))
$smcFunc['db_insert']('replace',
$db_prefix . 'settings',
array(
'variable' => 'string-255', 'value' => 'string-65534',
),
array(
'global_character_set', 'UTF-8',
),
array('variable')
);
// Maybe we can auto-detect better cookie settings?
preg_match('~^http[s]?://([^\.]+?)([^/]*?)(/.*)?$~', $boardurl, $matches);
if (!empty($matches))
{
// Default = both off.
$localCookies = false;
$globalCookies = false;
// Okay... let's see. Using a subdomain other than www.? (not a perfect check.)
if ($matches[2] != '' && (strpos(substr($matches[2], 1), '.') === false || in_array($matches[1], array('forum', 'board', 'community', 'forums', 'support', 'chat', 'help', 'talk', 'boards', 'www'))))
$globalCookies = true;
// If there's a / in the middle of the path, or it starts with ~... we want local.
if (isset($matches[3]) && strlen($matches[3]) > 3 && (substr($matches[3], 0, 2) == '/~' || strpos(substr($matches[3], 1), '/') !== false))
$localCookies = true;
$rows = array();
if ($globalCookies)
$rows[] = array('globalCookies', '1');
if ($localCookies)
$rows[] = array('localCookies', '1');
if (!empty($rows))
{
$smcFunc['db_insert']('replace',
$db_prefix . 'settings',
array('variable' => 'string-255', 'value' => 'string-65534'),
$rows,
array('variable')
);
}
}
// Are we allowing stat collection?
if (isset($_POST['stats']) && substr($_POST['boardurl'], 0, 16) != 'http://localhost')
{
// Attempt to register the site etc.
$fp = @fsockopen("www.simplemachines.org", 80, $errno, $errstr);
if ($fp)
{
$out = "GET /smf/stats/register_stats.php?site=" . base64_encode($_POST['boardurl']) . " HTTP/1.1\r\n";
$out .= "Host: www.simplemachines.org\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
$return_data = '';
while (!feof($fp))
$return_data .= fgets($fp, 128);
fclose($fp);
// Get the unique site ID.
preg_match('~SITE-ID:\s(\w{10})~', $return_data, $ID);
if (!empty($ID[1]))
$smcFunc['db_insert']('',
$db_prefix . 'settings',
array(
'variable' => 'string-255', 'value' => 'string-65534',
),
array(
'allow_sm_stats', $ID[1],
),
array('variable')
);
}
}
// As of PHP 5.1, setting a timezone is required.
if (!isset($modSettings['default_timezone']) && function_exists('date_default_timezone_set'))
{
$server_offset = mktime(0, 0, 0, 1, 1, 1970);
$timezone_id = 'Etc/GMT' . ($server_offset > 0 ? '+' : '') . ($server_offset / 3600);
if (date_default_timezone_set($timezone_id))
$smcFunc['db_insert']('',
$db_prefix . 'settings',
array(
'variable' => 'string-255', 'value' => 'string-65534',
),
array(
'default_timezone', $timezone_id,
),
array('variable')
);
}
// Let's optimize those new tables.
db_extend();
$tables = $smcFunc['db_list_tables']($db_name, $db_prefix . '%');
foreach ($tables as $table)
{
$smcFunc['db_optimize_table']($table) != -1 or $db_messed = true;
if (!empty($db_messed))
{
$incontext['failures'][-1] = $smcFunc['db_error']();
break;
}
}
// Check for the ALTER privilege.
if (!empty($databases[$db_type]['alter_support']) && $smcFunc['db_query']('', "ALTER TABLE {$db_prefix}boards ORDER BY id_board", array('security_override' => true, 'db_error_skip' => true)) === false)
{
$incontext['error'] = $txt['error_db_alter_priv'];
return false;
}
if (!empty($exists))
{
$incontext['page_title'] = $txt['user_refresh_install'];
$incontext['was_refresh'] = true;
}
return false;
}
// Ask for the administrator login information.
function AdminAccount()
{
global $txt, $db_type, $db_connection, $databases, $smcFunc, $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();
// Define the sha1 function, if it doesn't exist.
if (!function_exists('sha1') || @version_compare(PHP_VERSION, '5') == -1)
require_once($sourcedir . '/Subs-Compat.php');
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 = $smcFunc['db_query']('', '
SELECT id_member
FROM {db_prefix}members
WHERE id_group = {int:admin_group} OR FIND_IN_SET({int:admin_group}, additional_groups)
LIMIT 1',
array(
'db_error_skip' => true,
'admin_group' => 1,
)
);
if ($smcFunc['db_num_rows']($request) != 0)
$incontext['skip'] = 1;
$smcFunc['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 == 'noreply@myserver.com'))
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 = $smcFunc['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 ($smcFunc['db_num_rows']($result) != 0)
{
list ($incontext['member_id'], $incontext['member_salt']) = $smcFunc['db_fetch_row']($result);
$smcFunc['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']) || 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 = $smcFunc['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',
'icq' => 'string', 'msn' => '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'] . '
';
// Have we got a language drop down - if so do it on the first step only.
if (!empty($incontext['detected_languages']) && count($incontext['detected_languages']) > 1 && $incontext['current_step'] == 0)
{
echo '
';
}
echo '
', $incontext['page_title'], '
';
}
function template_install_below()
{
global $incontext, $txt;
if (!empty($incontext['continue']) || !empty($incontext['skip']))
{
echo '
';
if (!empty($incontext['continue']))
echo '
';
if (!empty($incontext['skip']))
echo '
';
echo '
';
}
// Show the closing form tag and other data only if not in the last step
if (count($incontext['steps']) - 1 !== (int) $incontext['current_step'])
echo '
';
echo '
';
}
// Welcome them to the wonderful world of SMF!
function template_welcome_message()
{
global $incontext, $installurl, $txt;
echo '
', $txt['error_message_click'], ' ', $txt['ftp_setup_again'];
}
// Get the database settings prepared.
function template_database_settings()
{
global $incontext, $installurl, $txt;
echo '