2 files added
17 files modified
New file |
| | |
| | | -- 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'); |
| | |
| | | |
| | | 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 |
| | |
| | | $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); |
| | | |
| | |
| | | } |
| | | |
| | | // 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"; |
| | | } |
| | |
| | | // 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()) { |
| | |
| | | } |
| | | |
| | | // 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'] . "..."; |
| | | |
| | |
| | | $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'] . "..."; |
| | | |
| | |
| | | |
| | | // 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(); |
| | |
| | | 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); |
| | | } |
| | | |
| | |
| | | |
| | | // 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>'; |
| | |
| | | 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()); |
| | |
| | | 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 |
| | |
| | | } |
| | | } // end if 'sql'-driver |
| | | } |
| | | |
| | | } |
| | |
| | | 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 |
| | |
| | | { |
| | | 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.'.%'); |
| | | } |
| | |
| | | $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()); |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | 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)) { |
| | |
| | | // 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; |
| | |
| | | // 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 |
| | |
| | | // 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); |
| | | } |
| | |
| | | |
| | | // 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); |
| | | } |
| | | |
| | |
| | | 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 |
| | |
| | | { |
| | | 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 . '.%'); |
| | | } |
| | | } |
| | |
| | | $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()); |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | 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)) { |
| | |
| | | |
| | | // 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 |
| | |
| | | // 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); |
| | | } |
| | |
| | | |
| | | // 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); |
| | |
| | | } |
| | | |
| | | $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))) { |
| | |
| | | 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))) { |
| | |
| | | $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, |
| | |
| | | |
| | | // 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']); |
| | | |
| | |
| | | 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 |
| | |
| | | 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 |
| | | ); |
| | |
| | | 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))) { |
| | |
| | | |
| | | 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).")" |
| | | ); |
| | | |
| | |
| | | |
| | | 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 |
| | | ); |
| | |
| | | |
| | | // 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 |
| | | ); |
| | | |
| | |
| | | |
| | | // 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 |
| | | ); |
| | | |
| | |
| | | { |
| | | $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(); |
| | | } |
| | |
| | | $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; |
| | | } |
| | |
| | | { |
| | | // 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 |
| | | ); |
| | | |
| | |
| | | $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 |
| | | ); |
| | | |
| | |
| | | |
| | | // 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))) { |
| | |
| | | |
| | | 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 |
| | |
| | | $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 |
| | | ); |
| | | |
| | |
| | | |
| | | 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); |
| | | |
| | |
| | | |
| | | return $checkname; |
| | | } |
| | | |
| | | } |
| | |
| | | ); |
| | | |
| | | const DEBUG_LINE_LENGTH = 4096; |
| | | const DEFAULT_QUOTE = '`'; |
| | | |
| | | /** |
| | | * Factory, returns driver-specific instance of the class |
| | |
| | | // 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]; |
| | | |
| | |
| | | $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; |
| | |
| | | $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) |
| | |
| | | $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; |
| | | } |
| | | |
| | | /** |
| | |
| | | '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'; |
| | |
| | | * Return correct name for a specific database table |
| | | * |
| | | * @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; |
New file |
| | |
| | | <?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 PHP PDO functions | |
| | | | for Oracle database | |
| | | +-----------------------------------------------------------------------+ |
| | | | Author: Aleksander Machniak <machniak@kolabsys.com> | |
| | | +-----------------------------------------------------------------------+ |
| | | */ |
| | | |
| | | /** |
| | | * Database independent query interface |
| | | * This is a wrapper for the PHP PDO |
| | | * |
| | | * @package Framework |
| | | * @subpackage Database |
| | | */ |
| | | class rcube_db_oracle extends rcube_db |
| | | { |
| | | public $db_provider = 'oracle'; |
| | | |
| | | /** |
| | | * Driver-specific configuration of database connection |
| | | * |
| | | * @param array $dsn DSN for DB connections |
| | | * @param PDO $dbh Connection handler |
| | | */ |
| | | protected function conn_configure($dsn, $dbh) |
| | | { |
| | | $dbh->query("ALTER SESSION SET nls_date_format = 'YYYY-MM-DD'"); |
| | | $dbh->query("ALTER SESSION SET nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS'"); |
| | | } |
| | | |
| | | /** |
| | | * 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 = $dbh->query("SELECT $sequence.currval FROM dual"); |
| | | |
| | | return $result ? $result->fetchColumn() : 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 |
| | | |
| | | $orderby = stristr($query, 'ORDER BY'); |
| | | $select = substr($query, 0, stripos($query, 'FROM')); |
| | | $offset += 1; |
| | | |
| | | if ($orderby !== false) { |
| | | $query = trim(substr($query, 0, -1 * strlen($orderby))); |
| | | } |
| | | else { |
| | | // it shouldn't happen, paging without sorting has not much sense |
| | | // @FIXME: I don't know how to build paging query without ORDER BY |
| | | $orderby = "ORDER BY 1"; |
| | | } |
| | | |
| | | $query = preg_replace('/^SELECT\s/i', '', $query); |
| | | $query = "$select FROM (SELECT ROW_NUMBER() OVER ($orderby) AS row_number, $query)" |
| | | . " WHERE row_number BETWEEN $offset AND $end"; |
| | | |
| | | 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 PDO DSN string from DSN array |
| | | */ |
| | | protected function dsn_string($dsn) |
| | | { |
| | | $params = array(); |
| | | $result = 'oci:'; |
| | | |
| | | if ($dsn['hostspec']) { |
| | | $host = $dsn['hostspec']; |
| | | if ($dsn['port']) { |
| | | $host .= ':' . $dsn['port']; |
| | | } |
| | | |
| | | $dsn['database'] = $host . '/' . $dsn['database']; |
| | | } |
| | | |
| | | if ($dsn['database']) { |
| | | $params[] = 'dbname=' . $dsn['database']; |
| | | } |
| | | |
| | | $params['charset'] = 'UTF8'; |
| | | |
| | | if (!empty($params)) { |
| | | $result .= implode(';', $params); |
| | | } |
| | | |
| | | return $result; |
| | | } |
| | | } |
| | |
| | | |
| | | // 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); |
| | | } |
| | | |
| | | |
| | |
| | | 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); |
| | |
| | | |
| | | 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)) { |
| | |
| | | // 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)) { |
| | |
| | | |
| | | // 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); |
| | | |
| | |
| | | // 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); |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | $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); |
| | | } |
| | | |
| | |
| | | |
| | | 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 { |
| | |
| | | } |
| | | |
| | | $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); |
| | | } |
| | | } |
| | |
| | | // 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 |
| | | ); |
| | | } |
| | |
| | | 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 |
| | | ); |
| | | |
| | |
| | | { |
| | | $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"); |
| | | } |
| | | |
| | | |
| | |
| | | { |
| | | // 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)) { |
| | |
| | | { |
| | | // 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)) { |
| | |
| | | (int) $mbox_data['UIDNEXT'], |
| | | $modseq ? $modseq : $mbox_data['HIGHESTMODSEQ'], |
| | | ); |
| | | |
| | | $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)) { |
| | |
| | | $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); |
| | | } |
| | | |
| | |
| | | (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)) { |
| | |
| | | $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); |
| | | |
| | |
| | | // 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); |
| | | } |
| | | |
| | |
| | | // 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)) { |
| | |
| | | } |
| | | |
| | | $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); |
| | | } |
| | | } |
| | |
| | | array($this, 'db_write'), |
| | | array($this, 'db_destroy'), |
| | | array($this, 'gc')); |
| | | |
| | | $this->table_name = $this->db->table_name('session', true); |
| | | } |
| | | } |
| | | |
| | |
| | | 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']); |
| | |
| | | public function db_write($key, $vars) |
| | | { |
| | | $now = $this->db->now(); |
| | | $table = $this->db->table_name('session'); |
| | | $ts = microtime(true); |
| | | |
| | | if ($this->nowrite) |
| | |
| | | $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); |
| | | } |
| | |
| | | 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; |
| | |
| | | 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) { |
| | |
| | | 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'])); |
| | | } |
| | | } |
| | |
| | | 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)) { |
| | |
| | | |
| | | return $this->dict; |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | 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); |
| | | } |
| | | |
| | |
| | | $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); |
| | |
| | | $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]; |
| | | } |
| | | |
| | |
| | | $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)) { |
| | |
| | | $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)); |
| | |
| | | $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'), |
| | |
| | | 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); |
| | |
| | | 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); |
| | | |
| | |
| | | { |
| | | 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); |
| | | |
| | |
| | | { |
| | | 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); |
| | | } |
| | | } |
| | |
| | | $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); |
| | | } |
| | |
| | | } |
| | | |
| | | $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'], |
| | |
| | | $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)) { |
| | |
| | | } |
| | | |
| | | $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)) { |
| | |
| | | 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(); |
| | |
| | | $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), '?')).")"; |
| | | |
| | |
| | | |
| | | return $this->db->insert_id('searches'); |
| | | } |
| | | |
| | | } |
| | |
| | | } |
| | | |
| | | // @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); |
| | | } |
| | |
| | | */ |
| | | 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"); |
| | | } |