thomascube
2011-02-25 e6bb836e053913ec8a5930a6d51af1fa55eb08e2
Create interactive update script with improved DB schema check; udated installer with new features and styles

4 files added
14 files modified
3 files deleted
469 ■■■■ changed files
CHANGELOG 1 ●●●● patch | view | raw | blame | history
SQL/mssql.upgrade.sql 2 ●●● patch | view | raw | blame | history
SQL/mysql.update.sql 2 ●●● patch | view | raw | blame | history
SQL/postgres.update.sql 2 ●●● patch | view | raw | blame | history
SQL/sqlite.update.sql 2 ●●● patch | view | raw | blame | history
UPGRADING 33 ●●●● patch | view | raw | blame | history
bin/installto.sh 73 ●●●●● patch | view | raw | blame | history
bin/update.sh 55 ●●●● patch | view | raw | blame | history
installer/check.php 1 ●●●● patch | view | raw | blame | history
installer/images/banner_bg.gif patch | view | raw | blame | history
installer/images/banner_gradient.gif patch | view | raw | blame | history
installer/images/banner_logo.gif patch | view | raw | blame | history
installer/images/banner_right.gif patch | view | raw | blame | history
installer/images/banner_schraffur.gif patch | view | raw | blame | history
installer/images/rcube_logo.gif patch | view | raw | blame | history
installer/index.php 17 ●●●● patch | view | raw | blame | history
installer/rcube_install.php 170 ●●●● patch | view | raw | blame | history
installer/styles.css 71 ●●●●● patch | view | raw | blame | history
installer/test.php 21 ●●●● patch | view | raw | blame | history
program/include/rcube_mdb2.php 17 ●●●●● patch | view | raw | blame | history
program/lib/MDB2/Driver/Reverse/sqlite.php 2 ●●● patch | view | raw | blame | history
CHANGELOG
@@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
- Interactive update script with improved DB schema check
- jQuery 1.5.1
- Fix problem with contactgroupmembers table creation on MySQL 4.x, add index on contact_id column
- Add LDAP SASL bind and proxy authentication (#1486692)
SQL/mssql.upgrade.sql
@@ -97,7 +97,7 @@
ALTER TABLE [dbo].[contacts] ALTER COLUMN [email] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL
GO
-- Updates from version 0.5.x
-- Updates from version 0.5.1
ALTER TABLE [dbo].[contacts] ADD [words] [text] COLLATE Latin1_General_CI_AI NULL 
GO
SQL/mysql.update.sql
@@ -133,7 +133,7 @@
TRUNCATE TABLE `messages`;
-- Updates from version 0.5.*
-- Updates from version 0.5.1
ALTER TABLE `contacts` ADD `words` TEXT NULL AFTER `vcard`;
ALTER TABLE `contactgroupmembers` ADD INDEX `contactgroupmembers_contact_index` (`contact_id`);
SQL/postgres.update.sql
@@ -90,7 +90,7 @@
TRUNCATE messages;
-- Updates from version 0.5.x
-- Updates from version 0.5.1
ALTER TABLE contacts ADD words TEXT NULL;
CREATE INDEX contactgroupmembers_contact_id_idx ON contactgroupmembers (contact_id);
SQL/sqlite.update.sql
@@ -183,7 +183,7 @@
DELETE FROM messages;
-- Updates from version 0.5.x
-- Updates from version 0.5.1
CREATE TABLE contacts_tmp (
    contact_id integer NOT NULL PRIMARY KEY,
UPGRADING
@@ -5,6 +5,26 @@
of Roundcube Webmail. We recommend to carefully backup the existing
installation as well as the database before executig the following steps.
Using the update script
-----------------------
There is a shell script (for unix based systems) that does the job for you.
To use it, unpack the archive of the new Roundcube version to a temporary location (don't replace the Roundcube installation you want to update)
and cd into that directory. From there, run the following command in a shell:
  ./bin/installto.sh <TARGET-FOLDER>
For <TARGET-FOLDER> you specify the path to the Roundcube installation
which should be updated. The update script will then copy all new files to the
target location and check and update the configuration and database schema.
After all is done, the temporary folder with the new Roundcube files can be
removed again.
Updating manually
-----------------
If you don't have shell access to the Roundcube instalaltion or if not running
it on a unix system, you need to do the following operations by hand:
1. Replace index.php and all files in
   - ./bin/
   - ./SQL/
@@ -14,14 +34,11 @@
   - ./plugins/
2. Run ./bin/update.sh from the commandline OR
   open http://url-to-roundcube/installer/ in a browser and choose "3 Test config".
   To enable the latter one, you have to temporary set 'enable_installer' to true
   in your local config/main.inc.php file.
   To enable the latter one, you have to temporary set 'enable_installer'
   to true in your local config/main.inc.php file.
3. Let the update script/installer check your configuration and
   update your config files as suggested by the updater.
4. If suggested by the update script, run all commands in
   ./SQL/[yourdbtype].update.sql that are superscribed with the
   currently installed version number.
5. Make sure 'enable_installer' is set to false again.
6. Check .htaccess settings (some php settings could become required)
   update your config files and database schema as suggested by the updater.
4. Make sure 'enable_installer' is set to false again.
5. Check .htaccess settings (some php settings could become required)
bin/installto.sh
New file
@@ -0,0 +1,73 @@
#!/usr/bin/env php
<?php
/*
 +-----------------------------------------------------------------------+
 | bin/installto.sh                                                      |
 |                                                                       |
 | This file is part of the Roundcube Webmail client                     |
 | Copyright (C) 2011, The Roundcube Dev Team                            |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 | PURPOSE:                                                              |
 |   Update an existing Roundcube installation with files from           |
 |   this version                                                        |
 +-----------------------------------------------------------------------+
 | Author: Thomas Bruederli <roundcube@gmail.com>                        |
 +-----------------------------------------------------------------------+
 $Id$
*/
if (php_sapi_name() != 'cli') {
    die('Not on the "shell" (php-cli).');
}
define('INSTALL_PATH', realpath(dirname(__FILE__) . '/..') . '/' );
require_once INSTALL_PATH . 'program/include/iniset.php';
$target_dir = unslashify($_SERVER['argv'][1]);
if (empty($target_dir) || !is_dir(realpath($target_dir)))
  die("Invalid target: not a directory\nUsage: installto.sh <TARGET>\n");
// read version from iniset.php
$iniset = @file_get_contents($target_dir . '/program/include/iniset.php');
if (!preg_match('/define\(.RCMAIL_VERSION.,\s*.([0-9.]+[a-z-]*)/', $iniset, $m))
  die("No valid Roundcube installation found at $target_dir\n");
$oldversion = $m[1];
if (version_compare($oldversion, RCMAIL_VERSION, '>='))
  die("Installation at target location is up-to-date!\n");
echo "Upgrading from $oldversion. Do you want to continue? (y/N)\n";
$input = trim(fgets(STDIN));
if (strtolower($input) == 'y') {
  $err = false;
  echo "Copying files to target location...";
  foreach (array('program','installer','bin','SQL','plugins','skins/default') as $dir) {
    if (!system("rsync -avuC " . INSTALL_PATH . "$dir/* $target_dir/$dir/")) {
      $err = true;
      break;
    }
  }
  foreach (array('index.php','.htaccess','config/main.inc.php.dist','config/db.inc.php.dist','CHANGELOG','README','UPGRADING') as $file) {
    if (!system("rsync -avu " . INSTALL_PATH . "$file $target_dir/$file")) {
      $err = true;
      break;
    }
  }
  echo "done.\n\n";
  if (!$err) {
    echo "Running update script at target...\n";
    system("cd $target_dir && bin/update.sh --version=$oldversion");
    echo "All done.\n";
  }
}
else
  echo "Update cancelled. See ya!\n";
?>
bin/update.sh
@@ -1,12 +1,45 @@
#!/usr/bin/env php
<?php
/*
 +-----------------------------------------------------------------------+
 | bin/update.sh                                                         |
 |                                                                       |
 | This file is part of the Roundcube Webmail client                     |
 | Copyright (C) 2010-2011, The Roundcube Dev Team                       |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 | PURPOSE:                                                              |
 |   Check local configuration and database schema after upgrading       |
 |   to a new version                                                    |
 +-----------------------------------------------------------------------+
 | Author: Thomas Bruederli <roundcube@gmail.com>                        |
 +-----------------------------------------------------------------------+
 $Id$
*/
if (php_sapi_name() != 'cli') {
    die('Not on the "shell" (php-cli).');
}
define('INSTALL_PATH', realpath(dirname(__FILE__) . '/..') . '/' );
require_once INSTALL_PATH . 'program/include/iniset.php';
require_once INSTALL_PATH . 'program/include/clisetup.php';
require_once INSTALL_PATH . 'installer/rcube_install.php';
// get arguments
$opts = get_opt(array('v' => 'version'));
// ask user if no version is specified
if (!$opts['version']) {
  echo "What version are you upgrading from? Type '?' if you don't know.\n";
  if (($input = trim(fgets(STDIN))) && preg_match('/^[0-9.]+[a-z-]*$/', $input))
    $opts['version'] = $input;
}
if ($opts['version'] && version_compare($opts['version'], RCMAIL_VERSION, '>'))
  die("Nothing to be done here. Bye!\n");
$RCI = rcube_install::get_instance();
$RCI->load_config();
@@ -88,7 +121,7 @@
        }
      }
      else {
        echo "Please update your config files manually according to the above messages.\n";
        echo "Please update your config files manually according to the above messages.\n\n";
      }
    }
