From f0398c87d9bd472d23b6dfce6943d97fbf9fabf5 Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Thu, 13 Jun 2013 08:16:00 -0400
Subject: [PATCH] Use rcube_cache class to store attachments in database. Add options to configure TTL and cache type.

---
 plugins/database_attachments/config.inc.php.dist      |   12 ++++
 plugins/database_attachments/package.xml              |    6 +-
 plugins/database_attachments/database_attachments.php |  116 ++++++++++++++++++--------------------
 3 files changed, 70 insertions(+), 64 deletions(-)

diff --git a/plugins/database_attachments/config.inc.php.dist b/plugins/database_attachments/config.inc.php.dist
new file mode 100644
index 0000000..b23a9a1
--- /dev/null
+++ b/plugins/database_attachments/config.inc.php.dist
@@ -0,0 +1,12 @@
+<?php
+
+// By default this plugin stores attachments in filesystem
+// and copies them into sql database.
+// You can change it to use 'memcache' or 'apc'.
+$rcmail_config['database_attachments_cache'] = 'db';
+
+// Attachment data expires after specied TTL time in seconds (max.2592000).
+// Default is 12 hours.
+$rcmail_config['database_attachments_cache_ttl'] = 12 * 60 * 60;
+
+?>
diff --git a/plugins/database_attachments/database_attachments.php b/plugins/database_attachments/database_attachments.php
index 2511dbb..47e2b52 100644
--- a/plugins/database_attachments/database_attachments.php
+++ b/plugins/database_attachments/database_attachments.php
@@ -1,6 +1,6 @@
 <?php
 /**
- * Filesystem Attachments
+ * Database Attachments
  *
  * This plugin which provides database backed storage for temporary
  * attachment file handling.  The primary advantage of this plugin
@@ -16,18 +16,11 @@
 require_once('plugins/filesystem_attachments/filesystem_attachments.php');
 class database_attachments extends filesystem_attachments
 {
+    // Cache object
+    protected $cache;
 
     // A prefix for the cache key used in the session and in the key field of the cache table
-    private $cache_prefix = "db_attach";
-
-    /**
-     * Helper method to generate a unique key for the given attachment file
-     */
-    private function _key($args)
-    {
-        $uname = $args['path'] ? $args['path'] : $args['name'];
-        return  $this->cache_prefix . $args['group'] . md5(mktime() . $uname . $_SESSION['user_id']);
-    }
+    protected $prefix = "db_attach";
 
     /**
      * Save a newly uploaded attachment
@@ -35,23 +28,17 @@
     function upload($args)
     {
         $args['status'] = false;
-        $rcmail = rcmail::get_instance();
-        $key = $this->_key($args);
 
-        $data = file_get_contents($args['path']);
+        $cache = $this->get_cache();
+        $key   = $this->_key($args);
+        $data  = file_get_contents($args['path']);
 
-        if ($data === false)
+        if ($data === false) {
             return $args;
+        }
 
-        $data = base64_encode($data);
-
-        $status = $rcmail->db->query(
-            "INSERT INTO ".$rcmail->db->table_name('cache')
-             ." (created, user_id, cache_key, data)"
-             ." VALUES (".$rcmail->db->now().", ?, ?, ?)",
-            $_SESSION['user_id'],
-            $key,
-            $data);
+        $data   = base64_encode($data);
+        $status = $cache->write($key, $data);
 
         if ($status) {
             $args['id'] = $key;
@@ -68,26 +55,20 @@
     function save($args)
     {
         $args['status'] = false;
-        $rcmail = rcmail::get_instance();
 
-        $key = $this->_key($args);
+        $cache = $this->get_cache();
+        $key   = $this->_key($args);
 
         if ($args['path']) {
             $args['data'] = file_get_contents($args['path']);
 
-            if ($args['data'] === false)
+            if ($args['data'] === false) {
                 return $args;
+            }
         }
 
-        $data = base64_encode($args['data']);
-
-        $status = $rcmail->db->query(
-            "INSERT INTO ".$rcmail->db->table_name('cache')
-             ." (created, user_id, cache_key, data)"
-             ." VALUES (".$rcmail->db->now().", ?, ?, ?)",
-            $_SESSION['user_id'],
-            $key,
-            $data);
+        $data   = base64_encode($args['data']);
+        $status = $cache->write($key, $data);
 
         if ($status) {
             $args['id'] = $key;
@@ -104,13 +85,9 @@
     function remove($args)
     {
         $args['status'] = false;
-        $rcmail = rcmail::get_instance();
-        $status = $rcmail->db->query(
-            "DELETE FROM ".$rcmail->db->table_name('cache')
-             ." WHERE user_id = ?"
-                ." AND cache_key = ?",
-            $_SESSION['user_id'],
-            $args['id']);
+
+        $cache  = $this->get_cache();
+        $status = $cache->remove($args['id']);
 
         if ($status) {
             $args['status'] = true;
@@ -135,18 +112,11 @@
      */
     function get($args)
     {
-        $rcmail = rcmail::get_instance();
+        $cache = $this->get_cache();
+        $data  = $cache->read($args['id']);
 
-        $sql_result = $rcmail->db->query(
-            "SELECT data"
-             ." FROM ".$rcmail->db->table_name('cache')
-             ." WHERE user_id=?"
-                ." AND cache_key=?",
-            $_SESSION['user_id'],
-            $args['id']);
-
-        if ($sql_arr = $rcmail->db->fetch_assoc($sql_result)) {
-            $args['data'] = base64_decode($sql_arr['data']);
+        if ($data) {
+            $args['data'] = base64_decode($data);
             $args['status'] = true;
         }
 
@@ -158,12 +128,36 @@
      */
     function cleanup($args)
     {
-        $prefix = $this->cache_prefix . $args['group'];
-        $rcmail = rcmail::get_instance();
-        $rcmail->db->query(
-            "DELETE FROM ".$rcmail->db->table_name('cache')
-            ." WHERE user_id = ?"
-                ." AND cache_key LIKE '{$prefix}%'",
-            $_SESSION['user_id']);
+        $cache = $this->get_cache();
+        $cache->remove($args['group'], true);
+    }
+
+    /**
+     * Helper method to generate a unique key for the given attachment file
+     */
+    protected function _key($args)
+    {
+        $uname = $args['path'] ? $args['path'] : $args['name'];
+        return $args['group'] . md5(mktime() . $uname . $_SESSION['user_id']);
+    }
+
+    /**
+     * Initialize and return cache object
+     */
+    protected function get_cache()
+    {
+        if (!$this->cache) {
+            $this->load_config();
+
+            $rcmail = rcube::get_instance();
+            $ttl    = 12 * 60 * 60; // default: 12 hours
+            $ttl    = $rcmail->config->get('database_attachments_cache_ttl', $ttl);
+            $type   = $rcmail->config->get('database_attachments_cache', 'db');
+
+            // Init SQL cache (disable cache data serialization)
+            $this->cache = $rcmail->get_cache($this->prefix, 'db', $ttl, false);
+        }
+
+        return $this->cache;
     }
 }
diff --git a/plugins/database_attachments/package.xml b/plugins/database_attachments/package.xml
index 40db858..44adc21 100644
--- a/plugins/database_attachments/package.xml
+++ b/plugins/database_attachments/package.xml
@@ -5,7 +5,7 @@
     http://pear.php.net/dtd/package-2.0.xsd">
 	<name>database_attachments</name>
 	<channel>pear.roundcube.net</channel>
-	<summary>SQL database storage for uploaded attachments</summary>
+	<summary>Database storage for uploaded attachments</summary>
 	<description>
 	    This plugin which provides database backed storage for temporary
         attachment file handling. The primary advantage of this plugin
@@ -24,9 +24,9 @@
 		<email>ziba@umich.edu</email>
 		<active>yes</active>
 	</developer>
-	<date>2011-11-21</date>
+	<date>2013-06-13</date>
 	<version>
-		<release>1.0</release>
+		<release>1.1</release>
 		<api>1.0</api>
 	</version>
 	<stability>

--
Gitblit v1.9.1