Aleksander Machniak
2015-11-22 9f1f754daf4b57a0d0d3aea95d2321716d218cf5
commit | author | age
48e9c1 1 <?php
b0349c 2
48e9c1 3 /**
f0398c 4  * Database Attachments
48e9c1 5  *
T 6  * This plugin which provides database backed storage for temporary
b0349c 7  * attachment file handling. The primary advantage of this plugin
48e9c1 8  * is its compatibility with round-robin dns multi-server roundcube
T 9  * installations.
10  *
11  * This plugin relies on the core filesystem_attachments plugin
12  *
13  * @author Ziba Scott <ziba@umich.edu>
14  * @author Aleksander Machniak <alec@alec.pl>
15  * @version @package_version@
b0349c 16  *
AM 17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License version 2
19  * as published by the Free Software Foundation.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License along
27  * with this program; if not, write to the Free Software Foundation, Inc.,
28  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
48e9c1 29  */
2feba7 30
37e9bd 31 if (class_exists('filesystem_attachments', false) && !defined('TESTS_DIR')) {
b0349c 32     die("Configuration issue. There can be only one enabled plugin for attachments handling");
AM 33 }
34
2feba7 35 require_once INSTALL_PATH . 'plugins/filesystem_attachments/filesystem_attachments.php';
AM 36
48e9c1 37 class database_attachments extends filesystem_attachments
T 38 {
f0398c 39     // Cache object
AM 40     protected $cache;
48e9c1 41
T 42     // A prefix for the cache key used in the session and in the key field of the cache table
e9ca5e 43     const PREFIX = "ATTACH";
48e9c1 44
T 45     /**
46      * Save a newly uploaded attachment
47      */
48     function upload($args)
49     {
50         $args['status'] = false;
51
f0398c 52         $cache = $this->get_cache();
AM 53         $key   = $this->_key($args);
54         $data  = file_get_contents($args['path']);
48e9c1 55
f0398c 56         if ($data === false) {
48e9c1 57             return $args;
f0398c 58         }
48e9c1 59
f0398c 60         $data   = base64_encode($data);
AM 61         $status = $cache->write($key, $data);
48e9c1 62
T 63         if ($status) {
b3bf9c 64             $args['id']     = $key;
48e9c1 65             $args['status'] = true;
b3bf9c 66             $args['path']   = null;
48e9c1 67         }
T 68
69         return $args;
70     }
71
72     /**
73      * Save an attachment from a non-upload source (draft or forward)
74      */
75     function save($args)
76     {
77         $args['status'] = false;
78
f0398c 79         $cache = $this->get_cache();
AM 80         $key   = $this->_key($args);
48e9c1 81
T 82         if ($args['path']) {
83             $args['data'] = file_get_contents($args['path']);
84
f0398c 85             if ($args['data'] === false) {
48e9c1 86                 return $args;
f0398c 87             }
48e9c1 88         }
T 89
f0398c 90         $data   = base64_encode($args['data']);
AM 91         $status = $cache->write($key, $data);
48e9c1 92
T 93         if ($status) {
94             $args['id'] = $key;
95             $args['status'] = true;
96         }
97
98         return $args;
99     }
100
101     /**
102      * Remove an attachment from storage
103      * This is triggered by the remove attachment button on the compose screen
104      */
105     function remove($args)
106     {
f0398c 107         $cache  = $this->get_cache();
AM 108         $status = $cache->remove($args['id']);
48e9c1 109
5d0cb0 110         $args['status'] = true;
48e9c1 111
T 112         return $args;
113     }
114
115     /**
116      * When composing an html message, image attachments may be shown
117      * For this plugin, $this->get() will check the file and
118      * return it's contents
119      */
120     function display($args)
121     {
122         return $this->get($args);
123     }
124
125     /**
126      * When displaying or sending the attachment the file contents are fetched
127      * using this method. This is also called by the attachment_display hook.
128      */
129     function get($args)
130     {
f0398c 131         $cache = $this->get_cache();
AM 132         $data  = $cache->read($args['id']);
48e9c1 133
f0398c 134         if ($data) {
AM 135             $args['data'] = base64_decode($data);
48e9c1 136             $args['status'] = true;
T 137         }
138
139         return $args;
140     }
141
142     /**
143      * Delete all temp files associated with this user
144      */
145     function cleanup($args)
146     {
e435d3 147         // check if cache object exist, it may be empty on session_destroy (#1489726)
AM 148         if ($cache = $this->get_cache()) {
149             $cache->remove($args['group'], true);
150         }
f0398c 151     }
AM 152
153     /**
154      * Helper method to generate a unique key for the given attachment file
155      */
156     protected function _key($args)
157     {
9f1f75 158         $uname = $args['path'] ?: $args['name'];
0389fa 159         return $args['group'] . md5(time() . $uname . $_SESSION['user_id']);
f0398c 160     }
AM 161
162     /**
163      * Initialize and return cache object
164      */
165     protected function get_cache()
166     {
167         if (!$this->cache) {
168             $this->load_config();
169
170             $rcmail = rcube::get_instance();
171             $ttl    = 12 * 60 * 60; // default: 12 hours
172             $ttl    = $rcmail->config->get('database_attachments_cache_ttl', $ttl);
173             $type   = $rcmail->config->get('database_attachments_cache', 'db');
e9ca5e 174             $prefix = self::PREFIX;
AM 175
176             // Add session identifier to the prefix to prevent from removing attachments
177             // in other sessions of the same user (#1490542)
178             if ($id = session_id()) {
179                 $prefix .= $id;
180             }
f0398c 181
AM 182             // Init SQL cache (disable cache data serialization)
e9ca5e 183             $this->cache = $rcmail->get_cache($prefix, $type, $ttl, false);
f0398c 184         }
AM 185
186         return $this->cache;
48e9c1 187     }
T 188 }