summaryrefslogtreecommitdiff
path: root/program/lib/Roundcube/rcube_imap_cache.php
diff options
context:
space:
mode:
Diffstat (limited to 'program/lib/Roundcube/rcube_imap_cache.php')
-rw-r--r--program/lib/Roundcube/rcube_imap_cache.php219
1 files changed, 62 insertions, 157 deletions
diff --git a/program/lib/Roundcube/rcube_imap_cache.php b/program/lib/Roundcube/rcube_imap_cache.php
index d72bfe0ab..5170e9e21 100644
--- a/program/lib/Roundcube/rcube_imap_cache.php
+++ b/program/lib/Roundcube/rcube_imap_cache.php
@@ -49,20 +49,6 @@ class rcube_imap_cache
private $userid;
/**
- * Expiration time in seconds
- *
- * @var int
- */
- private $ttl;
-
- /**
- * Maximum cached message size
- *
- * @var int
- */
- private $threshold;
-
- /**
* Internal (in-memory) cache
*
* @var array
@@ -97,26 +83,13 @@ class rcube_imap_cache
/**
* Object constructor.
- *
- * @param rcube_db $db DB handler
- * @param rcube_imap $imap IMAP handler
- * @param int $userid User identifier
- * @param bool $skip_deleted skip_deleted flag
- * @param string $ttl Expiration time of memcache/apc items
- * @param int $threshold Maximum cached message size
*/
- function __construct($db, $imap, $userid, $skip_deleted, $ttl=0, $threshold=0)
+ function __construct($db, $imap, $userid, $skip_deleted)
{
- // convert ttl string to seconds
- $ttl = get_offset_sec($ttl);
- if ($ttl > 2592000) $ttl = 2592000;
-
$this->db = $db;
$this->imap = $imap;
$this->userid = $userid;
$this->skip_deleted = $skip_deleted;
- $this->ttl = $ttl;
- $this->threshold = $threshold;
}
@@ -242,7 +215,9 @@ class rcube_imap_cache
* Return messages thread.
* If threaded index doesn't exist or is invalid, will be updated.
*
- * @param string $mailbox Folder name
+ * @param string $mailbox Folder name
+ * @param string $sort_field Sorting column
+ * @param string $sort_order Sorting order (ASC|DESC)
*
* @return array Messages threaded index
*/
@@ -281,11 +256,19 @@ class rcube_imap_cache
if ($index === null) {
// Get mailbox data (UIDVALIDITY, counters, etc.) for status check
$mbox_data = $this->imap->folder_data($mailbox);
- // Get THREADS result
- $index['object'] = $this->get_thread_data($mailbox, $mbox_data);
+
+ if ($mbox_data['EXISTS']) {
+ // get all threads (default sort order)
+ $threads = $this->imap->fetch_threads($mailbox, true);
+ }
+ else {
+ $threads = new rcube_result_thread($mailbox, '* THREAD');
+ }
+
+ $index['object'] = $threads;
// insert/update
- $this->add_thread_row($mailbox, $index['object'], $mbox_data, $exists);
+ $this->add_thread_row($mailbox, $threads, $mbox_data, $exists);
}
$this->icache[$mailbox]['thread'] = $index;
@@ -443,40 +426,23 @@ class rcube_imap_cache
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')
+ ." SET flags = ?, data = ?, changed = ".$this->db->now()
." WHERE user_id = ?"
." AND mailbox = ?"
." AND uid = ?",
$flags, $msg, $this->userid, $mailbox, (int) $message->uid);
- if ($this->db->affected_rows($res)) {
+ if ($this->db->affected_rows()) {
return;
}
}
- $this->db->set_option('ignore_key_errors', true);
-
// insert new record
- $res = $this->db->query(
+ $this->db->query(
"INSERT INTO ".$this->db->table_name('cache_messages')
- ." (user_id, mailbox, uid, flags, expires, data)"
- ." VALUES (?, ?, ?, ?, ". ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . ", ?)",
+ ." (user_id, mailbox, uid, flags, changed, data)"
+ ." VALUES (?, ?, ?, ?, ".$this->db->now().", ?)",
$this->userid, $mailbox, (int) $message->uid, $flags, $msg);
-
- // race-condition, insert failed so try update (#1489146)
- // 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 = ?",
- $flags, $msg, $this->userid, $mailbox, (int) $message->uid);
- }
-
- $this->db->set_option('ignore_key_errors', false);
}
@@ -517,7 +483,7 @@ class rcube_imap_cache
$this->db->query(
"UPDATE ".$this->db->table_name('cache_messages')
- ." SET expires = ". ($this->ttl ? $this->db->now($this->ttl) : 'NULL')
+ ." SET changed = ".$this->db->now()
.", flags = flags ".($enabled ? "+ $idx" : "- $idx")
." WHERE user_id = ?"
." AND mailbox = ?"
@@ -640,21 +606,23 @@ class rcube_imap_cache
/**
- * Delete expired cache entries
+ * Delete cache entries older than TTL
+ *
+ * @param string $ttl Lifetime of message cache entries
*/
- static function gc()
+ function expunge($ttl)
{
- $rcube = rcube::get_instance();
- $db = $rcube->get_dbh();
+ // get expiration timestamp
+ $ts = get_offset_time($ttl, -1);
- $db->query("DELETE FROM ".$db->table_name('cache_messages')
- ." WHERE expires < " . $db->now());
+ $this->db->query("DELETE FROM ".$this->db->table_name('cache_messages')
+ ." WHERE changed < " . $this->db->fromunixtime($ts));
- $db->query("DELETE FROM ".$db->table_name('cache_index')
- ." WHERE expires < " . $db->now());
+ $this->db->query("DELETE FROM ".$this->db->table_name('cache_index')
+ ." WHERE changed < " . $this->db->fromunixtime($ts));
- $db->query("DELETE FROM ".$db->table_name('cache_thread')
- ." WHERE expires < " . $db->now());
+ $this->db->query("DELETE FROM ".$this->db->table_name('cache_thread')
+ ." WHERE changed < " . $this->db->fromunixtime($ts));
}
@@ -746,38 +714,20 @@ class rcube_imap_cache
$data = implode('@', $data);
if ($exists) {
- $res = $this->db->query(
+ $sql_result = $this->db->query(
"UPDATE ".$this->db->table_name('cache_index')
- ." SET data = ?, valid = 1, expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL')
+ ." SET data = ?, valid = 1, changed = ".$this->db->now()
." WHERE user_id = ?"
." AND mailbox = ?",
$data, $this->userid, $mailbox);
-
- if ($this->db->affected_rows($res)) {
- return;
- }
}
-
- $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') .", ?)",
- $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 = ?",
- $data, $this->userid, $mailbox);
+ else {
+ $sql_result = $this->db->query(
+ "INSERT INTO ".$this->db->table_name('cache_index')
+ ." (user_id, mailbox, data, valid, changed)"
+ ." VALUES (?, ?, ?, 1, ".$this->db->now().")",
+ $this->userid, $mailbox, $data);
}
-
- $this->db->set_option('ignore_key_errors', false);
}
@@ -794,41 +744,21 @@ class rcube_imap_cache
);
$data = implode('@', $data);
- $expires = ($this->ttl ? $this->db->now($this->ttl) : 'NULL');
-
if ($exists) {
- $res = $this->db->query(
+ $sql_result = $this->db->query(
"UPDATE ".$this->db->table_name('cache_thread')
- ." SET data = ?, expires = $expires"
+ ." SET data = ?, changed = ".$this->db->now()
." WHERE user_id = ?"
." AND mailbox = ?",
$data, $this->userid, $mailbox);
-
- if ($this->db->affected_rows($res)) {
- return;
- }
}
-
- $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)"
- ." VALUES (?, ?, $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)) {
- $this->db->query(
- "UPDATE ".$this->db->table_name('cache_thread')
- ." SET expires = $expires, data = ?"
- ." WHERE user_id = ?"
- ." AND mailbox = ?",
- $data, $this->userid, $mailbox);
+ else {
+ $sql_result = $this->db->query(
+ "INSERT INTO ".$this->db->table_name('cache_thread')
+ ." (user_id, mailbox, data, changed)"
+ ." VALUES (?, ?, ?, ".$this->db->now().")",
+ $this->userid, $mailbox, $data);
}
-
- $this->db->set_option('ignore_key_errors', false);
}
@@ -1055,7 +985,7 @@ class rcube_imap_cache
$uids, true, array('FLAGS'), $index['modseq'], $qresync);
if (!empty($result)) {
- foreach ($result as $msg) {
+ foreach ($result as $id => $msg) {
$uid = $msg->uid;
// Remove deleted message
if ($this->skip_deleted && !empty($msg->flags['DELETED'])) {
@@ -1076,7 +1006,7 @@ class rcube_imap_cache
$this->db->query(
"UPDATE ".$this->db->table_name('cache_messages')
- ." SET flags = ?, expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL')
+ ." SET flags = ?, changed = ".$this->db->now()
." WHERE user_id = ?"
." AND mailbox = ?"
." AND uid = ?"
@@ -1104,18 +1034,17 @@ class rcube_imap_cache
}
}
+ // Invalidate thread index (?)
+ if (!$index['valid']) {
+ $this->remove_thread($mailbox);
+ }
+
$sort_field = $index['sort_field'];
$sort_order = $index['object']->get_parameters('ORDER');
$exists = true;
// Validate index
if (!$this->validate($mailbox, $index, $exists)) {
- // Invalidate (remove) thread index
- // if $exists=false it was already removed in validate()
- if ($exists) {
- $this->remove_thread($mailbox);
- }
-
// Update index
$data = $this->get_index_data($mailbox, $sort_field, $sort_order, $mbox_data);
}
@@ -1182,16 +1111,11 @@ class rcube_imap_cache
*
* @param rcube_message_header|rcube_message_part
*/
- private function message_object_prepare(&$msg, &$size = 0)
+ private function message_object_prepare(&$msg)
{
- // Remove body too big
- if ($msg->body && ($length = strlen($msg->body))) {
- $size += $length;
-
- if ($size > $this->threshold * 1024) {
- $size -= $length;
- unset($msg->body);
- }
+ // Remove body too big (>25kB)
+ if ($msg->body && strlen($msg->body) > 25 * 1024) {
+ unset($msg->body);
}
// Fix mimetype which might be broken by some code when message is displayed
@@ -1205,13 +1129,13 @@ class rcube_imap_cache
if (is_array($msg->structure->parts)) {
foreach ($msg->structure->parts as $part) {
- $this->message_object_prepare($part, $size);
+ $this->message_object_prepare($part);
}
}
if (is_array($msg->parts)) {
foreach ($msg->parts as $part) {
- $this->message_object_prepare($part, $size);
+ $this->message_object_prepare($part);
}
}
}
@@ -1236,25 +1160,6 @@ class rcube_imap_cache
return $index;
}
-
-
- /**
- * Fetches thread data from IMAP server
- */
- private function get_thread_data($mailbox, $mbox_data = array())
- {
- if (empty($mbox_data)) {
- $mbox_data = $this->imap->folder_data($mailbox);
- }
-
- if ($mbox_data['EXISTS']) {
- // get all threads (default sort order)
- return $this->imap->threads_direct($mailbox);
- }
-
- return new rcube_result_thread($mailbox, '* THREAD');
- }
-
}
// for backward compat.