source: subversion/branches/devel-api/plugins/database_attachments/database_attachments.php @ 2336

Last change on this file since 2336 was 2336, checked in by ziba, 4 years ago

Added an array of required plugins rcube_plugin_api.php. It's got room to grow.
New core plugin: filesystem_attachments - the existing disk based attachment handling now in plugin form (with one garbage collection bug fix)
New plugin: database_attachments - multi-server safe, database backed attachment temp file handling
New plugin hooks: remove_attachment, display_attachment, upload_attachment, save_attachment, cleanup_attachments, get_attachment

File size: 5.5 KB
Line 
1<?php
2/**
3 * Filesystem Attachments
4 *
5 * This plugin which provides database backed storage for temporary
6 * attachment file handling.  The primary advantage of this plugin
7 * is its compatibility with round-robin dns multi-server roundcube
8 * installations.
9 *
10 * This plugin relies on the core filesystem_attachments plugin
11 *
12 * @author Ziba Scott <ziba@umich.edu>
13 *
14 */
15require_once('plugins/filesystem_attachments/filesystem_attachments.php');
16class database_attachments extends filesystem_attachments
17{
18
19    // A prefix for the cache key used in the session and in the key field of the cache table
20    private $cache_prefix = "db_attach";
21
22
23    function _key($filepath){
24        return  $this->cache_prefix.md5(mktime().$filepath.$_SESSION['user_id']); 
25    }
26
27    // Save a newly uploaded attachment
28    function upload($args){
29        $args['status'] = TRUE;
30        $rcmail = rcmail::get_instance();
31        $key = $this->_key($args['filepath']);
32        $data = base64_encode(file_get_contents($args['filepath'])); 
33
34        $status = $rcmail->db->query(
35            "INSERT INTO ".get_table_name('cache')."
36            (created, user_id, cache_key, data)
37            VALUES (".$rcmail->db->now().", ?, ?, ?)",         
38            $_SESSION['user_id'],
39            $key,
40            $data);   
41        if($status){
42            $args['id'] = $key;
43            $_SESSION['compose']['attachments'][$key] = array(
44                'name' => $_FILES['_attachments']['name'][$args['index']],
45                'mimetype' => rc_mime_content_type($args['filepath'], $_FILES['_attachments']['type'][0]),
46                'path' => "stored in database",
47            );
48        } else {
49            $args['status'] = FALSE;
50        }
51        return $args;
52    }
53
54    // Save an attachment from a non-upload source (draft or forward)
55    function save($args){
56        $args['status'] = TRUE;
57        $rcmail = rcmail::get_instance();
58
59        $key = $this->_key($args['filename']);
60        $data = base64_encode($args['attachment']); 
61
62        $status = $rcmail->db->query(
63            "INSERT INTO ".get_table_name('cache')."
64            (created, user_id, cache_key, data)
65            VALUES (".$rcmail->db->now().", ?, ?, ?)",         
66            $_SESSION['user_id'],
67            $key,
68            $data);   
69        $args['id'] = $key;
70        if (!$status)
71        {
72            $args['status'] = FALSE;
73        }
74
75        return $args;
76    }
77
78    // Remove an attachment from storage
79    // This is triggered by the remove attachment button on the compose screen
80    function remove($args){
81        $args['status'] = TRUE;
82        $rcmail = rcmail::get_instance();
83        $status = $rcmail->db->query(
84            "DELETE FROM ".get_table_name('cache')."
85            WHERE  user_id=?
86            AND    cache_key=?",
87            $_SESSION['user_id'],
88            $args['id']);
89   
90        if(!$status){
91            $args['status'] = false;
92        }
93        return $args;
94    }
95
96    // When composing an html message, image attachments may be shown
97    // For this plugin, $this->get_attachment will check the file and
98    // place it on disk
99    function display($args){
100        return $this->get_attachment($args);
101    }
102
103    // When displaying or sending the attachment the file must be temporarily
104    // copied to disk.  This function is also called by the display_attachment hook.
105    function get_attachment($args){
106        $args['status'] = TRUE;
107        $args['erase_after_send'] = TRUE;
108        $rcmail = rcmail::get_instance();
109        if (!is_array($_SESSION['compose']['attachments'][$args['id']])){
110            $args['status'] = FALSE;
111        }
112        else{
113          $sql_result = $rcmail->db->query(
114            "SELECT cache_id, data
115             FROM ".get_table_name('cache')."
116             WHERE  user_id=?
117             AND    cache_key=?",
118            $_SESSION['user_id'],
119            $args['id']);
120
121          if ($sql_arr = $rcmail->db->fetch_assoc($sql_result)) {
122              $cache_data = base64_decode($sql_arr['data']);
123              $temp_dir = unslashify($rcmail->config->get('temp_dir'));
124              $tmp_path = tempnam($temp_dir, 'rcmAttmnt');
125              file_put_contents($tmp_path, $cache_data);
126              $_SESSION['compose']['attachments'][$args['id']]['path'] = $tmp_path;
127              $_SESSION['plugins']['database_attachments']['tmp_files'][] = $tmp_path;
128              $args['attachment']['path'] = $tmp_path;
129          } else {
130            $args['status'] = FALSE;
131          }
132
133        }
134        return $args;
135    }
136    // Delete all temp files associated with this user
137    function cleanup($args){
138        $rcmail = rcmail::get_instance();
139        $rcmail->db->query(
140            "DELETE FROM ".get_table_name('cache')."
141            WHERE  user_id=?
142            AND cache_key like '{$this->cache_prefix}%'",
143                $_SESSION['user_id']);
144
145        // When sending, attachments are copied to disk and should now be cleaned up
146        // Note that the cleanup must happen during the same php script execution
147        // as the send so that we can be sure it's the same machine in load ballanced
148        // environments.
149        if (is_array($_SESSION['plugins']['database_attachments']['tmp_files'])){
150            foreach ($_SESSION['plugins']['database_attachments']['tmp_files'] as $i=>$filename){
151                if(file_exists($filename)){
152                    unlink($filename);
153                }
154                unset($_SESSION['plugins']['database_attachments']['tmp_files']);
155            }
156        }
157        return $args;
158    }
159}
Note: See TracBrowser for help on using the repository browser.