From 2da8300fb7bb7b0a386d334d4c82a2ffbe3d9331 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Sun, 26 Oct 2014 09:34:24 +0100 Subject: Correctly detect charset of attachment names in TNEF messages --- program/lib/Roundcube/rcube_message.php | 57 ++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) (limited to 'program/lib/Roundcube') diff --git a/program/lib/Roundcube/rcube_message.php b/program/lib/Roundcube/rcube_message.php index 4f0f0fd1f..0d33ba411 100644 --- a/program/lib/Roundcube/rcube_message.php +++ b/program/lib/Roundcube/rcube_message.php @@ -858,7 +858,7 @@ class rcube_message foreach ($tnef_arr as $pid => $winatt) { $tpart = new rcube_message_part; - $tpart->filename = trim($winatt['name']); + $tpart->filename = $this->fix_attachment_name(trim($winatt['name']), $part); $tpart->encoding = 'stream'; $tpart->ctype_primary = trim(strtolower($winatt['type'])); $tpart->ctype_secondary = trim(strtolower($winatt['subtype'])); @@ -931,6 +931,61 @@ class rcube_message return $parts; } + /** + * Fix attachment name encoding if needed/possible + */ + protected function fix_attachment_name($name, $part) + { + if ($name == rcube_charset::clean($name)) { + return $name; + } + + // find charset from part or its parent(s) + if ($part->charset) { + $charsets[] = $part->charset; + } + else { + // check first part (common case) + $n = strpos($part->mime_id, '.') ? preg_replace('/\.[0-9]+$/', '', $part->mime_id) . '.1' : 1; + if (($_part = $this->mime_parts[$n]) && $_part->charset) { + $charsets[] = $_part->charset; + } + + // check parents' charset + $items = explode('.', $part->mime_id); + for ($i = count($items)-1; $i > 0; $i--) { + $last = array_pop($items); + $parent = $this->mime_parts[join('.', $items)]; + + if ($parent && $parent->charset) { + $charsets[] = $parent->charset; + } + } + } + + if ($this->headers->charset) { + $charsets[] = $this->headers->charset; + } + + if (empty($charsets)) { + $rcube = rcube::get_instance(); + $charsets[] = rcube_charset::detect($name, $rcube->config->get('default_charset', RCUBE_CHARSET)); + } + + foreach (array_unique($charsets) as $charset) { + $_name = rcube_charset::convert($name, $charset); + + if ($_name == rcube_charset::clean($_name)) { + if (!$part->charset) { + $part->charset = $charset; + } + + return $_name; + } + } + + return $name; + } /** * Deprecated methods (to be removed) -- cgit v1.2.3