diff -r 474f8be55943 -r ab66d6d1f1f4 install.php --- a/install.php Fri Dec 07 18:47:37 2007 -0500 +++ b/install.php Wed Dec 19 22:55:40 2007 -0500 @@ -45,6 +45,8 @@ global $_starttime, $this_page, $sideinfo; $_starttime = microtime(true); +global $db; + // Determine directory (special case for development servers) if ( strpos(__FILE__, '/repo/') && file_exists('.enanodev') ) { @@ -185,6 +187,9 @@ function stg_mysql_connect($act_get = false) { + global $db; + $db = new mysql(); + static $conn = false; if ( $act_get ) return $conn; @@ -309,15 +314,114 @@ return false; } } + // initialize DBAL + $db->connect(true, $_POST['db_host'], $db_user, $db_pass, $db_name); + // connected and database exists + return true; +} + +function stg_pgsql_connect($act_get = false) +{ + global $db; + $db = new postgresql(); + + static $conn = false; + if ( $act_get ) + return $conn; + + $db_user =& $_POST['db_user']; + $db_pass =& $_POST['db_pass']; + $db_name =& $_POST['db_name']; + + if ( !preg_match('/^[a-z0-9_-]+$/', $db_name) ) + { + $db_name = htmlspecialchars($db_name); + die("
SECURITY: malformed database name \"$db_name\"
"); + } + + // First, try to connect using the normal credentials + $conn = @pg_connect("host={$_POST['db_host']} port=5432 user={$_POST['db_user']} password={$_POST['db_pass']}"); + if ( !$conn ) + { + // Connection failed. Do we have the root username and password? + if ( !empty($_POST['db_root_user']) && !empty($_POST['db_root_pass']) ) + { + $conn_root = @pg_connect("host={$_POST['db_host']} port=5432 user={$_POST['db_root_user']} password={$_POST['db_root_pass']}"); + if ( !$conn_root ) + { + // Couldn't connect using either set of credentials. Bail out. + return false; + } + unset($db_user, $db_pass); + $db_user = pg_escape_string($_POST['db_user']); + $db_pass = pg_escape_string($_POST['db_pass']); + // Create the user account + $q = @pg_query("CREATE ROLE '$db_user' WITH NOSUPERUSER UNENCRYPTED PASSWORD '$db_pass';", $conn_root); + if ( !$q ) + { + return false; + } + pg_close($conn_root); + $conn = @pg_connect("host={$_POST['db_host']} port=5432 user={$_POST['db_user']} password={$_POST['db_pass']}"); + if ( !$conn ) + { + // This should honestly never happen. + return false; + } + } + } + if ( !$q ) + { + // access denied to the database; try the whole root schenanegan again + if ( !empty($_POST['db_root_user']) && !empty($_POST['db_root_pass']) ) + { + $conn_root = @pg_connect("host={$_POST['db_host']} port=5432 user={$_POST['db_root_user']} password={$_POST['db_root_pass']}"); + if ( !$conn_root ) + { + // Couldn't connect as root; bail out + return false; + } + unset($db_user, $db_pass); + $db_user = pg_escape_string($_POST['db_user']); + $db_pass = pg_escape_string($_POST['db_pass']); + // create the database, if it doesn't exist + $q = @mysql_query("CREATE DATABASE $db_name WITH OWNER $db_user;", $conn_root); + if ( !$q ) + { + // this really should never fail, so don't give any tolerance to it + return false; + } + // Setting the owner to $db_user should grant all the rights we need + pg_close($conn_root); + // grant tables have hopefully been flushed, kill and reconnect our regular user connection + pg_close($conn); + $conn = @pg_connect("host={$_POST['db_host']} port=5432 user={$_POST['db_user']} password={$_POST['db_pass']}"); + if ( !$conn ) + { + return false; + } + } + else + { + return false; + } + // try again + $q = @mysql_query("USE `$db_name`;", $conn); + if ( !$q ) + { + // really failed this time; bail out + return false; + } + } + // initialize DBAL + $db->connect(true, $_POST['db_host'], $db_user, $db_pass, $db_name); // connected and database exists return true; } function stg_drop_tables() { - $conn = stg_mysql_connect(true); - if ( !$conn ) - return false; + global $db; // Our list of tables included in Enano $tables = Array( 'categories', 'comments', 'config', 'logs', 'page_text', 'session_keys', 'pages', 'users', 'users_extra', 'themes', 'buddies', 'banlist', 'files', 'privmsgs', 'sidebar', 'hits', 'search_index', 'groups', 'group_members', 'acl', 'tags', 'page_groups', 'page_group_members' ); @@ -327,7 +431,7 @@ { // Remember that table_prefix is sanitized. $table = "{$_POST['table_prefix']}$table"; - @mysql_query("DROP TABLE $table;", $conn); + $db->sql_query("DROP TABLE $table;", $conn); } return true; } @@ -379,6 +483,8 @@ if ( $act_get ) return $schema; + global $db; + $admin_pass = stg_decrypt_admin_pass(true); $key = stg_generate_aes_key(true); $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); @@ -389,16 +495,29 @@ $admin_user = $_POST['admin_user']; $admin_user = str_replace('_', ' ', $admin_user); - $admin_user = mysql_real_escape_string($admin_user); + $admin_user = $db->escape($admin_user); + + switch ( $_POST['db_driver'] ) + { + case 'mysql': + $schema_file = 'schema.sql'; + break; + case 'postgresql': + $schema_file = 'schema-pg.sql'; + break; + } - $schema = file_get_contents('schema.sql'); - $schema = str_replace('{{SITE_NAME}}', mysql_real_escape_string($_POST['sitename'] ), $schema); - $schema = str_replace('{{SITE_DESC}}', mysql_real_escape_string($_POST['sitedesc'] ), $schema); - $schema = str_replace('{{COPYRIGHT}}', mysql_real_escape_string($_POST['copyright'] ), $schema); + if ( !isset($schema_file) ) + die('insanity'); + + $schema = file_get_contents($schema_file); + $schema = str_replace('{{SITE_NAME}}', $db->escape($_POST['sitename'] ), $schema); + $schema = str_replace('{{SITE_DESC}}', $db->escape($_POST['sitedesc'] ), $schema); + $schema = str_replace('{{COPYRIGHT}}', $db->escape($_POST['copyright'] ), $schema); $schema = str_replace('{{ADMIN_USER}}', $admin_user , $schema); - $schema = str_replace('{{ADMIN_PASS}}', mysql_real_escape_string($admin_pass ), $schema); - $schema = str_replace('{{ADMIN_EMAIL}}', mysql_real_escape_string($_POST['admin_email']), $schema); - $schema = str_replace('{{ENABLE_CACHE}}', mysql_real_escape_string($cacheonoff ), $schema); + $schema = str_replace('{{ADMIN_PASS}}', $db->escape($admin_pass ), $schema); + $schema = str_replace('{{ADMIN_EMAIL}}', $db->escape($_POST['admin_email']), $schema); + $schema = str_replace('{{ENABLE_CACHE}}', $db->escape($cacheonoff ), $schema); $schema = str_replace('{{REAL_NAME}}', '', $schema); $schema = str_replace('{{TABLE_PREFIX}}', $_POST['table_prefix'], $schema); $schema = str_replace('{{VERSION}}', ENANO_VERSION, $schema); @@ -818,6 +937,78 @@ mysql_close($conn); die('good'); break; + case 'pgsql_test': + error_reporting(0); + $dbhost = rawurldecode($_POST['host']); + $dbname = rawurldecode($_POST['name']); + $dbuser = rawurldecode($_POST['user']); + $dbpass = rawurldecode($_POST['pass']); + $dbrootuser = rawurldecode($_POST['root_user']); + $dbrootpass = rawurldecode($_POST['root_pass']); + if($dbrootuser != '') + { + $conn = @pg_connect("host=$dbhost port=5432 user=$dbuser password=$dbpass dbname=$dbname"); + if(!$conn) + { + $e = pg_last_error(); + if(strstr($e, "Lost connection")) + die('host'.$e); + else + die('root'.$e); + } + $rsp = 'good'; + $q = mysql_query('USE `' . mysql_real_escape_string($dbname) . '`;', $conn); + if(!$q) + { + $e = mysql_error(); + if(strstr($e, 'Unknown database')) + { + $rsp .= '_creating_db'; + } + } + mysql_close($conn); + $conn = mysql_connect($dbhost, $dbuser, $dbpass); + if(!$conn) + { + $e = mysql_error(); + if(strstr($e, "Lost connection")) + die('host'.$e); + else + $rsp .= '_creating_user'; + } + mysql_close($conn); + die($rsp); + } + else + { + $conn = mysql_connect($dbhost, $dbuser, $dbpass); + if(!$conn) + { + $e = mysql_error(); + if(strstr($e, "Lost connection")) + die('host'.$e); + else + die('auth'.$e); + } + $q = mysql_query('USE `' . mysql_real_escape_string($dbname) . '`;', $conn); + if(!$q) + { + $e = mysql_error(); + if(strstr($e, 'Unknown database')) + { + die('name'.$e); + } + else + { + die('perm'.$e); + } + } + } + $v = mysql_get_server_info(); + if(version_compare($v, '4.1.17', '<')) die('vers'.$v); + mysql_close($conn); + die('good'); + break; case 'pophelp': $topic = ( isset($_GET['topic']) ) ? $_GET['topic'] : 'invalid'; switch($topic) @@ -892,8 +1083,10 @@ 'welcome' => $lang->get('welcome_modetitle'), 'license' => $lang->get('license_modetitle'), 'sysreqs' => $lang->get('sysreqs_modetitle'), - 'database'=> $lang->get('database_modetitle'), - 'website' => $lang->get('website_modetitle'), + 'database' => $lang->get('database_modetitle'), + 'database_mysql'=> $lang->get('database_mysql_modetitle'), + 'database_pgsql'=> $lang->get('database_pgsql_modetitle'), + 'website' => $lang->get('website_modetitle'), 'login' => $lang->get('login_modetitle'), 'confirm' => $lang->get('confirm_modetitle'), 'install' => $lang->get('install_modetitle'), @@ -1027,12 +1220,17 @@ run_test('return version_compare(\'4.3.0\', PHP_VERSION, \'<\');', $lang->get('sysreqs_req_php'), $lang->get('sysreqs_req_desc_php') ); run_test('return version_compare(\'5.2.0\', PHP_VERSION, \'<\');', $lang->get('sysreqs_req_php5'), $lang->get('sysreqs_req_desc_php5'), true); run_test('return function_exists(\'mysql_connect\');', $lang->get('sysreqs_req_mysql'), $lang->get('sysreqs_req_desc_mysql') ); + run_test('return function_exists(\'pg_connect\');', 'PostgreSQL extension for PHP', 'It seems that your PHP installation does not have the PostgreSQL extension enabled. Because of this, you won\'t be able to use the PostgreSQL database driver. This is OK in the majority of cases. If you want to use PostgreSQL support, you\'ll need to either compile the PHP extension for Postgres or install the extension with your distribution\'s package manager. Windows administrators will need enable php_pgsql.dll in their php.ini.', true); run_test('return @ini_get(\'file_uploads\');', $lang->get('sysreqs_req_uploads'), $lang->get('sysreqs_req_desc_uploads') ); run_test('return is_apache();', $lang->get('sysreqs_req_apache'), $lang->get('sysreqs_req_desc_apache'), true); run_test('return is_writable(ENANO_ROOT.\'/config.new.php\');', $lang->get('sysreqs_req_config'), $lang->get('sysreqs_req_desc_config') ); run_test('return file_exists(\'/usr/bin/convert\');', $lang->get('sysreqs_req_magick'), $lang->get('sysreqs_req_desc_magick'), true); run_test('return is_writable(ENANO_ROOT.\'/cache/\');', $lang->get('sysreqs_req_cachewriteable'), $lang->get('sysreqs_req_desc_cachewriteable'), true); run_test('return is_writable(ENANO_ROOT.\'/files/\');', $lang->get('sysreqs_req_fileswriteable'), $lang->get('sysreqs_req_desc_fileswriteable'), true); + if ( !function_exists('mysql_connect') && !function_exists('pg_connect') ) + { + run_test('return false;', 'No database drivers are available.', 'You need to have at least one database driver working to install Enano. See the warnings on MySQL and PostgreSQL above for more information on installing these database drivers.', false); + } echo ''; if(!$failed) { @@ -1082,6 +1280,76 @@ Choose a database driver'; + echo 'The next step is to choose the database driver that Enano will use. In most cases this is MySQL, but there are certain + advantages to PostgreSQL, which is made available only experimentally.
'; + if ( @file_exists('/etc/enano-is-virt-appliance') ) + { + echo 'You\'re using the Enano virtual appliance.
Unless you configured the appliance manually, PostgreSQL support is not available. In 99% of cases you\'ll want to click MySQL below.