Aleksander Machniak
2012-12-07 a3985963f0df4fffa1a6d272c777f781ebd86d50
Fix big memory consumption of DB layer (#1488856)
2 files modified
101 ■■■■■ changed files
CHANGELOG 1 ●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_db.php 100 ●●●●● patch | view | raw | blame | history
CHANGELOG
@@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
- Fix big memory consumption of DB layer (#1488856)
- Add workaround for IE<=8 bug where Content-Disposition:inline was ignored (#1488844)
- Fix XSS vulnerability in vbscript: and data:text links handling (#1488850)
- Fix broken message/part bodies when FETCH response contains more untagged lines (#1488836)
program/lib/Roundcube/rcube_db.php
@@ -37,12 +37,11 @@
    protected $db_mode;               // Connection mode
    protected $dbh;                   // Connection handle
    protected $db_error        = false;
    protected $db_error_msg    = '';
    protected $conn_failure    = false;
    protected $a_query_results = array('dummy');
    protected $last_res_id     = 0;
    protected $db_index        = 0;
    protected $db_error     = false;
    protected $db_error_msg = '';
    protected $conn_failure = false;
    protected $db_index     = 0;
    protected $last_result;
    protected $tables;
    protected $variables;
@@ -267,14 +266,14 @@
    /**
     * Getter for error state
     *
     * @param int $res_id Optional query result identifier
     * @param mixed $result Optional query result
     *
     * @return string Error message
     */
    public function is_error($res_id = null)
    public function is_error($result = null)
    {
        if ($res_id !== null) {
            return $this->_get_result($res_id) === false ? $this->db_error_msg : null;
        if ($result !== null) {
            return $result === false ? $this->db_error_msg : null;
        }
        return $this->db_error ? $this->db_error_msg : null;
@@ -343,7 +342,7 @@
     * @param int    Number of rows for LIMIT statement
     * @param mixed  Values to be inserted in query
     *
     * @return int Query handle identifier
     * @return PDOStatement|bool Query handle or False on error
     */
    public function limitquery()
    {
@@ -363,7 +362,7 @@
     * @param int    $numrows Number of rows for LIMIT statement
     * @param array  $params  Values to be inserted in query
     *
     * @return int Query handle identifier
     * @return PDOStatement|bool Query handle or False on error
     */
    protected function _query($query, $offset, $numrows, $params)
    {
@@ -374,7 +373,7 @@
        // check connection before proceeding
        if (!$this->is_connected()) {
            return null;
            return $this->last_result = false;
        }
        if ($numrows || $offset) {
@@ -417,20 +416,21 @@
                'message' => $this->db_error_msg), true, false);
        }
        // add result, even if it's an error
        return $this->_add_result($query);
        $this->last_result = $query;
        return $query;
    }
    /**
     * Get number of affected rows for the last query
     *
     * @param  number $res_id Optional query handle identifier
     * @param mixed $result Optional query handle
     *
     * @return int Number of rows or false on failure
     */
    public function affected_rows($res_id = null)
    public function affected_rows($result = null)
    {
        if ($result = $this->_get_result($res_id)) {
        if ($result || ($result === null && ($result = $this->last_result))) {
            return $result->rowCount();
        }
@@ -464,13 +464,12 @@
     * Get an associative array for one row
     * If no query handle is specified, the last query will be taken as reference
     *
     * @param int $res_id Optional query handle identifier
     * @param mixed $result Optional query handle
     *
     * @return mixed Array with col values or false on failure
     */
    public function fetch_assoc($res_id = null)
    public function fetch_assoc($result = null)
    {
        $result = $this->_get_result($res_id);
        return $this->_fetch_row($result, PDO::FETCH_ASSOC);
    }
@@ -478,31 +477,30 @@
     * Get an index array for one row
     * If no query handle is specified, the last query will be taken as reference
     *
     * @param int $res_id Optional query handle identifier
     * @param mixed $result Optional query handle
     *
     * @return mixed Array with col values or false on failure
     */
    public function fetch_array($res_id = null)
    public function fetch_array($result = null)
    {
        $result = $this->_get_result($res_id);
        return $this->_fetch_row($result, PDO::FETCH_NUM);
    }
    /**
     * Get col values for a result row
     *
     * @param PDOStatement $result Result handle
     * @param int          $mode   Fetch mode identifier
     * @param mixed $result Optional query handle
     * @param int   $mode   Fetch mode identifier
     *
     * @return mixed Array with col values or false on failure
     */
    protected function _fetch_row($result, $mode)
    {
        if (!is_object($result) || !$this->is_connected()) {
            return false;
        if ($result || ($result === null && ($result = $this->last_result))) {
            return $result->fetch($mode);
        }
        return $result->fetch($mode);
        return false;
    }
    /**
@@ -538,8 +536,8 @@
        if ($this->tables === null) {
            $q = $this->query('SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES ORDER BY TABLE_NAME');
            if ($res = $this->_get_result($q)) {
                $this->tables = $res->fetchAll(PDO::FETCH_COLUMN, 0);
            if ($q) {
                $this->tables = $q->fetchAll(PDO::FETCH_COLUMN, 0);
            }
            else {
                $this->tables = array();
@@ -561,8 +559,8 @@
        $q = $this->query('SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ?',
            array($table));
        if ($res = $this->_get_result($q)) {
            return $res->fetchAll(PDO::FETCH_COLUMN, 0);
        if ($q) {
            return $q->fetchAll(PDO::FETCH_COLUMN, 0);
        }
        return array();
@@ -774,42 +772,6 @@
        }
        return utf8_decode($input);
    }
    /**
     * Adds a query result and returns a handle ID
     *
     * @param object $res Query handle
     *
     * @return int Handle ID
     */
    protected function _add_result($res)
    {
        $this->last_res_id = sizeof($this->a_query_results);
        $this->a_query_results[$this->last_res_id] = $res;
        return $this->last_res_id;
    }
    /**
     * Resolves a given handle ID and returns the according query handle
     * If no ID is specified, the last resource handle will be returned
     *
     * @param int $res_id Handle ID
     *
     * @return mixed Resource handle or false on failure
     */
    protected function _get_result($res_id = null)
    {
        if ($res_id == null) {
            $res_id = $this->last_res_id;
        }
        if (!empty($this->a_query_results[$res_id])) {
            return $this->a_query_results[$res_id];
        }
        return false;
    }
    /**