Thomas Bruederli
2013-10-04 92d18cf32edab81ac77f547cfa718cf28a573c92
program/lib/Roundcube/rcube_db.php
@@ -32,6 +32,7 @@
    protected $db_connected = false;  // Already connected ?
    protected $db_mode;               // Connection mode
    protected $dbh;                   // Connection handle
    protected $dbhs = array();
    protected $db_error     = false;
    protected $db_error_msg = '';
@@ -97,33 +98,29 @@
        $this->db_dsnw  = $db_dsnw;
        $this->db_dsnr  = $db_dsnr;
        $this->db_pconn = $pconn;
        $this->db_dsnw_noread = rcube::get_instance()->config->get('db_dsnw_noread', false);
        $this->db_dsnw_array = self::parse_dsn($db_dsnw);
        $this->db_dsnr_array = self::parse_dsn($db_dsnr);
        // Initialize driver class
        $this->init();
    }
    /**
     * Initialization of the object with driver specific code
     */
    protected function init()
    {
        // To be used by driver classes
    }
    /**
     * Connect to specific database
     *
     * @param array $dsn DSN for DB connections
     *
     * @return PDO database handle
     * @param array  $dsn  DSN for DB connections
     * @param string $mode Connection mode (r|w)
     */
    protected function dsn_connect($dsn)
    protected function dsn_connect($dsn, $mode)
    {
        $this->db_error     = false;
        $this->db_error_msg = null;
        // return existing handle
        if ($this->dbhs[$mode]) {
            $this->dbh = $this->dbhs[$mode];
            $this->db_mode = $mode;
            return $this->dbh;
        }
        // Get database specific connection options
        $dsn_string  = $this->dsn_string($dsn);
@@ -158,9 +155,11 @@
            return null;
        }
        $this->dbh          = $dbh;
        $this->dbhs[$mode]  = $dbh;
        $this->db_mode      = $mode;
        $this->db_connected = true;
        $this->conn_configure($dsn, $dbh);
        return $dbh;
    }
    /**
@@ -183,16 +182,6 @@
    }
    /**
     * Driver-specific database character set setting
     *
     * @param string $charset Character set name
     */
    protected function set_charset($charset)
    {
        $this->query("SET NAMES 'utf8'");
    }
    /**
     * Connect to appropriate database depending on the operation
     *
     * @param string $mode Connection mode (r|w)
@@ -211,31 +200,21 @@
        // Already connected
        if ($this->db_connected) {
            // connected to db with the same or "higher" mode
            if ($this->db_mode == 'w' || $this->db_mode == $mode) {
            // connected to db with the same or "higher" mode (if allowed)
            if ($this->db_mode == $mode || $this->db_mode == 'w' && !$this->db_dsnw_noread) {
                return;
            }
        }
        $dsn = ($mode == 'r') ? $this->db_dsnr_array : $this->db_dsnw_array;
        $this->dbh          = $this->dsn_connect($dsn);
        $this->db_connected = is_object($this->dbh);
        $this->dsn_connect($dsn, $mode);
        // use write-master when read-only fails
        if (!$this->db_connected && $mode == 'r' && $this->is_replicated()) {
            $mode = 'w';
            $this->dbh          = $this->dsn_connect($this->db_dsnw_array);
            $this->db_connected = is_object($this->dbh);
            $this->dsn_connect($this->db_dsnw_array, 'w');
        }
        if ($this->db_connected) {
            $this->db_mode = $mode;
            $this->set_charset('utf8');
        }
        else {
            $this->conn_failure = true;
        }
        $this->conn_failure = !$this->db_connected;
    }
    /**
@@ -368,8 +347,10 @@
     */
    protected function _query($query, $offset, $numrows, $params)
    {
        $query = trim($query);
        // Read or write ?
        $mode = preg_match('/^(select|show)/i', ltrim($query)) ? 'r' : 'w';
        $mode = preg_match('/^(select|show|set)/i', $query) ? 'r' : 'w';
        $this->db_connect($mode);
@@ -414,7 +395,26 @@
        $result = $this->dbh->query($query);
        if ($result === false) {
            $error = $this->dbh->errorInfo();
            $result = $this->handle_error($query);
        }
        $this->last_result = $result;
        return $result;
    }
    /**
     * Helper method to handle DB errors.
     * This by default logs the error but could be overriden by a driver implementation
     *
     * @param string Query that triggered the error
     * @return mixed Result to be stored and returned
     */
    protected function handle_error($query)
    {
        $error = $this->dbh->errorInfo();
        if (empty($this->options['ignore_key_errors']) || $error[0] != '23000') {
            $this->db_error = true;
            $this->db_error_msg = sprintf('[%s] %s', $error[1], $error[2]);
@@ -424,9 +424,7 @@
                ), true, false);
        }
        $this->last_result = $result;
        return $result;
        return false;
    }
    /**
@@ -708,11 +706,19 @@
    /**
     * Return SQL function for current time and date
     *
     * @param int $interval Optional interval (in seconds) to add/subtract
     *
     * @return string SQL function to use in query
     */
    public function now()
    public function now($interval = 0)
    {
        return "now()";
        if ($interval) {
            $add = ' ' . ($interval > 0 ? '+' : '-') . ' INTERVAL ';
            $add .= $interval > 0 ? intval($interval) : intval($interval) * -1;
            $add .= ' SECOND';
        }
        return "now()" . $add;
    }
    /**
@@ -835,9 +841,14 @@
     */
    public static function decode($input, $serialized = false)
    {
        // use Base64 encoding to workaround issues with invalid
        // or null characters in serialized string (#1489142)
        if ($serialized) {
            // use Base64 encoding to workaround issues with invalid
            // or null characters in serialized string (#1489142)
            // Keep backward compatybility where base64 wasn't used
            if (strpos(substr($input, 0, 16), ':') !== false) {
                return self::decode(@unserialize($input));
            }
            return @unserialize(base64_decode($input));
        }
@@ -877,6 +888,17 @@
    }
    /**
     * Set class option value
     *
     * @param string $name  Option name
     * @param mixed  $value Option value
     */
    public function set_option($name, $value)
    {
        $this->options[$name] = $value;
    }
    /**
     * MDB2 DSN string parser
     *
     * @param string $sequence Secuence name