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.

'; + } + + $mysql_disable_reason = ''; + $pgsql_disable_reason = ''; + $mysql_disable = ''; + $pgsql_disable = ''; + if ( !function_exists('mysql_connect') ) + { + $mysql_disable = ' disabled="disabled"'; + $mysql_disable_reason = 'You don\'t have the MySQL PHP extension installed.'; + } + if ( !function_exists('pg_connect') ) + { + $pgsql_disable = ' disabled="disabled"'; + $pgsql_disable_reason = 'You don\'t have the PostgreSQL PHP extensnion installed.'; + } + if ( function_exists('pg_connect') && version_compare(PHP_VERSION, '5.0.0', '<') ) + { + $pgsql_disable = ' disabled="disabled"'; + $pgsql_disable_reason = 'You need to have at least PHP 5 to use the PostgreSQL database driver.'; + } + + echo '
'; + ?> + + + + > + MySQL
+ Click this button to use MySQL as the database backend for your site. Most web hosts support MySQL, and if you have + administrative access to your MySQL server, you can create a new database and user during this installation process if you + haven't done so already. +
$mysql_disable_reason"; + } + ?> + +
+ + + > + PostgreSQL
+ Click this button to use PostgreSQL as the database backend for your site. While not as widely supported, PostgreSQL has more + liberal licensing conditions and when properly configured is faster than MySQL. Some plugins may not work with the PostgreSQL + driver. +
$pgsql_disable_reason"; + } + ?> + +
+
+ /> +
+ /> +
+ '; + break; + case "database_mysql": ?> +

Now we need some information that will allow Enano to contact your database server. Enano uses PostgreSQL as a data storage backend, + and we need to have access to a PostgreSQL server in order to continue.

+

If you do not have access to a PostgreSQL server, and you are using your own server, you can download PostgreSQL for free from + PostgreSQL.org.

+ + + + + + + + + + + + + + + +

Database information

Database hostname
This is the hostname (or sometimes the IP address) of your Postgres server. In many cases, this is "localhost".
Good/bad icon
Database name
The name of the actual database. If you don't already have a database, you can create one here, if you have the username and password of a PostgreSQL superuser.
Good/bad icon
Database login
These fields should be the username and password for a role that has permission to create and alter tables, select data, insert data, update data, and delete data. You may or may not choose to allow dropping tables.
Good/bad icon

Optional information

Table prefix
The value that you enter here will be added to the beginning of the name of each Enano table. You may use lowercase letters (a-z), numbers (0-9), and underscores (_).
Good/bad icon
Database administrative login
If the Postgres database or role that you entered above does not exist yet, you can create them here, assuming that you have the login information for a PostgreSQL superuser. Leave these fields blank unless you need to use them.
Good/bad icon
PostgreSQL versionPostgreSQL version information will
be checked when you click "Test
Connection". You need to have at
least PostgreSQL 8.2.0 to install Enano.
Good/bad icon
Delete existing tables?
If this option is checked, all the tables that will be used by Enano will be dropped (deleted) before the schema is executed. Do NOT use this option unless specifically instructed to.
+
footer(); exit; } + if ( !in_array($_POST['db_driver'], array('mysql', 'postgresql')) ) + { + echo 'Invalid database driver.'; + $template->footer(); + exit; + } switch($_POST['urlscheme']) { case "ugly":