@@ -113,12 +146,22 @@
      echo "Error connecting to database: $db_error_msg\n";
      $success = false;
    }
    else if ($RCI->db_schema_check($DB, false)) {
      $db_map = array('pgsql' => 'postgres', 'mysqli' => 'mysql', 'sqlsrv' => 'mssql');
      $updatefile = INSTALL_PATH . 'SQL/' . (isset($db_map[$DB->db_provider]) ? $db_map[$DB->db_provider] : $DB->db_provider) . '.update.sql';
    else if ($err = $RCI->db_schema_check($DB, false)) {
      $updatefile = INSTALL_PATH . 'SQL/' . (isset($RCI->db_map[$DB->db_provider]) ? $RCI->db_map[$DB->db_provider] : $DB->db_provider) . '.update.sql';
      echo "WARNING: Database schema needs to be updated!\n";
      echo "Open $updatefile and execute all queries that are superscribed with the currently installed version number\n";
      echo join("\n", $err) . "\n\n";
      $success = false;
      if ($opts['version']) {
        echo "Do you want to run the update queries to get the schmea fixed? (y/N)\n";
        $input = trim(fgets(STDIN));
        if (strtolower($input) == 'y') {
          $success = $RCI->update_db($DB, $opts['version']);
        }
      }
      if (!$success)
        echo "Open $updatefile and execute all queries below the comment with the currently installed version number.\n";
    }
  }
  
