diff options
Diffstat (limited to 'installer')
-rw-r--r-- | installer/check.php | 58 | ||||
-rw-r--r-- | installer/config.php | 54 | ||||
-rw-r--r-- | installer/index.php | 31 | ||||
-rw-r--r-- | installer/rcube_install.php | 278 | ||||
-rw-r--r-- | installer/test.php | 154 |
5 files changed, 368 insertions, 207 deletions
diff --git a/installer/check.php b/installer/check.php index 14fc4f06e..ee0c9f367 100644 --- a/installer/check.php +++ b/installer/check.php @@ -42,12 +42,13 @@ $ini_checks = array( 'suhosin.session.encrypt' => 0, 'magic_quotes_runtime' => 0, 'magic_quotes_sybase' => 0, - 'date.timezone' => '-NOTEMPTY-', ); $optional_checks = array( // required for utils/modcss.inc, should we require this? 'allow_url_fopen' => 1, + 'date.timezone' => '-VALID-', + 'register_globals' => 0, // #1489157 ); $source_urls = array( @@ -64,12 +65,12 @@ $source_urls = array( 'Intl' => 'http://www.php.net/manual/en/book.intl.php', 'Exif' => 'http://www.php.net/manual/en/book.exif.php', 'PDO' => 'http://www.php.net/manual/en/book.pdo.php', - 'pdo_mysql' => 'http://www.php.net/manual/en/book.pdo-mysql.php', - 'pdo_pgsql' => 'http://www.php.net/manual/en/book.pdo-pgsql.php', - 'pdo_sqlite' => 'http://www.php.net/manual/en/book.pdo-sqlite.php', - 'pdo_sqlite2' => 'http://www.php.net/manual/en/book.pdo-sqlite.php', - 'pdo_sqlsrv' => 'http://www.php.net/manual/en/book.pdo-sqlsrv.php', - 'pdo_dblib' => 'http://www.php.net/manual/en/book.pdo-dblib.php', + 'pdo_mysql' => 'http://www.php.net/manual/en/ref.pdo-mysql.php', + 'pdo_pgsql' => 'http://www.php.net/manual/en/ref.pdo-pgsql.php', + 'pdo_sqlite' => 'http://www.php.net/manual/en/ref.pdo-sqlite.php', + 'pdo_sqlite2' => 'http://www.php.net/manual/en/ref.pdo-sqlite.php', + 'pdo_sqlsrv' => 'http://www.php.net/manual/en/ref.pdo-sqlsrv.php', + 'pdo_dblib' => 'http://www.php.net/manual/en/ref.pdo-dblib.php', 'PEAR' => 'http://pear.php.net', 'Net_SMTP' => 'http://pear.php.net/package/Net_SMTP', 'Mail_mime' => 'http://pear.php.net/package/Mail_mime', @@ -139,10 +140,11 @@ foreach ($RCI->supported_dbs as $database => $ext) { if (extension_loaded($ext)) { // MySQL driver requires PHP >= 5.3 (#1488875) if ($ext == 'pdo_mysql' && version_compare(PHP_VERSION, '5.3.0', '<')) { - $RCI->fail($database, 'PHP >= 5.3 required'); + $RCI->fail($database, 'PHP >= 5.3 required', null, true); } else { $RCI->pass($database); + $found_db_driver = true; } } else { @@ -152,6 +154,9 @@ foreach ($RCI->supported_dbs as $database => $ext) { } echo '<br />'; } +if (empty($found_db_driver)) { + $RCI->failures++; +} ?> @@ -185,23 +190,15 @@ foreach ($ini_checks as $var => $val) { if ($val === '-NOTEMPTY-') { if (empty($status)) { $RCI->fail($var, "empty value detected"); - } else if ($var == 'date.timezone') { - try { - $tz = new DateTimeZone($status); - $RCI->pass($var); - } - catch (Exception $e) { - $RCI->fail($var, "invalid value detected: $status"); - } - } else { + } + else { $RCI->pass($var); } - echo '<br />'; - continue; } - if ($status == $val) { + else if (filter_var($status, FILTER_VALIDATE_BOOLEAN) == $val) { $RCI->pass($var); - } else { + } + else { $RCI->fail($var, "is '$status', should be '$val'"); } echo '<br />'; @@ -223,9 +220,24 @@ foreach ($optional_checks as $var => $val) { echo '<br />'; continue; } - if ($status == $val) { + if ($val === '-VALID-') { + if ($var == 'date.timezone') { + try { + $tz = new DateTimeZone($status); + $RCI->pass($var); + } + catch (Exception $e) { + $RCI->optfail($var, empty($status) ? "not set" : "invalid value detected: $status"); + } + } + else { + $RCI->pass($var); + } + } + else if (filter_var($status, FILTER_VALIDATE_BOOLEAN) == $val) { $RCI->pass($var); - } else { + } + else { $RCI->optfail($var, "is '$status', could be '$val'"); } echo '<br />'; diff --git a/installer/config.php b/installer/config.php index d6846edc7..f990fc23f 100644 --- a/installer/config.php +++ b/installer/config.php @@ -9,13 +9,9 @@ if (!class_exists('rcube_install') || !is_object($RCI)) { <input type="hidden" name="_step" value="2" /> <?php -// also load the default config to fill in the fields -$RCI->load_defaults(); - // register these boolean fields $RCI->bool_config_props = array( 'ip_check' => 1, - 'enable_caching' => 1, 'enable_spellcheck' => 1, 'auto_create_user' => 1, 'smtp_log' => 1, @@ -28,24 +24,24 @@ $RCI->bool_config_props = array( $_SESSION['allowinstaller'] = true; if (!empty($_POST['submit'])) { - - echo '<p class="notice">Copy or download the following configurations and save them in two files'; - echo ' (names above the text box) within the <tt>'.RCMAIL_CONFIG_DIR.'</tt> directory of your Roundcube installation.<br/>'; - echo ' Make sure that there are no characters outside the <tt><?php ?></tt> brackets when saving the files.</p>'; - + echo '<p class="notice">Copy or download the following configuration and save it'; + echo ' as <tt><b>config.inc.php</b></tt> within the <tt>'.RCUBE_CONFIG_DIR.'</tt> directory of your Roundcube installation.<br/>'; + echo ' Make sure that there are no characters outside the <tt><?php ?></tt> brackets when saving the file.'; + echo ' <input type="button" onclick="location.href=\'index.php?_getconfig=1\'" value="Download" />'; + if ($RCI->legacy_config) { + echo '<br/><br/>Afterwards, please <b>remove</b> the old configuration files <tt>main.inc.php</tt> and <tt>db.inc.php</tt>'; + echo ' from the config directory.'; + } + echo '</p>'; + $textbox = new html_textarea(array('rows' => 16, 'cols' => 60, 'class' => "configfile")); - - echo '<div><em>main.inc.php (<a href="index.php?_getfile=main">download</a>)</em></div>'; - echo $textbox->show(($_SESSION['main.inc.php'] = $RCI->create_config('main'))); - - echo '<div style="margin-top:1em"><em>db.inc.php (<a href="index.php?_getfile=db">download</a>)</em></div>'; - echo $textbox->show($_SESSION['db.inc.php'] = $RCI->create_config('db')); + echo $textbox->show(($_SESSION['config'] = $RCI->create_config())); echo '<p class="hint">Of course there are more options to configure. - Have a look at the config files or visit <a href="http://trac.roundcube.net/wiki/Howto_Config">Howto_Config</a> to find out.</p>'; + Have a look at the defaults.inc.php file or visit <a href="http://trac.roundcube.net/wiki/Howto_Config">Howto_Config</a> to find out.</p>'; echo '<p><input type="button" onclick="location.href=\'./index.php?_step=3\'" value="CONTINUE" /></p>'; - + // echo '<style type="text/css"> .configblock { display:none } </style>'; echo "\n<hr style='margin-bottom:1.6em' />\n"; } @@ -127,16 +123,6 @@ echo $check_ipcheck->show(intval($RCI->getprop('ip_check')), array('value' => 1) <p class="hint">This increases security but can cause sudden logouts when someone uses a proxy with changing IPs.</p> </dd> -<dt class="propname">enable_caching</dt> -<dd> -<?php - -$check_caching = new html_checkbox(array('name' => '_enable_caching', 'id' => "cfgcache")); -echo $check_caching->show(intval($RCI->getprop('enable_caching')), array('value' => 1)); - -?> -<label for="cfgcache">Cache messages in local database</label><br /> -</dd> <dt class="propname">enable_spellcheck</dt> <dd> @@ -301,6 +287,18 @@ echo '<label for="cfgdbpass">Database password (omit for sqlite)</label><br />'; ?> </dd> + +<dt class="propname">db_prefix</dt> +<dd> +<?php + +$input_prefix = new html_inputfield(array('name' => '_db_prefix', 'size' => 20, 'id' => "cfgdbprefix")); +echo $input_prefix->show($RCI->getprop('db_prefix')); + +?> +<div>Optional prefix that will be added to database object names (tables and sequences).</div> +</dd> + </dl> </fieldset> @@ -647,7 +645,7 @@ $select_param_folding->add('Full RFC 2231 (Roundcube, Thunderbird)', '0'); $select_param_folding->add('RFC 2047/2231 (MS Outlook, OE)', '1'); $select_param_folding->add('Full RFC 2047 (deprecated)', '2'); -echo $select_param_folding->show(intval($RCI->getprop('mime_param_folding'))); +echo $select_param_folding->show(strval($RCI->getprop('mime_param_folding'))); ?> <div>How to encode attachment long/non-ascii names</div> diff --git a/installer/index.php b/installer/index.php index 0e80b1cd6..d084c8aa5 100644 --- a/installer/index.php +++ b/installer/index.php @@ -5,7 +5,7 @@ | Roundcube Webmail setup tool | | Version 0.9-git | | | - | Copyright (C) 2009-2012, The Roundcube Dev Team | + | Copyright (C) 2009-2013, The Roundcube Dev Team | | | | This program is free software: you can redistribute it and/or modify | | it under the terms of the GNU General Public License (with exceptions | @@ -54,17 +54,18 @@ require_once 'rcube_install.php'; // deprecated aliases (to be removed) require_once 'bc.php'; -session_start(); +if (function_exists('session_start')) + session_start(); $RCI = rcube_install::get_instance(); $RCI->load_config(); -if (isset($_GET['_getfile']) && in_array($_GET['_getfile'], array('main', 'db'))) { - $filename = $_GET['_getfile'] . '.inc.php'; - if (!empty($_SESSION[$filename])) { +if (isset($_GET['_getconfig'])) { + $filename = 'config.inc.php'; + if (!empty($_SESSION['config'])) { header('Content-type: text/plain'); header('Content-Disposition: attachment; filename="'.$filename.'"'); - echo $_SESSION[$filename]; + echo $_SESSION['config']; exit; } else { @@ -74,14 +75,14 @@ if (isset($_GET['_getfile']) && in_array($_GET['_getfile'], array('main', 'db')) } if ($RCI->configured && ($RCI->getprop('enable_installer') || $_SESSION['allowinstaller']) && - isset($_GET['_mergeconfig']) && in_array($_GET['_mergeconfig'], array('main', 'db'))) { - $filename = $_GET['_mergeconfig'] . '.inc.php'; + !empty($_GET['_mergeconfig'])) { + $filename = 'config.inc.php'; header('Content-type: text/plain'); header('Content-Disposition: attachment; filename="'.$filename.'"'); $RCI->merge_config(); - echo $RCI->create_config($_GET['_mergeconfig'], true); + echo $RCI->create_config(); exit; } @@ -121,8 +122,16 @@ if ($RCI->configured && empty($_REQUEST['_step'])) { // exit if installation is complete if ($RCI->configured && !$RCI->getprop('enable_installer') && !$_SESSION['allowinstaller']) { // header("HTTP/1.0 404 Not Found"); - echo '<h2 class="error">The installer is disabled!</h2>'; - echo '<p>To enable it again, set <tt>$rcmail_config[\'enable_installer\'] = true;</tt> in RCUBE_CONFIG_DIR/main.inc.php</p>'; + if ($RCI->configured && $RCI->legacy_config) { + echo '<h2 class="error">Your configuration needs to be migrated!</h2>'; + echo '<p>We changed the configuration files structure and your installation needs to be updated accordingly.</p>'; + echo '<p>Please run the <tt>bin/update.sh</tt> script from the command line or set <p> <tt>$rcmail_config[\'enable_installer\'] = true;</tt></p>'; + echo ' in your RCUBE_CONFIG_DIR/main.inc.php to let the installer help you migrating it.</p>'; + } + else { + echo '<h2 class="error">The installer is disabled!</h2>'; + echo '<p>To enable it again, set <tt>$rcmail_config[\'enable_installer\'] = true;</tt> in RCUBE_CONFIG_DIR/config.inc.php</p>'; + } echo '</div></body></html>'; exit; } diff --git a/installer/rcube_install.php b/installer/rcube_install.php index d5811ded1..0f1bfe23e 100644 --- a/installer/rcube_install.php +++ b/installer/rcube_install.php @@ -28,10 +28,12 @@ class rcube_install var $failures = 0; var $config = array(); var $configured = false; + var $legacy_config = false; var $last_error = null; var $email_pattern = '([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9]([a-z0-9\-][.]?)*[a-z0-9])'; var $bool_config_props = array(); + var $local_config = array('db_dsnw', 'default_host', 'support_url', 'des_key', 'plugins'); var $obsolete_config = array('db_backend', 'double_auth'); var $replaced_config = array( 'skin_path' => 'skin', @@ -44,12 +46,6 @@ class rcube_install 'top_posting' => 'reply_mode', ); - // these config options are required for a working system - var $required_config = array( - 'db_dsnw', 'db_table_contactgroups', 'db_table_contactgroupmembers', - 'des_key', 'session_lifetime', 'support_url', - ); - // list of supported database drivers var $supported_dbs = array( 'MySQL' => 'pdo_mysql', @@ -84,43 +80,75 @@ class rcube_install } /** - * Read the default config files and store properties - */ - function load_defaults() - { - $this->_load_config('.php.dist'); - } - - - /** * Read the local config files and store properties */ function load_config() { - $this->config = array(); - $this->_load_config('.php'); - $this->configured = !empty($this->config); + // defaults + if ($config = $this->load_config_file(RCUBE_CONFIG_DIR . 'defaults.inc.php')) { + $this->config = (array) $config; + $this->defaults = $this->config; + } + + $config = null; + + // config + if ($config = $this->load_config_file(RCUBE_CONFIG_DIR . 'config.inc.php')) { + $this->config = array_merge($this->config, $config); + } + else { + if ($config = $this->load_config_file(RCUBE_CONFIG_DIR . 'main.inc.php')) { + $this->config = array_merge($this->config, $config); + $this->legacy_config = true; + } + if ($config = $this->load_config_file(RCUBE_CONFIG_DIR . 'db.inc.php')) { + $this->config = array_merge($this->config, $config); + $this->legacy_config = true; + } + } + + $this->configured = !empty($config); } /** * Read the default config file and store properties - * @access private */ - function _load_config($suffix) + public function load_config_file($file) { - if (is_readable($main_inc = RCUBE_CONFIG_DIR . 'main.inc' . $suffix)) { - include($main_inc); - if (is_array($rcmail_config)) - $this->config += $rcmail_config; - } - if (is_readable($db_inc = RCUBE_CONFIG_DIR . 'db.inc'. $suffix)) { - include($db_inc); - if (is_array($rcmail_config)) - $this->config += $rcmail_config; + if (is_readable($file)) { + include $file; + + // read comments from config file + if (function_exists('token_get_all')) { + $tokens = token_get_all(file_get_contents($file)); + $in_config = false; + $buffer = ''; + for ($i=0; $i < count($tokens); $i++) { + $token = $tokens[$i]; + if ($token[0] == T_VARIABLE && $token[1] == '$config' || $token[1] == '$rcmail_config') { + $in_config = true; + if ($buffer && $tokens[$i+1] == '[' && $tokens[$i+2][0] == T_CONSTANT_ENCAPSED_STRING) { + $propname = trim($tokens[$i+2][1], "'\""); + $this->comments[$propname] = $buffer; + $buffer = ''; + $i += 3; + } + } + else if ($in_config && $token[0] == T_COMMENT) { + $buffer .= strtr($token[1], array('\n' => "\n")); + } + } + } + + // deprecated name of config variable + if (is_array($rcmail_config)) { + return $rcmail_config; + } + + return $config; } } - /** * Getter for a certain config property * @@ -140,24 +168,31 @@ class rcube_install /** - * Take the default config file and replace the parameters - * with the submitted form data + * Create configuration file that contains parameters + * that differ from default values. * - * @param string Which config file (either 'main' or 'db') * @return string The complete config file content */ - function create_config($which, $force = false) + function create_config() { - $out = @file_get_contents(RCUBE_CONFIG_DIR . $which . '.inc.php.dist'); - - if (!$out) - return '[Warning: could not read the config template file]'; + $config = array(); foreach ($this->config as $prop => $default) { - $is_default = !isset($_POST["_$prop"]); $value = !$is_default || $this->bool_config_props[$prop] ? $_POST["_$prop"] : $default; + // always disable installer + if ($prop == 'enable_installer') + $value = false; + + // reset useragent to default (keeps version up-to-date) + if ($prop == 'useragent' && stripos($value, 'Roundcube Webmail/') !== false) + $value = $this->defaults[$prop]; + + // generate new encryption key, never use the default value + if ($prop == 'des_key' && $value == $this->defaults[$prop]) + $value = $this->random_key(24); + // convert some form data if ($prop == 'debug_level' && !$is_default) { if (is_array($value)) { @@ -167,7 +202,7 @@ class rcube_install $value = $val; } } - else if ($which == 'db' && $prop == 'db_dsnw' && !empty($_POST['_dbtype'])) { + else if ($prop == 'db_dsnw' && !empty($_POST['_dbtype'])) { if ($_POST['_dbtype'] == 'sqlite') $value = sprintf('%s://%s?mode=0646', $_POST['_dbtype'], $_POST['_dbname']{0} == '/' ? '/' . $_POST['_dbname'] : $_POST['_dbname']); else if ($_POST['_dbtype']) @@ -212,20 +247,24 @@ class rcube_install } // skip this property - if (!$force && !$this->configured && ($value == $default)) + if ((!array_key_exists($prop, $this->defaults) || ($value == $this->defaults[$prop])) && !in_array($prop, $this->local_config)) { continue; + } // save change $this->config[$prop] = $value; + $config[$prop] = $value; + } - // replace the matching line in config file - $out = preg_replace( - '/(\$rcmail_config\[\''.preg_quote($prop).'\'\])\s+=\s+(.+);/Uie', - "'\\1 = ' . rcube_install::_dump_var(\$value, \$prop) . ';'", - $out); + $out = "<?php\n\n"; + $out .= "/* Local configuration for Roundcube Webmail */\n\n"; + foreach ($config as $prop => $value) { + // copy option descriptions from existing config or defaults.inc.php + $out .= $this->comments[$prop]; + $out .= "\$config['$prop'] = " . rcube_install::_dump_var($value, $prop) . ";\n\n"; } - return trim($out); + return $out; } @@ -237,16 +276,13 @@ class rcube_install */ function check_config() { - $this->config = array(); - $this->load_defaults(); - $defaults = $this->config; - $this->load_config(); - if (!$this->configured) + + if (!$this->configured) { return null; + } $out = $seen = array(); - $required = array_flip($this->required_config); // iterate over the current configuration foreach ($this->config as $prop => $value) { @@ -265,12 +301,6 @@ class rcube_install $out['obsolete'][] = array('prop' => 'mime_magic', 'explain' => "Set value to null in order to use system default"); } - // iterate over default config - foreach ($defaults as $prop => $value) { - if (!isset($seen[$prop]) && isset($required[$prop]) && !(is_bool($this->config[$prop]) || strlen($this->config[$prop]))) - $out['missing'][] = array('prop' => $prop); - } - // check config dependencies and contradictions if ($this->config['enable_spellcheck'] && $this->config['spellcheck_engine'] == 'pspell') { if (!extension_loaded('pspell')) { @@ -288,7 +318,7 @@ class rcube_install if ($this->config['log_driver'] == 'syslog') { if (!function_exists('openlog')) { $out['dependencies'][] = array('prop' => 'log_driver', - 'explain' => 'This requires the <tt>sylog</tt> extension which could not be loaded.'); + 'explain' => 'This requires the <tt>syslog</tt> extension which could not be loaded.'); } if (empty($this->config['syslog_id'])) { $out['dependencies'][] = array('prop' => 'syslog_id', @@ -318,7 +348,6 @@ class rcube_install { $current = $this->config; $this->config = array(); - $this->load_defaults(); foreach ($this->replaced_config as $prop => $replacement) { if (isset($current[$prop])) { @@ -346,9 +375,9 @@ class rcube_install } } - $this->config = array_merge($this->config, $current); + $this->config = array_merge($this->config, $current); - foreach ((array)$current['ldap_public'] as $key => $values) { + foreach (array_keys((array)$current['ldap_public']) as $key) { $this->config['ldap_public'][$key] = $current['ldap_public'][$key]; } } @@ -357,10 +386,11 @@ class rcube_install * Compare the local database schema with the reference schema * required for this version of Roundcube * - * @param boolean True if the schema schould be updated + * @param rcube_db Database object + * * @return boolean True if the schema is up-to-date, false if not or an error occured */ - function db_schema_check($DB, $update = false) + function db_schema_check($DB) { if (!$this->configured) return false; @@ -373,7 +403,7 @@ class rcube_install $existing_tables = $DB->list_tables(); foreach ($db_schema as $table => $cols) { - $table = !empty($this->config['db_table_'.$table]) ? $this->config['db_table_'.$table] : $table; + $table = $this->config['db_prefix'] . $table; if (!in_array($table, $existing_tables)) { $errors[] = "Missing table '".$table."'"; } @@ -411,6 +441,51 @@ class rcube_install return $schema; } + /** + * Try to detect some file's mimetypes to test the correct behavior of fileinfo + */ + function check_mime_detection() + { + $files = array( + 'installer/images/roundcube_logo.png' => 'image/png', + 'program/resources/blank.tif' => 'image/tiff', + 'skins/larry/templates/login.html' => 'text/html', + ); + + $errors = array(); + foreach ($files as $path => $expected) { + $mimetype = rcube_mime::file_content_type(INSTALL_PATH . $path, basename($path)); + if ($mimetype != $expected) { + $errors[] = array($path, $mimetype, $expected); + } + } + + return $errors; + } + + /** + * Check the correct configuration of the 'mime_types' mapping option + */ + function check_mime_extensions() + { + $types = array( + 'application/zip' => 'zip', + 'application/x-tar' => 'tar', + 'application/java-archive' => 'jar', + 'image/bmp' => 'bmp', + 'image/svg+xml' => 'svg', + ); + + $errors = array(); + foreach ($types as $mimetype => $expected) { + $ext = rcube_mime::get_mime_extensions($mimetype); + if ($ext[0] != $expected) { + $errors[] = array($mimetype, $ext, $expected); + } + } + + return $errors; + } /** * Getter for the last error message @@ -452,11 +527,12 @@ class rcube_install '0.2-alpha', '0.2-beta', '0.2-stable', '0.3-stable', '0.3.1', '0.4-beta', '0.4.2', - '0.5-beta', '0.5', '0.5.1', + '0.5-beta', '0.5', '0.5.1', '0.5.2', '0.5.3', '0.5.4', '0.6-beta', '0.6', - '0.7-beta', '0.7', '0.7.1', '0.7.2', '0.7.3', - '0.8-beta', '0.8-rc', '0.8.0', '0.8.1', '0.8.2', '0.8.3', '0.8.4', '0.8.5', - '0.9-beta', '0.9-rc', + '0.7-beta', '0.7', '0.7.1', '0.7.2', '0.7.3', '0.7.4', + '0.8-beta', '0.8-rc', '0.8.0', '0.8.1', '0.8.2', '0.8.3', '0.8.4', '0.8.5', '0.8.6', + '0.9-beta', '0.9-rc', '0.9-rc2', + // Note: Do not add newer versions here )); return $select; } @@ -495,10 +571,13 @@ class rcube_install * @param string Test name * @param string Error message * @param string URL for details + * @param bool Do not count this failure */ - function fail($name, $message = '', $url = '') + function fail($name, $message = '', $url = '', $optional=false) { - $this->failures++; + if (!$optional) { + $this->failures++; + } echo Q($name) . ': <span class="fail">NOT OK</span>'; $this->_showhint($message, $url); @@ -562,7 +641,8 @@ class rcube_install } - static function _dump_var($var, $name=null) { + static function _dump_var($var, $name=null) + { // special values switch ($name) { case 'syslog_facility': @@ -575,8 +655,20 @@ class rcube_install if ($val = $list[$var]) return $val; break; - } + case 'mail_header_delimiter': + $var = str_replace(array("\r", "\n"), array('\r', '\n'), $var); + return '"' . $var. '"'; + break; +/* + // RCMAIL_VERSION is undefined here + case 'useragent': + if (preg_match('|^(.*)/('.preg_quote(RCMAIL_VERSION, '|').')$|i', $var, $m)) { + return '"' . addcslashes($var, '"') . '/" . RCMAIL_VERSION'; + } + break; +*/ + } if (is_array($var)) { if (empty($var)) { @@ -584,7 +676,7 @@ class rcube_install } else { // check if all keys are numeric $isnum = true; - foreach ($var as $key => $value) { + foreach (array_keys($var) as $key) { if (!is_numeric($key)) { $isnum = false; break; @@ -638,8 +730,10 @@ class rcube_install */ function update_db($version) { - system(INSTALL_PATH . "bin/updatedb.sh --package=roundcube --version=" . $version - . " --dir=" . INSTALL_PATH . "SQL", $result); + system(INSTALL_PATH . "bin/updatedb.sh --package=roundcube" + . " --version=" . escapeshellarg($version) + . " --dir=" . INSTALL_PATH . "SQL" + . " 2>&1", $result); return !$result; } @@ -654,6 +748,7 @@ class rcube_install */ function exec_sql($sql, $DB) { + $sql = $this->fix_table_names($sql, $DB); $buff = ''; foreach (explode("\n", $sql) as $line) { if (preg_match('/^--/', $line) || trim($line) == '') @@ -673,6 +768,35 @@ class rcube_install /** + * Parse SQL file and fix table names according to db_prefix + * Note: This need to be a complete database initial file + */ + private function fix_table_names($sql, $DB) + { + if (empty($this->config['db_prefix'])) { + return $sql; + } + + // replace table names + if (preg_match_all('/CREATE TABLE (\[dbo\]\.|IF NOT EXISTS )?[`"\[\]]*([^`"\[\] \r\n]+)/i', $sql, $matches)) { + foreach ($matches[2] as $table) { + $real_table = $this->config['db_prefix'] . $table; + $sql = preg_replace("/([^a-zA-Z0-9_])$table([^a-zA-Z0-9_])/", "\\1$real_table\\2", $sql); + } + } + // replace sequence names + if ($DB->db_provider == 'postgres' && preg_match_all('/CREATE SEQUENCE (IF NOT EXISTS )?"?([^" \n\r]+)/i', $sql, $matches)) { + foreach ($matches[2] as $sequence) { + $real_sequence = $this->config['db_prefix'] . $sequence; + $sql = preg_replace("/([^a-zA-Z0-9_])$sequence([^a-zA-Z0-9_])/", "\\1$real_sequence\\2", $sql); + } + } + + return $sql; + } + + + /** * Handler for Roundcube errors */ function raise_error($p) diff --git a/installer/test.php b/installer/test.php index bd49ac523..f834308ad 100644 --- a/installer/test.php +++ b/installer/test.php @@ -7,52 +7,44 @@ if (!class_exists('rcube_install') || !is_object($RCI)) { ?> <form action="index.php?_step=3" method="post"> -<h3>Check config files</h3> +<h3>Check config file</h3> <?php -$read_main = is_readable(RCUBE_CONFIG_DIR . 'main.inc.php'); -$read_db = is_readable(RCUBE_CONFIG_DIR . 'db.inc.php'); - -if ($read_main && !empty($RCI->config)) { - $RCI->pass('main.inc.php'); -} -else if ($read_main) { - $RCI->fail('main.inc.php', 'Syntax error'); +if ($read_config = is_readable(RCUBE_CONFIG_DIR . 'defaults.inc.php')) { + $config = $RCI->load_config_file(RCUBE_CONFIG_DIR . 'defaults.inc.php'); + if (!empty($config)) { + $RCI->pass('defaults.inc.php'); + } + else { + $RCI->fail('defaults.inc.php', 'Syntax error'); + } } -else if (!$read_main) { - $RCI->fail('main.inc.php', 'Unable to read file. Did you create the config files?'); +else { + $RCI->fail('defaults.inc.php', 'Unable to read default config file?'); } echo '<br />'; -if ($read_db && !empty($RCI->config['db_table_users'])) { - $RCI->pass('db.inc.php'); -} -else if ($read_db) { - $RCI->fail('db.inc.php', 'Syntax error'); +if ($read_config = is_readable(RCUBE_CONFIG_DIR . 'config.inc.php')) { + $config = $RCI->load_config_file(RCUBE_CONFIG_DIR . 'config.inc.php'); + if (!empty($config)) { + $RCI->pass('config.inc.php'); + } + else { + $RCI->fail('config.inc.php', 'Syntax error'); + } } -else if (!$read_db) { - $RCI->fail('db.inc.php', 'Unable to read file. Did you create the config files?'); +else { + $RCI->fail('config.inc.php', 'Unable to read file. Did you create the config file?'); } +echo '<br />'; -if ($RCI->configured && ($messages = $RCI->check_config())) { - - if (is_array($messages['missing'])) { - echo '<h3 class="warning">Missing config options</h3>'; - echo '<p class="hint">The following config options are not present in the current configuration.<br/>'; - echo 'Please check the default config files and add the missing properties to your local config files.</p>'; - - echo '<ul class="configwarings">'; - foreach ($messages['missing'] as $msg) { - echo html::tag('li', null, html::span('propname', $msg['prop']) . ($msg['name'] ? ': ' . $msg['name'] : '')); - } - echo '</ul>'; - } +if ($RCI->configured && ($messages = $RCI->check_config())) { if (is_array($messages['replaced'])) { echo '<h3 class="warning">Replaced config options</h3>'; echo '<p class="hint">The following config options have been replaced or renamed. '; echo 'Please update them accordingly in your config files.</p>'; - + echo '<ul class="configwarings">'; foreach ($messages['replaced'] as $msg) { echo html::tag('li', null, html::span('propname', $msg['prop']) . @@ -64,32 +56,28 @@ if ($RCI->configured && ($messages = $RCI->check_config())) { if (is_array($messages['obsolete'])) { echo '<h3>Obsolete config options</h3>'; echo '<p class="hint">You still have some obsolete or inexistent properties set. This isn\'t a problem but should be noticed.</p>'; - + echo '<ul class="configwarings">'; foreach ($messages['obsolete'] as $msg) { echo html::tag('li', null, html::span('propname', $msg['prop']) . ($msg['name'] ? ': ' . $msg['name'] : '')); } echo '</ul>'; } - - echo '<p class="suggestion">OK, lazy people can download the updated config files here: '; - echo html::a(array('href' => './?_mergeconfig=main'), 'main.inc.php') . ' '; - echo html::a(array('href' => './?_mergeconfig=db'), 'db.inc.php'); + + echo '<p class="suggestion">OK, lazy people can download the updated config file here: '; + echo html::a(array('href' => './?_mergeconfig=1'), 'config.inc.php') . ' '; echo "</p>"; - - + if (is_array($messages['dependencies'])) { echo '<h3 class="warning">Dependency check failed</h3>'; echo '<p class="hint">Some of your configuration settings require other options to be configured or additional PHP modules to be installed</p>'; - + echo '<ul class="configwarings">'; foreach ($messages['dependencies'] as $msg) { echo html::tag('li', null, html::span('propname', $msg['prop']) . ': ' . $msg['explain']); } echo '</ul>'; } - - } ?> @@ -98,30 +86,24 @@ if ($RCI->configured && ($messages = $RCI->check_config())) { <p>Roundcube may need to write/save files into these directories</p> <?php -if ($RCI->configured) { - $pass = false; - - $dirs[] = $RCI->config['temp_dir'] ? $RCI->config['temp_dir'] : 'temp'; - if($RCI->config['log_driver'] != 'syslog') - $dirs[] = $RCI->config['log_dir'] ? $RCI->config['log_dir'] : 'logs'; +$dirs[] = $RCI->config['temp_dir'] ? $RCI->config['temp_dir'] : 'temp'; +if ($RCI->config['log_driver'] != 'syslog') + $dirs[] = $RCI->config['log_dir'] ? $RCI->config['log_dir'] : 'logs'; - foreach ($dirs as $dir) { - $dirpath = $dir[0] == '/' ? $dir : INSTALL_PATH . $dir; - if (is_writable(realpath($dirpath))) { - $RCI->pass($dir); - $pass = true; - } - else { - $RCI->fail($dir, 'not writeable for the webserver'); - } - echo '<br />'; +foreach ($dirs as $dir) { + $dirpath = $dir[0] == '/' ? $dir : INSTALL_PATH . $dir; + if (is_writable(realpath($dirpath))) { + $RCI->pass($dir); + $pass = true; } - - if (!$pass) - echo '<p class="hint">Use <tt>chmod</tt> or <tt>chown</tt> to grant write privileges to the webserver</p>'; + else { + $RCI->fail($dir, 'not writeable for the webserver'); + } + echo '<br />'; } -else { - $RCI->fail('Config', 'Could not read config files'); + +if (!$pass) { + echo '<p class="hint">Use <tt>chmod</tt> or <tt>chown</tt> to grant write privileges to the webserver</p>'; } ?> @@ -151,7 +133,7 @@ if ($RCI->configured) { } } else { - $RCI->fail('Config', 'Could not read config files'); + $RCI->fail('DSN (write)', 'Could not read config file'); } // initialize db with schema found in /SQL/* @@ -171,7 +153,7 @@ else if ($db_working && $_POST['updatedb']) { // test database if ($db_working) { - $db_read = $DB->query("SELECT count(*) FROM {$RCI->config['db_table_users']}"); + $db_read = $DB->query("SELECT count(*) FROM {$RCI->config['db_prefix']}users"); if ($DB->is_error()) { $RCI->fail('DB Schema', "Database not initialized"); echo '<p><input type="submit" name="initdb" value="Initialize database" /></p>'; @@ -195,11 +177,11 @@ if ($db_working) { if ($db_working) { // write test $insert_id = md5(uniqid()); - $db_write = $DB->query("INSERT INTO {$RCI->config['db_table_session']} (sess_id, created, ip, vars) VALUES (?, ".$DB->now().", '127.0.0.1', 'foo')", $insert_id); + $db_write = $DB->query("INSERT INTO {$RCI->config['db_prefix']}session (sess_id, created, ip, vars) VALUES (?, ".$DB->now().", '127.0.0.1', 'foo')", $insert_id); if ($db_write) { $RCI->pass('DB Write'); - $DB->query("DELETE FROM {$RCI->config['db_table_session']} WHERE sess_id=?", $insert_id); + $DB->query("DELETE FROM {$RCI->config['db_prefix']}session WHERE sess_id=?", $insert_id); } else { $RCI->fail('DB Write', $RCI->get_error()); @@ -225,6 +207,42 @@ if ($db_working) { ?> +<h3>Test filetype detection</h3> + +<p> +<?php + +if ($errors = $RCI->check_mime_detection()) { + $RCI->fail('Fileinfo/mime_content_type configuration'); + if (!empty($RCI->config['mime_magic'])) { + echo '<p class="hint">Try setting the <tt>mime_magic</tt> config option to <tt>null</tt>.</p>'; + } + else { + echo '<p class="hint">Check the <a href="http://www.php.net/manual/en/function.finfo-open.php">Fileinfo functions</a> of your PHP installation.<br/>'; + echo 'The path to the magic.mime file can be set using the <tt>mime_magic</tt> config option in Roundcube.</p>'; + } +} +else { + $RCI->pass('Fileinfo/mime_content_type configuration'); +} + +?> +</p> +<p> +<?php + +if ($errors = $RCI->check_mime_extensions()) { + $RCI->fail('Mimetype to file extension mapping'); + echo '<p class="hint">Please set a valid path to your webserver\'s mime.types file to the <tt>mime_types</tt> config option.<br/>'; + echo 'If you can\'t find such a file, download it from <a href="http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types">svn.apache.org</a>.</p>'; +} +else { + $RCI->pass('Mimetype to file extension mapping'); +} + +?> + + <h3>Test SMTP config</h3> <p> @@ -427,7 +445,7 @@ if (isset($_POST['imaptest']) && !empty($_POST['_host']) && !empty($_POST['_user After completing the installation and the final tests please <b>remove</b> the whole installer folder from the document root of the webserver or make sure that -<tt>enable_installer</tt> option in config/main.inc.php is disabled.<br /> +<tt>enable_installer</tt> option in <tt>config.inc.php</tt> is disabled.<br /> <br /> These files may expose sensitive configuration data like server passwords and encryption keys |