$mimeType = '';
$path = CRM_Core_Config::singleton()->customFileUploadDir . $fileName;
}
- $passedInMimeType = CRM_Utils_Request::retrieveValue('mime-type', 'String', $mimeType, FALSE);
if (!$path) {
CRM_Core_Error::statusBounce('Could not retrieve the file');
}
- if (!empty($mimeType) && !empty($passedInMimeType)) {
- if ($passedInMimeType != $mimeType) {
- throw new CRM_Core_Exception("Supplied Mime Type does not match file Mime Type");
+
+ if (empty($mimeType)) {
+ $passedInMimeType = CRM_Utils_Request::retrieveValue('mime-type', 'String', $mimeType, FALSE);
+ if (!in_array($passedInMimeType, explode(',', Civi::settings()->get('requestableMimeTypes')))) {
+ throw new CRM_Core_Exception("Supplied mime-type is not accepted");
}
- }
- elseif (!empty($passedInMimeType)) {
- $testMimeType = CRM_Utils_File::getMimeType($path);
- if ($testMimeType != $passedInMimeType) {
- throw new CRM_Core_Exception("Supplied Mime Type does not match file Mime Type");
+ $extension = CRM_Utils_File::getExtensionFromPath($path);
+ $candidateExtensions = CRM_Utils_File::getAcceptableExtensionsForMimeType($passedInMimeType);
+ if (!in_array($extension, $candidateExtensions)) {
+ throw new CRM_Core_Exception("Supplied mime-type does not match file extension");
}
- // Now that we have ensured that the mime-type matches to what we believe is the mime-type of the file
+ // Now that we have validated mime-type supplied as much as possible lets now set the MimeType variable/
$mimeType = $passedInMimeType;
}
}
/**
- * Get the Mime-Type of a file based on the url path
- * @param string $path full filename path
- * @return string|bool
+ * Get the extensions that this MimeTpe is for
+ * @param string $mimeType the mime-type we want extensions for
+ * @return array
+ */
+ public static function getAcceptableExtensionsForMimeType($mimeType = NULL) {
+ $mapping = \MimeType\Mapping::$types;
+ $extensions = [];
+ foreach ($mapping as $extension => $type) {
+ if ($mimeType == $type) {
+ $extensions[] = $extension;
+ }
+ }
+ return $extensions;
+ }
+
+ /**
+ * Get the extension of a file based on its path
+ * @param string $path path of the file to query
+ * @return string
*/
- public function getMimeType($path = NULL) {
- return mime_content_type($path);
+ public static function getExtensionFromPath($path) {
+ return pathinfo($path, PATHINFO_EXTENSION);
}
}
"psr/simple-cache": "~1.0.1",
"cweagans/composer-patches": "~1.0",
"pear/log": "1.13.1",
- "ezyang/htmlpurifier": "4.10"
+ "ezyang/htmlpurifier": "4.10",
+ "katzien/php-mime-type": "2.1.0"
},
"scripts": {
"post-install-cmd": [
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "93a9f686f7eb00fb9d766d262eedb09b",
+ "content-hash": "2a06373b9174ae3aa2bfb820e2e5a35e",
"packages": [
{
"name": "civicrm/civicrm-cxn-rpc",
],
"time": "2017-03-20T17:10:46+00:00"
},
+ {
+ "name": "katzien/php-mime-type",
+ "version": "2.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/katzien/PhpMimeType.git",
+ "reference": "159dfbdcd5906442f3dad89951127f0b9dfa3b78"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/katzien/PhpMimeType/zipball/159dfbdcd5906442f3dad89951127f0b9dfa3b78",
+ "reference": "159dfbdcd5906442f3dad89951127f0b9dfa3b78",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "5.*",
+ "satooshi/php-coveralls": "1.*"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "MimeType\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Kat Zien"
+ }
+ ],
+ "description": "A PHP library to detect the mime type of files.",
+ "homepage": "https://github.com/katzien/PhpMimeType",
+ "keywords": [
+ "mimetype",
+ "php"
+ ],
+ "time": "2017-03-23T02:05:33+00:00"
+ },
{
"name": "marcj/topsort",
"version": "1.1.0",
'help_text' => NULL,
'validate_callback' => 'CRM_Utils_Rule::color',
],
+ 'requestableMimeTypes' => [
+ 'group_name' => 'CiviCRM Preferences',
+ 'group' => 'core',
+ 'name' => 'requestableMimeTypes',
+ 'type' => 'String',
+ 'html_type' => 'Text',
+ 'default' => 'image/jpeg,image/pjpeg,image/gif,image/x-png,image/png,image/jpg,text/html,application/pdf',
+ 'add' => '5.13',
+ 'title' => ts('Mime Types that can be passed as URL params'),
+ 'is_domain' => 1,
+ 'is_contact' => 0,
+ 'description' => ts('Acceptable Mime Types that can be used as part of file urls'),
+ 'help_text' => NULL,
+ ],
];
$this->assertEquals($expectedResult, CRM_Utils_File::isValidFileName($fileName));
}
+ public function pathToFileExtension() {
+ $cases = [];
+ $cases[] = ['/evil.pdf', 'pdf'];
+ $cases[] = ['/helloworld.jpg', 'jpg'];
+ $cases[] = ['/smartwatch_1736683_1280_9af3657015e8660cc234eb1601da871.jpg', 'jpg'];
+ return $cases;
+ }
+
+ /**
+ * Test returning appropriate file extension
+ * @dataProvider pathToFileExtension
+ * @param string $path
+ * @param string $expectedExtension
+ */
+ public function testPathToExtension($path, $expectedExtension) {
+ $this->assertEquals($expectedExtension, CRM_Utils_File::getExtensionFromPath($path));
+ }
+
+ public function mimeTypeToExtension() {
+ $cases = [];
+ $cases[] = ['text/plain', ['txt', 'text', 'conf', 'def', 'list', 'log', 'in']];
+ $cases[] = ['image/jpeg', ['jpeg','jpg', 'jpe']];
+ $cases[] = ['image/png', ['png']];
+ return $cases;
+ }
+
+ /**
+ * @dataProvider mimeTypeToExtension
+ * @param stirng $mimeType
+ * @param array $expectedExtensions
+ */
+ public function testMimeTypeToExtension($mimeType, $expectedExtensions) {
+ $this->assertEquals($expectedExtensions, CRM_Utils_File::getAcceptableExtensionsForMimeType($mimeType));
+ }
+
}