installer/check.php
@@ -22,6 +22,7 @@
    'PEAR'      => 'PEAR.php',
    'MDB2'      => 'MDB2.php',
    'Net_SMTP'  => 'Net/SMTP.php',
    'Net_IDNA2' => 'Net/IDNA2.php',
    'Mail_mime' => 'Mail/mime.php',
);
installer/images/banner_bg.gif
Binary files differ
installer/images/banner_gradient.gif
installer/images/banner_logo.gif
Binary files differ
installer/images/banner_right.gif
Binary files differ
installer/images/banner_schraffur.gif
installer/images/rcube_logo.gif
installer/index.php
@@ -68,14 +68,13 @@
<body>
<div id="banner">
  <div id="header">
    <div class="banner-logo"><a href="http://www.roundcube.net"><img src="images/banner_logo.gif" width="200" height="56" border="0" alt="Roundcube Webmal Project" /></a></div>
    <div class="banner-right"><img src="images/banner_right.gif" width="10" height="56" alt="" /></div>
  </div>
  <div id="topnav">
    <a href="http://trac.roundcube.net/wiki/Howto_Install">How-to Wiki</a>
  </div>
 </div>
  <div class="banner-bg"></div>
  <div class="banner-logo"><a href="http://roundcube.net"><img src="images/rcube_logo.gif" width="210" height="55" border="0" alt="Roundcube - Open source webmail project" /></a></div>
