Projects
Kolab:3.4
roundcubemail
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 39
View file
roundcubemail-1.1.tar.gz/CHANGELOG
Changed
@@ -1,6 +1,7 @@ CHANGELOG Roundcube Webmail =========================== +- Added Oracle database support - Support contacts import in GMail CSV format - Added namespace filter in Folder Manager - Added folder searching in Folder Manager @@ -60,6 +61,7 @@ - Fix handling of email addresses with quoted domain part (#1490040) - Fix comm_path update on task switch (#1490041) - Fix error in MSSQL update script 2013061000.sql (#1490061) +- Fix validation of email addresses with IDNA domains (#1490067) RELEASE 1.0.2 -------------
View file
roundcubemail-1.1.tar.gz/SQL/mssql.initial.sql
Changed
@@ -280,7 +280,7 @@ CONSTRAINT [CK_contactgroups_del] CHECK ([del] = '1' or [del] = '0') GO -CREATE INDEX [IX_contactgroups_user_id] ON [dbo].[contacts]([user_id]) ON [PRIMARY] +CREATE INDEX [IX_contactgroups_user_id] ON [dbo].[contactgroups]([user_id]) ON [PRIMARY] GO ALTER TABLE [dbo].[contactgroupmembers] ADD
View file
roundcubemail-1.1.tar.gz/SQL/oracle.initial.sql
Added
@@ -0,0 +1,221 @@ +-- Roundcube Webmail initial database structure +-- This was tested with Oracle 11g + +CREATE TABLE "users" ( + "user_id" integer PRIMARY KEY, + "username" varchar(128) NOT NULL, + "mail_host" varchar(128) NOT NULL, + "created" timestamp with time zone DEFAULT current_timestamp NOT NULL, + "last_login" timestamp with time zone DEFAULT NULL, + "language" varchar(5), + "preferences" long DEFAULT NULL, + CONSTRAINT "users_username_key" UNIQUE ("username", "mail_host") +); + +CREATE SEQUENCE "users_seq" + START WITH 1 INCREMENT BY 1 NOMAXVALUE; + +CREATE TRIGGER "users_seq_trig" +BEFORE INSERT ON "users" FOR EACH ROW +BEGIN + :NEW."user_id" := "users_seq".nextval; +END; + + +CREATE TABLE "session" ( + "sess_id" varchar(128) NOT NULL PRIMARY KEY, + "created" timestamp with time zone DEFAULT current_timestamp NOT NULL, + "changed" timestamp with time zone DEFAULT current_timestamp NOT NULL, + "ip" varchar(41) NOT NULL, + "vars" long NOT NULL +); + +CREATE INDEX "session_changed_idx" ON "session" ("changed"); + + +CREATE TABLE "identities" ( + "identity_id" integer PRIMARY KEY, + "user_id" integer NOT NULL + REFERENCES "users" ("user_id") ON DELETE CASCADE, + "changed" timestamp with time zone DEFAULT current_timestamp NOT NULL, + "del" smallint DEFAULT 0 NOT NULL, + "standard" smallint DEFAULT 0 NOT NULL, + "name" varchar(128) NOT NULL, + "organization" varchar(128), + "email" varchar(128) NOT NULL, + "reply-to" varchar(128), + "bcc" varchar(128), + "signature" long, + "html_signature" integer DEFAULT 0 NOT NULL +); + +CREATE INDEX "identities_user_id_idx" ON "identities" ("user_id", "del"); +CREATE INDEX "identities_email_idx" ON "identities" ("email", "del"); + +CREATE SEQUENCE "identities_seq" + START WITH 1 INCREMENT BY 1 NOMAXVALUE; + +CREATE TRIGGER "identities_seq_trig" +BEFORE INSERT ON "identities" FOR EACH ROW +BEGIN + :NEW."identity_id" := "identities_seq".nextval; +END; + + +CREATE TABLE "contacts" ( + "contact_id" integer PRIMARY KEY, + "user_id" integer NOT NULL + REFERENCES "users" ("user_id") ON DELETE CASCADE, + "changed" timestamp with time zone DEFAULT current_timestamp NOT NULL, + "del" smallint DEFAULT 0 NOT NULL, + "name" varchar(128) DEFAULT NULL, + "email" varchar(4000) DEFAULT NULL, + "firstname" varchar(128) DEFAULT NULL, + "surname" varchar(128) DEFAULT NULL, + "vcard" long, + "words" varchar(4000) +); + +CREATE INDEX "contacts_user_id_idx" ON "contacts" ("user_id", "del"); + +CREATE SEQUENCE "contacts_seq" + START WITH 1 INCREMENT BY 1 NOMAXVALUE; + +CREATE TRIGGER "contacts_seq_trig" +BEFORE INSERT ON "contacts" FOR EACH ROW +BEGIN + :NEW."contact_id" := "contacts_seq".nextval; +END; + + +CREATE TABLE "contactgroups" ( + "contactgroup_id" integer PRIMARY KEY, + "user_id" integer NOT NULL + REFERENCES "users" ("user_id") ON DELETE CASCADE, + "changed" timestamp with time zone DEFAULT current_timestamp NOT NULL, + "del" smallint DEFAULT 0 NOT NULL, + "name" varchar(128) NOT NULL +); + +CREATE INDEX "contactgroups_user_id_idx" ON "contactgroups" ("user_id", "del"); + +CREATE SEQUENCE "contactgroups_seq" + START WITH 1 INCREMENT BY 1 NOMAXVALUE; + +CREATE TRIGGER "contactgroups_seq_trig" +BEFORE INSERT ON "contactgroups" FOR EACH ROW +BEGIN + :NEW."contactgroup_id" := "contactgroups_seq".nextval; +END; + + +CREATE TABLE "contactgroupmembers" ( + "contactgroup_id" integer NOT NULL + REFERENCES "contactgroups" ("contactgroup_id") ON DELETE CASCADE, + "contact_id" integer NOT NULL + REFERENCES "contacts" ("contact_id") ON DELETE CASCADE, + "created" timestamp with time zone DEFAULT current_timestamp NOT NULL, + PRIMARY KEY ("contactgroup_id", "contact_id") +); + +CREATE INDEX "contactgroupmembers_idx" ON "contactgroupmembers" ("contact_id"); + + +CREATE TABLE "cache" ( + "user_id" integer NOT NULL + REFERENCES "users" ("user_id") ON DELETE CASCADE, + "cache_key" varchar(128) NOT NULL, + "created" timestamp with time zone DEFAULT current_timestamp NOT NULL, + "expires" timestamp with time zone DEFAULT NULL, + "data" long NOT NULL +); + +CREATE INDEX "cache_user_id_idx" ON "cache" ("user_id", "cache_key"); +CREATE INDEX "cache_expires_idx" ON "cache" ("expires"); + + +CREATE TABLE "cache_shared" ( + "cache_key" varchar(255) NOT NULL, + "created" timestamp with time zone DEFAULT current_timestamp NOT NULL, + "expires" timestamp with time zone DEFAULT NULL, + "data" long NOT NULL +); + +CREATE INDEX "cache_shared_cache_key_idx" ON "cache_shared" ("cache_key"); +CREATE INDEX "cache_shared_expires_idx" ON "cache_shared" ("expires"); + + +CREATE TABLE "cache_index" ( + "user_id" integer NOT NULL + REFERENCES "users" ("user_id") ON DELETE CASCADE, + "mailbox" varchar(255) NOT NULL, + "expires" timestamp with time zone DEFAULT NULL, + "valid" smallint DEFAULT 0 NOT NULL, + "data" long NOT NULL, + PRIMARY KEY ("user_id", "mailbox") +); + +CREATE INDEX "cache_index_expires_idx" ON "cache_index" ("expires"); + + +CREATE TABLE "cache_thread" ( + "user_id" integer NOT NULL + REFERENCES "users" ("user_id") ON DELETE CASCADE, + "mailbox" varchar(255) NOT NULL, + "expires" timestamp with time zone DEFAULT NULL, + "data" long NOT NULL, + PRIMARY KEY ("user_id", "mailbox") +); + +CREATE INDEX "cache_thread_expires_idx" ON "cache_thread" ("expires"); + + +CREATE TABLE "cache_messages" ( + "user_id" integer NOT NULL + REFERENCES "users" ("user_id") ON DELETE CASCADE, + "mailbox" varchar(255) NOT NULL, + "uid" integer NOT NULL, + "expires" timestamp with time zone DEFAULT NULL, + "data" long NOT NULL, + "flags" integer DEFAULT 0 NOT NULL, + PRIMARY KEY ("user_id", "mailbox", "uid") +); + +CREATE INDEX "cache_messages_expires_idx" ON "cache_messages" ("expires"); + + +CREATE TABLE "dictionary" ( + "user_id" integer DEFAULT NULL + REFERENCES "users" ("user_id") ON DELETE CASCADE, + "language" varchar(5) NOT NULL, + "data" long DEFAULT NULL, + CONSTRAINT "dictionary_user_id_lang_key" UNIQUE ("user_id", "language") +); + + +CREATE TABLE "searches" ( + "search_id" integer PRIMARY KEY, + "user_id" integer NOT NULL + REFERENCES "users" ("user_id") ON DELETE CASCADE, + "type" smallint DEFAULT 0 NOT NULL, + "name" varchar(128) NOT NULL, + "data" long NOT NULL, + CONSTRAINT "searches_user_id_key" UNIQUE ("user_id", "type", "name") +); + +CREATE SEQUENCE "searches_seq" + START WITH 1 INCREMENT BY 1 NOMAXVALUE; + +CREATE TRIGGER "searches_seq_trig" +BEFORE INSERT ON "searches" FOR EACH ROW +BEGIN + :NEW."search_id" := "searches_seq".nextval; +END; + + +CREATE TABLE "system" ( + "name" varchar(64) NOT NULL PRIMARY KEY, + "value" long +); + +INSERT INTO "system" ("name", "value") VALUES ('roundcube-version', '2014042900');
View file
roundcubemail-1.1.tar.gz/bin/cleandb.sh
Changed
@@ -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"; }
View file
roundcubemail-1.1.tar.gz/bin/deluser.sh
Changed
@@ -69,6 +69,7 @@ // connect to DB $db = $rcmail->get_dbh(); $db->db_connect('w'); +$transaction = false; if (!$db->is_connected() || $db->is_error()) { _die("No DB connection\n" . $db->is_error()); @@ -81,23 +82,44 @@ die("User not found.\n"); } +// inform plugins about approaching user deletion +$plugin = $rcmail->plugins->exec_hook('user_delete_prepare', array('user' => $user, 'username' => $username, 'host' => $args['host'])); + // let plugins cleanup their own user-related data -$plugin = $rcmail->plugins->exec_hook('user_delete', array('user' => $user, 'username' => $username, 'host' => $args['host'])); +if (!$plugin['abort']) { + $transaction = $db->startTransaction(); + $plugin = $rcmail->plugins->exec_hook('user_delete', $plugin); +} if ($plugin['abort']) { + if ($transaction) { + $db->rollbackTransaction(); + } _die("User deletion aborted by plugin"); } // 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); +foreach (array('identities','contacts','contactgroups','dictionary','cache','cache_index','cache_messages','cache_thread','searches','users') as $table) { + $db->query('DELETE FROM ' . $db->table_name($table, true) . ' WHERE `user_id` = ?', $user->ID); } if ($db->is_error()) { + $rcmail->plugins->exec_hook('user_delete_rollback', $plugin); _die("DB error occurred: " . $db->is_error()); } else { - echo "Successfully deleted user $user->ID\n"; + // inform plugins about executed user deletion + $plugin = $rcmail->plugins->exec_hook('user_delete_commit', $plugin); + + if ($plugin['abort']) { + unset($plugin['abort']); + $db->rollbackTransaction(); + $rcmail->plugins->exec_hook('user_delete_rollback', $plugin); + } + else { + $db->endTransaction(); + echo "Successfully deleted user $user->ID\n"; + } }
View file
roundcubemail-1.1.tar.gz/bin/indexcontacts.sh
Changed
@@ -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'] . "...";
View file
roundcubemail-1.1.tar.gz/bin/moduserprefs.sh
Changed
@@ -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'] . "...";
View file
roundcubemail-1.1.tar.gz/bin/updatedb.sh
Changed
@@ -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); }
View file
roundcubemail-1.1.tar.gz/installer/check.php
Changed
@@ -71,6 +71,7 @@ 'DOM' => 'http://www.php.net/manual/en/book.dom.php', 'Intl' => 'http://www.php.net/manual/en/book.intl.php', 'Exif' => 'http://www.php.net/manual/en/book.exif.php', + 'oci8' => 'http://www.php.net/manual/en/book.oci8.php', 'PDO' => 'http://www.php.net/manual/en/book.pdo.php', 'LDAP' => 'http://www.php.net/manual/en/book.ldap.php', 'pdo_mysql' => 'http://www.php.net/manual/en/ref.pdo-mysql.php',
View file
roundcubemail-1.1.tar.gz/installer/test.php
Changed
@@ -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);
View file
roundcubemail-1.1.tar.gz/plugins/squirrelmail_usercopy/squirrelmail_usercopy.php
Changed
@@ -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 } - }
View file
roundcubemail-1.1.tar.gz/program/include/clisetup.php
Changed
@@ -5,7 +5,7 @@ | program/include/clisetup.php | | | | This file is part of the Roundcube Webmail client | - | Copyright (C) 2010-2012, The Roundcube Dev Team | + | Copyright (C) 2010-2014, The Roundcube Dev Team | | | | Licensed under the GNU General Public License version 3 or | | any later version with exceptions for skins & plugins. | @@ -27,3 +27,6 @@ // Unset max. execution time limit, set to 120 seconds in iniset.php @set_time_limit(0); + +$rcmail = rcmail::get_instance(); +$rcmail->output = new rcmail_output_cli();
View file
roundcubemail-1.1.tar.gz/program/include/rcmail_install.php
Changed
@@ -55,6 +55,7 @@ 'SQLite (v2)' => 'pdo_sqlite2', 'SQL Server (SQLSRV)' => 'pdo_sqlsrv', 'SQL Server (DBLIB)' => 'pdo_dblib', + 'Oracle' => 'oci8', );
View file
roundcubemail-1.1.tar.gz/program/include/rcmail_output_cli.php
Added
@@ -0,0 +1,89 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/include/rcmail_output_cli.php | + | | + | This file is part of the Roundcube PHP suite | + | Copyright (C) 2005-2014 The Roundcube Dev Team | + | | + | Licensed under the GNU General Public License version 3 or | + | any later version with exceptions for skins & plugins. | + | See the README file for a full license statement. | + | CONTENTS: | + | Abstract class for output generation | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ +*/ + +/** + * Class for output generation + * + * @package Webmail + * @subpackage View + */ +class rcmail_output_cli extends rcmail_output +{ + public $type = 'cli'; + + /** + * Object constructor + */ + public function __construct($task = null, $framed = false) + { + parent::__construct(); + } + + /** + * Call a client method + * + * @see rcube_output::command() + */ + function command() + { + // NOP + } + + /** + * Add a localized label to the client environment + */ + function add_label() + { + // NOP + } + + /** + * Invoke display_message command + * + * @see rcube_output::show_message() + */ + function show_message($message, $type = 'notice', $vars = null, $override = true, $timeout = 0) + { + if ($this->app->text_exists($message)) { + $message = $this->app->gettext(array('name' => $message, 'vars' => $vars)); + } + + printf("[%s] %s\n", strtoupper($type), $message); + } + + /** + * Redirect to a certain url. + * + * @see rcube_output::redirect() + */ + function redirect($p = array(), $delay = 1) + { + // NOP + } + + /** + * Send output to the client. + */ + function send() + { + // NOP + } + +}
View file
roundcubemail-1.1.tar.gz/program/include/rcmail_output_html.php
Changed
@@ -927,17 +927,17 @@ $attrib['name'] = $this->eval_expression($attrib['expression']); if ($attrib['name'] || $attrib['command']) { - // @FIXME: 'noshow' is useless, remove? - if ($attrib['noshow']) { - return ''; - } - $vars = $attrib + array('product' => $this->config->get('product_name')); unset($vars['name'], $vars['command']); $label = $this->app->gettext($attrib + array('vars' => $vars)); $quoting = !empty($attrib['quoting']) ? strtolower($attrib['quoting']) : (rcube_utils::get_boolean((string)$attrib['html']) ? 'no' : ''); + // 'noshow' can be used in skins to define new labels + if ($attrib['noshow']) { + return ''; + } + switch ($quoting) { case 'no': case 'raw':
View file
roundcubemail-1.1.tar.gz/program/js/app.js
Changed
@@ -2482,7 +2482,7 @@ // expand all threads with unread children this.expand_unread = function() { - var r, tbody = this.gui_objects.messagelist.tBodies[0], + var r, tbody = this.message_list.tbody, new_row = tbody.firstChild; while (new_row) {
View file
roundcubemail-1.1.tar.gz/program/lib/Roundcube/rcube_cache.php
Changed
@@ -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); }
View file
roundcubemail-1.1.tar.gz/program/lib/Roundcube/rcube_cache_shared.php
Changed
@@ -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);
View file
roundcubemail-1.1.tar.gz/program/lib/Roundcube/rcube_contacts.php
Changed
@@ -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; } - }
View file
roundcubemail-1.1.tar.gz/program/lib/Roundcube/rcube_db.php
Changed
@@ -50,6 +50,7 @@ ); const DEBUG_LINE_LENGTH = 4096; + const DEFAULT_QUOTE = '`'; /** * Factory, returns driver-specific instance of the class @@ -69,6 +70,7 @@ 'dblib' => 'mssql', 'mysqli' => 'mysql', 'oci' => 'oracle', + 'oci8' => 'oracle', ); $driver = isset($driver_map[$driver]) ? $driver_map[$driver] : $driver; @@ -129,6 +131,20 @@ return $this->dbh; } + // connect to database + if ($dbh = $this->conn_create($dsn)) { + $this->dbh = $dbh; + $this->dbhs[$mode] = $dbh; + $this->db_mode = $mode; + $this->db_connected = true; + } + } + + /** + * Create PDO connection + */ + protected function conn_create($dsn) + { // Get database specific connection options $dsn_string = $this->dsn_string($dsn); $dsn_options = $this->dsn_options($dsn); @@ -150,6 +166,8 @@ // don't throw exceptions or warnings $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); + + $this->conn_configure($dsn, $dbh); } catch (Exception $e) { $this->db_error = true; @@ -162,11 +180,7 @@ return null; } - $this->dbh = $dbh; - $this->dbhs[$mode] = $dbh; - $this->db_mode = $mode; - $this->db_connected = true; - $this->conn_configure($dsn, $dbh); + return $dbh; } /** @@ -238,8 +252,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 +426,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,10 +452,19 @@ $query = str_replace('??', '?', $query); $query = rtrim($query, " \t\n\r\0\x0B;"); + // log query $this->debug($query); + return $this->query_execute($query); + } + + /** + * Query execution + */ + protected function query_execute($query) + { // destroy reference to previous result, required for SQLite driver (#1488874) - $this->last_result = null; + $this->last_result = null; $this->db_error_msg = null; // send query @@ -444,9 +474,52 @@ $result = $this->handle_error($query); } - $this->last_result = $result; + return $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; } /** @@ -483,7 +556,9 @@ public function affected_rows($result = null) { if ($result || ($result === null && ($result = $this->last_result))) { - return $result->rowCount(); + if ($result !== true) { + return $result->rowCount(); + } } return 0; @@ -499,7 +574,7 @@ */ public function num_rows($result = null) { - if ($result || ($result === null && ($result = $this->last_result))) { + if (($result || ($result === null && ($result = $this->last_result))) && $result !== true) { // repeat query with SELECT COUNT(*) ... if (preg_match('/^SELECT\s+(?:ALL\s+|DISTINCT\s+)?(?:.*?)\s+FROM\s+(.*)$/ims', $result->queryString, $m)) { $query = $this->dbh->query('SELECT COUNT(*) FROM ' . $m[1], PDO::FETCH_NUM); @@ -575,7 +650,9 @@ protected function _fetch_row($result, $mode) { if ($result || ($result === null && ($result = $this->last_result))) { - return $result->fetch($mode); + if ($result !== true) { + return $result->fetch($mode); + } } return false; @@ -645,6 +722,63 @@ } /** + * Start transaction + * + * @return bool True on success, False on failure + */ + public function startTransaction() + { + $this->db_connect('w', true); + + // check connection before proceeding + if (!$this->is_connected()) { + return $this->last_result = false; + } + + $this->debug('BEGIN TRANSACTION'); + + return $this->last_result = $this->dbh->beginTransaction(); + } + + /** + * Commit transaction + * + * @return bool True on success, False on failure + */ + public function endTransaction() + { + $this->db_connect('w', true); + + // check connection before proceeding + if (!$this->is_connected()) { + return $this->last_result = false; + } + + $this->debug('COMMIT TRANSACTION'); + + return $this->last_result = $this->dbh->commit(); + } + + /** + * Rollback transaction + * + * @return bool True on success, False on failure + */ + public function rollbackTransaction() + { + $this->db_connect('w', true); + + // check connection before proceeding + if (!$this->is_connected()) { + return $this->last_result = false; + } + + $this->debug('ROLLBACK TRANSACTION'); + + return $this->last_result = $this->dbh->rollBack(); + } + + /** * Formats input so it can be safely used in a query * * @param mixed $input Value to quote @@ -677,8 +811,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 +1056,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;
View file
roundcubemail-1.1.tar.gz/program/lib/Roundcube/rcube_db_oracle.php
Added
@@ -0,0 +1,599 @@ +<?php + +/** + +-----------------------------------------------------------------------+ + | This file is part of the Roundcube Webmail client | + | Copyright (C) 2011-2014, Kolab Systems AG | + | | + | Licensed under the GNU General Public License version 3 or | + | any later version with exceptions for skins & plugins. | + | See the README file for a full license statement. | + | | + | PURPOSE: | + | Database wrapper class that implements database functions | + | for Oracle database using OCI8 extension | + +-----------------------------------------------------------------------+ + | Author: Aleksander Machniak <machniak@kolabsys.com> | + +-----------------------------------------------------------------------+ +*/ + +/** + * Database independent query interface + * + * @package Framework + * @subpackage Database + */ +class rcube_db_oracle extends rcube_db +{ + public $db_provider = 'oracle'; + + + /** + * Create connection instance + */ + protected function conn_create($dsn) + { + // Get database specific connection options + $dsn_options = $this->dsn_options($dsn); + + $function = $this->db_pconn ? 'oci_pconnect' : 'oci_connect'; + + if (!function_exists($function)) { + $this->db_error = true; + $this->db_error_msg = 'OCI8 extension not loaded. See http://php.net/manual/en/book.oci8.php'; + + rcube::raise_error(array('code' => 500, 'type' => 'db', + 'line' => __LINE__, 'file' => __FILE__, + 'message' => $this->db_error_msg), true, false); + + return; + } + + // connect + $dbh = @$function($dsn['username'], $dsn['password'], $dsn_options['database'], $dsn_options['charset']); + + if (!$dbh) { + $error = oci_error(); + $this->db_error = true; + $this->db_error_msg = $error['message']; + + rcube::raise_error(array('code' => 500, 'type' => 'db', + 'line' => __LINE__, 'file' => __FILE__, + 'message' => $this->db_error_msg), true, false); + + return; + } + + // configure session + $this->conn_configure($dsn, $dbh); + + return $dbh; + } + + /** + * Driver-specific configuration of database connection + * + * @param array $dsn DSN for DB connections + * @param PDO $dbh Connection handler + */ + protected function conn_configure($dsn, $dbh) + { + $init_queries = array( + "ALTER SESSION SET nls_date_format = 'YYYY-MM-DD'", + "ALTER SESSION SET nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS'", + ); + + foreach ($init_queries as $query) { + $stmt = oci_parse($dbh, $query); + oci_execute($stmt); + } + } + + /** + * Connection state checker + * + * @return boolean True if in connected state + */ + public function is_connected() + { + return empty($this->dbh) ? false : $this->db_connected; + } + + /** + * Execute a SQL query with limits + * + * @param string $query SQL query to execute + * @param int $offset Offset for LIMIT statement + * @param int $numrows Number of rows for LIMIT statement + * @param array $params Values to be inserted in query + * + * @return PDOStatement|bool Query handle or False on error + */ + protected function _query($query, $offset, $numrows, $params) + { + $query = ltrim($query); + + $this->db_connect($this->dsn_select($query), true); + + // check connection before proceeding + if (!$this->is_connected()) { + return $this->last_result = false; + } + + if ($numrows || $offset) { + $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; + $idx = 0; + $args = array(); + + if (count($params)) { + while ($pos = strpos($query, '?', $pos)) { + if ($query[$pos+1] == '?') { // skip escaped '?' + $pos += 2; + } + else { + $val = $this->quote($params[$idx++]); + + // long strings are not allowed inline, need to be parametrized + if (strlen($val) > 4000) { + $key = ':param' . (count($args) + 1); + $args[$key] = $params[$idx-1]; + $val = $key; + } + + unset($params[$idx-1]); + $query = substr_replace($query, $val, $pos, 1); + $pos += strlen($val); + } + } + } + + // replace escaped '?' back to normal, see self::quote() + $query = str_replace('??', '?', $query); + $query = rtrim($query, " \t\n\r\0\x0B;"); + + // log query + $this->debug($query); + + // destroy reference to previous result + $this->last_result = null; + $this->db_error_msg = null; + + // prepare query + $result = @oci_parse($this->dbh, $query); + $mode = $this->in_transaction ? OCI_NO_AUTO_COMMIT : OCI_COMMIT_ON_SUCCESS; + + if ($result) { + foreach ($args as $param => $arg) { + oci_bind_by_name($result, $param, $args[$param], -1, SQLT_LNG); + } + } + + // execute query + if (!$result || !@oci_execute($result, $mode)) { + $result = $this->handle_error($query, $result); + } + + return $this->last_result = $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, $result = null) + { + $error = oci_error(is_resource($result) ? $result : $this->dbh); + + // @TODO: Find error codes for key errors + if (empty($this->options['ignore_key_errors']) || !in_array($error['code'], array('23000', '23505'))) { + $this->db_error = true; + $this->db_error_msg = sprintf('[%s] %s', $error['code'], $error['message']); + + rcube::raise_error(array('code' => 500, 'type' => 'db', + 'line' => __LINE__, 'file' => __FILE__, + 'message' => $this->db_error_msg . " (SQL Query: $query)" + ), true, false); + } + + return false; + } + + /** + * Get last inserted record ID + * + * @param string $table Table name (to find the incremented sequence) + * + * @return mixed ID or false on failure + */ + public function insert_id($table = null) + { + if (!$this->db_connected || $this->db_mode == 'r' || empty($table)) { + return false; + } + + $sequence = $this->quote_identifier($this->sequence_name($table)); + $result = $this->query("SELECT $sequence.currval FROM dual"); + $result = $this->fetch_array($result); + + return $result[0] ?: false; + } + + /** + * Get number of affected rows for the last query + * + * @param mixed $result Optional query handle + * + * @return int Number of (matching) rows + */ + public function affected_rows($result = null) + { + if ($result || ($result === null && ($result = $this->last_result))) { + return oci_num_rows($result); + } + + return 0; + } + + /** + * Get number of rows for a SQL query + * If no query handle is specified, the last query will be taken as reference + * + * @param mixed $result Optional query handle + * @return mixed Number of rows or false on failure + * @deprecated This method shows very poor performance and should be avoided. + */ + public function num_rows($result = null) + { + // not implemented + return false; + } + + /** + * Get an associative array for one row + * If no query handle is specified, the last query will be taken as reference + * + * @param mixed $result Optional query handle + * + * @return mixed Array with col values or false on failure + */ + public function fetch_assoc($result = null) + { + return $this->_fetch_row($result, OCI_ASSOC); + } + + /** + * Get an index array for one row + * If no query handle is specified, the last query will be taken as reference + * + * @param mixed $result Optional query handle + * + * @return mixed Array with col values or false on failure + */ + public function fetch_array($result = null) + { + return $this->_fetch_row($result, OCI_NUM); + } + + /** + * Get col values for a result row + * + * @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 ($result || ($result === null && ($result = $this->last_result))) { + return oci_fetch_array($result, $mode + OCI_RETURN_NULLS + OCI_RETURN_LOBS); + } + + return false; + } + + /** + * Formats input so it can be safely used in a query + * PDO_OCI does not implement quote() method + * + * @param mixed $input Value to quote + * @param string $type Type of data (integer, bool, ident) + * + * @return string Quoted/converted string for use in query + */ + public function quote($input, $type = null) + { + // handle int directly for better performance + if ($type == 'integer' || $type == 'int') { + return intval($input); + } + + if (is_null($input)) { + return 'NULL'; + } + + if ($type == 'ident') { + return $this->quote_identifier($input); + } + + switch ($type) { + case 'bool': + case 'integer': + return intval($input); + default: + return "'" . strtr($input, array( + '?' => '??', + "'" => "''", + rcube_db::DEFAULT_QUOTE => rcube_db::DEFAULT_QUOTE . rcube_db::DEFAULT_QUOTE + )) . "'"; + } + } + + /** + * Return correct name for a specific database sequence + * + * @param string $table Table name + * + * @return string Translated sequence name + */ + protected function sequence_name($table) + { + // Note: we support only one sequence per table + // Note: The sequence name must be <table_name>_seq + $sequence = $table . '_seq'; + + // modify sequence name if prefix is configured + if ($prefix = $this->options['table_prefix']) { + return $prefix . $sequence; + } + + return $sequence; + } + + /** + * Return SQL statement for case insensitive LIKE + * + * @param string $column Field name + * @param string $value Search value + * + * @return string SQL statement to use in query + */ + public function ilike($column, $value) + { + return 'UPPER(' . $this->quote_identifier($column) . ') LIKE UPPER(' . $this->quote($value) . ')'; + } + + /** + * 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($interval = 0) + { + if ($interval) { + $interval = intval($interval); + return "current_timestamp + INTERVAL '$interval' SECOND"; + } + + return "current_timestamp"; + } + + /** + * Return SQL statement to convert a field value into a unix timestamp + * + * @param string $field Field name + * + * @return string SQL statement to use in query + * @deprecated + */ + public function unixtimestamp($field) + { + return "(($field - to_date('1970-01-01','YYYY-MM-DD')) * 60 * 60 * 24)"; + } + + /** + * Adds TOP (LIMIT,OFFSET) clause to the query + * + * @param string $query SQL query + * @param int $limit Number of rows + * @param int $offset Offset + * + * @return string SQL query + */ + protected function set_limit($query, $limit = 0, $offset = 0) + { + $limit = intval($limit); + $offset = intval($offset); + $end = $offset + $limit; + + // @TODO: Oracle 12g has better OFFSET support + + if (!$offset) { + $query = "SELECT * FROM ($query) a WHERE rownum <= $end"; + } + else { + $query = "SELECT * FROM (SELECT a.*, rownum as rn FROM ($query) a WHERE rownum <= $end) b WHERE rn > $offset"; + } + + return $query; + } + + /** + * Parse SQL file and fix table names according to table prefix + */ + protected function fix_table_names($sql) + { + if (!$this->options['table_prefix']) { + return $sql; + } + + $sql = parent::fix_table_names($sql); + + // replace sequence names, and other Oracle-specific commands + $sql = preg_replace_callback('/((SEQUENCE ["]?)([^" \r\n]+)/', + array($this, 'fix_table_names_callback'), + $sql + ); + + $sql = preg_replace_callback( + '/([ \r\n]+["]?)([^"\' \r\n\.]+)(["]?\.nextval)/', + array($this, 'fix_table_names_seq_callback'), + $sql + ); + + return $sql; + } + + /** + * Preg_replace callback for fix_table_names() + */ + protected function fix_table_names_seq_callback($matches) + { + return $matches[1] . $this->options['table_prefix'] . $matches[2] . $matches[3]; + } + + /** + * Returns connection options from DSN array + */ + protected function dsn_options($dsn) + { + $params = array(); + + if ($dsn['hostspec']) { + $host = $dsn['hostspec']; + if ($dsn['port']) { + $host .= ':' . $dsn['port']; + } + + $params['database'] = $host . '/' . $dsn['database']; + } + + $params['charset'] = 'UTF8'; + + return $params; + } + + /** + * Execute the given SQL script + * + * @param string SQL queries to execute + * + * @return boolen True on success, False on error + */ + public function exec_script($sql) + { + $sql = $this->fix_table_names($sql); + $buff = ''; + $body = false; + + foreach (explode("\n", $sql) as $line) { + $tok = strtolower(trim($line)); + if (preg_match('/^--/', $line) || $tok == '') { + continue; + } + + $buff .= $line . "\n"; + + // detect PL/SQL function bodies, don't break on semicolon + if ($body && $tok == 'end;') { + $body = false; + } + else if (!$body && $tok == 'begin') { + $body = true; + } + + if (!$body && substr($tok, -1) == ';') { + $this->query($buff); + $buff = ''; + if ($this->db_error) { + break; + } + } + } + + return !$this->db_error; + } + + /** + * Start transaction + * + * @return bool True on success, False on failure + */ + public function startTransaction() + { + $this->db_connect('w', true); + + // check connection before proceeding + if (!$this->is_connected()) { + return $this->last_result = false; + } + + $this->debug('BEGIN TRANSACTION'); + + return $this->last_result = $this->in_transaction = true; + } + + /** + * Commit transaction + * + * @return bool True on success, False on failure + */ + public function endTransaction() + { + $this->db_connect('w', true); + + // check connection before proceeding + if (!$this->is_connected()) { + return $this->last_result = false; + } + + $this->debug('COMMIT TRANSACTION'); + + if ($result = @oci_commit($this->dbh)) { + $this->in_transaction = true; + } + else { + $this->handle_error('COMMIT'); + } + + return $this->last_result = $result; + } + + /** + * Rollback transaction + * + * @return bool True on success, False on failure + */ + public function rollbackTransaction() + { + $this->db_connect('w', true); + + // check connection before proceeding + if (!$this->is_connected()) { + return $this->last_result = false; + } + + $this->debug('ROLLBACK TRANSACTION'); + + if ($result = @oci_rollback($this->dbh)) { + $this->in_transaction = false; + } + else { + $this->handle_error('ROLLBACK'); + } + + return $this->last_result = $this->dbh->rollBack(); + } +}
View file
roundcubemail-1.1.tar.gz/program/lib/Roundcube/rcube_imap_cache.php
Changed
@@ -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); } @@ -557,14 +562,16 @@ } } + $binary_check = $this->db->db_provider == 'oracle' ? "BITAND(`flags`, %d)" : "(`flags` & %d)"; + $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 " . sprintf($binary_check, $idx) . ($enabled ? " = 0" : " = $idx"), $this->userid, $mailbox); } @@ -583,8 +590,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 +604,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 +626,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 +661,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 +699,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 +719,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 +756,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 +797,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 +817,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 +848,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 +868,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 +877,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 +1096,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 +1135,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); } }
View file
roundcubemail-1.1.tar.gz/program/lib/Roundcube/rcube_imap_generic.php
Changed
@@ -3199,9 +3199,9 @@ for ($i=0; $i<$size; $i++) { if (isset($mbox) && is_array($data[$i])) { $size_sub = count($data[$i]); - for ($x=0; $x<$size_sub; $x++) { + for ($x=0; $x<$size_sub; $x+=2) { if ($data[$i][$x+1] !== null) - $result[$mbox][$data[$i][$x]] = $data[$i][++$x]; + $result[$mbox][$data[$i][$x]] = $data[$i][$x+1]; } unset($data[$i]); } @@ -3219,8 +3219,8 @@ } } else if (isset($mbox)) { - if ($data[$i+1] !== null) - $result[$mbox][$data[$i]] = $data[++$i]; + if ($data[++$i] !== null) + $result[$mbox][$data[$i-1]] = $data[$i]; unset($data[$i]); unset($data[$i-1]); }
View file
roundcubemail-1.1.tar.gz/program/lib/Roundcube/rcube_session.php
Changed
@@ -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) {
View file
roundcubemail-1.1.tar.gz/program/lib/Roundcube/rcube_spellchecker.php
Changed
@@ -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; } - }
View file
roundcubemail-1.1.tar.gz/program/lib/Roundcube/rcube_user.php
Changed
@@ -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)); @@ -344,11 +341,11 @@ $insert_cols[] = $this->db->quote_identifier($col); $insert_values[] = $value; } - $insert_cols[] = 'user_id'; + $insert_cols[] = $this->db->quote_identifier('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'); } - }
View file
roundcubemail-1.1.tar.gz/program/lib/Roundcube/rcube_utils.php
Changed
@@ -103,13 +103,14 @@ } foreach ($domain_array as $part) { - if (!preg_match('/^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|([A-Za-z0-9]))$/', $part)) { + if (!preg_match('/^((xn--)?([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|([A-Za-z0-9]))$/', $part)) { return false; } } // last domain part - if (preg_match('/[^a-zA-Z]/', array_pop($domain_array))) { + $last_part = array_pop($domain_array); + if (strpos($last_part, 'xn--') !== 0 && preg_match('/[^a-zA-Z]/', $last_part)) { return false; }
View file
roundcubemail-1.1.tar.gz/program/steps/utils/killcache.inc
Changed
@@ -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); }
View file
roundcubemail-1.1.tar.gz/skins/larry/ui.js
Changed
@@ -507,7 +507,8 @@ // $('#composeformbuttons')[(btns ? 'show' : 'hide')](); var abooks = $('#directorylist'); - $('#compose-contacts .scroller').css('top', abooks.position().top + abooks.outerHeight()); + if (abooks.length) + $('#compose-contacts .scroller').css('top', abooks.position().top + abooks.outerHeight()); } @@ -1279,8 +1280,8 @@ this.resize = function() { if (this.horizontal) { - this.p1.css('height', Math.floor(this.pos - this.p1pos.top - this.halfsize) + 'px'); - this.p2.css('top', Math.ceil(this.pos + this.halfsize + 2) + 'px'); + this.p1.css('height', Math.floor(this.pos - this.p1pos.top - Math.floor(this.halfsize)) + 'px'); + this.p2.css('top', Math.ceil(this.pos + Math.ceil(this.halfsize) + 2) + 'px'); this.handle.css('top', Math.round(this.pos - this.halfsize + this.offset)+'px'); if (bw.ie) { var new_height = parseInt(this.parent.outerHeight(), 10) - parseInt(this.p2.css('top'), 10) - (bw.ie8 ? 2 : 0); @@ -1288,8 +1289,8 @@ } } else { - this.p1.css('width', Math.floor(this.pos - this.p1pos.left - this.halfsize) + 'px'); - this.p2.css('left', Math.ceil(this.pos + this.halfsize) + 'px'); + this.p1.css('width', Math.floor(this.pos - this.p1pos.left - Math.floor(this.halfsize)) + 'px'); + this.p2.css('left', Math.ceil(this.pos + Math.ceil(this.halfsize)) + 'px'); this.handle.css('left', Math.round(this.pos - this.halfsize + this.offset + 3)+'px'); if (bw.ie) { var new_width = parseInt(this.parent.outerWidth(), 10) - parseInt(this.p2.css('left'), 10) ; @@ -1372,7 +1373,7 @@ if (me.horizontal) { if (((pos.y - me.halfsize) > me.p1pos.top) && ((pos.y + me.halfsize) < (me.p2pos.top + me.p2.outerHeight()))) { - me.pos = Math.max(me.min, pos.y - me.offset); + me.pos = Math.max(me.min, pos.y - Math.max(0, me.offset)); if (me.pos > me.min) me.pos = Math.min(me.pos, me.parent.height() - me.min); @@ -1381,7 +1382,7 @@ } else { if (((pos.x - me.halfsize) > me.p1pos.left) && ((pos.x + me.halfsize) < (me.p2pos.left + me.p2.outerWidth()))) { - me.pos = Math.max(me.min, pos.x - me.offset); + me.pos = Math.max(me.min, pos.x - Math.max(0, me.offset)); if (me.pos > me.min) me.pos = Math.min(me.pos, me.parent.width() - me.min);
View file
roundcubemail-1.1.tar.gz/tests/Framework/ImapCache.php
Changed
@@ -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"); }
View file
roundcubemail-1.1.tar.gz/tests/Framework/Utils.php
Changed
@@ -29,6 +29,7 @@ array('email@domain.name', '.name is valid Top Level Domain name'), array('email@domain.co.jp', 'Dot in Top Level Domain name also considered valid (use co.jp as example here)'), array('firstname-lastname@domain.com', 'Dash in address field is valid'), + array('test@xn--e1aaa0cbbbcacac.xn--p1ai', 'IDNA domain'), ); }
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.