diff --git a/include/class.format.php b/include/class.format.php index 892cc42f17bd56fe2e934d6c1ffb0c2a6f305fa5..f016896deb39cfefb05b43bf4913bb06feb6fe84 100644 --- a/include/class.format.php +++ b/include/class.format.php @@ -86,6 +86,23 @@ class Format { return $text; } + /** + * Decodes filenames given in the content-disposition header according + * to RFC5987, such as filename*=utf-8''filename.png. Note that the + * language sub-component is defined in RFC5646, and that the filename + * is URL encoded (in the charset specified) + */ + function decodeRfc5987($filename) { + $match = array(); + if (preg_match("/([\w!#$%&+^_`{}~-]+)'([\w-]*)'(.*)$/", + $filename, $match)) + // XXX: Currently we don't care about the language component. + // The encoding hint is sufficient. + return self::utf8encode(urldecode($match[3]), $match[1]); + else + return $filename; + } + function phone($phone) { $stripped= preg_replace("/[^0-9]/", "", $phone); diff --git a/include/class.mailfetch.php b/include/class.mailfetch.php index 7fee6868a50a70cb1681f05ae8e2c7604510234f..c4d0d0b3297878fa558e94111e771f362c9d2395 100644 --- a/include/class.mailfetch.php +++ b/include/class.mailfetch.php @@ -308,6 +308,31 @@ class MailFetcher { return $text; } + /** + * Searches the attribute list for a possible filename attribute. If + * found, the attribute value is returned. If the attribute uses rfc5987 + * to encode the attribute value, the value is returned properly decoded + * if possible + * + * Attribute Search Preference: + * filename + * filename* + * name + * name* + */ + function findFilename($attributes) { + foreach (array('filename', 'name') as $pref) { + foreach ($attributes as $a) { + if (strtolower($a->attribute) == $pref) + return $a->value; + // Allow the RFC5987 specification of the filename + elseif (strtolower($a->attribute) == $pref.'*') + return Format::decodeRfc5987($a->value); + } + } + return false; + } + /* getAttachments @@ -319,23 +344,16 @@ class MailFetcher { if($part && !$part->parts) { //Check if the part is an attachment. - $filename = ''; - if($part->ifdisposition && in_array(strtolower($part->disposition), array('attachment', 'inline'))) { - $filename = $part->dparameters[0]->value; - //Some inline attachments have multiple parameters. - if(count($part->dparameters)>1) { - foreach($part->dparameters as $dparameter) { - if(!in_array(strtoupper($dparameter->attribute), array('FILENAME', 'NAME'))) continue; - $filename = $dparameter->value; - break; - } - } - } elseif($part->ifparameters && $part->parameters && $part->type > 0) { //inline attachments without disposition. - foreach($part->parameters as $parameter) { - if(!in_array(strtoupper($parameter->attribute), array('FILENAME', 'NAME'))) continue; - $filename = $parameter->value; - break; - } + $filename = false; + if ($part->ifdisposition + && in_array(strtolower($part->disposition), + array('attachment', 'inline'))) { + $filename = $this->findFilename($part->dparameters); + } + // Inline attachments without disposition. + if (!$filename && $part->ifparameters && $part->parameters + && $part->type > 0) { + $filename = $this->findFilename($part->parameters); } if($filename) { diff --git a/include/class.mailparse.php b/include/class.mailparse.php index b02f2448a98a370cc0901231b11b435288d3c599..1132073d08886852ed78d80f2efd57b8eef79eb1 100644 --- a/include/class.mailparse.php +++ b/include/class.mailparse.php @@ -199,23 +199,6 @@ class Mail_Parse { return Format::encode($text, $charset, $encoding); } - /** - * Decodes filenames given in the content-disposition header according - * to RFC5987, such as filename*=utf-8''filename.png. Note that the - * language sub-component is defined in RFC5646, and that the filename - * is URL encoded (in the charset specified) - */ - function decodeRfc5987($filename) { - $match = array(); - if (preg_match("/([\w!#$%&+^_`{}~-]+)'([\w-]*)'(.*)$/", - $filename, $match)) - // XXX: Currently we don't care about the language component. - // The encoding hint is sufficient. - return self::mime_encode(urldecode($match[3]), $match[1]); - else - return $filename; - } - function getAttachments($part=null){ if($part==null) @@ -240,7 +223,7 @@ class Mail_Parse { $filename = $part->d_parameters['filename']; elseif (isset($part->d_parameters['filename*'])) // Support RFC 6266, section 4.3 and RFC, and RFC 5987 - $filename = self::decodeRfc5987( + $filename = Format::decodeRfc5987( $part->d_parameters['filename*']); // Support attachments that do not specify a content-disposition @@ -248,7 +231,7 @@ class Mail_Parse { elseif (isset($part->ctype_parameters['name'])) $filename=$part->ctype_parameters['name']; elseif (isset($part->ctype_parameters['name*'])) - $filename = self::decodeRfc5987( + $filename = Format::decodeRfc5987( $part->ctype_parameters['name*']); else // Not an attachment?