</div>
<div id="topnav">
  <a href="http://trac.roundcube.net/wiki/Howto_Install">How-to Wiki</a>
</div>
<div id="content">
@@ -120,7 +119,7 @@
</div>
<div id="footer">
  Installer by the Roundcube Dev Team. Copyright &copy; 2008 - Published under the GNU Public License;&nbsp;
  Installer by the Roundcube Dev Team. Copyright &copy; 2008-2011 - Published under the GNU Public License;&nbsp;
  Icons by <a href="http://famfamfam.com">famfamfam</a>
</div>
</body>
installer/rcube_install.php
@@ -29,10 +29,11 @@
  var $config = array();
  var $configured = false;
  var $last_error = null;
  var $db_map = array('pgsql' => 'postgres', 'mysqli' => 'mysql', 'sqlsrv' => 'mssql');
  var $email_pattern = '([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9]([a-z0-9\-][.]?)*[a-z0-9])';
  var $bool_config_props = array();
  var $obsolete_config = array('db_backend');
  var $obsolete_config = array('db_backend', 'double_auth');
  var $replaced_config = array(
    'skin_path' => 'skin',
    'locale_string' => 'language',
@@ -42,7 +43,10 @@
  );
  
  // these config options are required for a working system
  var $required_config = array('db_dsnw', 'db_table_contactgroups', 'db_table_contactgroupmembers', 'des_key');
  var $required_config = array(
    'db_dsnw', 'db_table_contactgroups', 'db_table_contactgroupmembers',
    'des_key', 'session_lifetime',
  );
  
  /**
   * Constructor
@@ -294,7 +298,7 @@
    $this->config = array();
    $this->load_defaults();
    
    foreach ($this->replaced_config as $prop => $replacement)
    foreach ($this->replaced_config as $prop => $replacement) {
      if (isset($current[$prop])) {
        if ($prop == 'skin_path')
          $this->config[$replacement] = preg_replace('#skins/(\w+)/?$#', '\\1', $current[$prop]);
@@ -302,8 +306,8 @@
          $this->config[$replacement] = $current[$prop] ? 2 : 0;
        else
          $this->config[$replacement] = $current[$prop];
        unset($current[$prop]);
      }
      unset($current[$prop]);
    }
    
    foreach ($this->obsolete_config as $prop) {
@@ -319,6 +323,9 @@
        }
      }
    }
    if ($current['keep_alive'] && $current['session_lifetime'] < $current['keep_alive'])
      $current['session_lifetime'] = max(10, ceil($current['keep_alive'] / 60) * 2);
    
    $this->config  = array_merge($this->config, $current);
    
@@ -339,18 +346,8 @@
    if (!$this->configured)
      return false;
    
    // simple ad hand-made db schema
    $db_schema = array(
      'users' => array(),
      'identities' => array(),
      'contacts' => array(),
      'contactgroups' => array(),
      'contactgroupmembers' => array(),
      'cache' => array(),
      'messages' => array(),
      'session' => array(),
    );
    // read reference schema from mysql.initial.sql
    $db_schema = $this->db_read_schema(INSTALL_PATH . 'SQL/mysql.initial.sql');
    $errors = array();
    
    // check list of tables
@@ -358,13 +355,43 @@
    foreach ($db_schema as $table => $cols) {
      $table = !empty($this->config['db_table_'.$table]) ? $this->config['db_table_'.$table] : $table;
      if (!in_array($table, $existing_tables))
        $errors[] = "Missing table ".$table;
      // TODO: check cols and indices
      if (!in_array($table, $existing_tables)) {
        $errors[] = "Missing table '".$table."'";
      }
      else {  // compare cols
        $db_cols = $DB->list_cols($table);
        $diff = array_diff(array_keys($cols), $db_cols);
        if (!empty($diff))
          $errors[] = "Missing columns in table '$table': " . join(',', $diff);
      }
    }
    
    return !empty($errors) ? $errors : false;
  }
  /**
   * Utility function to read database schema from an .sql file
   */
  private function db_read_schema($schemafile)
  {
    $lines = file($schemafile);
    $table_block = false;
    $schema = array();
    foreach ($lines as $line) {
      if (preg_match('/^\s*create table `?([a-z0-9_]+)`?/i', $line, $m)) {
        $table_block = $m[1];
      }
      else if ($table_block && preg_match('/^\s*`?([a-z0-9_-]+)`?\s+([a-z]+)/', $line, $m)) {
        $col = $m[1];
        if (!in_array(strtoupper($col), array('PRIMARY','KEY','INDEX','UNIQUE','CONSTRAINT','REFERENCES','FOREIGN'))) {
          $schema[$table_block][$col] = $m[2];
        }
      }
    }
    return $schema;
  }
  
  /**
   * Compare the local database schema with the reference schema
@@ -472,6 +499,16 @@
    }
    
    return $out;
  }
  /**
   * Create a HTML dropdown to select a previous version of Roundcube
   */
  function versions_select($attrib = array())
  {
    $select = new html_select($attrib);
    $select->add(array('0.1-stable', '0.1.1', '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'));
    return $select;
  }
  
  
