Skip to content
Snippets Groups Projects
Commit be02c8d4 authored by Jared Hancock's avatar Jared Hancock
Browse files

Detect attachments with Content-Type: ...; name=

RFC2045, section 5.1 seems to indicate that arbitrary parameters can be
appended to a Content-Type header specification. Some email clients seem to
use the Content-Type header to specify an attachment without giving a
separate Content-Disposition header normally used to signify attachments.

This patch corrects attachment detection for piped emails to detect such
emails. The patch also correctly decodes filenames specified either in the
Content-Disposition or Content-Type headers using RFC5987, where the
filename can be encoded using an arbitrary character set (ie, not us-ascii).
parent 92eb45bb
No related branches found
No related tags found
No related merge requests found
......@@ -199,18 +199,60 @@ 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)
$part=$this->getStruct();
if($part && $part->disposition
&& (!strcasecmp($part->disposition,'attachment')
|| !strcasecmp($part->disposition,'inline')
|| !strcasecmp($part->ctype_primary,'image'))){
if(!($filename=$part->d_parameters['filename']) && $part->d_parameters['filename*'])
$filename=$part->d_parameters['filename*']; //Do we need to decode?
/* Consider this part as an attachment if
* * It has a Content-Disposition header
* * AND it is specified as either 'attachment' or 'inline'
* * The Content-Type header specifies
* * type is image/* or application/*
* * has a name parameter
*/
if($part && (
($part->disposition
&& (!strcasecmp($part->disposition,'attachment')
|| !strcasecmp($part->disposition,'inline'))
)
|| (!strcasecmp($part->ctype_primary,'image')
|| !strcasecmp($part->ctype_primary,'application')))) {
if (isset($part->d_parameters['filename']))
$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(
$part->d_parameters['filename*']);
// Support attachments that do not specify a content-disposition
// but do specify a "name" parameter in the content-type header.
elseif (isset($part->ctype_parameters['name']))
$filename=$part->ctype_parameters['name'];
elseif (isset($part->ctype_parameters['name*']))
$filename = self::decodeRfc5987(
$part->ctype_parameters['name*']);
else
// Not an attachment?
return false;
$file=array(
'name' => $filename,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment