commit | author | age
|
4e17e6
|
1 |
<?php |
T |
2 |
|
a95874
|
3 |
/** |
4e17e6
|
4 |
+-----------------------------------------------------------------------+ |
T |
5 |
| program/steps/mail/get.inc | |
|
6 |
| | |
e019f2
|
7 |
| This file is part of the Roundcube Webmail client | |
c97625
|
8 |
| Copyright (C) 2005-2013, The Roundcube Dev Team | |
7fe381
|
9 |
| | |
T |
10 |
| Licensed under the GNU General Public License version 3 or | |
|
11 |
| any later version with exceptions for skins & plugins. | |
|
12 |
| See the README file for a full license statement. | |
4e17e6
|
13 |
| | |
T |
14 |
| PURPOSE: | |
|
15 |
| Delivering a specific part of a mail message | |
|
16 |
| | |
|
17 |
+-----------------------------------------------------------------------+ |
|
18 |
| Author: Thomas Bruederli <roundcube@gmail.com> | |
|
19 |
+-----------------------------------------------------------------------+ |
|
20 |
*/ |
|
21 |
|
|
22 |
|
|
23 |
// show loading page |
8fa58e
|
24 |
if (!empty($_GET['_preload'])) { |
b1d13e
|
25 |
$_get = $_GET + array('_mimewarning' => 1, '_embed' => 1); |
TB |
26 |
unset($_get['_preload']); |
|
27 |
$url = $RCMAIL->url($_get); |
c97625
|
28 |
$message = $RCMAIL->gettext('loadingdata'); |
4e17e6
|
29 |
|
c97625
|
30 |
header('Content-Type: text/html; charset=' . RCUBE_CHARSET); |
AM |
31 |
print "<html>\n<head>\n" |
6b2b2e
|
32 |
. '<meta http-equiv="refresh" content="0; url='.rcube::Q($url).'">' . "\n" |
AM |
33 |
. '<meta http-equiv="content-type" content="text/html; charset='.RCUBE_CHARSET.'">' . "\n" |
3e8b11
|
34 |
. "</head>\n<body>\n$message\n</body>\n</html>"; |
c97625
|
35 |
exit; |
8fa58e
|
36 |
} |
4e17e6
|
37 |
|
d51c93
|
38 |
ob_end_clean(); |
4e17e6
|
39 |
|
T |
40 |
// similar code as in program/steps/mail/show.inc |
8fa58e
|
41 |
if (!empty($_GET['_uid'])) { |
c97625
|
42 |
$uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_GET); |
AM |
43 |
$RCMAIL->config->set('prefer_html', true); |
63e793
|
44 |
$MESSAGE = new rcube_message($uid, null, intval($_GET['_safe'])); |
8fa58e
|
45 |
} |
4bfe4e
|
46 |
|
AM |
47 |
// check connection status |
|
48 |
check_storage_status(); |
4e17e6
|
49 |
|
6b2b2e
|
50 |
$part_id = rcube_utils::get_input_value('_part', rcube_utils::INPUT_GPC); |
eaf383
|
51 |
|
4e17e6
|
52 |
// show part page |
8fa58e
|
53 |
if (!empty($_GET['_frame'])) { |
c97625
|
54 |
if ($part_id && ($part = $MESSAGE->mime_parts[$part_id])) { |
AM |
55 |
$filename = rcmail_attachment_name($part); |
|
56 |
$OUTPUT->set_pagetitle($filename); |
|
57 |
} |
b6da0b
|
58 |
|
c97625
|
59 |
// register UI objects |
AM |
60 |
$OUTPUT->add_handlers(array( |
|
61 |
'messagepartframe' => 'rcmail_message_part_frame', |
|
62 |
'messagepartcontrols' => 'rcmail_message_part_controls', |
|
63 |
)); |
eaf383
|
64 |
|
323fa2
|
65 |
$mimetype = $part ? rcmail_fix_mimetype($part->mimetype) : ''; |
AM |
66 |
if ($part_id && $mimetype == 'message/rfc822') { |
|
67 |
$uid = preg_replace('/\.[0-9.]+/', '', $uid); |
|
68 |
$uid .= '.' . $part_id; |
|
69 |
} |
|
70 |
|
c97625
|
71 |
$OUTPUT->set_env('mailbox', $RCMAIL->storage->get_folder()); |
AM |
72 |
$OUTPUT->set_env('uid', $uid); |
|
73 |
$OUTPUT->set_env('part', $part_id); |
|
74 |
$OUTPUT->set_env('filename', $filename); |
323fa2
|
75 |
$OUTPUT->set_env('mimetype', $mimetype); |
049428
|
76 |
|
c97625
|
77 |
$OUTPUT->send('messagepart'); |
AM |
78 |
exit; |
8fa58e
|
79 |
} |
4e17e6
|
80 |
|
031491
|
81 |
// render thumbnail of an image attachment |
TB |
82 |
else if ($_GET['_thumb']) { |
c97625
|
83 |
$pid = rcube_utils::get_input_value('_part', rcube_utils::INPUT_GET); |
AM |
84 |
if ($part = $MESSAGE->mime_parts[$pid]) { |
|
85 |
$thumbnail_size = $RCMAIL->config->get('image_thumbnail_size', 240); |
|
86 |
$temp_dir = $RCMAIL->config->get('temp_dir'); |
|
87 |
$mimetype = $part->mimetype; |
|
88 |
$file_ident = $MESSAGE->headers->messageID . ':' . $part->mime_id . ':' . $part->size . ':' . $part->mimetype; |
|
89 |
$cache_basename = $temp_dir . '/' . md5($file_ident . ':' . $RCMAIL->user->ID . ':' . $thumbnail_size); |
03aa84
|
90 |
$cache_file = $cache_basename . '.thumb'; |
031491
|
91 |
|
c97625
|
92 |
// render thumbnail image if not done yet |
AM |
93 |
if (!is_file($cache_file)) { |
03aa84
|
94 |
if ($fp = fopen(($orig_name = $cache_basename . '.tmp'), 'w')) { |
7ff227
|
95 |
$MESSAGE->get_part_body($part->mime_id, false, 0, $fp); |
c97625
|
96 |
fclose($fp); |
031491
|
97 |
|
c97625
|
98 |
$image = new rcube_image($orig_name); |
AM |
99 |
if ($imgtype = $image->resize($thumbnail_size, $cache_file, true)) { |
|
100 |
$mimetype = 'image/' . $imgtype; |
|
101 |
unlink($orig_name); |
|
102 |
} |
40d734
|
103 |
else if (stripos($mimetype, 'image/svg') === 0) { |
AM |
104 |
$content = rcmail_svg_filter(file_get_contents($orig_name)); |
|
105 |
file_put_contents($cache_file, $content); |
|
106 |
unlink($orig_name); |
|
107 |
} |
c97625
|
108 |
else { |
AM |
109 |
rename($orig_name, $cache_file); |
|
110 |
} |
|
111 |
} |
19cc5b
|
112 |
} |
AM |
113 |
|
c97625
|
114 |
if (is_file($cache_file)) { |
AM |
115 |
header('Content-Type: ' . $mimetype); |
|
116 |
readfile($cache_file); |
19cc5b
|
117 |
} |
8fa58e
|
118 |
} |
8d4bcd
|
119 |
|
4e17e6
|
120 |
exit; |
8fa58e
|
121 |
} |
c97625
|
122 |
else if (strlen($part_id)) { |
AM |
123 |
if ($part = $MESSAGE->mime_parts[$part_id]) { |
|
124 |
$mimetype = rcmail_fix_mimetype($part->mimetype); |
|
125 |
|
|
126 |
// allow post-processing of the message body |
|
127 |
$plugin = $RCMAIL->plugins->exec_hook('message_part_get', array( |
|
128 |
'uid' => $MESSAGE->uid, |
|
129 |
'id' => $part->mime_id, |
|
130 |
'mimetype' => $mimetype, |
|
131 |
'part' => $part, |
|
132 |
'download' => !empty($_GET['_download']) |
|
133 |
)); |
|
134 |
|
|
135 |
if ($plugin['abort']) { |
|
136 |
exit; |
|
137 |
} |
|
138 |
|
4a4088
|
139 |
// require CSRF protected url for downloads |
TB |
140 |
if ($plugin['download']) |
|
141 |
$RCMAIL->request_security_check(rcube_utils::INPUT_GET); |
|
142 |
|
c97625
|
143 |
// overwrite modified vars from plugin |
AM |
144 |
$mimetype = $plugin['mimetype']; |
|
145 |
$extensions = rcube_mime::get_mime_extensions($mimetype); |
|
146 |
|
|
147 |
if ($plugin['body']) { |
48ba44
|
148 |
$body = $plugin['body']; |
c97625
|
149 |
} |
AM |
150 |
|
|
151 |
// compare file mimetype with the stated content-type headers and file extension to avoid malicious operations |
|
152 |
if (!empty($_REQUEST['_embed']) && empty($_REQUEST['_nocheck'])) { |
|
153 |
$file_extension = strtolower(pathinfo($part->filename, PATHINFO_EXTENSION)); |
|
154 |
|
|
155 |
// 1. compare filename suffix with expected suffix derived from mimetype |
4a2a62
|
156 |
$valid = $file_extension && in_array($file_extension, (array)$extensions) || empty($extensions) || !empty($_REQUEST['_mimeclass']); |
c97625
|
157 |
|
AM |
158 |
// 2. detect the real mimetype of the attachment part and compare it with the stated mimetype and filename extension |
|
159 |
if ($valid || !$file_extension || $mimetype == 'application/octet-stream' || stripos($mimetype, 'text/') === 0) { |
48ba44
|
160 |
$tmp_body = $body ?: $MESSAGE->get_part_body($part->mime_id, false, 2048); |
c97625
|
161 |
|
AM |
162 |
// detect message part mimetype |
48ba44
|
163 |
$real_mimetype = rcube_mime::file_content_type($tmp_body, $part->filename, $mimetype, true, true); |
c97625
|
164 |
list($real_ctype_primary, $real_ctype_secondary) = explode('/', $real_mimetype); |
AM |
165 |
|
|
166 |
// accept text/plain with any extension |
|
167 |
if ($real_mimetype == 'text/plain' && $real_mimetype == $mimetype) { |
|
168 |
$valid_extension = true; |
|
169 |
} |
556d28
|
170 |
// ignore differences in text/* mimetypes. Filetype detection isn't very reliable here |
AM |
171 |
else if ($real_ctype_primary == 'text' && strpos($mimetype, $real_ctype_primary) === 0) { |
|
172 |
$real_mimetype = $mimetype; |
|
173 |
$valid_extension = true; |
|
174 |
} |
|
175 |
// ignore filename extension if mimeclass matches (#1489029) |
|
176 |
else if (!empty($_REQUEST['_mimeclass']) && $real_ctype_primary == $_REQUEST['_mimeclass']) { |
|
177 |
$valid_extension = true; |
|
178 |
} |
|
179 |
else { |
|
180 |
// get valid file extensions |
|
181 |
$extensions = rcube_mime::get_mime_extensions($real_mimetype); |
45256e
|
182 |
$valid_extension = !$file_extension || empty($extensions) || in_array($file_extension, (array)$extensions); |
556d28
|
183 |
} |
c97625
|
184 |
|
AM |
185 |
// fix mimetype for images wrongly declared as octet-stream |
|
186 |
if ($mimetype == 'application/octet-stream' && strpos($real_mimetype, 'image/') === 0 && $valid_extension) { |
|
187 |
$mimetype = $real_mimetype; |
|
188 |
} |
|
189 |
|
4a2a62
|
190 |
// "fix" real mimetype the same way the original is before comparison |
AM |
191 |
$real_mimetype = rcmail_fix_mimetype($real_mimetype); |
|
192 |
|
|
193 |
$valid = $real_mimetype == $mimetype && $valid_extension; |
c97625
|
194 |
} |
AM |
195 |
else { |
|
196 |
$real_mimetype = $mimetype; |
|
197 |
} |
|
198 |
|
|
199 |
// show warning if validity checks failed |
|
200 |
if (!$valid) { |
|
201 |
// send blocked.gif for expected images |
|
202 |
if (empty($_REQUEST['_mimewarning']) && strpos($mimetype, 'image/') === 0) { |
|
203 |
// Do not cache. Failure might be the result of a misconfiguration, thus real content should be returned once fixed. |
c6efcf
|
204 |
$content = $RCMAIL->get_resource_content('blocked.gif'); |
c97625
|
205 |
$OUTPUT->nocacheing_headers(); |
AM |
206 |
header("Content-Type: image/gif"); |
|
207 |
header("Content-Transfer-Encoding: binary"); |
c6efcf
|
208 |
header("Content-Length: " . strlen($content)); |
AM |
209 |
echo $content; |
c97625
|
210 |
} |
AM |
211 |
else { // html warning with a button to load the file anyway |
|
212 |
$OUTPUT = new rcmail_html_page(); |
|
213 |
$OUTPUT->write(html::tag('html', null, html::tag('body', 'embed', |
|
214 |
html::div(array('class' => 'rcmail-inline-message rcmail-inline-warning'), |
|
215 |
$RCMAIL->gettext(array( |
|
216 |
'name' => 'attachmentvalidationerror', |
|
217 |
'vars' => array( |
|
218 |
'expected' => $mimetype . ($file_extension ? " (.$file_extension)" : ''), |
|
219 |
'detected' => $real_mimetype . ($extensions[0] ? " (.$extensions[0])" : ''), |
|
220 |
) |
|
221 |
)) |
|
222 |
. html::p(array('class' => 'rcmail-inline-buttons'), |
|
223 |
html::tag('button', array( |
|
224 |
'onclick' => "location.href='" . $RCMAIL->url(array_merge($_GET, array('_nocheck' => 1))) . "'" |
|
225 |
), |
|
226 |
$RCMAIL->gettext('showanyway')) |
|
227 |
) |
|
228 |
)))); |
|
229 |
} |
|
230 |
|
|
231 |
exit; |
|
232 |
} |
|
233 |
} |
|
234 |
|
|
235 |
|
|
236 |
// TIFF to JPEG conversion, if needed |
|
237 |
$tiff_support = !empty($_SESSION['browser_caps']) && !empty($_SESSION['browser_caps']['tif']); |
|
238 |
if (!empty($_REQUEST['_embed']) && !$tiff_support |
8968f9
|
239 |
&& rcube_image::is_convertable('image/tiff') |
c97625
|
240 |
&& rcmail_part_image_type($part) == 'image/tiff' |
AM |
241 |
) { |
|
242 |
$tiff2jpeg = true; |
|
243 |
$mimetype = 'image/jpeg'; |
|
244 |
} |
|
245 |
|
|
246 |
|
|
247 |
$browser = $RCMAIL->output->browser; |
|
248 |
list($ctype_primary, $ctype_secondary) = explode('/', $mimetype); |
|
249 |
|
|
250 |
if (!$plugin['download'] && $ctype_primary == 'text') { |
827159
|
251 |
header("Content-Type: text/$ctype_secondary; charset=" . ($part->charset ?: RCUBE_CHARSET)); |
c97625
|
252 |
} |
AM |
253 |
else { |
|
254 |
header("Content-Type: $mimetype"); |
|
255 |
header("Content-Transfer-Encoding: binary"); |
|
256 |
} |
|
257 |
|
|
258 |
// deliver part content |
|
259 |
if ($ctype_primary == 'text' && $ctype_secondary == 'html' && empty($plugin['download'])) { |
|
260 |
// Check if we have enough memory to handle the message in it |
|
261 |
// #1487424: we need up to 10x more memory than the body |
|
262 |
if (!rcube_utils::mem_check($part->size * 10)) { |
|
263 |
$out = '<body>' . $RCMAIL->gettext('messagetoobig'). ' ' |
|
264 |
. html::a('?_task=mail&_action=get&_download=1&_uid='.$MESSAGE->uid.'&_part='.$part->mime_id |
c83940
|
265 |
.'&_mbox='. urlencode($MESSAGE->folder), $RCMAIL->gettext('download')) . '</body></html>'; |
c97625
|
266 |
} |
AM |
267 |
else { |
|
268 |
// get part body if not available |
48ba44
|
269 |
if (!isset($body)) { |
AM |
270 |
$body = $MESSAGE->get_part_body($part->mime_id, true); |
c97625
|
271 |
} |
AM |
272 |
|
|
273 |
// show images? |
|
274 |
rcmail_check_safe($MESSAGE); |
|
275 |
|
|
276 |
// render HTML body |
48ba44
|
277 |
$out = rcmail_print_body($body, $part, array('safe' => $MESSAGE->is_safe, 'inline_html' => false)); |
c97625
|
278 |
|
AM |
279 |
// insert remote objects warning into HTML body |
|
280 |
if ($REMOTE_OBJECTS) { |
|
281 |
$body_start = 0; |
|
282 |
if ($body_pos = strpos($out, '<body')) { |
|
283 |
$body_start = strpos($out, '>', $body_pos) + 1; |
|
284 |
} |
|
285 |
|
|
286 |
$out = substr($out, 0, $body_start) |
|
287 |
. html::div(array('class' => 'rcmail-inline-message rcmail-inline-warning'), |
|
288 |
rcube::Q($RCMAIL->gettext('blockedimages')) . ' ' . |
|
289 |
html::tag('button', |
|
290 |
array('onclick' => "location.href='" . $RCMAIL->url(array_merge($_GET, array('_safe' => 1))) . "'"), |
|
291 |
rcube::Q($RCMAIL->gettext('showimages'))) |
|
292 |
) |
|
293 |
. substr($out, $body_start); |
|
294 |
} |
|
295 |
} |
|
296 |
|
|
297 |
// check connection status |
48ba44
|
298 |
if ($part->size && empty($body)) { |
c97625
|
299 |
check_storage_status(); |
AM |
300 |
} |
|
301 |
|
|
302 |
$OUTPUT = new rcmail_html_page(); |
|
303 |
$OUTPUT->write($out); |
|
304 |
} |
|
305 |
else { |
|
306 |
// don't kill the connection if download takes more than 30 sec. |
|
307 |
@set_time_limit(0); |
|
308 |
|
|
309 |
$filename = rcmail_attachment_name($part); |
|
310 |
|
5515db
|
311 |
if ($browser->ie) |
c97625
|
312 |
$filename = rawurlencode($filename); |
AM |
313 |
else |
|
314 |
$filename = addcslashes($filename, '"'); |
|
315 |
|
|
316 |
$disposition = !empty($plugin['download']) ? 'attachment' : 'inline'; |
|
317 |
|
|
318 |
// Workaround for nasty IE bug (#1488844) |
|
319 |
// If Content-Disposition header contains string "attachment" e.g. in filename |
|
320 |
// IE handles data as attachment not inline |
|
321 |
if ($disposition == 'inline' && $browser->ie && $browser->ver < 9) { |
|
322 |
$filename = str_ireplace('attachment', 'attach', $filename); |
|
323 |
} |
|
324 |
|
|
325 |
// add filename extension if missing |
|
326 |
if (!pathinfo($filename, PATHINFO_EXTENSION) && ($extensions = rcube_mime::get_mime_extensions($mimetype))) { |
|
327 |
$filename .= '.' . $extensions[0]; |
|
328 |
} |
|
329 |
|
|
330 |
header("Content-Disposition: $disposition; filename=\"$filename\""); |
|
331 |
|
|
332 |
// handle tiff to jpeg conversion |
|
333 |
if (!empty($tiff2jpeg)) { |
|
334 |
$temp_dir = unslashify($RCMAIL->config->get('temp_dir')); |
|
335 |
$file_path = tempnam($temp_dir, 'rcmAttmnt'); |
|
336 |
|
|
337 |
// write content to temp file |
48ba44
|
338 |
if ($body) { |
AM |
339 |
$saved = file_put_contents($file_path, $body); |
c97625
|
340 |
} |
AM |
341 |
else if ($part->size) { |
|
342 |
$fd = fopen($file_path, 'w'); |
48ba44
|
343 |
$saved = $MESSAGE->get_part_body($part->mime_id, false, 0, $fd); |
c97625
|
344 |
fclose($fd); |
AM |
345 |
} |
|
346 |
|
|
347 |
// convert image to jpeg and send it to the browser |
40d734
|
348 |
if ($sent = $saved) { |
c97625
|
349 |
$image = new rcube_image($file_path); |
AM |
350 |
if ($image->convert(rcube_image::TYPE_JPG, $file_path)) { |
|
351 |
header("Content-Length: " . filesize($file_path)); |
|
352 |
readfile($file_path); |
|
353 |
} |
|
354 |
unlink($file_path); |
|
355 |
} |
|
356 |
} |
|
357 |
else { |
40d734
|
358 |
$sent = rcmail_message_part_output($body, $part, $mimetype, $plugin['download']); |
c97625
|
359 |
} |
AM |
360 |
|
|
361 |
// check connection status |
|
362 |
if ($part->size && !$sent) { |
|
363 |
check_storage_status(); |
|
364 |
} |
|
365 |
} |
|
366 |
|
|
367 |
exit; |
|
368 |
} |
|
369 |
} |
4e17e6
|
370 |
// print message |
8fa58e
|
371 |
else { |
c97625
|
372 |
// send correct headers for content type |
AM |
373 |
header("Content-Type: text/html"); |
4e17e6
|
374 |
|
c97625
|
375 |
$cont = "<html>\n<head><title></title>\n</head>\n<body>"; |
AM |
376 |
$cont .= rcmail_message_body(array()); |
|
377 |
$cont .= "\n</body>\n</html>"; |
4e17e6
|
378 |
|
c97625
|
379 |
$OUTPUT = new rcmail_html_page(); |
AM |
380 |
$OUTPUT->write($cont); |
4e17e6
|
381 |
|
c97625
|
382 |
exit; |
8fa58e
|
383 |
} |
4e17e6
|
384 |
|
T |
385 |
|
|
386 |
// if we arrive here, the requested part was not found |
|
387 |
header('HTTP/1.1 404 Not Found'); |
|
388 |
exit; |
|
389 |
|
eaf383
|
390 |
/** |
AM |
391 |
* Handles nicely storage connection errors |
|
392 |
*/ |
4bfe4e
|
393 |
function check_storage_status() |
AM |
394 |
{ |
|
395 |
$error = rcmail::get_instance()->storage->get_error_code(); |
|
396 |
|
|
397 |
// Check if we have a connection error |
|
398 |
if ($error == rcube_imap_generic::ERROR_BAD) { |
|
399 |
ob_end_clean(); |
|
400 |
|
|
401 |
// Get action is often executed simultanously. |
|
402 |
// Some servers have MAXPERIP or other limits. |
|
403 |
// To workaround this we'll wait for some time |
|
404 |
// and try again (once). |
|
405 |
// Note: Random sleep interval is used to minimize concurency |
|
406 |
// in getting message parts |
|
407 |
|
|
408 |
if (!isset($_GET['_redirected'])) { |
|
409 |
usleep(rand(10,30)*100000); // 1-3 sec. |
|
410 |
header('Location: ' . $_SERVER['REQUEST_URI'] . '&_redirected=1'); |
|
411 |
} |
|
412 |
else { |
6b2b2e
|
413 |
rcube::raise_error(array( |
4bfe4e
|
414 |
'code' => 500, 'type' => 'php', |
AM |
415 |
'file' => __FILE__, 'line' => __LINE__, |
|
416 |
'message' => 'Unable to get/display message part. IMAP connection error'), |
|
417 |
true, true); |
|
418 |
} |
|
419 |
|
|
420 |
// Don't kill session, just quit (#1486995) |
|
421 |
exit; |
|
422 |
} |
|
423 |
} |
049428
|
424 |
|
eaf383
|
425 |
/** |
AM |
426 |
* Attachment properties table |
|
427 |
*/ |
049428
|
428 |
function rcmail_message_part_controls($attrib) |
AM |
429 |
{ |
|
430 |
global $MESSAGE, $RCMAIL; |
|
431 |
|
6b2b2e
|
432 |
$part = asciiwords(rcube_utils::get_input_value('_part', rcube_utils::INPUT_GPC)); |
049428
|
433 |
if (!is_object($MESSAGE) || !is_array($MESSAGE->parts) |
AM |
434 |
|| !($_GET['_uid'] && $_GET['_part']) || !$MESSAGE->mime_parts[$part] |
|
435 |
) { |
|
436 |
return ''; |
|
437 |
} |
|
438 |
|
|
439 |
$part = $MESSAGE->mime_parts[$part]; |
|
440 |
$table = new html_table(array('cols' => 2)); |
|
441 |
|
6b2b2e
|
442 |
$table->add('title', rcube::Q($RCMAIL->gettext('namex')).':'); |
AM |
443 |
$table->add('header', rcube::Q(rcmail_attachment_name($part))); |
049428
|
444 |
|
6b2b2e
|
445 |
$table->add('title', rcube::Q($RCMAIL->gettext('type')).':'); |
AM |
446 |
$table->add('header', rcube::Q($part->mimetype)); |
049428
|
447 |
|
6b2b2e
|
448 |
$table->add('title', rcube::Q($RCMAIL->gettext('size')).':'); |
AM |
449 |
$table->add('header', rcube::Q($RCMAIL->message_part_size($part))); |
049428
|
450 |
|
AM |
451 |
return $table->show($attrib); |
|
452 |
} |
|
453 |
|
eaf383
|
454 |
/** |
AM |
455 |
* Attachment preview frame |
|
456 |
*/ |
049428
|
457 |
function rcmail_message_part_frame($attrib) |
AM |
458 |
{ |
323fa2
|
459 |
global $RCMAIL; |
049428
|
460 |
|
323fa2
|
461 |
$mimetype = $RCMAIL->output->get_env('mimetype'); |
049428
|
462 |
|
323fa2
|
463 |
if ($mimetype == 'message/rfc822') { |
AM |
464 |
$attrib['src'] = $RCMAIL->url(array( |
|
465 |
'task' => 'mail', |
|
466 |
'action' => 'preview', |
|
467 |
'uid' => $RCMAIL->output->get_env('uid'), |
|
468 |
'mbox' => $RCMAIL->output->get_env('mailbox'), |
|
469 |
'framed' => 1, |
|
470 |
)); |
|
471 |
} |
|
472 |
else { |
|
473 |
$frame_replace = strpos($mimetype, 'text/') === 0 ? '_embed=' : '_preload='; |
|
474 |
$attrib['src'] = './?' . str_replace('_frame=', $frame_replace, $_SERVER['QUERY_STRING']); |
|
475 |
} |
049428
|
476 |
|
AM |
477 |
$RCMAIL->output->add_gui_object('messagepartframe', $attrib['id']); |
|
478 |
|
|
479 |
return html::iframe($attrib); |
|
480 |
} |
40d734
|
481 |
|
AM |
482 |
/** |
|
483 |
* Output attachment body with content filtering |
|
484 |
*/ |
|
485 |
function rcmail_message_part_output($body, $part, $mimetype, $download) |
|
486 |
{ |
|
487 |
global $MESSAGE, $RCMAIL; |
|
488 |
|
|
489 |
if (!$part->size && !$body) { |
|
490 |
return false; |
|
491 |
} |
|
492 |
|
|
493 |
$browser = $RCMAIL->output->browser; |
|
494 |
$secure = stripos($mimetype, 'image/') === false || $download; |
|
495 |
|
|
496 |
// Remove <script> in SVG images |
|
497 |
if (!$secure && stripos($mimetype, 'image/svg') === 0) { |
|
498 |
if (!$body) { |
|
499 |
$body = $MESSAGE->get_part_body($part->mime_id, false); |
|
500 |
if (empty($body)) { |
|
501 |
return false; |
|
502 |
} |
|
503 |
} |
|
504 |
|
|
505 |
echo rcmail_svg_filter($body); |
|
506 |
return true; |
|
507 |
} |
|
508 |
|
|
509 |
// Remove dangerous content in images for older IE (to be removed) |
|
510 |
if (!$secure && $browser->ie && $browser->ver <= 8) { |
|
511 |
if ($body) { |
|
512 |
echo preg_match('/<(script|iframe|object)/i', $body) ? '' : $body; |
|
513 |
return true; |
|
514 |
} |
|
515 |
else { |
|
516 |
$stdout = fopen('php://output', 'w'); |
|
517 |
stream_filter_register('rcube_content', 'rcube_content_filter') or die('Failed to register content filter'); |
|
518 |
stream_filter_append($stdout, 'rcube_content'); |
|
519 |
return $MESSAGE->get_part_body($part->mime_id, true, 0, $stdout); |
|
520 |
} |
|
521 |
} |
|
522 |
|
|
523 |
if ($body && !$download) { |
|
524 |
header("Content-Length: " . strlen($body)); |
|
525 |
echo $body; |
|
526 |
return true; |
|
527 |
} |
|
528 |
|
|
529 |
// Don't be tempted to set Content-Length to $part->d_parameters['size'] (#1490482) |
|
530 |
// RFC2183 says "The size parameter indicates an approximate size" |
|
531 |
|
|
532 |
return $MESSAGE->get_part_body($part->mime_id, false, 0, -1); |
|
533 |
} |
|
534 |
|
|
535 |
/** |
|
536 |
* Remove <script> in SVG images |
|
537 |
*/ |
|
538 |
function rcmail_svg_filter($body) |
|
539 |
{ |
a1fdb2
|
540 |
// clean SVG with washhtml |
AM |
541 |
$wash_opts = array( |
|
542 |
'show_washed' => false, |
|
543 |
'allow_remote' => false, |
|
544 |
'charset' => RCUBE_CHARSET, |
|
545 |
'html_elements' => array('title'), |
|
546 |
// 'blocked_src' => 'program/resources/blocked.gif', |
|
547 |
); |
40d734
|
548 |
|
a1fdb2
|
549 |
// initialize HTML washer |
AM |
550 |
$washer = new rcube_washtml($wash_opts); |
40d734
|
551 |
|
a1fdb2
|
552 |
// allow CSS styles, will be sanitized by rcmail_washtml_callback() |
AM |
553 |
$washer->add_callback('style', 'rcmail_washtml_callback'); |
|
554 |
|
|
555 |
return $washer->wash($body); |
40d734
|
556 |
} |