@@ -592,25 +629,12 @@
   */
  function init_db($DB)
  {
    $db_map = array('pgsql' => 'postgres', 'mysqli' => 'mysql');
    $engine = isset($db_map[$DB->db_provider]) ? $db_map[$DB->db_provider] : $DB->db_provider;
    $engine = isset($this->db_map[$DB->db_provider]) ? $this->db_map[$DB->db_provider] : $DB->db_provider;
    
    // read schema file from /SQL/*
    $fname = "../SQL/$engine.initial.sql";
    if ($lines = @file($fname, FILE_SKIP_EMPTY_LINES)) {
      $buff = '';
      foreach ($lines as $i => $line) {
        if (preg_match('/^--/', $line))
          continue;
        $buff .= $line . "\n";
        if (preg_match('/;$/', trim($line))) {
          $DB->query($buff);
          $buff = '';
          if ($this->get_error())
            break;
        }
      }
    $fname = INSTALL_PATH . "SQL/$engine.initial.sql";
    if ($sql = @file_get_contents($fname)) {
      $this->exec_sql($sql, $DB);
    }
    else {
      $this->fail('DB Schema', "Cannot read the schema file: $fname");
@@ -625,6 +649,78 @@
    return true;
  }
  
  /**
   * Update database with SQL statements from SQL/*.update.sql
   *
   * @param object rcube_db Database connection
   * @param string Version to update from
   * @return boolen True on success, False on error
   */
  function update_db($DB, $version)
  {
    $version = strtolower($version);
    $engine = isset($this->db_map[$DB->db_provider]) ? $this->db_map[$DB->db_provider] : $DB->db_provider;
    // read schema file from /SQL/*
    $fname = INSTALL_PATH . "SQL/$engine.update.sql";
    if ($lines = @file($fname, FILE_SKIP_EMPTY_LINES)) {
      $from = false; $sql = '';
      foreach ($lines as $line) {
        $is_comment = preg_match('/^--/', $line);
        if (!$from && $is_comment && preg_match('/from version\s([0-9.]+[a-z-]*)/', $line, $m)) {
          $v = strtolower($m[1]);
          if ($v == $version || version_compare($version, $v, '<='))
            $from = true;
        }
        if ($from && !$is_comment)
          $sql .= $line. "\n";
      }
      if ($sql)
        $this->exec_sql($sql, $DB);
    }
    else {
      $this->fail('DB Schema', "Cannot read the update file: $fname");
      return false;
    }
    if ($err = $this->get_error()) {
      $this->fail('DB Schema', "Error updating database: $err");
      return false;
    }
    return true;
  }
  /**
   * Execute the given SQL queries on the database connection
   *
   * @param string SQL queries to execute
   * @param object rcube_db Database connection
   * @return boolen True on success, False on error
   */
  function exec_sql($sql, $DB)
  {
    $buff = '';
    foreach (explode("\n", $sql) as $line) {
      if (preg_match('/^--/', $line) || trim($line) == '')
        continue;
      $buff .= $line . "\n";
      if (preg_match('/(;|^GO)$/', trim($line))) {
        $DB->query($buff);
        $buff = '';
        if ($DB->is_error())
          break;
      }
    }
    return !$DB->is_error();
  }
  /**
   * Handler for Roundcube errors
   */
installer/styles.css
@@ -1,62 +1,53 @@
body {
  margin: 1em 2em 2em 2em;
  background-color: #fff;
}
body, td, th, div, p {
  font-family: "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;
  font-size: small;
  color: #000;
    background: white;
    font-family: "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;
    font-size: small;
    color: black;
    margin: 0;
}
#banner {
  position: relative;
    position: relative;
    height: 58px;
    margin: 0 0 1em 0;
    padding: 10px 20px;
    background: url('images/banner_gradient.gif') top left repeat-x #d8edfd;
    overflow: hidden;
}
#header {
  position: relative;
  height: 56px;
  background: url('images/banner_bg.gif') top left repeat-x #fff;
#banner .banner-bg {
    position: absolute;
    top: 0;
    right: 0;
    width: 630px;
    height: 78px;
    background: url('images/banner_schraffur.gif') top right no-repeat;
    z-index: 0;
}
#header div.banner-logo {
  position: absolute;
  top: 0px;
  left: 0px;
  width: 200px;
  height: 56px;
