View source
<?php
namespace Drupal\mimedetect;
use Drupal\file\FileInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\File\FileSystemInterface;
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface;
class MimeDetectService implements MimeDetectServiceInterface {
protected $fileSystem;
protected $mimeTypeGuesser;
protected $mimeDetectorPluginManager;
protected $finfo;
protected $unixfilecmd;
public function __construct(ConfigFactoryInterface $config_factory, FileSystemInterface $file_system, MimeTypeGuesserInterface $mime_type_guesser, MimeDetectPluginManager $mime_detector_plugin) {
$this->fileSystem = $file_system;
$this->mimeTypeGuesser = $mime_type_guesser;
$this->mimeDetectorPluginManager = $mime_detector_plugin;
$config = $config_factory
->get('mimedetect.settings');
if ($config
->get('fileinfo.enable') && $this
->checkFileinfo($config
->get('magicfile'))) {
$this->finfo = new \finfo(FILEINFO_MIME_TYPE, $config
->get('magicfile'));
}
if ($config
->get('unixfile.enable') && $this
->checkUnixfile($config
->get('unixfile.binary'), $config
->get('magicfile'))) {
$this->unixfilecmd = $config
->get('unixfile.binary') . ' --brief --mime' . (!empty($config
->get('magicfile')) ? ' --magic-file=' . escapeshellarg($config
->get('magicfile')) : '') . ' ';
}
}
public function getMime(FileInterface $file) {
$file_path = $this->fileSystem
->realpath($file
->getFileUri());
$mime = $this
->getMimeByDetector($file);
if (!$mime && $this->finfo) {
$mime = $this->finfo
->file($file_path);
}
if ((!$mime || $mime == 'application/octet-stream') && $this->unixfilecmd) {
$mime = trim(exec($this->unixfilecmd . escapeshellarg($file_path)));
}
if ($mime) {
$mime = explode(';', $mime);
$mime = trim($mime[0]);
}
else {
$mime = $this->mimeTypeGuesser
->guess($file_path);
}
return $mime ?: 'application/octet-stream';
}
protected function getMimeByDetector(FileInterface $file) {
$filename_parts = explode('.', $file
->getFilename());
$filename_extension = strtolower(array_pop($filename_parts));
$file_path = $this->fileSystem
->realpath($file
->getFileUri());
$mime = NULL;
foreach ($this->mimeDetectorPluginManager
->getDefinitions() as $plugin_id => $definition) {
if (in_array($filename_extension, $definition['filename_extensions']) && ($mime = $this->mimeDetectorPluginManager
->createInstance($plugin_id)
->detect($file_path))) {
break;
}
}
return $mime;
}
public static function checkMagicfile($magic_file, &$msg = '') {
$errors = FALSE;
if ($errors = !file_exists($magic_file)) {
$msg = t("The path %path does not exist or is not readable by your webserver.", [
'%path' => $magic_file,
]);
}
elseif ($errors = filetype($magic_file) != 'file' || !@filesize($magic_file)) {
$msg = t("Could not load the magic file %path.", [
'%path' => $magic_file,
]);
}
return !$errors;
}
public static function checkFileinfo($magic_file = '', &$msg = '') {
$errors = !empty($magic_file) ? !MimeDetectService::checkMagicfile($magic_file, $msg) : FALSE;
if ($errors) {
return FALSE;
}
if ($errors = !extension_loaded('fileinfo')) {
$msg = t('PHP file information extension not found.');
}
elseif ($errors = !@finfo_open(FILEINFO_MIME, $magic_file)) {
if (!empty($magic_file)) {
$msg = t('Fileinfo cannot load the configured magic file %path. It could be corrupted. Try another magic file or remove your magic file path settings to use defaults.', [
'%path' => $magic_file,
]);
}
else {
$msg = t('Fileinfo could not load magic information. Check the MAGIC environment variable on your system and that fileinfo PHP extension is properly installed.');
}
}
return !$errors;
}
public static function checkUnixfile($bin_file = '/usr/bin/file', $magic_file = '', &$msg = '') {
$errors = !empty($magic_file) ? !MimeDetectService::checkMagicfile($magic_file, $msg) : FALSE;
if ($errors) {
return FALSE;
}
if ($errors = empty($bin_file)) {
$msg = t("You must specify the path to the 'file' binary if it is enabled.");
}
elseif ($errors = basename($bin_file) != 'file') {
$msg = t("Base name %basename for the 'file' binary not allowed. Must be 'file'.", [
'%basename' => basename($bin_file),
]);
}
elseif ($errors = !file_exists($bin_file)) {
$msg = t("The path %path does not exist or is not readable by your webserver.", [
'%path' => $bin_file,
]);
}
elseif ($errors = !is_executable($bin_file)) {
$msg = t("%path is not executable by your webserver.", [
'%path' => $bin_file,
]);
}
else {
$exit_code = 0;
$output = NULL;
exec($bin_file . (!empty($magic_file) ? ' --magic-file=' . escapeshellarg($magic_file) : '') . ' --version', $output, $exit_code);
if ($errors = $exit_code !== 0) {
if (!empty($magic_file)) {
$msg = t('File command execution failed with exit code %code. Could not load the magic file %file.', [
'%code' => $exit_code,
'%file' => $magic_file,
]);
}
else {
$msg = t('File command execution failed with exit code %code.', [
'%code' => $exit_code,
]);
}
}
elseif ($errors = !is_array($output) || !count($output) || strpos($output[0], 'file-') !== 0) {
$msg = t('Unable to determine the UNIX file command version.');
}
else {
$msg = substr($output[0], strlen('file-'));
}
}
return !$errors;
}
}