From 4e00237cc43542abd72d69bbf03bcd738a16af48 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Sun, 7 Jun 2020 10:45:33 +0200 Subject: [PATCH] Allow opening application/octet-stream attachments according to filename extension (#6821) --- CHANGELOG | 1 + program/lib/Roundcube/rcube_mime.php | 44 +++++++++++++++++++--------- program/steps/mail/get.inc | 4 +-- program/steps/mail/show.inc | 6 +++- 4 files changed, 38 insertions(+), 17 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index d0f5b1b5b..e13507722 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -8,6 +8,7 @@ CHANGELOG Roundcube Webmail - MySQL: Use utf8mb4 charset and utf8mb4_unicode_ci collation (#6535, #7113) - Support for language codes up to 16 chars long (e.g. es-419) in database schema (#6851) - Relaxed domain name validation for extended TLDs support (#5588) +- Allow opening application/octet-stream attachments according to filename extension (#6821) - Added support for INSERT OR REPLACE queries (#6771) - Extract RFC2231 attachment name from message headers (#6729, #6783) - Archive: Added options to split archive by year or year+month and folder (#7216) diff --git a/program/lib/Roundcube/rcube_mime.php b/program/lib/Roundcube/rcube_mime.php index 7d75d6b00..e0204d545 100644 --- a/program/lib/Roundcube/rcube_mime.php +++ b/program/lib/Roundcube/rcube_mime.php @@ -699,7 +699,7 @@ class rcube_mime * @param string $name File name (with suffix) * @param string $failover Mime type supplied for failover * @param boolean $is_stream Set to True if $path contains file contents - * @param boolean $skip_suffix Set to True if the config/mimetypes.php mappig should be ignored + * @param boolean $skip_suffix Set to True if the config/mimetypes.php map should be ignored * * @return string * @author Till Klampaeckel @@ -708,22 +708,12 @@ class rcube_mime */ public static function file_content_type($path, $name, $failover = 'application/octet-stream', $is_stream = false, $skip_suffix = false) { - static $mime_ext = array(); - $mime_type = null; $config = rcube::get_instance()->config; - if (!$skip_suffix && empty($mime_ext)) { - foreach ($config->resolve_paths('mimetypes.php') as $fpath) { - $mime_ext = array_merge($mime_ext, (array) @include($fpath)); - } - } - - // use file name suffix with hard-coded mime-type map - if (!$skip_suffix && is_array($mime_ext) && $name) { - if ($suffix = substr($name, strrpos($name, '.')+1)) { - $mime_type = $mime_ext[strtolower($suffix)]; - } + // Detect mimetype using filename extension + if (!$skip_suffix) { + $mime_type = self::file_ext_type($name); } // try fileinfo extension if available @@ -758,6 +748,32 @@ class rcube_mime return $mime_type; } + /** + * File type detection based on file name only. + * + * @param string $filename Path to the file or file contents + * + * @return string|null Mimetype label + */ + public static function file_ext_type($filename) + { + static $mime_ext = array(); + + if (empty($mime_ext)) { + foreach (rcube::get_instance()->config->resolve_paths('mimetypes.php') as $fpath) { + $mime_ext = array_merge($mime_ext, (array) @include($fpath)); + } + } + + // use file name suffix with hard-coded mime-type map + if (!empty($mime_ext) && $filename) { + $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); + if ($ext && !empty($mime_ext[$ext])) { + return $mime_ext[$ext]; + } + } + } + /** * Get mimetype => file extension mapping * diff --git a/program/steps/mail/get.inc b/program/steps/mail/get.inc index 9327307f5..92745a37d 100644 --- a/program/steps/mail/get.inc +++ b/program/steps/mail/get.inc @@ -150,8 +150,8 @@ if (empty($_GET['_thumb']) && $attachment->is_valid()) { $valid_extension = !$file_extension || empty($extensions) || 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) { + // fix mimetype for files wrongly declared as octet-stream + if ($mimetype == 'application/octet-stream' && $valid_extension) { $mimetype = $real_mimetype; } // fix mimetype for images with wrong mimetype diff --git a/program/steps/mail/show.inc b/program/steps/mail/show.inc index a36dce918..1c11583d7 100644 --- a/program/steps/mail/show.inc +++ b/program/steps/mail/show.inc @@ -194,10 +194,14 @@ function rcmail_message_attachments($attrib) foreach ($MESSAGE->attachments as $attach_prop) { $filename = rcmail_attachment_name($attach_prop, true); $filesize = $RCMAIL->message_part_size($attach_prop); - $mimetype = $attach_prop->mimetype; + $mimetype = rcube_mime::fix_mimetype($attach_prop->mimetype); $class = rcube_utils::file2class($mimetype, $filename); $id = 'attach' . $attach_prop->mime_id; + if ($mimetype == 'application/octet-stream' && ($type = rcube_mime::file_ext_type($filename))) { + $mimetype = $type; + } + if ($attrib['maxlength'] && mb_strlen($filename) > $attrib['maxlength']) { $title = $filename; $filename = abbreviate_string($filename, $attrib['maxlength']);