#banner .banner-logo {
    position: absolute;
    top: 10px;
    left: 20px;
    z-index: 4;
}
#header div.banner-right {
  position: absolute;
  right: 0px;
  top: 0px;
  width: 10px;
  height: 56px;
#banner .banner-logo a {
    border: 0;
}
#topnav {
  position: absolute;
  right: 20px;
  bottom: 8px;
  text-align: right;
  color: #ebebeb;
  font-size: smaller;
    position: absolute;
    top: 3.6em;
    right: 20px;
}
#topnav a {
  color: #ebebeb;
  font-size: 11px;
  text-decoration: none;
}
#topnav a:hover {
  text-decoration: underline;
    color: #666;
}
#content {
  margin: 8px 20px;
    margin: 2em 20px;
}
#footer {
installer/test.php
@@ -156,6 +156,14 @@
    }
}
else if ($db_working && $_POST['updatedb']) {
  if (!($success = $RCI->update_db($DB, $_POST['version']))) {
      $updatefile = INSTALL_PATH . 'SQL/' . (isset($RCI->db_map[$DB->db_provider]) ? $RCI->db_map[$DB->db_provider] : $DB->db_provider) . '.update.sql';
      echo '<p class="warning">Please manually execute the SQL statements from '.$updatefile.' on your database.<br/>';
      echo 'See comments in the file and execute queries below the comment with the currently installed version number.</p>';
  }
}
// test database
if ($db_working) {
    $db_read = $DB->query("SELECT count(*) FROM {$RCI->config['db_table_users']}");
@@ -164,12 +172,13 @@
        echo '<p><input type="submit" name="initdb" value="Initialize database" /></p>';
        $db_working = false;
    }
    else if ($RCI->db_schema_check($DB, $update = !empty($_POST['updatedb']))) {
    else if ($err = $RCI->db_schema_check($DB, $update = !empty($_POST['updatedb']))) {
        $RCI->fail('DB Schema', "Database schema differs");
        $db_map = array('pgsql' => 'postgres', 'mysqli' => 'mysql', 'sqlsrv' => 'mssql');
        $updatefile = INSTALL_PATH . 'SQL/' . (isset($db_map[$DB->db_provider]) ? $db_map[$DB->db_provider] : $DB->db_provider) . '.update.sql';
        echo '<p class="warning">Please manually execute the SQL statements from '.$updatefile.' on your database.<br/>';
        echo 'See comments in the file and execute queries that are superscribed with the currently installed version number.</p>';
        echo '<ul style="margin:0"><li>' . join("</li>\n<li>", $err) . "</li></ul>";
        $select = $RCI->versions_select(array('name' => 'version'));
        echo '<p class="suggestion">You should run the update queries to get the schmea fixed.<br/><br/>Version to update from: ' . $select->show() . '&nbsp;<input type="submit" name="updatedb" value="Update" /></p>';
//        echo '<p class="warning">Please manually execute the SQL statements from '.$updatefile.' on your database.<br/>';
//        echo 'See comments in the file and execute queries that are superscribed with the currently installed version number.</p>';
        $db_working = false;
    }
    else {
@@ -412,7 +421,7 @@
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
enable_installer option in main.inc.php is disabled.<br />
<tt>enable_installer</tt> option in config/main.inc.php is disabled.<br />
<br />
These files may expose sensitive configuration data like server passwords and encryption keys
program/include/rcube_mdb2.php
@@ -413,6 +413,23 @@
    /**
     * Wrapper for SHOW COLUMNS command
     *
     * @param string Table name
     * @return array List of table cols
     */
    function list_cols($table)
    {
        $this->db_handle->loadModule('Manager');
        if (!PEAR::isError($result = $this->db_handle->listTableFields($table))) {
            return $result;
        }
        return null;
    }
    /**
     * Formats input so it can be safely used in a query
     *
     * @param  mixed  $input  Value to quote
program/lib/MDB2/Driver/Reverse/sqlite.php
@@ -95,7 +95,7 @@
            return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
                'unexpected empty table column definition list', __FUNCTION__);
        }
        $regexp = '/^\s*([^\s]+) +(CHAR|VARCHAR|VARCHAR2|TEXT|BOOLEAN|SMALLINT|INT|INTEGER|DECIMAL|BIGINT|DOUBLE|FLOAT|DATETIME|DATE|TIME|LONGTEXT|LONGBLOB)( ?\(([1-9][0-9]*)(:([1-9][0-9]*))?\))?( NULL| NOT NULL)?( UNSIGNED)?( NULL| NOT NULL)?( PRIMARY KEY)?( DEFAULT (\'[^\']*\'|[^ ]+))?( NULL| NOT NULL)?( PRIMARY KEY)?(\s*\-\-.*)?$/i';
        $regexp = '/^\s*([^\s]+) +(CHAR|VARCHAR|VARCHAR2|TEXT|BOOLEAN|SMALLINT|INT|INTEGER|DECIMAL|TINYINT|BIGINT|DOUBLE|FLOAT|DATETIME|DATE|TIME|LONGTEXT|LONGBLOB)( ?\(([1-9][0-9]*)(:([1-9][0-9]*))?\))?( NULL| NOT NULL)?( UNSIGNED)?( NULL| NOT NULL)?( PRIMARY KEY)?( DEFAULT (\'[^\']*\'|[^ ]+))?( NULL| NOT NULL)?( PRIMARY KEY)?(\s*\-\-.*)?$/i';
        $regexp2 = '/^\s*([^ ]+) +(PRIMARY|UNIQUE|CHECK)$/i';
        for ($i=0, $j=0; $i<$count; ++$i) {
            if (!preg_match($regexp, trim($column_sql[$i]), $matches)) {