From c1bc8f6c827a27540b5510b42dcc65b39d38f2c1 Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Mon, 14 Oct 2013 07:19:37 -0400
Subject: [PATCH] Change so abort=true does not break the loop in exec_hook(), provide a new 'break' flag for this purpose

---
 program/lib/Roundcube/rcube_cache.php |   78 +++++++++++++++++++++++++++++----------
 1 files changed, 58 insertions(+), 20 deletions(-)

diff --git a/program/lib/Roundcube/rcube_cache.php b/program/lib/Roundcube/rcube_cache.php
index 92f12a8..a708cb2 100644
--- a/program/lib/Roundcube/rcube_cache.php
+++ b/program/lib/Roundcube/rcube_cache.php
@@ -38,6 +38,7 @@
     private $type;
     private $userid;
     private $prefix;
+    private $table;
     private $ttl;
     private $packed;
     private $index;
@@ -71,8 +72,9 @@
             $this->db   = function_exists('apc_exists'); // APC 3.1.4 required
         }
         else {
-            $this->type = 'db';
-            $this->db   = $rcube->get_dbh();
+            $this->type  = 'db';
+            $this->db    = $rcube->get_dbh();
+            $this->table = $this->db->table_name('cache');
         }
 
         // convert ttl string to seconds
@@ -145,7 +147,7 @@
      */
     function write($key, $data)
     {
-        return $this->write_record($key, $this->packed ? serialize($data) : $data);
+        return $this->write_record($key, $this->serialize($data));
     }
 
 
@@ -192,16 +194,27 @@
      */
     function expunge()
     {
-        if ($this->type == 'db' && $this->db) {
+        if ($this->type == 'db' && $this->db && $this->ttl) {
             $this->db->query(
-                "DELETE FROM ".$this->db->table_name('cache').
+                "DELETE FROM ".$this->table.
                 " WHERE user_id = ?".
                 " AND cache_key LIKE ?".
-                " AND " . $this->db->unixtimestamp('created')." < ?",
+                " AND expires < " . $this->db->now(),
                 $this->userid,
-                $this->prefix.'.%',
-                time() - $this->ttl);
+                $this->prefix.'.%');
         }
+    }
+
+
+    /**
+     * Remove expired records of all caches
+     */
+    static function gc()
+    {
+        $rcube = rcube::get_instance();
+        $db    = $rcube->get_dbh();
+
+        $db->query("DELETE FROM " . $db->table_name('cache') . " WHERE expires < " . $db->now());
     }
 
 
@@ -219,7 +232,7 @@
             if ($this->cache_changes[$key]) {
                 // Make sure we're not going to write unchanged data
                 // by comparing current md5 sum with the sum calculated on DB read
-                $data = $this->packed ? serialize($data) : $data;
+                $data = $this->serialize($data);
 
                 if (!$this->cache_sums[$key] || $this->cache_sums[$key] != md5($data)) {
                     $this->write_record($key, $data);
@@ -255,7 +268,7 @@
 
             if ($data) {
                 $md5sum = md5($data);
-                $data   = $this->packed ? unserialize($data) : $data;
+                $data   = $this->unserialize($data);
 
                 if ($nostore) {
                     return $data;
@@ -271,7 +284,7 @@
         else {
             $sql_result = $this->db->limitquery(
                 "SELECT data, cache_key".
-                " FROM ".$this->db->table_name('cache').
+                " FROM " . $this->table.
                 " WHERE user_id = ?".
                 " AND cache_key = ?".
                 // for better performance we allow more records for one key
@@ -283,7 +296,7 @@
                 $key = substr($sql_arr['cache_key'], strlen($this->prefix)+1);
                 $md5sum = $sql_arr['data'] ? md5($sql_arr['data']) : null;
                 if ($sql_arr['data']) {
-                    $data = $this->packed ? unserialize($sql_arr['data']) : $sql_arr['data'];
+                    $data = $this->unserialize($sql_arr['data']);
                 }
 
                 if ($nostore) {
@@ -326,7 +339,7 @@
         // Remove NULL rows (here we don't need to check if the record exist)
         if ($data == 'N;') {
             $this->db->query(
-                "DELETE FROM ".$this->db->table_name('cache').
+                "DELETE FROM " . $this->table.
                 " WHERE user_id = ?".
                 " AND cache_key = ?",
                 $this->userid, $key);
@@ -337,8 +350,10 @@
         // update existing cache record
         if ($key_exists) {
             $result = $this->db->query(
-                "UPDATE ".$this->db->table_name('cache').
-                " SET created = ". $this->db->now().", data = ?".
+                "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);
@@ -348,9 +363,9 @@
             // 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->db->table_name('cache').
-                " (created, user_id, cache_key, data)".
-                " VALUES (".$this->db->now().", ?, ?, ?)",
+                "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);
         }
 
@@ -364,7 +379,6 @@
      * @param string  $key         Cache key name or pattern
      * @param boolean $prefix_mode Enable it to clear all keys starting
      *                             with prefix specified in $key
-     *
      */
     private function remove_record($key=null, $prefix_mode=false)
     {
@@ -412,7 +426,7 @@
         }
 
         $this->db->query(
-            "DELETE FROM ".$this->db->table_name('cache').
+            "DELETE FROM " . $this->table.
             " WHERE user_id = ?" . $where,
             $this->userid);
     }
@@ -553,4 +567,28 @@
         // This way each cache will have its own index
         return sprintf('%d:%s%s', $this->userid, $this->prefix, 'INDEX');
     }
+
+    /**
+     * Serializes data for storing
+     */
+    private function serialize($data)
+    {
+        if ($this->type == 'db') {
+            return $this->db->encode($data, $this->packed);
+        }
+
+        return $this->packed ? serialize($data) : $data;
+    }
+
+    /**
+     * Unserializes serialized data
+     */
+    private function unserialize($data)
+    {
+        if ($this->type == 'db') {
+            return $this->db->decode($data, $this->packed);
+        }
+
+        return $this->packed ? @unserialize($data) : $data;
+    }
 }

--
Gitblit v1.9.1