author | Dan |
Tue, 30 Mar 2010 11:37:00 -0400 | |
changeset 1231 | 4797a4a88533 |
parent 1227 | bdac73ed481e |
child 1351 | a57727e67241 |
permissions | -rw-r--r-- |
<?php /* * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between * Copyright (C) 2006-2009 Dan Fuhry * Installation package * cli-core.php - CLI installation wizard/core * * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. * * Thanks to Stephan for helping out with l10n in the installer (his work is in includes/stages/*.php). */ require(dirname(__FILE__) . '/common.php'); if ( !defined('ENANO_CLI') ) { $ui = new Enano_Installer_UI('Enano installation', false); $ui->set_visible_stage($ui->add_stage('Error', true)); $ui->step = 'Access denied'; $ui->show_header(); echo '<h2>CLI only</h2> <p>This script must be run from the command line.</p>'; $ui->show_footer(); exit; } if ( defined('ENANO_INSTALLED') ) { // start up the API to let it error out if something's wrong require(ENANO_ROOT . '/includes/common.php'); installer_fail('Enano is already installed. Uninstall it by deleting config.php and creating a blank file called config.new.php.'); } // parse command line args foreach ( array('silent', 'driver', 'dbhost', 'dbport', 'dbuser', 'dbpasswd', 'dbname', 'db_prefix', 'user', 'pass', 'email', 'sitename', 'sitedesc', 'copyright', 'urlscheme', 'lang_id', 'scriptpath') as $var ) { if ( !isset($$var) ) { $$var = false; } } for ( $i = 1; $i < count($argv); $i++ ) { switch($argv[$i]) { case '-q': $silent = true; break; case '--db-driver': case '-b': $driver = @$argv[++$i]; break; case '--db-host': case '-h': $dbhost = @$argv[++$i]; break; case '--db-port': case '-o': $dbport = @$argv[++$i]; break; case '--db-user': case '-u': $dbuser = @$argv[++$i]; break; case '--db-pass': case '-p': $dbpasswd = @$argv[++$i]; break; case '--db-name': case '-d': $dbname = @$argv[++$i]; break; case '--table-prefix': case '-t': $db_prefix = @$argv[++$i]; break; case '--admin-user': case '-a': $user = @$argv[++$i]; break; case '--admin-pass': case '-w': $pass = @$argv[++$i]; break; case '--admin-email': case '-e': $email = @$argv[++$i]; break; case '--site-name': case '-n': $sitename = @$argv[++$i]; break; case '--site-desc': case '-s': $sitedesc = @$argv[++$i]; break; case '--copyright': case '-c': $copyright = @$argv[++$i]; break; case '--url-scheme': case '-r': $urlscheme_temp = @$argv[++$i]; if ( in_array($urlscheme_temp, array('standard', 'short', 'rewrite', 'tiny')) ) $urlscheme = $urlscheme_temp; break; case '--language': case '-l': $lang_id = @$argv[++$i]; break; case '-i': case '--scriptpath': $scriptpath = @$argv[++$i]; break; default: $vers = installer_enano_version(); echo <<<EOF Enano CMS v$vers - CLI Installer Usage: {$argv[0]} [-q] [-b driver] [-h host] [-u username] [-p password] [-d database] [-a adminuser] [-w adminpass] [-e email] All arguments are optional; missing information will be prompted for. -q Quiet mode (minimal output) -b, --db-driver Database driver (mysql or postgresql) -h, --db-host Hostname of database server -o, --db-port TCP port on which to connect to database server -u, --db-user Username to use on database server -p, --db-pass Password to use on database server -d, --db-name Name of database -a, --admin-user Administrator username -w, --admin-pass Administrator password -e, --admin-email Administrator e-mail address -n, --site-name Name of site -s, --site-desc *SHORT* Description of site -c, --copyright Copyright notice shown on pages -r, --url-scheme URL scheme (standard, short, rewrite, or tiny) -l, --language Language to be used on site and in installer -i, --scriptpath Where Enano is relative to your website root (no trailing slash) EOF; exit(1); break; } } if ( $silent ) { define('ENANO_LIBINSTALL_SILENT', ''); } ## ## PHP VERSION CHECK ## if ( version_compare(PHP_VERSION, '5.0.0', '<' ) ) { if ( !$silent ) { echo "\x1B[1mWelcome to the \x1B[34mEnano\x1B[0m CMS\x1B[1m installation wizard.\x1B[0m\n"; echo "Installing Enano version \x1B[1m" . installer_enano_version() . "\x1B[0m on PHP " . PHP_VERSION . "\n"; } installer_fail('Your version of PHP (' . PHP_VERSION . ') doesn\'t meet Enano requirements (5.0.0)'); } ## ## LANGUAGE STARTUP ## // Include language lib and additional PHP5-only JSON functions require_once( ENANO_ROOT . '/includes/json2.php' ); require_once( ENANO_ROOT . '/includes/lang.php' ); // Determine language ID to use $langids = array_keys($languages); if ( $silent ) { if ( !in_array($lang_id, $langids ) ) $lang_id = $langids[0]; } else if ( !in_array($lang_id, $langids) ) { echo "\x1B[1mPlease select a language.\x1B[0m\n"; echo "\x1B[32mAvailable languages:\x1B[0m\n"; foreach ( $languages as $id => $metadata ) { $id_spaced = $id; while ( strlen($id_spaced) < 10 ) $id_spaced = "$id_spaced "; echo " \x1B[1;34m$id_spaced\x1B[0m {$metadata['name']} ({$metadata['name_eng']})\n"; } while ( !in_array($lang_id, $langids) ) { $lang_id = cli_prompt('Language: ', $langids[0]); } } // We have a language ID - init language $language_dir = $languages[$lang_id]['dir']; // Initialize language support $lang = new Language($lang_id); $lang->load_file(ENANO_ROOT . '/language/' . $language_dir . '/install.json'); ## ## WELCOME MESSAGE ## if ( !$silent ) { echo parse_shellcolor_string($lang->get('cli_welcome_line1')); echo parse_shellcolor_string($lang->get('cli_welcome_line2', array('enano_version' => installer_enano_version(), 'php_version' => PHP_VERSION))); } $defaults = array( 'driver' => 'mysql', 'dbhost' => 'localhost', 'dbport' => 3306, 'dbuser' => false, 'dbpasswd' => false, 'dbname' => false, 'db_prefix' => '', 'user' => 'admin', 'pass' => false, 'email' => false, 'sitename' => $lang->get('cli_default_site_name'), 'sitedesc' => $lang->get('cli_default_site_desc'), 'copyright' => $lang->get('cli_default_copyright', array('year' => date('Y'))), 'urlscheme' => 'standard', 'scriptpath'=> '/enano' ); $terms = array( 'driver' => $lang->get('cli_prompt_driver'), 'dbhost' => $lang->get('cli_prompt_dbhost'), 'dbport' => $lang->get('cli_prompt_dbport'), 'dbuser' => $lang->get('cli_prompt_dbuser'), 'dbpasswd' => $lang->get('cli_prompt_dbpasswd'), 'dbname' => $lang->get('cli_prompt_dbname'), 'db_prefix' => $lang->get('cli_prompt_db_prefix'), 'user' => $lang->get('cli_prompt_user'), 'pass' => $lang->get('cli_prompt_pass'), 'email' => $lang->get('cli_prompt_email'), 'sitename' => $lang->get('cli_prompt_sitename'), 'sitedesc' => $lang->get('cli_prompt_sitedesc'), 'copyright' => $lang->get('cli_prompt_copyright'), 'urlscheme' => $lang->get('cli_prompt_urlscheme'), 'scriptpath'=> $lang->get('cli_prompt_scriptpath') ); $defaults['dbport'] = ( strtolower($driver) == 'postgresql' ) ? 5432 : 3306; foreach ( array('driver', 'dbhost', 'dbport', 'dbuser', 'dbpasswd', 'dbname', 'db_prefix', 'scriptpath', 'user', 'pass', 'email', 'sitename', 'sitedesc', 'copyright', 'urlscheme') as $var ) { if ( empty($$var) ) { switch($var) { default: $$var = cli_prompt($terms[$var], $defaults[$var]); break; case 'driver': $$var = cli_prompt($terms[$var], $defaults[$var]); $defaults['dbport'] = ( strtolower($driver) == 'postgresql' ) ? 5432 : 3306; break; case 'pass': case 'dbpasswd': if ( @file_exists('/bin/stty') && @is_executable('/bin/stty') ) { exec('/bin/stty -echo'); while ( true ) { $$var = cli_prompt($terms[$var], $defaults[$var]); echo "\n"; $confirm = cli_prompt($lang->get('cli_prompt_confirm'), $defaults[$var]); echo "\n"; if ( $$var === $confirm ) break; else echo parse_shellcolor_string($lang->get('cli_err_pass_no_match')); } exec('/bin/stty echo'); } else { $$var = cli_prompt("{$terms[$var]} " . $lang->get('cli_msg_echo_warning'), $defaults[$var]); } break; case 'urlscheme': $temp = ''; while ( !in_array($temp, array('standard', 'short', 'rewrite', 'tiny')) ) { $temp = cli_prompt($terms[$var], $defaults[$var]); } $$var = $temp; break; case 'db_prefix': while ( !preg_match('/^[a-z0-9_]*$/', $$var) ) { $$var = cli_prompt($terms[$var], $defaults[$var]); } break; case 'dbport': $$var = cli_prompt($terms[$var], strval($defaults[$var])); while ( !preg_match('/^[0-9]*$/', $$var) ) { $$var = cli_prompt($terms[$var], $defaults[$var]); } $$var = intval($$var); break; } } } ## ## DB TEST ## require( ENANO_ROOT . '/includes/dbal.php' ); require( ENANO_ROOT . '/includes/sql_parse.php' ); $dbal = new $driver(); if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_msg_testing_db')); $result = $dbal->connect(true, $dbhost, $dbuser, $dbpasswd, $dbname, $dbport); if ( !$result ) { if ( !$silent ) { echo parse_shellcolor_string($lang->get('cli_test_fail')) . "\n"; echo "[$driver] " . $dbal->sql_error() . "\n"; } installer_fail($lang->get('cli_err_db_connect_fail')); } if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_test_pass')) . "\n"; ## ## SERVER REQUIREMENTS ## if ( !$silent ) { echo parse_shellcolor_string($lang->get('cli_stage_sysreqs')); } $failed = false; $warnings = array(); // Test: PHP if ( !$silent ) echo ' ' . $lang->get('sysreqs_req_php') . ': '; if ( version_compare(PHP_VERSION, '5.2.0', '>=') ) { if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_test_pass')) . "\n"; } else if ( version_compare(PHP_VERSION, '5.0.0', '>=') ) { if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_test_vwarn')) . "\n"; $warnings[] = $lang->get('sysreqs_req_help_php', array('php_version' => PHP_VERSION)); } else { $failed = true; if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_test_fail')) . "\n"; } // Test: MySQL if ( !$silent ) echo ' ' . $lang->get('sysreqs_req_mysql') . ': '; $req_mysql = function_exists('mysql_connect'); if ( $req_mysql ) { if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_test_pass')) . "\n"; $have_dbms = true; } else { if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_test_fail')) . "\n"; } // Test: PostgreSQL if ( !$silent ) echo ' ' . $lang->get('sysreqs_req_postgresql') . ': '; $req_pgsql = function_exists('pg_connect'); if ( $req_pgsql ) { if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_test_pass')) . "\n"; $have_dbms = true; } else { if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_test_fail')) . "\n"; } if ( !$have_dbms ) $failed = true; // Test: Safe Mode if ( !$silent ) echo ' ' . $lang->get('sysreqs_req_safemode') . ': '; $req_safemode = !intval(@ini_get('safe_mode')); if ( !$req_safemode ) { if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_test_fail')) . "\n"; $warnings[] = $lang->get('sysreqs_req_help_safemode'); $failed = true; } else { if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_test_pass')) . "\n"; } // Test: File uploads if ( !$silent ) echo ' ' . $lang->get('sysreqs_req_uploads') . ': '; $req_uploads = intval(@ini_get('file_uploads')); if ( $req_uploads ) { if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_test_pass')) . "\n"; } else { if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_test_warn')) . "\n"; } // Test: ctype validation if ( !$silent ) echo ' ' . $lang->get('sysreqs_req_ctype') . ': '; $req_ctype = function_exists('ctype_digit'); if ( $req_ctype ) { if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_test_pass')) . "\n"; } else { if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_test_fail')) . "\n"; $failed = true; } // Test: crypto $crypto_backend = install_get_crypto_backend(); if ( !$silent ) { echo ' ' . $lang->get('sysreqs_req_crypto') . ': '; switch($crypto_backend) { case 'bcmath': echo parse_shellcolor_string($lang->get('cli_test_warn') . " [<c 0;33>" . $lang->get("sysreqs_req_{$crypto_backend}") . "</c>]") . "\n"; $warnings[] = $lang->get('sysreqs_req_help_crypto_bcmath'); break; case 'none': echo parse_shellcolor_string($lang->get('cli_test_warn') . " [<c 0;31>" . $lang->get("sysreqs_req_notfound") . "</c>]") . "\n"; $warnings[] = $lang->get('sysreqs_req_help_crypto_none'); break; default: echo parse_shellcolor_string($lang->get('cli_test_pass') . " [<c 0;32>" . $lang->get("sysreqs_req_{$crypto_backend}") . "</c>]") . "\n"; break; } } // Write tests $req_config_w = write_test('config.new.php'); $req_htaccess_w = write_test('.htaccess.new'); $req_files_w = write_test('files'); $req_cache_w = write_test('cache'); if ( !$silent ) echo ' ' . $lang->get('sysreqs_req_config_writable') . ': ' . parse_shellcolor_string($lang->get($req_config_w ? 'cli_test_pass' : 'cli_test_fail')) . "\n"; if ( !$silent ) echo ' ' . $lang->get('sysreqs_req_htaccess_writable') . ': ' . parse_shellcolor_string($lang->get($req_htaccess_w ? 'cli_test_pass' : 'cli_test_warn')) . "\n"; if ( !$silent ) echo ' ' . $lang->get('sysreqs_req_files_writable') . ': ' . parse_shellcolor_string($lang->get($req_files_w ? 'cli_test_pass' : 'cli_test_warn')) . "\n"; if ( !$silent ) echo ' ' . $lang->get('sysreqs_req_cache_writable') . ': ' . parse_shellcolor_string($lang->get($req_cache_w ? 'cli_test_pass' : 'cli_test_warn')) . "\n"; if ( !$req_config_w || !$req_htaccess_w || !$req_files_w || !$req_cache_w ) $warnings[] = $lang->get('sysreqs_req_help_writable'); if ( !$req_config_w ) $failed = true; // Extension test: GD $req_gd = function_exists('imagecreatefrompng') && function_exists('getimagesize') && function_exists('imagecreatetruecolor') && function_exists('imagecopyresampled'); if ( !$req_gd ) $warnings[] = $lang->get('sysreqs_req_help_gd2'); if ( !$silent ) echo ' ' . $lang->get('sysreqs_req_gd2') . ': ' . parse_shellcolor_string($lang->get($req_gd ? 'cli_test_pass' : 'cli_test_warn')) . "\n"; // FS test: ImageMagick $req_imagick = which('convert'); if ( !$req_imagick ) $warnings[] = $lang->get('sysreqs_req_help_imagemagick'); if ( !$silent ) echo ' ' . $lang->get('sysreqs_req_imagemagick') . ': ' . parse_shellcolor_string($lang->get($req_imagick ? 'cli_test_pass' : 'cli_test_warn')) . "\n"; if ( !empty($warnings) && !$silent ) { echo parse_shellcolor_string($lang->get('cli_msg_test_warnings')) . "\n"; echo " " . implode("\n ", $warnings) . "\n"; } if ( !function_exists('mysql_connect') && !function_exists('pg_connect') ) { installer_fail($lang->get('cli_err_no_drivers')); } if ( $failed ) { installer_fail($lang->get('cli_err_sysreqs_fail')); } ## ## STAGE 1 INSTALLATION ## if ( !$silent ) { echo parse_shellcolor_string($lang->get('cli_msg_tests_passed')); echo parse_shellcolor_string($lang->get('cli_msg_installing_db_stage1')); } // Create the config table try { $sql_parser = new SQL_Parser( ENANO_ROOT . "/install/schemas/{$driver}_stage1.sql" ); } catch ( Exception $e ) { if ( !$silent ) echo "\n"; installer_fail($lang->get('cli_err_schema_load')); } // Check to see if the config table already exists $q = $dbal->sql_query('SELECT config_name, config_value FROM ' . $db_prefix . 'config LIMIT 1;'); if ( !$q ) { $sql_parser->assign_vars(array( 'TABLE_PREFIX' => $db_prefix )); $sql = $sql_parser->parse(); foreach ( $sql as $q ) { if ( !$dbal->sql_query($q) ) { if ( !$silent ) echo "\n"; echo "[$driver] " . $dbal->sql_error() . "\n"; installer_fail($lang->get('cli_err_db_query')); } } } else { $dbal->free_result(); if ( !$dbal->sql_query('DELETE FROM ' . $db_prefix . 'config WHERE config_name = \'install_aes_key\';') ) { if ( !$silent ) echo "\n"; echo "[$driver] " . $dbal->sql_error() . "\n"; installer_fail($lang->get('cli_err_db_query')); } } if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_msg_ok')) . "\n"; define('table_prefix', $db_prefix); ## ## STAGE 2 INSTALLATION ## $db =& $dbal; $dbdriver =& $driver; // Yes, I am predicting the future here. Because I have that kind of power. $_SERVER['REMOTE_ADDR'] = ( intval(date('Y')) >= 2011 ) ? '::1' : '127.0.0.1'; if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_msg_parsing_schema')); require_once( ENANO_ROOT . '/includes/rijndael.php' ); require_once( ENANO_ROOT . '/includes/hmac.php' ); $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); $hmac_secret = hexencode(AESCrypt::randkey(20), '', ''); $admin_pass_clean =& $pass; $admin_pass = hmac_sha1($admin_pass_clean, $hmac_secret); unset($admin_pass_clean); // Security try { $sql_parser = new SQL_Parser( ENANO_ROOT . "/install/schemas/{$dbdriver}_stage2.sql" ); } catch ( Exception $e ) { if ( !$silent ) echo "\n"; installer_fail($lang->get('cli_err_schema_load')); } $vars = array( 'TABLE_PREFIX' => table_prefix, 'SITE_NAME' => $db->escape($sitename), 'SITE_DESC' => $db->escape($sitedesc), 'COPYRIGHT' => $db->escape($copyright), 'WIKI_MODE' => '0', 'ENABLE_CACHE' => ( is_writable( ENANO_ROOT . '/cache/' ) ? '1' : '0' ), 'VERSION' => installer_enano_version(), 'ADMIN_USER' => $db->escape($user), 'ADMIN_PASS' => $admin_pass, 'ADMIN_PASS_SALT' => $hmac_secret, 'ADMIN_EMAIL' => $db->escape($email), 'REAL_NAME' => '', // This has always been stubbed. 'ADMIN_EMBED_PHP' => strval(AUTH_DISALLOW), 'UNIX_TIME' => strval(time()), 'IP_ADDRESS' => $_SERVER['REMOTE_ADDR'] ); $sql_parser->assign_vars($vars); $schema = $sql_parser->parse(); if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_msg_ok')) . "\n"; ## ## PAYLOAD DELIVERY ## if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_msg_installing_db_stage2')); foreach ( $schema as $sql ) { if ( !$db->check_query($sql) ) { if ( !$silent ) echo "\n"; installer_fail($lang->get('cli_err_query_sanity_failed')); } } foreach ( $schema as $sql ) { if ( !$db->sql_query($sql) ) { if ( !$silent ) echo "\n"; echo "[$dbdriver] " . $db->sql_error() . "\n"; installer_fail($lang->get('cli_err_db_query')); } } if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_msg_ok')) . "\n"; ## ## CONFIG FILE GENERATION ## require_once( ENANO_ROOT . '/install/includes/payload.php' ); require_once( ENANO_ROOT . '/install/includes/libenanoinstallcli.php' ); define('scriptPath', $scriptpath); $urlscheme = strtr($urlscheme, array( 'short' => 'shortened' )); $_POST['url_scheme'] =& $urlscheme; run_installer_stage('writeconfig', 'writing_config', 'stg_write_config', 'install_stg_writeconfig_body'); ## ## FINAL STAGES ## if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_msg_starting_api')); // Start up the Enano API $db->close(); @define('ENANO_ALLOW_LOAD_NOLANG', 1); // If this fails, it fails hard. require(ENANO_ROOT . '/includes/common.php'); if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_msg_ok')) . "\n"; $_POST['username'] =& $user; $_POST['default_content_type'] = ( isset($start_with) ) ? $start_with : 'blank'; run_installer_stage('importlang', 'importing_language', 'stg_language_setup', $lang->get('install_stg_importlang_body')); run_installer_stage('importcontent', 'importing_content', 'stg_add_content', $lang->get('install_stg_importcontent_body')); run_installer_stage('initlogs', 'initting_logs', 'stg_init_logs', $lang->get('install_stg_initlogs_body')); run_installer_stage('cleanup', 'cleaning_up', 'stg_aes_cleanup', $lang->get('install_stg_cleanup_body'), false); run_installer_stage('buildindex', 'initting_index', 'stg_build_index', $lang->get('install_stg_buildindex_body')); run_installer_stage('renameconfig', 'renaming_config', 'stg_rename_config', $lang->get('install_stg_rename_body', array('mainpage_link' => scriptPath . '/index.php'))); if ( !$silent ) { echo parse_shellcolor_string($lang->get('cli_msg_install_success')); } return true; ## ## FUNCTIONS ## function cli_prompt($prompt, $default = false) { if ( is_string($default) ) { echo "$prompt [$default]: "; $stdin = fopen('php://stdin', 'r'); $input = trim(fgets($stdin, 1024)); fclose($stdin); if ( empty($input) ) return $default; return $input; } else { while ( true ) { echo "$prompt: "; $stdin = fopen('php://stdin', 'r'); $input = trim(fgets($stdin, 1024)); fclose($stdin); if ( !empty($input) ) return $input; } } } function run_test($evalme, $test, $description, $warnonly = false) { global $silent, $test_failed, $lang; if ( !$silent ) echo "$test: "; $result = eval($evalme); if ( $result ) { if ( !$silent ) echo parse_shellcolor_string($lang->get('cli_test_pass')); } else { if ( !$silent ) echo $warnonly ? parse_shellcolor_string($lang->get('cli_test_warn')) : parse_shellcolor_string($lang->get('cli_test_fail')); if ( !$silent ) echo "\n" . preg_replace('/^/m', ' ', wordwrap(strip_tags($description))); if ( !$warnonly ) $test_failed = true; } if ( !$silent ) echo "\n"; } function installer_fail($message) { global $silent; if ( $silent ) file_put_contents('php://stderr', "$message\n"); else echo "\x1B[1;31m" . "Error:\x1B[0;1m $message\x1B[0m\n"; exit(1); } function config_write_test() { if ( !is_writable(ENANO_ROOT.'/config.new.php') ) return false; // We need to actually _open_ the file to make sure it can be written, because sometimes this fails even when is_writable() returns // true on Windows/IIS servers. Don't ask me why. $h = @fopen( ENANO_ROOT . '/config.new.php', 'a+' ); if ( !$h ) return false; fclose($h); return true; } function parse_shellcolor_string($str) { // only compute this once (saves some CPU time) static $do_colors = null; if ( $do_colors === null ) { $do_colors = ( isset($_SERVER['TERM']) && $_SERVER['TERM'] != 'dumb' ); } $expr = '/<c ((?:[0-9]+)(?:;[0-9]+)*)>([\w\W]*?)<\/c>/'; while ( preg_match($expr, $str) ) $str = $do_colors ? preg_replace($expr, "\x1B[\\1m\\2\x1B[0m", $str) : preg_replace($expr, "\\2", $str); return $str; }