Aleksander Machniak
2014-09-12 34a0902089a410d1f7dda78d1f8b0771333c09df
Use consistent column/table quoting in sql queries
17 files modified
746 ■■■■ changed files
bin/cleandb.sh 12 ●●●● patch | view | raw | blame | history
bin/deluser.sh 2 ●●● patch | view | raw | blame | history
bin/indexcontacts.sh 2 ●●● patch | view | raw | blame | history
bin/moduserprefs.sh 4 ●●●● patch | view | raw | blame | history
bin/updatedb.sh 15 ●●●● patch | view | raw | blame | history
installer/test.php 10 ●●●●● patch | view | raw | blame | history
plugins/squirrelmail_usercopy/squirrelmail_usercopy.php 7 ●●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_cache.php 51 ●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_cache_shared.php 40 ●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_contacts.php 160 ●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_db.php 74 ●●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_imap_cache.php 196 ●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_session.php 30 ●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_spellchecker.php 25 ●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_user.php 103 ●●●● patch | view | raw | blame | history
program/steps/utils/killcache.inc 13 ●●●●● patch | view | raw | blame | history
tests/Framework/ImapCache.php 2 ●●● patch | view | raw | blame | history
bin/cleandb.sh
@@ -48,7 +48,7 @@
foreach (array('contacts','contactgroups','identities') as $table) {
    $sqltable = $db->table_name($table);
    $sqltable = $db->table_name($table, true);
    // also delete linked records
    // could be skipped for databases which respect foreign key constraints
@@ -59,10 +59,10 @@
        $memberstable = $db->table_name('contactgroupmembers');
        $db->query(
            "DELETE FROM $memberstable".
            " WHERE $pk IN (".
                "SELECT $pk FROM $sqltable".
                " WHERE del=1 AND changed < ?".
            "DELETE FROM " . $db->quote_identifier($memberstable).
            " WHERE `$pk` IN (".
                "SELECT `$pk` FROM $sqltable".
                " WHERE `del` = 1 AND `changed` < ?".
            ")",
            $threshold);
@@ -70,7 +70,7 @@
    }
    // delete outdated records
    $db->query("DELETE FROM $sqltable WHERE del=1 AND changed < ?", $threshold);
    $db->query("DELETE FROM $sqltable WHERE `del` = 1 AND `changed` < ?", $threshold);
    echo $db->affected_rows() . " records deleted from '$table'\n";
}
bin/deluser.sh
@@ -91,7 +91,7 @@
// deleting the user record should be sufficient due to ON DELETE CASCADE foreign key references
// but not all database backends actually support this so let's do it by hand
foreach (array('identities','contacts','contactgroups','dictionaries','cache','cache_index','cache_messages','cache_thread','searches','users') as $table) {
    $db->query('DELETE FROM ' . $db->table_name($table) . ' WHERE user_id=?', $user->ID);
    $db->query('DELETE FROM ' . $db->table_name($table, true) . ' WHERE `user_id` = ?', $user->ID);
}
if ($db->is_error()) {
bin/indexcontacts.sh
@@ -35,7 +35,7 @@
}
// iterate over all users
$sql_result = $db->query("SELECT user_id FROM " . $db->table_name('users') . " ORDER BY user_id");
$sql_result = $db->query("SELECT `user_id` FROM " . $db->table_name('users', true) . " ORDER BY `user_id`");
while ($sql_result && ($sql_arr = $db->fetch_assoc($sql_result))) {
    echo "Indexing contacts for user " . $sql_arr['user_id'] . "...";
bin/moduserprefs.sh
@@ -58,10 +58,10 @@
$query = '1=1';
if ($args['user'])
    $query = 'user_id=' . intval($args['user']);
    $query = '`user_id` = ' . intval($args['user']);
// iterate over all users
$sql_result = $db->query("SELECT * FROM " . $db->table_name('users') . " WHERE $query");
$sql_result = $db->query("SELECT * FROM " . $db->table_name('users', true) . " WHERE $query");
while ($sql_result && ($sql_arr = $db->fetch_assoc($sql_result))) {
    echo "Updating prefs for user " . $sql_arr['user_id'] . "...";
bin/updatedb.sh
@@ -55,9 +55,9 @@
// Read DB schema version from database (if 'system' table exists)
if (in_array($DB->table_name('system'), (array)$DB->list_tables())) {
    $DB->query("SELECT " . $DB->quote_identifier('value')
        ." FROM " . $DB->quote_identifier($DB->table_name('system'))
        ." WHERE " . $DB->quote_identifier('name') ." = ?",
    $DB->query("SELECT `value`"
        ." FROM " . $DB->table_name('system', true)
        ." WHERE `name` = ?",
        $opts['package'] . '-version');
    $row     = $DB->fetch_array();
@@ -159,17 +159,16 @@
        return;
    }
    $system_table = $DB->quote_identifier($DB->table_name('system'));
    $system_table = $DB->table_name('system', true);
    $DB->query("UPDATE " . $system_table
        ." SET " . $DB->quote_identifier('value') . " = ?"
        ." WHERE " . $DB->quote_identifier('name') . " = ?",
        ." SET `value` = ?"
        ." WHERE `name` = ?",
        $version, $package . '-version');
    if (!$DB->is_error() && !$DB->affected_rows()) {
        $DB->query("INSERT INTO " . $system_table
            ." (" . $DB->quote_identifier('name') . ", " . $DB->quote_identifier('value') . ")"
            ." VALUES (?, ?)",
            ." (`name`, `value`) VALUES (?, ?)",
            $package . '-version', $version);
    }
installer/test.php
@@ -154,7 +154,7 @@
// test database
if ($db_working) {
    $db_read = $DB->query("SELECT count(*) FROM {$RCI->config['db_prefix']}users");
    $db_read = $DB->query("SELECT count(*) FROM " . $DB->quote_identifier($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>';
@@ -178,17 +178,19 @@
if ($db_working) {
    // write test
    $insert_id = md5(uniqid());
    $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);
    $db_write = $DB->query("INSERT INTO " . $DB->quote_identifier($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_prefix']}session WHERE sess_id=?", $insert_id);
      $DB->query("DELETE FROM " . $DB->quote_identifier($RCI->config['db_prefix'] . 'session')
        . " WHERE `sess_id` = ?", $insert_id);
    }
    else {
      $RCI->fail('DB Write', $RCI->get_error());
    }
    echo '<br />';
    // check timezone settings
    $tz_db = 'SELECT ' . $DB->unixtimestamp($DB->now()) . ' AS tz_db';
    $tz_db = $DB->query($tz_db);
plugins/squirrelmail_usercopy/squirrelmail_usercopy.php
@@ -164,14 +164,16 @@
            if ($db_charset)
                $db->query('SET NAMES '.$db_charset);
            $sql_result = $db->query('SELECT * FROM '.$userprefs_table.' WHERE user=?', $uname); // ? is replaced with emailaddress
            $sql_result = $db->query('SELECT * FROM ' . $db->quote_identifier($userprefs_table)
                .' WHERE `user` = ?', $uname); // ? is replaced with emailaddress
            while ($sql_array = $db->fetch_assoc($sql_result) ) { // fetch one row from result
                $this->prefs[$sql_array['prefkey']] = rcube_charset::convert(rtrim($sql_array['prefval']), $db_charset);
            }
            /* retrieve address table data */
            $sql_result = $db->query('SELECT * FROM '.$address_table.' WHERE owner=?', $uname); // ? is replaced with emailaddress
            $sql_result = $db->query('SELECT * FROM ' . $db->quote_identifier($address_table)
                .' WHERE `owner` = ?', $uname); // ? is replaced with emailaddress
            // parse addres book
            while ($sql_array = $db->fetch_assoc($sql_result) ) { // fetch one row from result
@@ -186,5 +188,4 @@
            }
        } // end if 'sql'-driver
    }
}
program/lib/Roundcube/rcube_cache.php
@@ -75,7 +75,7 @@
        else {
            $this->type  = 'db';
            $this->db    = $rcube->get_dbh();
            $this->table = $this->db->table_name('cache');
            $this->table = $this->db->table_name('cache', true);
        }
        // convert ttl string to seconds
@@ -197,10 +197,10 @@
    {
        if ($this->type == 'db' && $this->db && $this->ttl) {
            $this->db->query(
                "DELETE FROM ".$this->table.
                " WHERE user_id = ?".
                " AND cache_key LIKE ?".
                " AND expires < " . $this->db->now(),
                "DELETE FROM {$this->table}".
                " WHERE `user_id` = ?".
                " AND `cache_key` LIKE ?".
                " AND `expires` < " . $this->db->now(),
                $this->userid,
                $this->prefix.'.%');
        }
@@ -215,7 +215,7 @@
        $rcube = rcube::get_instance();
        $db    = $rcube->get_dbh();
        $db->query("DELETE FROM " . $db->table_name('cache') . " WHERE expires < " . $db->now());
        $db->query("DELETE FROM " . $db->table_name('cache', true) . " WHERE `expires` < " . $db->now());
    }
@@ -284,13 +284,12 @@
        }
        else {
            $sql_result = $this->db->limitquery(
                "SELECT data, cache_key".
                " FROM " . $this->table.
                " WHERE user_id = ?".
                " AND cache_key = ?".
                "SELECT `data`, `cache_key`".
                " FROM {$this->table}".
                " WHERE `user_id` = ? AND `cache_key` = ?".
                // for better performance we allow more records for one key
                // get the newer one
                " ORDER BY created DESC",
                " ORDER BY `created` DESC",
                0, 1, $this->userid, $this->prefix.'.'.$key);
            if ($sql_arr = $this->db->fetch_assoc($sql_result)) {
@@ -346,9 +345,8 @@
        // Remove NULL rows (here we don't need to check if the record exist)
        if ($data == 'N;') {
            $this->db->query(
                "DELETE FROM " . $this->table.
                " WHERE user_id = ?".
                " AND cache_key = ?",
                "DELETE FROM {$this->table}".
                " WHERE `user_id` = ? AND `cache_key` = ?",
                $this->userid, $key);
            return true;
@@ -357,12 +355,12 @@
        // update existing cache record
        if ($key_exists) {
            $result = $this->db->query(
                "UPDATE " . $this->table.
                " SET created = " . $this->db->now().
                    ", expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL').
                    ", data = ?".
                " WHERE user_id = ?".
                " AND cache_key = ?",
                "UPDATE {$this->table}".
                " SET `created` = " . $this->db->now().
                    ", `expires` = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL').
                    ", `data` = ?".
                " WHERE `user_id` = ?".
                " AND `cache_key` = ?",
                $data, $this->userid, $key);
        }
        // add new cache record
@@ -370,8 +368,8 @@
            // for better performance we allow more records for one key
            // so, no need to check if record exist (see rcube_cache::read_record())
            $result = $this->db->query(
                "INSERT INTO " . $this->table.
                " (created, expires, user_id, cache_key, data)".
                "INSERT INTO {$this->table}".
                " (`created`, `expires`, `user_id`, `cache_key`, `data`)".
                " VALUES (" . $this->db->now() . ", " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . ", ?, ?, ?)",
                $this->userid, $key, $data);
        }
@@ -421,20 +419,19 @@
        // Remove all keys (in specified cache)
        if ($key === null) {
            $where = " AND cache_key LIKE " . $this->db->quote($this->prefix.'.%');
            $where = " AND `cache_key` LIKE " . $this->db->quote($this->prefix.'.%');
        }
        // Remove keys by name prefix
        else if ($prefix_mode) {
            $where = " AND cache_key LIKE " . $this->db->quote($this->prefix.'.'.$key.'%');
            $where = " AND `cache_key` LIKE " . $this->db->quote($this->prefix.'.'.$key.'%');
        }
        // Remove one key by name
        else {
            $where = " AND cache_key = " . $this->db->quote($this->prefix.'.'.$key);
            $where = " AND `cache_key` = " . $this->db->quote($this->prefix.'.'.$key);
        }
        $this->db->query(
            "DELETE FROM " . $this->table.
            " WHERE user_id = ?" . $where,
            "DELETE FROM {$this->table} WHERE `user_id` = ?" . $where,
            $this->userid);
    }
program/lib/Roundcube/rcube_cache_shared.php
@@ -72,7 +72,7 @@
        else {
            $this->type  = 'db';
            $this->db    = $rcube->get_dbh();
            $this->table = $this->db->table_name('cache_shared');
            $this->table = $this->db->table_name('cache_shared', true);
        }
        // convert ttl string to seconds
@@ -193,9 +193,9 @@
    {
        if ($this->type == 'db' && $this->db && $this->ttl) {
            $this->db->query(
                "DELETE FROM " . $this->table
                . " WHERE cache_key LIKE ?"
                . " AND expires < " . $this->db->now(),
                "DELETE FROM {$this->table}"
                . " WHERE `cache_key` LIKE ?"
                . " AND `expires` < " . $this->db->now(),
                $this->prefix . '.%');
        }
    }
@@ -209,7 +209,7 @@
        $rcube = rcube::get_instance();
        $db    = $rcube->get_dbh();
        $db->query("DELETE FROM " . $db->table_name('cache_shared') . " WHERE expires < " . $db->now());
        $db->query("DELETE FROM " . $db->table_name('cache_shared', true) . " WHERE `expires` < " . $db->now());
    }
@@ -278,12 +278,12 @@
        }
        else {
            $sql_result = $this->db->limitquery(
                "SELECT data, cache_key".
                " FROM " . $this->table .
                " WHERE cache_key = ?".
                "SELECT `data`, `cache_key`".
                " FROM {$this->table}" .
                " WHERE `cache_key` = ?".
                // for better performance we allow more records for one key
                // get the newer one
                " ORDER BY created DESC",
                " ORDER BY `created` DESC",
                0, 1, $this->prefix . '.' . $key);
            if ($sql_arr = $this->db->fetch_assoc($sql_result)) {
@@ -331,18 +331,18 @@
        // Remove NULL rows (here we don't need to check if the record exist)
        if ($data == 'N;') {
            $this->db->query("DELETE FROM " . $this->table . " WHERE cache_key = ?", $key);
            $this->db->query("DELETE FROM {$this->table} WHERE `cache_key` = ?", $key);
            return true;
        }
        // update existing cache record
        if ($key_exists) {
            $result = $this->db->query(
                "UPDATE " . $this->table .
                " SET created = " . $this->db->now() .
                    ", expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') .
                    ", data = ?".
                " WHERE cache_key = ?",
                "UPDATE {$this->table}" .
                " SET `created` = " . $this->db->now() .
                    ", `expires` = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') .
                    ", `data` = ?".
                " WHERE `cache_key` = ?",
                $data, $key);
        }
        // add new cache record
@@ -350,8 +350,8 @@
            // for better performance we allow more records for one key
            // so, no need to check if record exist (see rcube_cache::read_record())
            $result = $this->db->query(
                "INSERT INTO ".$this->table.
                " (created, expires, cache_key, data)".
                "INSERT INTO {$this->table}".
                " (`created`, `expires`, `cache_key`, `data`)".
                " VALUES (".$this->db->now().", " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . ", ?, ?)",
                $key, $data);
        }
@@ -401,15 +401,15 @@
        // Remove all keys (in specified cache)
        if ($key === null) {
            $where = " WHERE cache_key LIKE " . $this->db->quote($this->prefix.'.%');
            $where = " WHERE `cache_key` LIKE " . $this->db->quote($this->prefix.'.%');
        }
        // Remove keys by name prefix
        else if ($prefix_mode) {
            $where = " WHERE cache_key LIKE " . $this->db->quote($this->prefix.'.'.$key.'%');
            $where = " WHERE `cache_key` LIKE " . $this->db->quote($this->prefix.'.'.$key.'%');
        }
        // Remove one key by name
        else {
            $where = " WHERE cache_key = " . $this->db->quote($this->prefix.'.'.$key);
            $where = " WHERE `cache_key` = " . $this->db->quote($this->prefix.'.'.$key);
        }
        $this->db->query("DELETE FROM " . $this->table . $where);
program/lib/Roundcube/rcube_contacts.php
@@ -167,11 +167,9 @@
        }
        $sql_result = $this->db->query(
            "SELECT * FROM ".$this->db->table_name($this->db_groups).
            " WHERE del<>1".
            " AND user_id=?".
            $sql_filter.
            " ORDER BY name",
            "SELECT * FROM " . $this->db->table_name($this->db_groups, true)
            . " WHERE `del` <> 1 AND `user_id` = ?" . $sql_filter
            . " ORDER BY `name`",
            $this->user_id);
        while ($sql_result && ($sql_arr = $this->db->fetch_assoc($sql_result))) {
@@ -192,10 +190,8 @@
    function get_group($group_id)
    {
        $sql_result = $this->db->query(
            "SELECT * FROM ".$this->db->table_name($this->db_groups).
            " WHERE del<>1".
            " AND contactgroup_id=?".
            " AND user_id=?",
            "SELECT * FROM " . $this->db->table_name($this->db_groups, true)
            . " WHERE `del` <> 1 AND `contactgroup_id` = ? AND `user_id` = ?",
            $group_id, $this->user_id);
        if ($sql_result && ($sql_arr = $this->db->fetch_assoc($sql_result))) {
@@ -228,25 +224,25 @@
        $length = $subset != 0 ? abs($subset) : $this->page_size;
        if ($this->group_id)
            $join = " LEFT JOIN ".$this->db->table_name($this->db_groupmembers)." AS m".
                " ON (m.contact_id = c.".$this->primary_key.")";
            $join = " LEFT JOIN " . $this->db->table_name($this->db_groupmembers, true) . " AS m".
                " ON (m.`contact_id` = c.`".$this->primary_key."`)";
        $order_col = (in_array($this->sort_col, $this->table_cols) ? $this->sort_col : 'name');
        $order_cols = array('c.'.$order_col);
        $order_cols = array("c.`$order_col`");
        if ($order_col == 'firstname')
            $order_cols[] = 'c.surname';
            $order_cols[] = 'c.`surname`';
        else if ($order_col == 'surname')
            $order_cols[] = 'c.firstname';
            $order_cols[] = 'c.`firstname`';
        if ($order_col != 'name')
            $order_cols[] = 'c.name';
        $order_cols[] = 'c.email';
            $order_cols[] = 'c.`name`';
        $order_cols[] = 'c.`email`';
        $sql_result = $this->db->limitquery(
            "SELECT * FROM ".$this->db->table_name($this->db_name)." AS c" .
            "SELECT * FROM " . $this->db->table_name($this->db_name, true) . " AS c" .
            $join .
            " WHERE c.del<>1" .
                " AND c.user_id=?" .
                ($this->group_id ? " AND m.contactgroup_id=?" : "").
            " WHERE c.`del` <> 1" .
                " AND c.`user_id` = ?" .
                ($this->group_id ? " AND m.`contactgroup_id` = ?" : "").
                ($this->filter ? " AND (".$this->filter.")" : "") .
            " ORDER BY ". $this->db->concat($order_cols) .
            " " . $this->sort_order,
@@ -442,7 +438,7 @@
            // build WHERE clause
            $ids = $this->db->array2list($ids, 'integer');
            $where = 'c.' . $this->primary_key.' IN ('.$ids.')';
            $where = 'c.`' . $this->primary_key.'` IN ('.$ids.')';
            // reset counter
            unset($this->cache['count']);
@@ -486,17 +482,17 @@
    private function _count()
    {
        if ($this->group_id)
            $join = " LEFT JOIN ".$this->db->table_name($this->db_groupmembers)." AS m".
                " ON (m.contact_id=c.".$this->primary_key.")";
            $join = " LEFT JOIN " . $this->db->table_name($this->db_groupmembers, true) . " AS m".
                " ON (m.`contact_id` = c.`".$this->primary_key."`)";
        // count contacts for this user
        $sql_result = $this->db->query(
            "SELECT COUNT(c.contact_id) AS rows".
            " FROM ".$this->db->table_name($this->db_name)." AS c".
            "SELECT COUNT(c.`contact_id`) AS rows".
            " FROM " . $this->db->table_name($this->db_name, true) . " AS c".
                $join.
            " WHERE c.del<>1".
            " AND c.user_id=?".
            ($this->group_id ? " AND m.contactgroup_id=?" : "").
            " WHERE c.`del` <> 1".
            " AND c.`user_id` = ?".
            ($this->group_id ? " AND m.`contactgroup_id` = ?" : "").
            ($this->filter ? " AND (".$this->filter.")" : ""),
            $this->user_id,
            $this->group_id
@@ -534,10 +530,10 @@
            return $assoc ? $first : $this->result;
        $this->db->query(
            "SELECT * FROM ".$this->db->table_name($this->db_name).
            " WHERE contact_id=?".
                " AND user_id=?".
                " AND del<>1",
            "SELECT * FROM " . $this->db->table_name($this->db_name, true).
            " WHERE `contact_id` = ?".
                " AND `user_id` = ?".
                " AND `del` <> 1",
            $id,
            $this->user_id
        );
@@ -566,9 +562,11 @@
          return $results;
      $sql_result = $this->db->query(
        "SELECT cgm.contactgroup_id, cg.name FROM " . $this->db->table_name($this->db_groupmembers) . " AS cgm" .
        " LEFT JOIN " . $this->db->table_name($this->db_groups) . " AS cg ON (cgm.contactgroup_id = cg.contactgroup_id AND cg.del<>1)" .
        " WHERE cgm.contact_id=?",
        "SELECT cgm.`contactgroup_id`, cg.`name` "
        . " FROM " . $this->db->table_name($this->db_groupmembers, true) . " AS cgm"
        . " LEFT JOIN " . $this->db->table_name($this->db_groups, true) . " AS cg"
            . " ON (cgm.`contactgroup_id` = cg.`contactgroup_id` AND cg.`del` <> 1)"
        . " WHERE cgm.`contact_id` = ?",
        $id
      );
      while ($sql_result && ($sql_arr = $this->db->fetch_assoc($sql_result))) {
@@ -636,8 +634,8 @@
        if (!$existing->count && !empty($a_insert_cols)) {
            $this->db->query(
                "INSERT INTO ".$this->db->table_name($this->db_name).
                " (user_id, changed, del, ".join(', ', $a_insert_cols).")".
                "INSERT INTO " . $this->db->table_name($this->db_name, true).
                " (`user_id`, `changed`, `del`, ".join(', ', $a_insert_cols).")".
                " VALUES (".intval($this->user_id).", ".$this->db->now().", 0, ".join(', ', $a_insert_values).")"
            );
@@ -671,11 +669,11 @@
        if (!empty($write_sql)) {
            $this->db->query(
                "UPDATE ".$this->db->table_name($this->db_name).
                " SET changed=".$this->db->now().", ".join(', ', $write_sql).
                " WHERE contact_id=?".
                    " AND user_id=?".
                    " AND del<>1",
                "UPDATE " . $this->db->table_name($this->db_name, true).
                " SET `changed` = ".$this->db->now().", ".join(', ', $write_sql).
                " WHERE `contact_id` = ?".
                    " AND `user_id` = ?".
                    " AND `del` <> 1",
                $id,
                $this->user_id
            );
@@ -771,10 +769,10 @@
        // flag record as deleted (always)
        $this->db->query(
            "UPDATE ".$this->db->table_name($this->db_name).
            " SET del=1, changed=".$this->db->now().
            " WHERE user_id=?".
                " AND contact_id IN ($ids)",
            "UPDATE " . $this->db->table_name($this->db_name, true).
            " SET `del` = 1, `changed` = ".$this->db->now().
            " WHERE `user_id` = ?".
                " AND `contact_id` IN ($ids)",
            $this->user_id
        );
@@ -798,10 +796,10 @@
        // clear deleted flag
        $this->db->query(
            "UPDATE ".$this->db->table_name($this->db_name).
            " SET del=0, changed=".$this->db->now().
            " WHERE user_id=?".
                " AND contact_id IN ($ids)",
            "UPDATE " . $this->db->table_name($this->db_name, true).
            " SET `del` = 0, `changed` = ".$this->db->now().
            " WHERE `user_id` = ?".
                " AND `contact_id` IN ($ids)",
            $this->user_id
        );
@@ -822,16 +820,18 @@
    {
        $this->cache = null;
        $this->db->query("UPDATE " . $this->db->table_name($this->db_name)
            . " SET del = 1, changed = " . $this->db->now()
            . " WHERE user_id = ?", $this->user_id);
        $now = $this->db->now();
        $this->db->query("UPDATE " . $this->db->table_name($this->db_name, true)
            . " SET `del` = 1, `changed` = $now"
            . " WHERE `user_id` = ?", $this->user_id);
        $count = $this->db->affected_rows();
        if ($with_groups) {
            $this->db->query("UPDATE " . $this->db->table_name($this->db_groups)
                . " SET del = 1, changed = " . $this->db->now()
                . " WHERE user_id = ?", $this->user_id);
            $this->db->query("UPDATE " . $this->db->table_name($this->db_groups, true)
                . " SET `del` = 1, `changed` = $now"
                . " WHERE `user_id` = ?", $this->user_id);
            $count += $this->db->affected_rows();
        }
@@ -854,13 +854,14 @@
        $name = $this->unique_groupname($name);
        $this->db->query(
            "INSERT INTO ".$this->db->table_name($this->db_groups).
            " (user_id, changed, name)".
            "INSERT INTO " . $this->db->table_name($this->db_groups, true).
            " (`user_id`, `changed`, `name`)".
            " VALUES (".intval($this->user_id).", ".$this->db->now().", ".$this->db->quote($name).")"
        );
        if ($insert_id = $this->db->insert_id($this->db_groups))
        if ($insert_id = $this->db->insert_id($this->db_groups)) {
            $result = array('id' => $insert_id, 'name' => $name);
        }
        return $result;
    }
@@ -876,10 +877,10 @@
    {
        // flag group record as deleted
        $this->db->query(
            "UPDATE " . $this->db->table_name($this->db_groups)
            . " SET del = 1, changed = " . $this->db->now()
            . " WHERE contactgroup_id = ?"
            . " AND user_id = ?",
            "UPDATE " . $this->db->table_name($this->db_groups, true)
            . " SET `del` = 1, `changed` = " . $this->db->now()
            . " WHERE `contactgroup_id` = ?"
                . " AND `user_id` = ?",
            $gid, $this->user_id
        );
@@ -901,10 +902,10 @@
        $name = $this->unique_groupname($newname);
        $sql_result = $this->db->query(
            "UPDATE ".$this->db->table_name($this->db_groups).
            " SET name=?, changed=".$this->db->now().
            " WHERE contactgroup_id=?".
            " AND user_id=?",
            "UPDATE " . $this->db->table_name($this->db_groups, true).
            " SET `name` = ?, `changed` = ".$this->db->now().
            " WHERE `contactgroup_id` = ?".
                " AND `user_id` = ?",
            $name, $gid, $this->user_id
        );
@@ -930,9 +931,9 @@
        // get existing assignments ...
        $sql_result = $this->db->query(
            "SELECT contact_id FROM ".$this->db->table_name($this->db_groupmembers).
            " WHERE contactgroup_id=?".
                " AND contact_id IN (".$this->db->array2list($ids, 'integer').")",
            "SELECT `contact_id` FROM " . $this->db->table_name($this->db_groupmembers, true).
            " WHERE `contactgroup_id` = ?".
                " AND `contact_id` IN (".$this->db->array2list($ids, 'integer').")",
            $group_id
        );
        while ($sql_result && ($sql_arr = $this->db->fetch_assoc($sql_result))) {
@@ -943,8 +944,8 @@
        foreach ($ids as $contact_id) {
            $this->db->query(
                "INSERT INTO ".$this->db->table_name($this->db_groupmembers).
                " (contactgroup_id, contact_id, created)".
                "INSERT INTO " . $this->db->table_name($this->db_groupmembers, true).
                " (`contactgroup_id`, `contact_id`, `created`)".
                " VALUES (?, ?, ".$this->db->now().")",
                $group_id,
                $contact_id
@@ -976,9 +977,9 @@
        $ids = $this->db->array2list($ids, 'integer');
        $sql_result = $this->db->query(
            "DELETE FROM ".$this->db->table_name($this->db_groupmembers).
            " WHERE contactgroup_id=?".
                " AND contact_id IN ($ids)",
            "DELETE FROM " . $this->db->table_name($this->db_groupmembers, true).
            " WHERE `contactgroup_id` = ?".
                " AND `contact_id` IN ($ids)",
            $group_id
        );
@@ -999,10 +1000,10 @@
        do {
            $sql_result = $this->db->query(
                "SELECT 1 FROM ".$this->db->table_name($this->db_groups).
                " WHERE del<>1".
                    " AND user_id=?".
                    " AND name=?",
                "SELECT 1 FROM " . $this->db->table_name($this->db_groups, true).
                " WHERE `del` <> 1".
                    " AND `user_id` = ?".
                    " AND `name` = ?",
                $this->user_id,
                $checkname);
@@ -1014,5 +1015,4 @@
        return $checkname;
    }
}
program/lib/Roundcube/rcube_db.php
@@ -50,6 +50,7 @@
    );
    const DEBUG_LINE_LENGTH = 4096;
    const DEFAULT_QUOTE     = '`';
    /**
     * Factory, returns driver-specific instance of the class
@@ -238,8 +239,12 @@
        // Read or write ?
        $mode = preg_match('/^(select|show|set)/i', $query) ? 'r' : 'w';
        $start = '[' . $this->options['identifier_start'] . self::DEFAULT_QUOTE . ']';
        $end   = '[' . $this->options['identifier_end']   . self::DEFAULT_QUOTE . ']';
        $regex = '/(?:^|\s)(from|update|into|join)\s+'.$start.'?([a-z0-9._]+)'.$end.'?\s+/i';
        // find tables involved in this query
        if (preg_match_all('/(?:^|\s)(from|update|into|join)\s+'.$this->options['identifier_start'].'?([a-z0-9._]+)'.$this->options['identifier_end'].'?\s+/i', $query, $matches, PREG_SET_ORDER)) {
        if (preg_match_all($regex, $query, $matches, PREG_SET_ORDER)) {
            foreach ($matches as $m) {
                $table = $m[2];
@@ -408,6 +413,9 @@
            $query = $this->set_limit($query, $numrows, $offset);
        }
        // replace self::DEFAULT_QUOTE with driver-specific quoting
        $query = $this->query_parse($query);
        // Because in Roundcube we mostly use queries that are
        // executed only once, we will not use prepared queries
        $pos = 0;
@@ -431,6 +439,7 @@
        $query = str_replace('??', '?', $query);
        $query = rtrim($query, " \t\n\r\0\x0B;");
        // log query
        $this->debug($query);
        // destroy reference to previous result, required for SQLite driver (#1488874)
@@ -447,6 +456,51 @@
        $this->last_result = $result;
        return $result;
    }
    /**
     * Parse SQL query and replace identifier quoting
     *
     * @param string $query SQL query
     *
     * @return string SQL query
     */
    protected function query_parse($query)
    {
        $start = $this->options['identifier_start'];
        $end   = $this->options['identifier_end'];
        $quote = self::DEFAULT_QUOTE;
        if ($start == $quote) {
            return $query;
        }
        $pos = 0;
        $in  = false;
        while ($pos = strpos($query, $quote, $pos)) {
            if ($query[$pos+1] == $quote) {  // skip escaped quote
                $pos += 2;
            }
            else {
                if ($in) {
                    $q  = $end;
                    $in = false;
                }
                else {
                    $q  = $start;
                    $in = true;
                }
                $query = substr_replace($query, $q, $pos, 1);
                $pos++;
            }
        }
        // replace escaped quote back to normal, see self::quote()
        $query = str_replace($quote.$quote, $quote, $query);
        return $query;
    }
    /**
@@ -677,8 +731,13 @@
                'bool'    => PDO::PARAM_BOOL,
                'integer' => PDO::PARAM_INT,
            );
            $type = isset($map[$type]) ? $map[$type] : PDO::PARAM_STR;
            return strtr($this->dbh->quote($input, $type), array('?' => '??'));  // escape ?
            return strtr($this->dbh->quote($input, $type),
                // escape ? and `
                array('?' => '??', self::DEFAULT_QUOTE => self::DEFAULT_QUOTE.self::DEFAULT_QUOTE)
            );
        }
        return 'NULL';
@@ -917,15 +976,20 @@
    /**
     * Return correct name for a specific database table
     *
     * @param string $table Table name
     * @param string $table  Table name
     * @param bool   $quoted Quote table identifier
     *
     * @return string Translated table name
     */
    public function table_name($table)
    public function table_name($table, $quoted = false)
    {
        // add prefix to the table name if configured
        if (($prefix = $this->options['table_prefix']) && strpos($table, $prefix) !== 0) {
            return $prefix . $table;
            $table = $prefix . $table;
        }
        if ($quoted) {
            $table = $this->quote_identifier($table);
        }
        return $table;
program/lib/Roundcube/rcube_imap_cache.php
@@ -125,6 +125,11 @@
        // cache all possible information by default
        $this->mode = self::MODE_INDEX | self::MODE_MESSAGE;
        // database tables
        $this->index_table    = $db->table_name('cache_index', true);
        $this->thread_table   = $db->table_name('cache_thread', true);
        $this->messages_table = $db->table_name('cache_messages', true);
    }
@@ -333,11 +338,11 @@
        if ($this->mode & self::MODE_MESSAGE) {
            // Fetch messages from cache
            $sql_result = $this->db->query(
                "SELECT uid, data, flags"
                ." FROM ".$this->db->table_name('cache_messages')
                ." WHERE user_id = ?"
                    ." AND mailbox = ?"
                    ." AND uid IN (".$this->db->array2list($msgs, 'integer').")",
                "SELECT `uid`, `data`, `flags`"
                ." FROM {$this->messages_table}"
                ." WHERE `user_id` = ?"
                    ." AND `mailbox` = ?"
                    ." AND `uid` IN (".$this->db->array2list($msgs, 'integer').")",
                $this->userid, $mailbox);
            $msgs = array_flip($msgs);
@@ -400,11 +405,11 @@
        if ($this->mode & self::MODE_MESSAGE) {
            $sql_result = $this->db->query(
                "SELECT flags, data"
                ." FROM ".$this->db->table_name('cache_messages')
                ." WHERE user_id = ?"
                    ." AND mailbox = ?"
                    ." AND uid = ?",
                "SELECT `flags`, `data`"
                ." FROM {$this->messages_table}"
                ." WHERE `user_id` = ?"
                    ." AND `mailbox` = ?"
                    ." AND `uid` = ?",
                    $this->userid, $mailbox, (int)$uid);
            if ($sql_arr = $this->db->fetch_assoc($sql_result)) {
@@ -480,11 +485,11 @@
        // here will work as select, assume row exist if affected_rows=0)
        if (!$force) {
            $res = $this->db->query(
                "UPDATE ".$this->db->table_name('cache_messages')
                ." SET flags = ?, data = ?, expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL')
                ." WHERE user_id = ?"
                    ." AND mailbox = ?"
                    ." AND uid = ?",
                "UPDATE {$this->messages_table}"
                ." SET `flags` = ?, `data` = ?, `expires` = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL')
                ." WHERE `user_id` = ?"
                    ." AND `mailbox` = ?"
                    ." AND `uid` = ?",
                $flags, $msg, $this->userid, $mailbox, (int) $message->uid);
            if ($this->db->affected_rows($res)) {
@@ -496,8 +501,8 @@
        // insert new record
        $res = $this->db->query(
            "INSERT INTO ".$this->db->table_name('cache_messages')
            ." (user_id, mailbox, uid, flags, expires, data)"
            "INSERT INTO {$this->messages_table}"
            ." (`user_id`, `mailbox`, `uid`, `flags`, `expires`, `data`)"
            ." VALUES (?, ?, ?, ?, ". ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . ", ?)",
            $this->userid, $mailbox, (int) $message->uid, $flags, $msg);
@@ -505,12 +510,12 @@
        // thanks to ignore_key_errors "duplicate row" errors will be ignored
        if ($force && !$res && !$this->db->is_error($res)) {
            $this->db->query(
                "UPDATE ".$this->db->table_name('cache_messages')
                ." SET expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL')
                    .", flags = ?, data = ?"
                ." WHERE user_id = ?"
                    ." AND mailbox = ?"
                    ." AND uid = ?",
                "UPDATE {$this->messages_table}"
                ." SET `expires` = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL')
                    .", `flags` = ?, `data` = ?"
                ." WHERE `user_id` = ?"
                    ." AND `mailbox` = ?"
                    ." AND `uid` = ?",
                $flags, $msg, $this->userid, $mailbox, (int) $message->uid);
        }
@@ -558,13 +563,13 @@
        }
        $this->db->query(
            "UPDATE ".$this->db->table_name('cache_messages')
            ." SET expires = ". ($this->ttl ? $this->db->now($this->ttl) : 'NULL')
            .", flags = flags ".($enabled ? "+ $idx" : "- $idx")
            ." WHERE user_id = ?"
                ." AND mailbox = ?"
                .(!empty($uids) ? " AND uid IN (".$this->db->array2list($uids, 'integer').")" : "")
                ." AND (flags & $idx) ".($enabled ? "= 0" : "= $idx"),
            "UPDATE {$this->messages_table}"
            ." SET `expires` = ". ($this->ttl ? $this->db->now($this->ttl) : 'NULL')
            .", `flags` = `flags` ".($enabled ? "+ $idx" : "- $idx")
            ." WHERE `user_id` = ?"
                ." AND `mailbox` = ?"
                .(!empty($uids) ? " AND `uid` IN (".$this->db->array2list($uids, 'integer').")" : "")
                ." AND (`flags` & $idx) ".($enabled ? "= 0" : "= $idx"),
            $this->userid, $mailbox);
    }
@@ -583,8 +588,8 @@
        if (!strlen($mailbox)) {
            $this->db->query(
                "DELETE FROM ".$this->db->table_name('cache_messages')
                ." WHERE user_id = ?",
                "DELETE FROM {$this->messages_table}"
                ." WHERE `user_id` = ?",
                $this->userid);
        }
        else {
@@ -597,10 +602,10 @@
            }
            $this->db->query(
                "DELETE FROM ".$this->db->table_name('cache_messages')
                ." WHERE user_id = ?"
                    ." AND mailbox = ?"
                    .($uids !== null ? " AND uid IN (".$this->db->array2list((array)$uids, 'integer').")" : ""),
                "DELETE FROM {$this->messages_table}"
                ." WHERE `user_id` = ?"
                    ." AND `mailbox` = ?"
                    .($uids !== null ? " AND `uid` IN (".$this->db->array2list((array)$uids, 'integer').")" : ""),
                $this->userid, $mailbox);
        }
    }
@@ -619,18 +624,18 @@
        // otherwise use 'valid' flag to not loose HIGHESTMODSEQ value
        if ($remove) {
            $this->db->query(
                "DELETE FROM ".$this->db->table_name('cache_index')
                ." WHERE user_id = ?"
                    .(strlen($mailbox) ? " AND mailbox = ".$this->db->quote($mailbox) : ""),
                "DELETE FROM {$this->index_table}"
                ." WHERE `user_id` = ?"
                    .(strlen($mailbox) ? " AND `mailbox` = ".$this->db->quote($mailbox) : ""),
                $this->userid
            );
        }
        else {
            $this->db->query(
                "UPDATE ".$this->db->table_name('cache_index')
                ." SET valid = 0"
                ." WHERE user_id = ?"
                    .(strlen($mailbox) ? " AND mailbox = ".$this->db->quote($mailbox) : ""),
                "UPDATE {$this->index_table}"
                ." SET `valid` = 0"
                ." WHERE `user_id` = ?"
                    .(strlen($mailbox) ? " AND `mailbox` = ".$this->db->quote($mailbox) : ""),
                $this->userid
            );
        }
@@ -654,9 +659,9 @@
    function remove_thread($mailbox = null)
    {
        $this->db->query(
            "DELETE FROM ".$this->db->table_name('cache_thread')
            ." WHERE user_id = ?"
                .(strlen($mailbox) ? " AND mailbox = ".$this->db->quote($mailbox) : ""),
            "DELETE FROM {$this->thread_table}"
            ." WHERE `user_id` = ?"
                .(strlen($mailbox) ? " AND `mailbox` = ".$this->db->quote($mailbox) : ""),
            $this->userid
        );
@@ -692,15 +697,16 @@
    {
        $rcube = rcube::get_instance();
        $db    = $rcube->get_dbh();
        $now   = $db->now();
        $db->query("DELETE FROM ".$db->table_name('cache_messages')
              ." WHERE expires < " . $db->now());
        $db->query("DELETE FROM " . $db->table_name('cache_messages', true)
              ." WHERE `expires` < $now");
        $db->query("DELETE FROM ".$db->table_name('cache_index')
              ." WHERE expires < " . $db->now());
        $db->query("DELETE FROM " . $db->table_name('cache_index', true)
              ." WHERE `expires` < $now");
        $db->query("DELETE FROM ".$db->table_name('cache_thread')
              ." WHERE expires < " . $db->now());
        $db->query("DELETE FROM ".$db->table_name('cache_thread', true)
              ." WHERE `expires` < $now");
    }
@@ -711,10 +717,10 @@
    {
        // Get index from DB
        $sql_result = $this->db->query(
            "SELECT data, valid"
            ." FROM ".$this->db->table_name('cache_index')
            ." WHERE user_id = ?"
                ." AND mailbox = ?",
            "SELECT `data`, `valid`"
            ." FROM {$this->index_table}"
            ." WHERE `user_id` = ?"
                ." AND `mailbox` = ?",
            $this->userid, $mailbox);
        if ($sql_arr = $this->db->fetch_assoc($sql_result)) {
@@ -748,10 +754,10 @@
    {
        // Get thread from DB
        $sql_result = $this->db->query(
            "SELECT data"
            ." FROM ".$this->db->table_name('cache_thread')
            ." WHERE user_id = ?"
                ." AND mailbox = ?",
            "SELECT `data`"
            ." FROM {$this->thread_table}"
            ." WHERE `user_id` = ?"
                ." AND `mailbox` = ?",
            $this->userid, $mailbox);
        if ($sql_arr = $this->db->fetch_assoc($sql_result)) {
@@ -789,14 +795,16 @@
            (int) $mbox_data['UIDNEXT'],
            $modseq ? $modseq : $mbox_data['HIGHESTMODSEQ'],
        );
        $data = implode('@', $data);
        $data    = implode('@', $data);
        $expires = $this->ttl ? $this->db->now($this->ttl) : 'NULL';
        if ($exists) {
            $res = $this->db->query(
                "UPDATE ".$this->db->table_name('cache_index')
                ." SET data = ?, valid = 1, expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL')
                ." WHERE user_id = ?"
                    ." AND mailbox = ?",
                "UPDATE {$this->index_table}"
                ." SET `data` = ?, `valid` = 1, `expires` = $expires"
                ." WHERE `user_id` = ?"
                    ." AND `mailbox` = ?",
                $data, $this->userid, $mailbox);
            if ($this->db->affected_rows($res)) {
@@ -807,19 +815,19 @@
        $this->db->set_option('ignore_key_errors', true);
        $res = $this->db->query(
            "INSERT INTO ".$this->db->table_name('cache_index')
            ." (user_id, mailbox, valid, expires, data)"
            ." VALUES (?, ?, 1, ". ($this->ttl ? $this->db->now($this->ttl) : 'NULL') .", ?)",
            "INSERT INTO {$this->index_table}"
            ." (`user_id`, `mailbox`, `valid`, `expires`, `data`)"
            ." VALUES (?, ?, 1, $expires, ?)",
            $this->userid, $mailbox, $data);
        // race-condition, insert failed so try update (#1489146)
        // thanks to ignore_key_errors "duplicate row" errors will be ignored
        if (!$exists && !$res && !$this->db->is_error($res)) {
            $res = $this->db->query(
                "UPDATE ".$this->db->table_name('cache_index')
                ." SET data = ?, valid = 1, expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL')
                ." WHERE user_id = ?"
                    ." AND mailbox = ?",
                "UPDATE {$this->index_table}"
                ." SET `data` = ?, `valid` = 1, `expires` = $expires"
                ." WHERE `user_id` = ?"
                    ." AND `mailbox` = ?",
                $data, $this->userid, $mailbox);
        }
@@ -838,16 +846,16 @@
            (int) $mbox_data['UIDVALIDITY'],
            (int) $mbox_data['UIDNEXT'],
        );
        $data = implode('@', $data);
        $expires = ($this->ttl ? $this->db->now($this->ttl) : 'NULL');
        $data    = implode('@', $data);
        $expires = $this->ttl ? $this->db->now($this->ttl) : 'NULL';
        if ($exists) {
            $res = $this->db->query(
                "UPDATE ".$this->db->table_name('cache_thread')
                ." SET data = ?, expires = $expires"
                ." WHERE user_id = ?"
                    ." AND mailbox = ?",
                "UPDATE {$this->thread_table}"
                ." SET `data` = ?, `expires` = $expires"
                ." WHERE `user_id` = ?"
                    ." AND `mailbox` = ?",
                $data, $this->userid, $mailbox);
            if ($this->db->affected_rows($res)) {
@@ -858,8 +866,8 @@
        $this->db->set_option('ignore_key_errors', true);
        $res = $this->db->query(
            "INSERT INTO ".$this->db->table_name('cache_thread')
            ." (user_id, mailbox, expires, data)"
            "INSERT INTO {$this->thread_table}"
            ." (`user_id`, `mailbox`, `expires`, `data`)"
            ." VALUES (?, ?, $expires, ?)",
            $this->userid, $mailbox, $data);
@@ -867,10 +875,10 @@
        // thanks to ignore_key_errors "duplicate row" errors will be ignored
        if (!$exists && !$res && !$this->db->is_error($res)) {
            $this->db->query(
                "UPDATE ".$this->db->table_name('cache_thread')
                ." SET expires = $expires, data = ?"
                ." WHERE user_id = ?"
                    ." AND mailbox = ?",
                "UPDATE {$this->thread_table}"
                ." SET `expires` = $expires, `data` = ?"
                ." WHERE `user_id` = ?"
                    ." AND `mailbox` = ?",
                $data, $this->userid, $mailbox);
        }
@@ -1086,10 +1094,10 @@
        // Get known UIDs
        if ($this->mode & self::MODE_MESSAGE) {
            $sql_result = $this->db->query(
                "SELECT uid"
                ." FROM ".$this->db->table_name('cache_messages')
                ." WHERE user_id = ?"
                    ." AND mailbox = ?",
                "SELECT `uid`"
                ." FROM {$this->messages_table}"
                ." WHERE `user_id` = ?"
                    ." AND `mailbox` = ?",
                $this->userid, $mailbox);
            while ($sql_arr = $this->db->fetch_assoc($sql_result)) {
@@ -1125,12 +1133,12 @@
                    }
                    $this->db->query(
                        "UPDATE ".$this->db->table_name('cache_messages')
                        ." SET flags = ?, expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL')
                        ." WHERE user_id = ?"
                            ." AND mailbox = ?"
                            ." AND uid = ?"
                            ." AND flags <> ?",
                        "UPDATE {$this->messages_table}"
                        ." SET `flags` = ?, `expires` = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL')
                        ." WHERE `user_id` = ?"
                            ." AND `mailbox` = ?"
                            ." AND `uid` = ?"
                            ." AND `flags` <> ?",
                        $flags, $this->userid, $mailbox, $uid, $flags);
                }
            }
program/lib/Roundcube/rcube_session.php
@@ -103,6 +103,8 @@
                array($this, 'db_write'),
                array($this, 'db_destroy'),
                array($this, 'gc'));
            $this->table_name = $this->db->table_name('session', true);
        }
    }
@@ -175,9 +177,8 @@
    public function db_read($key)
    {
        $sql_result = $this->db->query(
            "SELECT vars, ip, changed, " . $this->db->now() . " AS ts"
            . " FROM " . $this->db->table_name('session')
            . " WHERE sess_id = ?", $key);
            "SELECT `vars`, `ip`, `changed`, " . $this->db->now() . " AS ts"
            . " FROM {$this->table_name} WHERE `sess_id` = ?", $key);
        if ($sql_result && ($sql_arr = $this->db->fetch_assoc($sql_result))) {
            $this->time_diff = time() - strtotime($sql_arr['ts']);
@@ -204,9 +205,8 @@
     */
    public function db_write($key, $vars)
    {
        $now   = $this->db->now();
        $table = $this->db->table_name('session');
        $ts    = microtime(true);
        $now = $this->db->now();
        $ts  = microtime(true);
        if ($this->nowrite)
            return true;
@@ -227,17 +227,18 @@
            $newvars = $this->_fixvars($vars, $oldvars);
            if ($newvars !== $oldvars) {
                $this->db->query("UPDATE $table "
                    . "SET changed = $now, vars = ? WHERE sess_id = ?",
                $this->db->query("UPDATE {$this->table_name} "
                    . "SET `changed` = $now, `vars` = ? WHERE `sess_id` = ?",
                    base64_encode($newvars), $key);
            }
            else if ($ts - $this->changed + $this->time_diff > $this->lifetime / 2) {
                $this->db->query("UPDATE $table SET changed = $now"
                    . " WHERE sess_id = ?", $key);
                $this->db->query("UPDATE {$this->table_name} SET `changed` = $now"
                    . " WHERE `sess_id` = ?", $key);
            }
        }
        else {
            $this->db->query("INSERT INTO $table (sess_id, vars, ip, created, changed)"
            $this->db->query("INSERT INTO {$this->table_name}"
                . " (`sess_id`, `vars`, `ip`, `created`, `changed`)"
                . " VALUES (?, ?, ?, $now, $now)",
                $key, base64_encode($vars), (string)$this->ip);
        }
@@ -290,8 +291,7 @@
    public function db_destroy($key)
    {
        if ($key) {
            $this->db->query(sprintf("DELETE FROM %s WHERE sess_id = ?",
                $this->db->table_name('session')), $key);
            $this->db->query("DELETE FROM {$this->table_name} WHERE `sess_id` = ?", $key);
        }
        return true;
@@ -407,8 +407,8 @@
        if ($this->gc_enabled) {
            // just delete all expired sessions
            if ($this->storage == 'db') {
                $this->db->query("DELETE FROM " . $this->db->table_name('session')
                    . " WHERE changed < " . $this->db->now(-$this->gc_enabled));
                $this->db->query("DELETE FROM {$this->table_name}"
                    . " WHERE `changed` < " . $this->db->now(-$this->gc_enabled));
            }
            foreach ($this->gc_handlers as $fct) {
program/lib/Roundcube/rcube_spellchecker.php
@@ -360,25 +360,25 @@
        if ($this->have_dict) {
            if (!empty($this->dict)) {
                $this->rc->db->query(
                    "UPDATE ".$this->rc->db->table_name('dictionary')
                    ." SET data = ?"
                    ." WHERE user_id " . ($plugin['userid'] ? "= ".$this->rc->db->quote($plugin['userid']) : "IS NULL")
                        ." AND " . $this->rc->db->quote_identifier('language') . " = ?",
                    "UPDATE " . $this->rc->db->table_name('dictionary', true)
                    ." SET `data` = ?"
                    ." WHERE `user_id` " . ($plugin['userid'] ? "= ".$this->rc->db->quote($plugin['userid']) : "IS NULL")
                        ." AND `language` = ?",
                    implode(' ', $plugin['dictionary']), $plugin['language']);
            }
            // don't store empty dict
            else {
                $this->rc->db->query(
                    "DELETE FROM " . $this->rc->db->table_name('dictionary')
                    ." WHERE user_id " . ($plugin['userid'] ? "= ".$this->rc->db->quote($plugin['userid']) : "IS NULL")
                        ." AND " . $this->rc->db->quote_identifier('language') . " = ?",
                    "DELETE FROM " . $this->rc->db->table_name('dictionary', true)
                    ." WHERE `user_id` " . ($plugin['userid'] ? "= ".$this->rc->db->quote($plugin['userid']) : "IS NULL")
                        ." AND `language` = ?",
                    $plugin['language']);
            }
        }
        else if (!empty($this->dict)) {
            $this->rc->db->query(
                "INSERT INTO " .$this->rc->db->table_name('dictionary')
                ." (user_id, " . $this->rc->db->quote_identifier('language') . ", data) VALUES (?, ?, ?)",
                "INSERT INTO " . $this->rc->db->table_name('dictionary', true)
                ." (`user_id`, `language`, `data`) VALUES (?, ?, ?)",
                $plugin['userid'], $plugin['language'], implode(' ', $plugin['dictionary']));
        }
    }
@@ -403,9 +403,9 @@
        if (empty($plugin['abort'])) {
            $dict = array();
            $sql_result = $this->rc->db->query(
                "SELECT data FROM ".$this->rc->db->table_name('dictionary')
                ." WHERE user_id ". ($plugin['userid'] ? "= ".$this->rc->db->quote($plugin['userid']) : "IS NULL")
                    ." AND " . $this->rc->db->quote_identifier('language') . " = ?",
                "SELECT `data` FROM " . $this->rc->db->table_name('dictionary', true)
                ." WHERE `user_id` ". ($plugin['userid'] ? "= ".$this->rc->db->quote($plugin['userid']) : "IS NULL")
                    ." AND `language` = ?",
                $plugin['language']);
            if ($sql_arr = $this->rc->db->fetch_assoc($sql_result)) {
@@ -427,5 +427,4 @@
        return $this->dict;
    }
}
program/lib/Roundcube/rcube_user.php
@@ -67,7 +67,8 @@
        if ($id && !$sql_arr) {
            $sql_result = $this->db->query(
                "SELECT * FROM ".$this->db->table_name('users')." WHERE user_id = ?", $id);
                "SELECT * FROM " . $this->db->table_name('users', true)
                . " WHERE `user_id` = ?", $id);
            $sql_arr = $this->db->fetch_assoc($sql_result);
        }
@@ -189,10 +190,9 @@
        $save_prefs = serialize($save_prefs);
        $this->db->query(
            "UPDATE ".$this->db->table_name('users').
            " SET preferences = ?".
                ", language = ?".
            " WHERE user_id = ?",
            "UPDATE ".$this->db->table_name('users', true).
            " SET `preferences` = ?, `language` = ?".
            " WHERE `user_id` = ?",
            $save_prefs,
            $_SESSION['language'],
            $this->ID);
@@ -243,7 +243,7 @@
        $id = (int)$id;
        // cache identities for better performance
        if (!array_key_exists($id, $this->identities)) {
            $result = $this->list_identities($id ? 'AND identity_id = ' . $id : '');
            $result = $this->list_identities($id ? "AND `identity_id` = $id" : '');
            $this->identities[$id] = $result[0];
        }
@@ -264,13 +264,10 @@
        $result = array();
        $sql_result = $this->db->query(
            "SELECT * FROM ".$this->db->table_name('identities').
            " WHERE del <> 1 AND user_id = ?".
            "SELECT * FROM ".$this->db->table_name('identities', true).
            " WHERE `del` <> 1 AND `user_id` = ?".
            ($sql_add ? " ".$sql_add : "").
            " ORDER BY ". $this->db->quote_identifier('standard') . " DESC, "
                . $this->db->quote_identifier('name') . " ASC, "
                . $this->db->quote_identifier('email') . " ASC, "
                . $this->db->quote_identifier('identity_id') . " ASC",
            " ORDER BY `standard` DESC, `name` ASC, `email` ASC, `identity_id` ASC",
            $this->ID);
        while ($sql_arr = $this->db->fetch_assoc($sql_result)) {
@@ -311,11 +308,11 @@
        $query_params[] = $iid;
        $query_params[] = $this->ID;
        $sql = "UPDATE ".$this->db->table_name('identities').
            " SET changed = ".$this->db->now().", ".join(', ', $query_cols).
            " WHERE identity_id = ?".
                " AND user_id = ?".
                " AND del <> 1";
        $sql = "UPDATE ".$this->db->table_name('identities', true).
            " SET `changed` = ".$this->db->now().", ".join(', ', $query_cols).
            " WHERE `identity_id` = ?".
                " AND `user_id` = ?".
                " AND `del` <> 1";
        call_user_func_array(array($this->db, 'query'),
            array_merge(array($sql), $query_params));
@@ -347,8 +344,8 @@
        $insert_cols[]   = 'user_id';
        $insert_values[] = $this->ID;
        $sql = "INSERT INTO ".$this->db->table_name('identities').
            " (changed, ".join(', ', $insert_cols).")".
        $sql = "INSERT INTO ".$this->db->table_name('identities', true).
            " (`changed`, ".join(', ', $insert_cols).")".
            " VALUES (".$this->db->now().", ".join(', ', array_pad(array(), sizeof($insert_values), '?')).")";
        call_user_func_array(array($this->db, 'query'),
@@ -372,8 +369,8 @@
            return false;
        $sql_result = $this->db->query(
            "SELECT count(*) AS ident_count FROM ".$this->db->table_name('identities').
            " WHERE user_id = ? AND del <> 1",
            "SELECT count(*) AS ident_count FROM ".$this->db->table_name('identities', true).
            " WHERE `user_id` = ? AND `del` <> 1",
            $this->ID);
        $sql_arr = $this->db->fetch_assoc($sql_result);
@@ -383,10 +380,10 @@
            return -1;
        $this->db->query(
            "UPDATE ".$this->db->table_name('identities').
            " SET del = 1, changed = ".$this->db->now().
            " WHERE user_id = ?".
                " AND identity_id = ?",
            "UPDATE ".$this->db->table_name('identities', true).
            " SET `del` = 1, `changed` = ".$this->db->now().
            " WHERE `user_id` = ?".
                " AND `identity_id` = ?",
            $this->ID,
            $iid);
@@ -405,11 +402,9 @@
    {
        if ($this->ID && $iid) {
            $this->db->query(
                "UPDATE ".$this->db->table_name('identities').
                " SET ".$this->db->quote_identifier('standard')." = '0'".
                " WHERE user_id = ?".
                    " AND identity_id <> ?".
                    " AND del <> 1",
                "UPDATE ".$this->db->table_name('identities', true).
                " SET `standard` = '0'".
                " WHERE `user_id` = ? AND `identity_id` <> ?",
                $this->ID,
                $iid);
@@ -425,9 +420,9 @@
    {
        if ($this->ID) {
            $this->db->query(
                "UPDATE ".$this->db->table_name('users').
                " SET last_login = ".$this->db->now().
                " WHERE user_id = ?",
                "UPDATE ".$this->db->table_name('users', true).
                " SET `last_login` = ".$this->db->now().
                " WHERE `user_id` = ?",
                $this->ID);
        }
    }
@@ -456,17 +451,17 @@
        $config = rcube::get_instance()->config;
        // query for matching user name
        $sql_result = $dbh->query("SELECT * FROM " . $dbh->table_name('users')
            ." WHERE mail_host = ? AND username = ?", $host, $user);
        $sql_result = $dbh->query("SELECT * FROM " . $dbh->table_name('users', true)
            ." WHERE `mail_host` = ? AND `username` = ?", $host, $user);
        $sql_arr = $dbh->fetch_assoc($sql_result);
        // username not found, try aliases from identities
        if (empty($sql_arr) && $config->get('user_aliases') && strpos($user, '@')) {
            $sql_result = $dbh->limitquery("SELECT u.*"
                ." FROM " . $dbh->table_name('users') . " u"
                ." JOIN " . $dbh->table_name('identities') . " i ON (i.user_id = u.user_id)"
                ." WHERE email = ? AND del <> 1", 0, 1, $user);
                ." FROM " . $dbh->table_name('users', true) . " u"
                ." JOIN " . $dbh->table_name('identities', true) . " i ON (i.`user_id` = u.`user_id`)"
                ." WHERE `email` = ? AND `del` <> 1", 0, 1, $user);
            $sql_arr = $dbh->fetch_assoc($sql_result);
        }
@@ -513,8 +508,8 @@
        }
        $dbh->query(
            "INSERT INTO ".$dbh->table_name('users').
            " (created, last_login, username, mail_host, language)".
            "INSERT INTO ".$dbh->table_name('users', true).
            " (`created`, `last_login`, `username`, `mail_host`, `language`)".
            " VALUES (".$dbh->now().", ".$dbh->now().", ?, ?, ?)",
            $data['user'],
            $data['host'],
@@ -646,11 +641,10 @@
        $result = array();
        $sql_result = $this->db->query(
            "SELECT search_id AS id, ".$this->db->quote_identifier('name')
            ." FROM ".$this->db->table_name('searches')
            ." WHERE user_id = ?"
                ." AND ".$this->db->quote_identifier('type')." = ?"
            ." ORDER BY ".$this->db->quote_identifier('name'),
            "SELECT `search_id` AS id, `name`"
            ." FROM ".$this->db->table_name('searches', true)
            ." WHERE `user_id` = ? AND `type` = ?"
            ." ORDER BY `name`",
            (int) $this->ID, (int) $type);
        while ($sql_arr = $this->db->fetch_assoc($sql_result)) {
@@ -678,12 +672,10 @@
        }
        $sql_result = $this->db->query(
            "SELECT ".$this->db->quote_identifier('name')
                .", ".$this->db->quote_identifier('data')
                .", ".$this->db->quote_identifier('type')
            ." FROM ".$this->db->table_name('searches')
            ." WHERE user_id = ?"
                ." AND search_id = ?",
            "SELECT `name`, `data`, `type`"
            . " FROM ".$this->db->table_name('searches', true)
            . " WHERE `user_id` = ?"
                ." AND `search_id` = ?",
            (int) $this->ID, (int) $id);
        while ($sql_arr = $this->db->fetch_assoc($sql_result)) {
@@ -712,9 +704,9 @@
            return false;
        $this->db->query(
            "DELETE FROM ".$this->db->table_name('searches')
            ." WHERE user_id = ?"
                ." AND search_id = ?",
            "DELETE FROM ".$this->db->table_name('searches', true)
            ." WHERE `user_id` = ?"
                ." AND `search_id` = ?",
            (int) $this->ID, $sid);
        return $this->db->affected_rows();
@@ -742,7 +734,7 @@
        $insert_cols[]   = $this->db->quote_identifier('data');
        $insert_values[] = serialize($data['data']);
        $sql = "INSERT INTO ".$this->db->table_name('searches')
        $sql = "INSERT INTO ".$this->db->table_name('searches', true)
            ." (".join(', ', $insert_cols).")"
            ." VALUES (".join(', ', array_pad(array(), sizeof($insert_values), '?')).")";
@@ -751,5 +743,4 @@
        return $this->db->insert_id('searches');
    }
}
program/steps/utils/killcache.inc
@@ -26,22 +26,27 @@
}
// @TODO: transaction here (if supported by DB) would be a good thing
$res = $RCMAIL->db->query("DELETE FROM cache");
$res = $RCMAIL->db->query("DELETE FROM " . $RCMAIL->db->table_name('cache', true));
if ($err = $RCMAIL->db->is_error($res)) {
    exit($err);
}
$res = $RCMAIL->db->query("DELETE FROM cache_messages");
$res = $RCMAIL->db->query("DELETE FROM " . $RCMAIL->db->table_name('cache_shared', true));
if ($err = $RCMAIL->db->is_error($res)) {
    exit($err);
}
$res = $RCMAIL->db->query("DELETE FROM cache_index");
$res = $RCMAIL->db->query("DELETE FROM " . $RCMAIL->db->table_name('cache_messages', true));
if ($err = $RCMAIL->db->is_error($res)) {
    exit($err);
}
$res = $RCMAIL->db->query("DELETE FROM cache_thread");
$res = $RCMAIL->db->query("DELETE FROM " . $RCMAIL->db->table_name('cache_index', true));
if ($err = $RCMAIL->db->is_error($res)) {
    exit($err);
}
$res = $RCMAIL->db->query("DELETE FROM " . $RCMAIL->db->table_name('cache_thread', true));
if ($err = $RCMAIL->db->is_error($res)) {
    exit($err);
}
tests/Framework/ImapCache.php
@@ -13,7 +13,7 @@
     */
    function test_class()
    {
        $object = new rcube_imap_cache(null, null, null, null);
        $object = new rcube_imap_cache(new rcube_db('test'), null, null, null);
        $this->assertInstanceOf('rcube_imap_cache', $object, "Class constructor");
    }