Although it is possible to configure and check for specific attachment file extensions (eg, jpg, jpeg, pdf, png) the file content/mime type is not checked and as a result any file type can be attached by simply changing the file extension to match one of the allowed extensions.
With a new forum I am setting up there is a requirement to only allow files with specific content/mime types to be attached and I've done this by making the following code changes:
In ./Sources/ManageAttachments.php
Find:
array('check', 'attachmentRecodeLineEndings'),
Add After:
array('check', 'attachmentCheckMimes'),
array('text', 'attachmentMimes', 40),
In ./Sources/Subs-Post.php
Find:
if (!in_array(strtolower(substr(strrchr($attachmentOptions['name'], '.'), 1)), $allowed))
$attachmentOptions['errors'][] = 'bad_extension';
}
Add After:
if (!empty($modSettings['attachmentCheckMimes']))
{
$allowed = explode(',', strtolower($modSettings['attachmentMimes']));
foreach ($allowed as $k => $dummy)
$allowed[$k] = trim($dummy);
if (!in_array(strtolower(substr(strrchr($attachmentOptions['file_type'], '/'), 1)), $allowed))
$attachmentOptions['errors'][] = 'bad_mime';
}
In ./Sources/Post.php
Find:
fatal_error($_FILES['attachment']['name'][$n] . '.<br />' . $txt['cant_upload_type'] . ' ' . $modSettings['attachmentExtensions'] . '.', false);
}
Add After
if (!empty($modSettings['attachmentCheckMimes']))
{
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $_FILES['attachment']['tmp_name'][$n]);
finfo_close($finfo);
if (!in_array($mime, explode(',', strtolower($modSettings['attachmentMimes']))))
fatal_error('<strong>' . $_FILES['attachment']['name'][$n] . '</strong><br /><br />' . sprintf($txt['cant_upload_mime'], $mime) . '</strong>' . $modSettings['attachmentMimes'] . '</strong>', false);
}
Find:
fatal_lang_error('file_too_big', false, array($modSettings['attachmentPostLimit']));
}
Add After:
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $_FILES['attachment']['tmp_name'][$n]);
finfo_close($finfo);
Find:
'approved' => !$modSettings['postmod_active'] || allowedTo('post_attachment'),
Add After:
'file_type' => $mime,
Find:
fatal_error($attachmentOptions['name'] . '.<br />' . $txt['cant_upload_type'] . ' ' . $modSettings['attachmentExtensions'] . '.', false);
}
Add After:
if (in_array('bad_mime', $attachmentOptions['errors']))
{
checkSubmitOnce('free');
fatal_error('<strong>' . $attachmentOptions['name'] . '</strong><br /><br />' . sprintf($txt['cant_upload_mime'], $attachmentOptions['file_type']) . '</strong>' . $modSettings['attachmentMimes'] . '</strong>', false);
}
In ./Themes/default/languages/Post.english.php
Find:
$txt['cant_upload_type'] = 'You cannot upload that type of file. The only allowed extensions are';
Add After:
$txt['cant_upload_mime'] = 'You cannot upload that type of file (ie, "%1$s"). The only allowed file content/mime types are: ';
In ./Themes/default/languages/Admin.english.php
Find:
$txt['attachmentRecodeLineEndings'] = 'Recode line endings in textual attachments';
Add After:
$txt['attachmentCheckMimes'] = 'Check attachment\'s file content/mime type';
$txt['attachmentMimes'] = 'Allowed file content/mime types<div class="smalltext"/>Note: Enter <b>jpeg</b> for JPG and JPEG image files.</div>';