@ -112,6 +112,71 @@ else if (strlen($pid = get_input_value('_part', RCUBE_INPUT_GET))) {
// overwrite modified vars from plugin
$mimetype = $plugin['mimetype'];
$extensions = rcube_mime::get_mime_extensions($mimetype);
if ($plugin['body'])
$part->body = $plugin['body'];
// compare file mimetype with the stated content-type headers and file extension to avoid malicious operations
if (!empty($_REQUEST['_embed']) & & empty($_REQUEST['_nocheck'])) {
$file_extension = strtolower(pathinfo($part->filename, PATHINFO_EXTENSION));
// 1. compare filename suffix with expected suffix derived from mimetype
$valid = $file_extension & & in_array($file_extension, (array)$extensions);
// 2. detect the real mimetype of the attachment part and compare it with the stated mimetype and filename extension
if ($valid || !$file_extension || $mimetype == 'application/octet-stream') {
if ($part->body) // part body is already loaded
$body = $part->body;
else if ($part->size & & $part->size < 1024 * 1024 ) / / load the entire part if it ' s small enough
$body = $part->body = $MESSAGE->get_part_content($part->mime_id);
else // fetch the first 2K of the message part
$body = $MESSAGE->get_part_content($part->mime_id, null, true, 2048);
// detect message part mimetype
$real_mimetype = rcube_mime::file_content_type($body, $part->filename, $mimetype, true, true);
list($real_ctype_primary, $real_ctype_secondary) = explode('/', $real_mimetype);
// ignore differences in text/* mimetypes. Filetype detection isn't very reliable here
if ($real_ctype_primary == 'text' & & strpos($mimetype, $real_ctype_primary) === 0)
$real_mimetype = $mimetype;
// get valid file extensions
$extensions = rcube_mime::get_mime_extensions($real_mimetype);
$valid_extension = (!$file_extension || in_array($file_extension, (array)$extensions));
// fix mimetype for images wrongly declared as octet-stream
if ($mimetype == 'application/octet-stream' & & strpos($real_mimetype, 'image/') === 0 & & $valid_extension)
$mimetype = $real_mimetype;
$valid = ($real_mimetype == $mimetype & & $valid_extension);
}
else {
$real_mimetype = $mimetype;
}
// show warning if validity checks failed
if (!$valid) {
$OUTPUT = new rcmail_html_page();
$OUTPUT->write(html::tag('html', null, html::tag('body', array('style' => 'font-family:sans-serif; margin:1em'),
html::div(array('class' => 'warning', 'style' => 'border:2px solid #ffdf0e; background:#fef893; padding:1em 1em 0 1em;'),
rcube_label(array(
'name' => 'attachmentvalidationerror',
'vars' => array('expected' => "$mimetype (.$file_extension)", 'detected' => "$real_mimetype (.$extensions[0])")
)) .
html::p('buttons',
html::tag('button', null,
html::a(array(
'href' => $RCMAIL->url(array_merge($_GET, array('_nocheck' => 1))),
'style' => 'text-decoration:none;color:#000',
), rcube_label('showanyway')))
))
)));
exit;
}
}
// TIFF to JPEG conversion, if needed
$tiff_support = !empty($_SESSION['browser_caps']) & & !empty($_SESSION['browser_caps']['tif']);
@ -123,11 +188,9 @@ else if (strlen($pid = get_input_value('_part', RCUBE_INPUT_GET))) {
$mimetype = 'image/jpeg';
}
list($ctype_primary, $ctype_secondary) = explode('/', $mimetype);
if ($plugin['body'])
$part->body = $plugin['body'];
$browser = $RCMAIL->output->browser;
list($ctype_primary, $ctype_secondary) = explode('/', $mimetype);
// send download headers
if ($plugin['download']) {
@ -144,6 +207,7 @@ else if (strlen($pid = get_input_value('_part', RCUBE_INPUT_GET))) {
header("Content-Transfer-Encoding: binary");
}
// deliver part content
if ($ctype_primary == 'text' & & $ctype_secondary == 'html' & & empty($plugin['download'])) {
// Check if we have enough memory to handle the message in it
@ -166,7 +230,7 @@ else if (strlen($pid = get_input_value('_part', RCUBE_INPUT_GET))) {
check_storage_status();
}
$OUTPUT = new rcube_output_ html();
$OUTPUT = new rcube_html_page ();
$OUTPUT->write($out);
}
else {