Mercurial > hg > rc2
comparison plugins/filesystem_attachments/filesystem_attachments.php @ 8:bf99236cc5cd
try to recover from upgrade fail
author | Charlie Root |
---|---|
date | Sat, 29 Dec 2018 07:07:34 -0500 |
parents | 4681f974d28b |
children |
comparison
equal
deleted
inserted
replaced
7:65fd7d441cf1 | 8:bf99236cc5cd |
---|---|
5 * This is a core plugin which provides basic, filesystem based | 5 * This is a core plugin which provides basic, filesystem based |
6 * attachment temporary file handling. This includes storing | 6 * attachment temporary file handling. This includes storing |
7 * attachments of messages currently being composed, writing attachments | 7 * attachments of messages currently being composed, writing attachments |
8 * to disk when drafts with attachments are re-opened and writing | 8 * to disk when drafts with attachments are re-opened and writing |
9 * attachments to disk for inline display in current html compositions. | 9 * attachments to disk for inline display in current html compositions. |
10 * It also handles uploaded files for other uses, so not only attachments. | |
10 * | 11 * |
11 * Developers may wish to extend this class when creating attachment | 12 * Developers may wish to extend this class when creating attachment |
12 * handler plugins: | 13 * handler plugins: |
13 * require_once('plugins/filesystem_attachments/filesystem_attachments.php'); | 14 * require_once('plugins/filesystem_attachments/filesystem_attachments.php'); |
14 * class myCustom_attachments extends filesystem_attachments | 15 * class myCustom_attachments extends filesystem_attachments |
16 * | |
17 * Note for developers: It is plugin's responsibility to care about security. | |
18 * So, e.g. if the plugin is asked about some file path it should check | |
19 * if it's really the storage path of the plugin and not e.g. /etc/passwd. | |
20 * It is done by setting 'status' flag on every plugin hook it uses. | |
21 * Roundcube core will trust the returned path if status=true. | |
15 * | 22 * |
16 * @license GNU GPLv3+ | 23 * @license GNU GPLv3+ |
17 * @author Ziba Scott <ziba@umich.edu> | 24 * @author Ziba Scott <ziba@umich.edu> |
18 * @author Thomas Bruederli <roundcube@gmail.com> | 25 * @author Thomas Bruederli <roundcube@gmail.com> |
19 */ | 26 */ |
48 */ | 55 */ |
49 function upload($args) | 56 function upload($args) |
50 { | 57 { |
51 $args['status'] = false; | 58 $args['status'] = false; |
52 $group = $args['group']; | 59 $group = $args['group']; |
53 $rcmail = rcmail::get_instance(); | 60 $rcmail = rcube::get_instance(); |
54 | 61 |
55 // use common temp dir for file uploads | 62 // use common temp dir for file uploads |
56 $temp_dir = $rcmail->config->get('temp_dir'); | 63 $temp_dir = $rcmail->config->get('temp_dir'); |
57 $tmpfname = tempnam($temp_dir, 'rcmAttmnt'); | 64 $tmpfname = tempnam($temp_dir, 'rcmAttmnt'); |
58 | 65 |
76 { | 83 { |
77 $group = $args['group']; | 84 $group = $args['group']; |
78 $args['status'] = false; | 85 $args['status'] = false; |
79 | 86 |
80 if (!$args['path']) { | 87 if (!$args['path']) { |
81 $rcmail = rcmail::get_instance(); | 88 $rcmail = rcube::get_instance(); |
82 $temp_dir = $rcmail->config->get('temp_dir'); | 89 $temp_dir = $rcmail->config->get('temp_dir'); |
83 $tmp_path = tempnam($temp_dir, 'rcmAttmnt'); | 90 $tmp_path = tempnam($temp_dir, 'rcmAttmnt'); |
84 | 91 |
85 if ($fp = fopen($tmp_path, 'w')) { | 92 if ($fp = fopen($tmp_path, 'w')) { |
86 fwrite($fp, $args['data']); | 93 fwrite($fp, $args['data']); |
105 * Remove an attachment from storage | 112 * Remove an attachment from storage |
106 * This is triggered by the remove attachment button on the compose screen | 113 * This is triggered by the remove attachment button on the compose screen |
107 */ | 114 */ |
108 function remove($args) | 115 function remove($args) |
109 { | 116 { |
110 $args['status'] = @unlink($args['path']); | 117 $args['status'] = $this->verify_path($args['path']) && @unlink($args['path']); |
111 return $args; | 118 return $args; |
112 } | 119 } |
113 | 120 |
114 /** | 121 /** |
115 * When composing an html message, image attachments may be shown | 122 * When composing an html message, image attachments may be shown |
116 * For this plugin, the file is already in place, just check for | 123 * For this plugin, the file is already in place, just check for |
117 * the existance of the proper metadata | 124 * the existence of the proper metadata |
118 */ | 125 */ |
119 function display($args) | 126 function display($args) |
120 { | 127 { |
121 $args['status'] = file_exists($args['path']); | 128 $args['status'] = $this->verify_path($args['path']) && file_exists($args['path']); |
122 return $args; | 129 return $args; |
123 } | 130 } |
124 | 131 |
125 /** | 132 /** |
126 * This attachment plugin doesn't require any steps to put the file | 133 * This attachment plugin doesn't require any steps to put the file |
127 * on disk for use. This stub function is kept here to make this | 134 * on disk for use. This stub function is kept here to make this |
128 * class handy as a parent class for other plugins which may need it. | 135 * class handy as a parent class for other plugins which may need it. |
129 */ | 136 */ |
130 function get($args) | 137 function get($args) |
131 { | 138 { |
139 if (!$this->verify_path($args['path'])) { | |
140 $args['path'] = null; | |
141 } | |
142 | |
132 return $args; | 143 return $args; |
133 } | 144 } |
134 | 145 |
135 /** | 146 /** |
136 * Delete all temp files associated with this user | 147 * Delete all temp files associated with this user |
145 if ($args['group'] && $args['group'] != $group) { | 156 if ($args['group'] && $args['group'] != $group) { |
146 continue; | 157 continue; |
147 } | 158 } |
148 | 159 |
149 foreach ((array)$files as $filename) { | 160 foreach ((array)$files as $filename) { |
150 if(file_exists($filename)) { | 161 if (file_exists($filename)) { |
151 unlink($filename); | 162 unlink($filename); |
152 } | 163 } |
153 } | 164 } |
154 | 165 |
155 unset($_SESSION['plugins']['filesystem_attachments'][$group]); | 166 unset($_SESSION['plugins']['filesystem_attachments'][$group]); |
158 return $args; | 169 return $args; |
159 } | 170 } |
160 | 171 |
161 function file_id() | 172 function file_id() |
162 { | 173 { |
163 $userid = rcmail::get_instance()->user->ID; | 174 $userid = rcube::get_instance()->user->ID; |
164 list($usec, $sec) = explode(' ', microtime()); | 175 list($usec, $sec) = explode(' ', microtime()); |
165 $id = preg_replace('/[^0-9]/', '', $userid . $sec . $usec); | 176 $id = preg_replace('/[^0-9]/', '', $userid . $sec . $usec); |
166 | 177 |
167 // make sure the ID is really unique (#1489546) | 178 // make sure the ID is really unique (#1489546) |
168 while ($this->find_file_by_id($id)) { | 179 while ($this->find_file_by_id($id)) { |
180 if (isset($files[$id])) { | 191 if (isset($files[$id])) { |
181 return true; | 192 return true; |
182 } | 193 } |
183 } | 194 } |
184 } | 195 } |
196 | |
197 /** | |
198 * For security we'll always verify the file path stored in session, | |
199 * as session entries can be faked in various ways e.g. #6026. | |
200 * We allow only files in Roundcube temp dir | |
201 */ | |
202 protected function verify_path($path) | |
203 { | |
204 if (empty($path)) { | |
205 return false; | |
206 } | |
207 | |
208 $rcmail = rcube::get_instance(); | |
209 $temp_dir = $rcmail->config->get('temp_dir'); | |
210 $file_path = pathinfo($path, PATHINFO_DIRNAME); | |
211 | |
212 if ($temp_dir !== $file_path) { | |
213 rcube::raise_error(array( | |
214 'code' => 403, | |
215 'file' => __FILE__, | |
216 'line' => __LINE__, | |
217 'message' => sprintf("%s can't read %s (not in temp_dir)", | |
218 $rcmail->get_user_name(), substr($path, 0, 512)) | |
219 ), true, false); | |
220 | |
221 return false; | |
222 } | |
223 | |
224 return true; | |
225 } | |
185 } | 226 } |