diff options
| author | thomasb <thomasb@208e9e7b-5314-0410-a742-e7e81cd9613c> | 2011-05-09 17:36:03 +0000 |
|---|---|---|
| committer | thomasb <thomasb@208e9e7b-5314-0410-a742-e7e81cd9613c> | 2011-05-09 17:36:03 +0000 |
| commit | f5b83d7458407c822830dc2e75be8bd78e61893e (patch) | |
| tree | ad25dbed49974918525939e0aa8afcf975443caf /plugins | |
| parent | d3897d8ff8a6cc3c3c79f468efda9e2177139635 (diff) | |
New attachment driver with redundant storage for HA environments
git-svn-id: https://svn.roundcube.net/trunk@4745 208e9e7b-5314-0410-a742-e7e81cd9613c
Diffstat (limited to 'plugins')
| -rw-r--r-- | plugins/redundant_attachments/redundant_attachments.php | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/plugins/redundant_attachments/redundant_attachments.php b/plugins/redundant_attachments/redundant_attachments.php new file mode 100644 index 000000000..70976b43c --- /dev/null +++ b/plugins/redundant_attachments/redundant_attachments.php @@ -0,0 +1,169 @@ +<?php +/** + * Redundant attachments + * + * This plugin provides a redundant storage for temporary uploaded + * attachment files. They are stored in both the database backed + * as well as on the local file system. + * + * This plugin relies on the core filesystem_attachments plugin + * and combines it with the functionality of the database_attachments plugin. + * + * @author Thomas Bruederli <roundcube@gmail.com> + * + */ +require_once('plugins/filesystem_attachments/filesystem_attachments.php'); + +class redundant_attachments extends filesystem_attachments +{ + // A prefix for the cache key used in the session and in the key field of the cache table + private $cache_prefix = "ATTACH."; + + /** + * Default constructor + */ + function init() + { + parent::init(); + + $this->db = rcmail::get_instance()->get_dbh(); + } + + /** + * 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']); + } + + /** + * Save a newly uploaded attachment + */ + function upload($args) + { + $args = parent::upload($args); + + $key = $this->_key($args); + $data = base64_encode(file_get_contents($args['path'])); + + $status = $this->db->query( + "INSERT INTO ".get_table_name('cache')." + (created, user_id, cache_key, data) + VALUES (".$this->db->now().", ?, ?, ?)", + $_SESSION['user_id'], + $key, + $data); + + if ($status) { + $args['id'] = $key; + $args['status'] = true; + unset($args['path']); + } + + return $args; + } + + /** + * Save an attachment from a non-upload source (draft or forward) + */ + function save($args) + { + $args = parent::save($args); + + if ($args['path']) + $args['data'] = file_get_contents($args['path']); + + $data = base64_encode($args['data']); + $key = $this->_key($args); + + $status = $this->db->query( + "INSERT INTO ".get_table_name('cache')." + (created, user_id, cache_key, data) + VALUES (".$this->db->now().", ?, ?, ?)", + $_SESSION['user_id'], + $key, + $data); + + if ($status) { + $args['id'] = $key; + $args['status'] = true; + } + + return $args; + } + + /** + * Remove an attachment from storage + * This is triggered by the remove attachment button on the compose screen + */ + function remove($args) + { + $args['status'] = false; + $status = $this->db->query( + "DELETE FROM ".get_table_name('cache')." + WHERE user_id=? + AND cache_key=?", + $_SESSION['user_id'], + $args['id']); + + if ($status) + $args['status'] = true; + + return parent::remove($args); + } + + /** + * When composing an html message, image attachments may be shown + * For this plugin, $this->get() will check the file and + * return it's contents + */ + function display($args) + { + return $this->get($args); + } + + /** + * When displaying or sending the attachment the file contents are fetched + * using this method. This is also called by the attachment_display hook. + */ + function get($args) + { + // attempt to get file from local file system + $args = parent::get($args); + if ($args['path'] && ($args['status'] = file_exists($args['path']))) + return $args; + + // fetch from database if not found on FS + $sql_result = $this->db->query( + "SELECT cache_id, data + FROM ".get_table_name('cache')." + WHERE user_id=? + AND cache_key=?", + $_SESSION['user_id'], + $args['id']); + + if ($sql_arr = $this->db->fetch_assoc($sql_result)) { + $args['data'] = base64_decode($sql_arr['data']); + $args['status'] = true; + } + + return $args; + } + + /** + * Delete all temp files associated with this user + */ + function cleanup($args) + { + $prefix = $this->cache_prefix . $args['group']; + $this->db->query( + "DELETE FROM ".get_table_name('cache')." + WHERE user_id=? + AND cache_key like '{$prefix}%'", + $_SESSION['user_id']); + + parent::cleanup($args); + } +} |
