Source of file MimeUploadValidator.php
Size: 5,394 Bytes - Last Modified: 2021-12-23T10:33:12+00:00
/var/www/docs.ssmods.com/process/src/src/MimeUploadValidator.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 | <?php namespace SilverStripe\MimeValidator; use finfo; use Exception; use SilverStripe\Core\Config\Config; use SilverStripe\Control\HTTP; use SilverStripe\Assets\Upload_Validator; /** * Adds an additional validation rule to Upload_Validator that attempts to detect * the file extension of an uploaded file matches it's contents, which is done * by detecting the MIME type and doing a fuzzy match. * * Class MimeUploadValidator * @package SilverStripe\MimeValidator */ class MimeUploadValidator extends Upload_Validator { /** * The preg_replace() pattern to use against MIME types. Used to strip out * useless characters so matching of MIME types can be fuzzy. * * @var string Regexp pattern */ protected $filterPattern = '/.*[\/\.\-\+]/i'; /** * @param string $pattern */ public function setFilterPattern($pattern) { $this->filterPattern = $pattern; } /** * @return string */ public function getFilterPattern() { return $this->filterPattern; } /** * Check if the temporary file has a valid MIME type for it's extension. * * @uses finfo php extension * @return bool|null * @throws MimeUploadValidatorException */ public function isValidMime() { $extension = strtolower(pathinfo($this->tmpFile['name'], PATHINFO_EXTENSION)); // we can't check filenames without an extension or no temp file path, let them pass validation. if (!$extension || !$this->tmpFile['tmp_name']) { return true; } $expectedMimes = $this->getExpectedMimeTypes($this->tmpFile); if (empty($expectedMimes)) { throw new MimeUploadValidatorException( sprintf('Could not find a MIME type for extension %s', $extension) ); } $fileInfo = new finfo(FILEINFO_MIME_TYPE); $foundMime = $fileInfo->file($this->tmpFile['tmp_name']); if (!$foundMime) { throw new MimeUploadValidatorException( sprintf('Could not find a MIME type for file %s', $this->tmpFile['tmp_name']) ); } foreach ($expectedMimes as $expected) { if ($this->compareMime($foundMime, $expected)) { return true; } } return false; } /** * Fetches an array of valid mimetypes. * * @param $file * @return array * @throws MimeUploadValidatorException */ public function getExpectedMimeTypes($file) { $extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION)); // if the finfo php extension isn't loaded, we can't complete this check. if (!class_exists('finfo')) { throw new MimeUploadValidatorException('PHP extension finfo is not loaded'); } // Attempt to figure out which mime types are expected/acceptable here. $expectedMimes = array(); // Get the mime types set in framework core $knownMimes = Config::inst()->get(HTTP::class, 'MimeTypes'); if (isset($knownMimes[$extension])) { $expectedMimes[] = $knownMimes[$extension]; } // Get the mime types and their variations from mime validator $knownMimes = $this->config()->get('MimeTypes'); if (isset($knownMimes[$extension])) { $mimes = (array) $knownMimes[$extension]; foreach ($mimes as $mime) { if (!in_array($mime, $expectedMimes)) { $expectedMimes[] = $mime; } } } return $expectedMimes; } /** * Check two MIME types roughly match eachother. * * Before we check MIME types, remove known prefixes "vnd.", "x-" etc. * If there is a suffix, we'll use that to compare. Examples: * * application/x-json = json * application/json = json * application/xhtml+xml = xml * application/xml = xml * * @param string $first The first MIME type to compare to the second * @param string $second The second MIME type to compare to the first * @return boolean */ public function compareMime($first, $second) { return preg_replace($this->filterPattern, '', $first) === preg_replace($this->filterPattern, '', $second); } public function validate() { if (parent::validate() === false) { return false; } try { $result = $this->isValidMime(); if ($result === false) { $extension = strtolower(pathinfo($this->tmpFile['name'], PATHINFO_EXTENSION)); $this->errors[] = _t( __CLASS__ . '.INVALIDMIME', 'File type does not match extension (.{extension})', [ 'extension' => $extension, ] ); return false; } } catch (MimeUploadValidatorException $e) { $this->errors[] = _t( __CLASS__ . '.FAILEDMIMECHECK', 'MIME validation failed: {message}', 'Argument 1: Message about why MIME type detection failed', ['message' => $e->getMessage()] ); return false; } return true; } } |