feature #29896 [Mime] Add the component (fabpot)
This PR was squashed before being merged into the 4.3-dev branch (closes #29896). Discussion ---------- [Mime] Add the component | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no <!-- see https://symfony.com/bc --> | Deprecations? | yes | Tests pass? | yes | Fixed tickets | #28832 #21985 makes #15460 trivial | License | MIT | Doc PR | symfony/symfony-docs#10886 This has been on my todo-list for X years :) Commits -------bdca5d999b
tweaked code5268389191
[Mime] added freedesktop as a source for mime types74ca91deaa
[Mime] added the componentd7ee0ecc49
[HttpFoundation] updated File code
This commit is contained in:
commit
db6784bb09
@ -60,6 +60,7 @@
|
|||||||
"symfony/ldap": "self.version",
|
"symfony/ldap": "self.version",
|
||||||
"symfony/lock": "self.version",
|
"symfony/lock": "self.version",
|
||||||
"symfony/messenger": "self.version",
|
"symfony/messenger": "self.version",
|
||||||
|
"symfony/mime": "self.version",
|
||||||
"symfony/monolog-bridge": "self.version",
|
"symfony/monolog-bridge": "self.version",
|
||||||
"symfony/options-resolver": "self.version",
|
"symfony/options-resolver": "self.version",
|
||||||
"symfony/process": "self.version",
|
"symfony/process": "self.version",
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers custom mime types guessers.
|
||||||
|
*
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class AddMimeTypeGuesserPass implements CompilerPassInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function process(ContainerBuilder $container)
|
||||||
|
{
|
||||||
|
if ($container->has('mime_types')) {
|
||||||
|
$definition = $container->findDefinition('mime_types');
|
||||||
|
foreach ($container->findTaggedServiceIds('mime.mime_type_guesser', true) as $id => $attributes) {
|
||||||
|
$definition->addMethodCall('registerGuesser', [new Reference($id)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -42,6 +42,7 @@ class UnusedTagsPass implements CompilerPassInterface
|
|||||||
'messenger.bus',
|
'messenger.bus',
|
||||||
'messenger.receiver',
|
'messenger.receiver',
|
||||||
'messenger.message_handler',
|
'messenger.message_handler',
|
||||||
|
'mime.mime_type_guesser',
|
||||||
'monolog.logger',
|
'monolog.logger',
|
||||||
'proxy',
|
'proxy',
|
||||||
'routing.expression_language_provider',
|
'routing.expression_language_provider',
|
||||||
|
@ -73,6 +73,8 @@ use Symfony\Component\Messenger\MessageBusInterface;
|
|||||||
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
|
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
|
||||||
use Symfony\Component\Messenger\Transport\TransportFactoryInterface;
|
use Symfony\Component\Messenger\Transport\TransportFactoryInterface;
|
||||||
use Symfony\Component\Messenger\Transport\TransportInterface;
|
use Symfony\Component\Messenger\Transport\TransportInterface;
|
||||||
|
use Symfony\Component\Mime\MimeTypeGuesserInterface;
|
||||||
|
use Symfony\Component\Mime\MimeTypes;
|
||||||
use Symfony\Component\PropertyAccess\PropertyAccessor;
|
use Symfony\Component\PropertyAccess\PropertyAccessor;
|
||||||
use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface;
|
use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface;
|
||||||
use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface;
|
use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface;
|
||||||
@ -310,6 +312,10 @@ class FrameworkExtension extends Extension
|
|||||||
'Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController',
|
'Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if (class_exists(MimeTypes::class)) {
|
||||||
|
$loader->load('mime_type.xml');
|
||||||
|
}
|
||||||
|
|
||||||
$container->registerForAutoconfiguration(Command::class)
|
$container->registerForAutoconfiguration(Command::class)
|
||||||
->addTag('console.command');
|
->addTag('console.command');
|
||||||
$container->registerForAutoconfiguration(ResourceCheckerInterface::class)
|
$container->registerForAutoconfiguration(ResourceCheckerInterface::class)
|
||||||
@ -374,6 +380,8 @@ class FrameworkExtension extends Extension
|
|||||||
->addTag('messenger.message_handler');
|
->addTag('messenger.message_handler');
|
||||||
$container->registerForAutoconfiguration(TransportFactoryInterface::class)
|
$container->registerForAutoconfiguration(TransportFactoryInterface::class)
|
||||||
->addTag('messenger.transport_factory');
|
->addTag('messenger.transport_factory');
|
||||||
|
$container->registerForAutoconfiguration(MimeTypeGuesserInterface::class)
|
||||||
|
->addTag('mime.mime_type_guesser');
|
||||||
$container->registerForAutoconfiguration(LoggerAwareInterface::class)
|
$container->registerForAutoconfiguration(LoggerAwareInterface::class)
|
||||||
->addMethodCall('setLogger', [new Reference('logger')]);
|
->addMethodCall('setLogger', [new Reference('logger')]);
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ namespace Symfony\Bundle\FrameworkBundle;
|
|||||||
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass;
|
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass;
|
||||||
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddDebugLogProcessorPass;
|
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddDebugLogProcessorPass;
|
||||||
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddExpressionLanguageProvidersPass;
|
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddExpressionLanguageProvidersPass;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddMimeTypeGuesserPass;
|
||||||
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilderDebugDumpPass;
|
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilderDebugDumpPass;
|
||||||
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\DataCollectorTranslatorPass;
|
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\DataCollectorTranslatorPass;
|
||||||
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass;
|
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass;
|
||||||
@ -72,6 +73,11 @@ class FrameworkBundle extends Bundle
|
|||||||
if ($trustedHosts = $this->container->getParameter('kernel.trusted_hosts')) {
|
if ($trustedHosts = $this->container->getParameter('kernel.trusted_hosts')) {
|
||||||
Request::setTrustedHosts($trustedHosts);
|
Request::setTrustedHosts($trustedHosts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->container->has('mime_types')) {
|
||||||
|
$mt = $this->container->get('mime_types');
|
||||||
|
$mt->setDefault($mt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function build(ContainerBuilder $container)
|
public function build(ContainerBuilder $container)
|
||||||
@ -118,6 +124,7 @@ class FrameworkBundle extends Bundle
|
|||||||
$container->addCompilerPass(new ResettableServicePass());
|
$container->addCompilerPass(new ResettableServicePass());
|
||||||
$container->addCompilerPass(new TestServiceContainerWeakRefPass(), PassConfig::TYPE_BEFORE_REMOVING, -32);
|
$container->addCompilerPass(new TestServiceContainerWeakRefPass(), PassConfig::TYPE_BEFORE_REMOVING, -32);
|
||||||
$container->addCompilerPass(new TestServiceContainerRealRefPass(), PassConfig::TYPE_AFTER_REMOVING);
|
$container->addCompilerPass(new TestServiceContainerRealRefPass(), PassConfig::TYPE_AFTER_REMOVING);
|
||||||
|
$container->addCompilerPass(new AddMimeTypeGuesserPass());
|
||||||
$this->addCompilerPassIfExists($container, MessengerPass::class);
|
$this->addCompilerPassIfExists($container, MessengerPass::class);
|
||||||
|
|
||||||
if ($container->getParameter('kernel.debug')) {
|
if ($container->getParameter('kernel.debug')) {
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" ?>
|
||||||
|
|
||||||
|
<container xmlns="http://symfony.com/schema/dic/services"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||||
|
|
||||||
|
<services>
|
||||||
|
<defaults public="false" />
|
||||||
|
|
||||||
|
<service id="mime_types" class="Symfony\Component\Mime\MimeTypes" public="true" />
|
||||||
|
</services>
|
||||||
|
</container>
|
@ -42,6 +42,7 @@
|
|||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service id="serializer.normalizer.data_uri" class="Symfony\Component\Serializer\Normalizer\DataUriNormalizer">
|
<service id="serializer.normalizer.data_uri" class="Symfony\Component\Serializer\Normalizer\DataUriNormalizer">
|
||||||
|
<argument type="service" id="mime_types" on-invalid="null" />
|
||||||
<!-- Run before serializer.normalizer.object -->
|
<!-- Run before serializer.normalizer.object -->
|
||||||
<tag name="serializer.normalizer" priority="-920" />
|
<tag name="serializer.normalizer" priority="-920" />
|
||||||
</service>
|
</service>
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddMimeTypeGuesserPass;
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use Symfony\Component\DependencyInjection\Definition;
|
||||||
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
|
use Symfony\Component\Mime\FileinfoMimeTypeGuesser;
|
||||||
|
use Symfony\Component\Mime\MimeTypes;
|
||||||
|
|
||||||
|
class AddMimeTypeGuesserPassTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testTags()
|
||||||
|
{
|
||||||
|
$container = new ContainerBuilder();
|
||||||
|
$container->addCompilerPass(new AddMimeTypeGuesserPass());
|
||||||
|
|
||||||
|
$definition = new Definition(FileinfoMimeTypeGuesser::class);
|
||||||
|
$definition->addArgument('/path/to/magic/file');
|
||||||
|
$definition->addTag('mime.mime_type_guesser');
|
||||||
|
$container->setDefinition('some_mime_type_guesser', $definition->setPublic(true));
|
||||||
|
$container->register('mime_types', MimeTypes::class)->setPublic(true);
|
||||||
|
$container->compile();
|
||||||
|
|
||||||
|
$router = $container->getDefinition('mime_types');
|
||||||
|
$calls = $router->getMethodCalls();
|
||||||
|
$this->assertCount(1, $calls);
|
||||||
|
$this->assertEquals('registerGuesser', $calls[0][0]);
|
||||||
|
$this->assertEquals(new Reference('some_mime_type_guesser'), $calls[0][1][0]);
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,7 @@
|
|||||||
"symfony/contracts": "^1.0.2",
|
"symfony/contracts": "^1.0.2",
|
||||||
"symfony/dependency-injection": "^4.2",
|
"symfony/dependency-injection": "^4.2",
|
||||||
"symfony/event-dispatcher": "^4.1",
|
"symfony/event-dispatcher": "^4.1",
|
||||||
"symfony/http-foundation": "^4.1.2",
|
"symfony/http-foundation": "^4.3",
|
||||||
"symfony/http-kernel": "^4.2",
|
"symfony/http-kernel": "^4.2",
|
||||||
"symfony/polyfill-mbstring": "~1.0",
|
"symfony/polyfill-mbstring": "~1.0",
|
||||||
"symfony/filesystem": "~3.4|~4.0",
|
"symfony/filesystem": "~3.4|~4.0",
|
||||||
@ -43,10 +43,11 @@
|
|||||||
"symfony/form": "^4.2",
|
"symfony/form": "^4.2",
|
||||||
"symfony/expression-language": "~3.4|~4.0",
|
"symfony/expression-language": "~3.4|~4.0",
|
||||||
"symfony/messenger": "^4.2",
|
"symfony/messenger": "^4.2",
|
||||||
|
"symfony/mime": "^4.3",
|
||||||
"symfony/process": "~3.4|~4.0",
|
"symfony/process": "~3.4|~4.0",
|
||||||
"symfony/security-core": "~3.4|~4.0",
|
"symfony/security-core": "~3.4|~4.0",
|
||||||
"symfony/security-csrf": "~3.4|~4.0",
|
"symfony/security-csrf": "~3.4|~4.0",
|
||||||
"symfony/serializer": "^4.2",
|
"symfony/serializer": "^4.3",
|
||||||
"symfony/stopwatch": "~3.4|~4.0",
|
"symfony/stopwatch": "~3.4|~4.0",
|
||||||
"symfony/translation": "~4.2",
|
"symfony/translation": "~4.2",
|
||||||
"symfony/templating": "~3.4|~4.0",
|
"symfony/templating": "~3.4|~4.0",
|
||||||
|
@ -13,8 +13,7 @@ namespace Symfony\Component\HttpFoundation\File;
|
|||||||
|
|
||||||
use Symfony\Component\HttpFoundation\File\Exception\FileException;
|
use Symfony\Component\HttpFoundation\File\Exception\FileException;
|
||||||
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
|
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
|
||||||
use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser;
|
use Symfony\Component\Mime\MimeTypes;
|
||||||
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A file in the file system.
|
* A file in the file system.
|
||||||
@ -50,33 +49,28 @@ class File extends \SplFileInfo
|
|||||||
*
|
*
|
||||||
* @return string|null The guessed extension or null if it cannot be guessed
|
* @return string|null The guessed extension or null if it cannot be guessed
|
||||||
*
|
*
|
||||||
* @see ExtensionGuesser
|
* @see MimeTypes
|
||||||
* @see getMimeType()
|
* @see getMimeType()
|
||||||
*/
|
*/
|
||||||
public function guessExtension()
|
public function guessExtension()
|
||||||
{
|
{
|
||||||
$type = $this->getMimeType();
|
return MimeTypes::getDefault()->getExtensions($this->getMimeType())[0] ?? null;
|
||||||
$guesser = ExtensionGuesser::getInstance();
|
|
||||||
|
|
||||||
return $guesser->guess($type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the mime type of the file.
|
* Returns the mime type of the file.
|
||||||
*
|
*
|
||||||
* The mime type is guessed using a MimeTypeGuesser instance, which uses finfo(),
|
* The mime type is guessed using a MimeTypeGuesserInterface instance,
|
||||||
* mime_content_type() and the system binary "file" (in this order), depending on
|
* which uses finfo_file() then the "file" system binary,
|
||||||
* which of those are available.
|
* depending on which of those are available.
|
||||||
*
|
*
|
||||||
* @return string|null The guessed mime type (e.g. "application/pdf")
|
* @return string|null The guessed mime type (e.g. "application/pdf")
|
||||||
*
|
*
|
||||||
* @see MimeTypeGuesser
|
* @see MimeTypes
|
||||||
*/
|
*/
|
||||||
public function getMimeType()
|
public function getMimeType()
|
||||||
{
|
{
|
||||||
$guesser = MimeTypeGuesser::getInstance();
|
return MimeTypes::getDefault()->guessMimeType($this->getPathname());
|
||||||
|
|
||||||
return $guesser->guess($this->getPathname());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,6 +11,10 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\HttpFoundation\File\MimeType;
|
namespace Symfony\Component\HttpFoundation\File\MimeType;
|
||||||
|
|
||||||
|
use Symfony\Component\Mime\MimeTypes;
|
||||||
|
|
||||||
|
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" instead.', ExtensionGuesser::class, MimeTypes::class), E_USER_DEPRECATED);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A singleton mime type to file extension guesser.
|
* A singleton mime type to file extension guesser.
|
||||||
*
|
*
|
||||||
@ -22,6 +26,8 @@ namespace Symfony\Component\HttpFoundation\File\MimeType;
|
|||||||
* $guesser->register(new MyCustomExtensionGuesser());
|
* $guesser->register(new MyCustomExtensionGuesser());
|
||||||
*
|
*
|
||||||
* The last registered guesser is preferred over previously registered ones.
|
* The last registered guesser is preferred over previously registered ones.
|
||||||
|
*
|
||||||
|
* @deprecated since Symfony 4.3, use {@link MimeTypes} instead
|
||||||
*/
|
*/
|
||||||
class ExtensionGuesser implements ExtensionGuesserInterface
|
class ExtensionGuesser implements ExtensionGuesserInterface
|
||||||
{
|
{
|
||||||
|
@ -11,8 +11,12 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\HttpFoundation\File\MimeType;
|
namespace Symfony\Component\HttpFoundation\File\MimeType;
|
||||||
|
|
||||||
|
use Symfony\Component\Mime\MimeTypes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Guesses the file extension corresponding to a given mime type.
|
* Guesses the file extension corresponding to a given mime type.
|
||||||
|
*
|
||||||
|
* @deprecated since Symfony 4.3, use {@link MimeTypes} instead
|
||||||
*/
|
*/
|
||||||
interface ExtensionGuesserInterface
|
interface ExtensionGuesserInterface
|
||||||
{
|
{
|
||||||
|
@ -13,11 +13,16 @@ namespace Symfony\Component\HttpFoundation\File\MimeType;
|
|||||||
|
|
||||||
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
|
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
|
||||||
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
|
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
|
||||||
|
use Symfony\Component\Mime\FileBinaryMimeTypeGuesser as NewFileBinaryMimeTypeGuesser;
|
||||||
|
|
||||||
|
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" instead.', FileBinaryMimeTypeGuesser::class, NewFileBinaryMimeTypeGuesser::class), E_USER_DEPRECATED);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Guesses the mime type with the binary "file" (only available on *nix).
|
* Guesses the mime type with the binary "file" (only available on *nix).
|
||||||
*
|
*
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*
|
||||||
|
* @deprecated since Symfony 4.3, use {@link NewFileBinaryMimeTypeGuesser} instead
|
||||||
*/
|
*/
|
||||||
class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface
|
class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface
|
||||||
{
|
{
|
||||||
|
@ -13,11 +13,16 @@ namespace Symfony\Component\HttpFoundation\File\MimeType;
|
|||||||
|
|
||||||
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
|
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
|
||||||
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
|
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
|
||||||
|
use Symfony\Component\Mime\FileinfoMimeTypeGuesser as NewFileinfoMimeTypeGuesser;
|
||||||
|
|
||||||
|
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" instead.', FileinfoMimeTypeGuesser::class, NewFileinfoMimeTypeGuesser::class), E_USER_DEPRECATED);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Guesses the mime type using the PECL extension FileInfo.
|
* Guesses the mime type using the PECL extension FileInfo.
|
||||||
*
|
*
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*
|
||||||
|
* @deprecated since Symfony 4.3, use {@link NewFileinfoMimeTypeGuesser} instead
|
||||||
*/
|
*/
|
||||||
class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface
|
class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface
|
||||||
{
|
{
|
||||||
|
@ -11,8 +11,14 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\HttpFoundation\File\MimeType;
|
namespace Symfony\Component\HttpFoundation\File\MimeType;
|
||||||
|
|
||||||
|
use Symfony\Component\Mime\MimeTypes;
|
||||||
|
|
||||||
|
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" instead.', MimeTypeExtensionGuesser::class, MimeTypes::class), E_USER_DEPRECATED);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a best-guess mapping of mime type to file extension.
|
* Provides a best-guess mapping of mime type to file extension.
|
||||||
|
*
|
||||||
|
* @deprecated since Symfony 4.3, use {@link MimeTypes} instead
|
||||||
*/
|
*/
|
||||||
class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
|
class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
|
||||||
{
|
{
|
||||||
|
@ -13,6 +13,9 @@ namespace Symfony\Component\HttpFoundation\File\MimeType;
|
|||||||
|
|
||||||
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
|
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
|
||||||
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
|
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
|
||||||
|
use Symfony\Component\Mime\MimeTypes;
|
||||||
|
|
||||||
|
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" instead.', MimeTypeGuesser::class, MimeTypes::class), E_USER_DEPRECATED);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A singleton mime type guesser.
|
* A singleton mime type guesser.
|
||||||
|
@ -13,11 +13,14 @@ namespace Symfony\Component\HttpFoundation\File\MimeType;
|
|||||||
|
|
||||||
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
|
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
|
||||||
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
|
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
|
||||||
|
use Symfony\Component\Mime\MimeTypes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Guesses the mime type of a file.
|
* Guesses the mime type of a file.
|
||||||
*
|
*
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*
|
||||||
|
* @deprecated since Symfony 4.3, use {@link MimeTypes} instead
|
||||||
*/
|
*/
|
||||||
interface MimeTypeGuesserInterface
|
interface MimeTypeGuesserInterface
|
||||||
{
|
{
|
||||||
|
@ -20,7 +20,7 @@ use Symfony\Component\HttpFoundation\File\Exception\IniSizeFileException;
|
|||||||
use Symfony\Component\HttpFoundation\File\Exception\NoFileException;
|
use Symfony\Component\HttpFoundation\File\Exception\NoFileException;
|
||||||
use Symfony\Component\HttpFoundation\File\Exception\NoTmpDirFileException;
|
use Symfony\Component\HttpFoundation\File\Exception\NoTmpDirFileException;
|
||||||
use Symfony\Component\HttpFoundation\File\Exception\PartialFileException;
|
use Symfony\Component\HttpFoundation\File\Exception\PartialFileException;
|
||||||
use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser;
|
use Symfony\Component\Mime\MimeTypes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A file uploaded through a form.
|
* A file uploaded through a form.
|
||||||
@ -140,10 +140,7 @@ class UploadedFile extends File
|
|||||||
*/
|
*/
|
||||||
public function guessClientExtension()
|
public function guessClientExtension()
|
||||||
{
|
{
|
||||||
$type = $this->getClientMimeType();
|
return MimeTypes::getDefault()->getExtensions($this->getClientMimeType())[0] ?? null;
|
||||||
$guesser = ExtensionGuesser::getInstance();
|
|
||||||
|
|
||||||
return $guesser->guess($type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,8 +13,10 @@ namespace Symfony\Component\HttpFoundation\Tests\File;
|
|||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\HttpFoundation\File\File;
|
use Symfony\Component\HttpFoundation\File\File;
|
||||||
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires extension fileinfo
|
||||||
|
*/
|
||||||
class FileTest extends TestCase
|
class FileTest extends TestCase
|
||||||
{
|
{
|
||||||
protected $file;
|
protected $file;
|
||||||
@ -22,50 +24,24 @@ class FileTest extends TestCase
|
|||||||
public function testGetMimeTypeUsesMimeTypeGuessers()
|
public function testGetMimeTypeUsesMimeTypeGuessers()
|
||||||
{
|
{
|
||||||
$file = new File(__DIR__.'/Fixtures/test.gif');
|
$file = new File(__DIR__.'/Fixtures/test.gif');
|
||||||
$guesser = $this->createMockGuesser($file->getPathname(), 'image/gif');
|
|
||||||
|
|
||||||
MimeTypeGuesser::getInstance()->register($guesser);
|
|
||||||
|
|
||||||
$this->assertEquals('image/gif', $file->getMimeType());
|
$this->assertEquals('image/gif', $file->getMimeType());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGuessExtensionWithoutGuesser()
|
public function testGuessExtensionWithoutGuesser()
|
||||||
{
|
{
|
||||||
$file = new File(__DIR__.'/Fixtures/directory/.empty');
|
$file = new File(__DIR__.'/Fixtures/directory/.empty');
|
||||||
|
|
||||||
$this->assertNull($file->guessExtension());
|
$this->assertNull($file->guessExtension());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGuessExtensionIsBasedOnMimeType()
|
public function testGuessExtensionIsBasedOnMimeType()
|
||||||
{
|
{
|
||||||
$file = new File(__DIR__.'/Fixtures/test');
|
$file = new File(__DIR__.'/Fixtures/test');
|
||||||
$guesser = $this->createMockGuesser($file->getPathname(), 'image/gif');
|
|
||||||
|
|
||||||
MimeTypeGuesser::getInstance()->register($guesser);
|
|
||||||
|
|
||||||
$this->assertEquals('gif', $file->guessExtension());
|
$this->assertEquals('gif', $file->guessExtension());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @requires extension fileinfo
|
|
||||||
*/
|
|
||||||
public function testGuessExtensionWithReset()
|
|
||||||
{
|
|
||||||
$file = new File(__DIR__.'/Fixtures/other-file.example');
|
|
||||||
$guesser = $this->createMockGuesser($file->getPathname(), 'image/gif');
|
|
||||||
MimeTypeGuesser::getInstance()->register($guesser);
|
|
||||||
|
|
||||||
$this->assertEquals('gif', $file->guessExtension());
|
|
||||||
|
|
||||||
MimeTypeGuesser::reset();
|
|
||||||
|
|
||||||
$this->assertNull($file->guessExtension());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testConstructWhenFileNotExists()
|
public function testConstructWhenFileNotExists()
|
||||||
{
|
{
|
||||||
$this->expectException('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException');
|
$this->expectException('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException');
|
||||||
|
|
||||||
new File(__DIR__.'/Fixtures/not_here');
|
new File(__DIR__.'/Fixtures/not_here');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,17 +140,4 @@ class FileTest extends TestCase
|
|||||||
@unlink($targetPath);
|
@unlink($targetPath);
|
||||||
@rmdir($targetDir);
|
@rmdir($targetDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createMockGuesser($path, $mimeType)
|
|
||||||
{
|
|
||||||
$guesser = $this->getMockBuilder('Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface')->getMock();
|
|
||||||
$guesser
|
|
||||||
->expects($this->once())
|
|
||||||
->method('guess')
|
|
||||||
->with($this->equalTo($path))
|
|
||||||
->will($this->returnValue($mimeType))
|
|
||||||
;
|
|
||||||
|
|
||||||
return $guesser;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,10 @@ use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @requires extension fileinfo
|
* @requires extension fileinfo
|
||||||
|
* @group legacy
|
||||||
*/
|
*/
|
||||||
class MimeTypeTest extends TestCase
|
class MimeTypeTest extends TestCase
|
||||||
{
|
{
|
||||||
protected $path;
|
|
||||||
|
|
||||||
public function testGuessImageWithoutExtension()
|
public function testGuessImageWithoutExtension()
|
||||||
{
|
{
|
||||||
$this->assertEquals('image/gif', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test'));
|
$this->assertEquals('image/gif', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test'));
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.1.3",
|
"php": "^7.1.3",
|
||||||
|
"symfony/mime": "^4.3",
|
||||||
"symfony/polyfill-mbstring": "~1.1"
|
"symfony/polyfill-mbstring": "~1.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
3
src/Symfony/Component/Mime/.gitignore
vendored
Normal file
3
src/Symfony/Component/Mime/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
composer.lock
|
||||||
|
phpunit.xml
|
||||||
|
vendor/
|
90
src/Symfony/Component/Mime/FileBinaryMimeTypeGuesser.php
Normal file
90
src/Symfony/Component/Mime/FileBinaryMimeTypeGuesser.php
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Mime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guesses the MIME type with the binary "file" (only available on *nix).
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface
|
||||||
|
{
|
||||||
|
private $cmd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The $cmd pattern must contain a "%s" string that will be replaced
|
||||||
|
* with the file name to guess.
|
||||||
|
*
|
||||||
|
* The command output must start with the MIME type of the file.
|
||||||
|
*
|
||||||
|
* @param string $cmd The command to run to get the MIME type of a file
|
||||||
|
*/
|
||||||
|
public function __construct(string $cmd = 'file -b --mime %s 2>/dev/null')
|
||||||
|
{
|
||||||
|
$this->cmd = $cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function isGuesserSupported(): bool
|
||||||
|
{
|
||||||
|
static $supported = null;
|
||||||
|
|
||||||
|
if (null !== $supported) {
|
||||||
|
return $supported;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('\\' === \DIRECTORY_SEPARATOR || !\function_exists('passthru') || !\function_exists('escapeshellarg')) {
|
||||||
|
return $supported = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
passthru('command -v file', $exitStatus);
|
||||||
|
$binPath = trim(ob_get_clean());
|
||||||
|
|
||||||
|
return $supported = 0 === $exitStatus && '' !== $binPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function guessMimeType(string $path): ?string
|
||||||
|
{
|
||||||
|
if (!is_file($path) || !is_readable($path)) {
|
||||||
|
throw new \InvalidArgumentException(sprintf('The "%s" file does not exist or is not readable.', $path));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->isGuesserSupported()) {
|
||||||
|
throw new \LogicException(sprintf('The "%s" guesser is not supported.', __CLASS__));
|
||||||
|
}
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
|
||||||
|
// need to use --mime instead of -i. see #6641
|
||||||
|
passthru(sprintf($this->cmd, escapeshellarg($path)), $return);
|
||||||
|
if ($return > 0) {
|
||||||
|
ob_end_clean();
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$type = trim(ob_get_clean());
|
||||||
|
|
||||||
|
if (!preg_match('#^([a-z0-9\-]+/[a-z0-9\-\.]+)#i', $type, $match)) {
|
||||||
|
// it's not a type, but an error message
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $match[1];
|
||||||
|
}
|
||||||
|
}
|
60
src/Symfony/Component/Mime/FileinfoMimeTypeGuesser.php
Normal file
60
src/Symfony/Component/Mime/FileinfoMimeTypeGuesser.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Mime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guesses the MIME type using the PECL extension FileInfo.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface
|
||||||
|
{
|
||||||
|
private $magicFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $magicFile A magic file to use with the finfo instance
|
||||||
|
*
|
||||||
|
* @see http://www.php.net/manual/en/function.finfo-open.php
|
||||||
|
*/
|
||||||
|
public function __construct(string $magicFile = null)
|
||||||
|
{
|
||||||
|
$this->magicFile = $magicFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function isGuesserSupported(): bool
|
||||||
|
{
|
||||||
|
return \function_exists('finfo_open');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function guessMimeType(string $path): ?string
|
||||||
|
{
|
||||||
|
if (!is_file($path) || !is_readable($path)) {
|
||||||
|
throw new \InvalidArgumentException(sprintf('The "%s" file does not exist or is not readable.', $path));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->isGuesserSupported()) {
|
||||||
|
throw new \LogicException(sprintf('The "%s" guesser is not supported.', __CLASS__));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $finfo = new \finfo(FILEINFO_MIME_TYPE, $this->magicFile)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $finfo->file($path);
|
||||||
|
}
|
||||||
|
}
|
19
src/Symfony/Component/Mime/LICENSE
Normal file
19
src/Symfony/Component/Mime/LICENSE
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Copyright (c) 2010-2019 Fabien Potencier
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is furnished
|
||||||
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
37
src/Symfony/Component/Mime/MimeTypeGuesserInterface.php
Normal file
37
src/Symfony/Component/Mime/MimeTypeGuesserInterface.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Mime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guesses the MIME type of a file.
|
||||||
|
*
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
interface MimeTypeGuesserInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns true if this guesser is supported.
|
||||||
|
*/
|
||||||
|
public function isGuesserSupported(): bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guesses the MIME type of the file with the given path.
|
||||||
|
*
|
||||||
|
* @param string $path The path to the file
|
||||||
|
*
|
||||||
|
* @return string The MIME type or null, if none could be guessed
|
||||||
|
*
|
||||||
|
* @throws \LogicException If the guesser is not supported
|
||||||
|
* @throws \InvalidArgumentException If the file does not exist or is not readable
|
||||||
|
*/
|
||||||
|
public function guessMimeType(string $path): ?string;
|
||||||
|
}
|
3130
src/Symfony/Component/Mime/MimeTypes.php
Normal file
3130
src/Symfony/Component/Mime/MimeTypes.php
Normal file
File diff suppressed because it is too large
Load Diff
32
src/Symfony/Component/Mime/MimeTypesInterface.php
Normal file
32
src/Symfony/Component/Mime/MimeTypesInterface.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Mime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
interface MimeTypesInterface extends MimeTypeGuesserInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Gets the extensions for the given MIME type.
|
||||||
|
*
|
||||||
|
* @return array an array of extensions (first one is the preferred one)
|
||||||
|
*/
|
||||||
|
public function getExtensions(string $mimeType): array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the MIME types for the given extension.
|
||||||
|
*
|
||||||
|
* @return array an array of MIME types (first one is the preferred one)
|
||||||
|
*/
|
||||||
|
public function getMimeTypes(string $ext): array;
|
||||||
|
}
|
14
src/Symfony/Component/Mime/README.md
Normal file
14
src/Symfony/Component/Mime/README.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
MIME Component
|
||||||
|
==============
|
||||||
|
|
||||||
|
The MIME component allows manipulating MIME types.
|
||||||
|
|
||||||
|
|
||||||
|
Resources
|
||||||
|
---------
|
||||||
|
|
||||||
|
* [Documentation](https://symfony.com/doc/current/components/mime.html)
|
||||||
|
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||||
|
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||||
|
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||||
|
in the [main Symfony repository](https://github.com/symfony/symfony)
|
104
src/Symfony/Component/Mime/Resources/bin/update_mime_types.php
Normal file
104
src/Symfony/Component/Mime/Resources/bin/update_mime_types.php
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// load new map
|
||||||
|
$data = file_get_contents('https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types');
|
||||||
|
$new = [];
|
||||||
|
foreach (explode("\n", $data) as $line) {
|
||||||
|
if (!$line || '#' == $line[0]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$mimeType = substr($line, 0, strpos($line, "\t"));
|
||||||
|
$extensions = explode(' ', substr($line, strrpos($line, "\t") + 1));
|
||||||
|
$new[$mimeType] = $extensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
$xml = simplexml_load_string(file_get_contents('https://raw.github.com/minad/mimemagic/master/script/freedesktop.org.xml'));
|
||||||
|
foreach ($xml as $node) {
|
||||||
|
$exts = [];
|
||||||
|
foreach ($node->glob as $glob) {
|
||||||
|
$pattern = (string) $glob['pattern'];
|
||||||
|
if ('*' != $pattern[0] || '.' != $pattern[1]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$exts[] = substr($pattern, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$exts) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$mt = strtolower((string) $node['type']);
|
||||||
|
$new[$mt] = array_merge($new[$mt] ?? [], $exts);
|
||||||
|
foreach ($node->alias as $alias) {
|
||||||
|
$mt = strtolower((string) $alias['type']);
|
||||||
|
$new[$mt] = array_merge($new[$mt] ?? [], $exts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// load current map
|
||||||
|
$data = file_get_contents($output = __DIR__.'/../../MimeTypes.php');
|
||||||
|
$current = [];
|
||||||
|
$pre = '';
|
||||||
|
$post = '';
|
||||||
|
foreach (explode("\n", $data) as $line) {
|
||||||
|
if (!preg_match("{^ '([^']+/[^']+)' => \['(.+)'\],$}", $line, $matches)) {
|
||||||
|
if (!$current) {
|
||||||
|
$pre .= $line."\n";
|
||||||
|
} else {
|
||||||
|
$post .= $line."\n";
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$current[$matches[1]] = explode("', '", $matches[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we merge the 2 maps (we never remove old mime types)
|
||||||
|
$map = array_replace_recursive($current, $new);
|
||||||
|
ksort($map);
|
||||||
|
|
||||||
|
$data = $pre;
|
||||||
|
foreach ($map as $mimeType => $exts) {
|
||||||
|
$data .= sprintf(" '%s' => ['%s'],\n", $mimeType, implode("', '", array_unique($exts)));
|
||||||
|
}
|
||||||
|
$data .= $post;
|
||||||
|
|
||||||
|
// reverse map
|
||||||
|
$exts = [];
|
||||||
|
foreach ($map as $mimeType => $extensions) {
|
||||||
|
foreach ($extensions as $extension) {
|
||||||
|
$exts[$extension][] = $mimeType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ksort($exts);
|
||||||
|
|
||||||
|
$updated = '';
|
||||||
|
$state = 0;
|
||||||
|
foreach (explode("\n", $data) as $line) {
|
||||||
|
if (!preg_match("{^ '([^'/]+)' => \['(.+)'\],$}", $line, $matches)) {
|
||||||
|
if (1 === $state) {
|
||||||
|
$state = 2;
|
||||||
|
foreach ($exts as $ext => $mimeTypes) {
|
||||||
|
$updated .= sprintf(" '%s' => ['%s'],\n", $ext, implode("', '", array_unique($mimeTypes)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$updated .= $line."\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$updated = preg_replace('{Updated from upstream on .+?\.}', 'Updated from upstream on '.date('Y-m-d'), $updated, -1);
|
||||||
|
|
||||||
|
file_put_contents($output, rtrim($updated, "\n")."\n");
|
||||||
|
|
||||||
|
echo "Done.\n";
|
102
src/Symfony/Component/Mime/Tests/AbstractMimeTypeGuesserTest.php
Normal file
102
src/Symfony/Component/Mime/Tests/AbstractMimeTypeGuesserTest.php
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Mime\Tests;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\Mime\MimeTypeGuesserInterface;
|
||||||
|
|
||||||
|
abstract class AbstractMimeTypeGuesserTest extends TestCase
|
||||||
|
{
|
||||||
|
public static function tearDownAfterClass()
|
||||||
|
{
|
||||||
|
$path = __DIR__.'/Fixtures/to_delete';
|
||||||
|
if (file_exists($path)) {
|
||||||
|
@chmod($path, 0666);
|
||||||
|
@unlink($path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected function getGuesser(): MimeTypeGuesserInterface;
|
||||||
|
|
||||||
|
public function testGuessImageWithoutExtension()
|
||||||
|
{
|
||||||
|
if (!$this->getGuesser()->isGuesserSupported()) {
|
||||||
|
$this->markTestSkipped('Guesser is not supported');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertEquals('image/gif', $this->getGuesser()->guessMimeType(__DIR__.'/Fixtures/test'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGuessImageWithDirectory()
|
||||||
|
{
|
||||||
|
if (!$this->getGuesser()->isGuesserSupported()) {
|
||||||
|
$this->markTestSkipped('Guesser is not supported');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->expectException('\InvalidArgumentException');
|
||||||
|
$this->getGuesser()->guessMimeType(__DIR__.'/Fixtures/directory');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGuessImageWithKnownExtension()
|
||||||
|
{
|
||||||
|
if (!$this->getGuesser()->isGuesserSupported()) {
|
||||||
|
$this->markTestSkipped('Guesser is not supported');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertEquals('image/gif', $this->getGuesser()->guessMimeType(__DIR__.'/Fixtures/test.gif'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGuessFileWithUnknownExtension()
|
||||||
|
{
|
||||||
|
if (!$this->getGuesser()->isGuesserSupported()) {
|
||||||
|
$this->markTestSkipped('Guesser is not supported');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertEquals('application/octet-stream', $this->getGuesser()->guessMimeType(__DIR__.'/Fixtures/.unknownextension'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGuessWithIncorrectPath()
|
||||||
|
{
|
||||||
|
if (!$this->getGuesser()->isGuesserSupported()) {
|
||||||
|
$this->markTestSkipped('Guesser is not supported');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->expectException('\InvalidArgumentException');
|
||||||
|
$this->getGuesser()->guessMimeType(__DIR__.'/Fixtures/not_here');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGuessWithNonReadablePath()
|
||||||
|
{
|
||||||
|
if (!$this->getGuesser()->isGuesserSupported()) {
|
||||||
|
$this->markTestSkipped('Guesser is not supported');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('\\' === \DIRECTORY_SEPARATOR) {
|
||||||
|
$this->markTestSkipped('Can not verify chmod operations on Windows');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!getenv('USER') || 'root' === getenv('USER')) {
|
||||||
|
$this->markTestSkipped('This test will fail if run under superuser');
|
||||||
|
}
|
||||||
|
|
||||||
|
$path = __DIR__.'/Fixtures/to_delete';
|
||||||
|
touch($path);
|
||||||
|
@chmod($path, 0333);
|
||||||
|
|
||||||
|
if ('0333' == substr(sprintf('%o', fileperms($path)), -4)) {
|
||||||
|
$this->expectException('\InvalidArgumentException');
|
||||||
|
$this->getGuesser()->guessMimeType($path);
|
||||||
|
} else {
|
||||||
|
$this->markTestSkipped('Can not verify chmod operations, change of file permissions failed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Mime\Tests;
|
||||||
|
|
||||||
|
use Symfony\Component\Mime\FileBinaryMimeTypeGuesser;
|
||||||
|
use Symfony\Component\Mime\MimeTypeGuesserInterface;
|
||||||
|
|
||||||
|
class FileBinaryMimeTypeGuesserTest extends AbstractMimeTypeGuesserTest
|
||||||
|
{
|
||||||
|
protected function getGuesser(): MimeTypeGuesserInterface
|
||||||
|
{
|
||||||
|
return new FileBinaryMimeTypeGuesser();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Mime\Tests;
|
||||||
|
|
||||||
|
use Symfony\Component\Mime\FileinfoMimeTypeGuesser;
|
||||||
|
use Symfony\Component\Mime\MimeTypeGuesserInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires extension fileinfo
|
||||||
|
*/
|
||||||
|
class FileinfoMimeTypeGuesserTest extends AbstractMimeTypeGuesserTest
|
||||||
|
{
|
||||||
|
protected function getGuesser(): MimeTypeGuesserInterface
|
||||||
|
{
|
||||||
|
return new FileinfoMimeTypeGuesser();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
f
|
BIN
src/Symfony/Component/Mime/Tests/Fixtures/test
Normal file
BIN
src/Symfony/Component/Mime/Tests/Fixtures/test
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 B |
BIN
src/Symfony/Component/Mime/Tests/Fixtures/test.gif
Normal file
BIN
src/Symfony/Component/Mime/Tests/Fixtures/test.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 B |
60
src/Symfony/Component/Mime/Tests/MimeTypesTest.php
Normal file
60
src/Symfony/Component/Mime/Tests/MimeTypesTest.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Mime\Tests;
|
||||||
|
|
||||||
|
use Symfony\Component\Mime\MimeTypeGuesserInterface;
|
||||||
|
use Symfony\Component\Mime\MimeTypes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires extension fileinfo
|
||||||
|
*/
|
||||||
|
class MimeTypesTest extends AbstractMimeTypeGuesserTest
|
||||||
|
{
|
||||||
|
protected function getGuesser(): MimeTypeGuesserInterface
|
||||||
|
{
|
||||||
|
return new MimeTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUnsupportedGuesser()
|
||||||
|
{
|
||||||
|
$guesser = $this->getGuesser();
|
||||||
|
$guesser->registerGuesser(new class() implements MimeTypeGuesserInterface {
|
||||||
|
public function isGuesserSupported(): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function guessMimeType(string $mimeType): ?string
|
||||||
|
{
|
||||||
|
throw new \RuntimeException('Should never be called.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$this->assertEquals('image/gif', $guesser->guessMimeType(__DIR__.'/Fixtures/test'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetExtensions()
|
||||||
|
{
|
||||||
|
$mt = new MimeTypes();
|
||||||
|
$this->assertSame(['mbox'], $mt->getExtensions('application/mbox'));
|
||||||
|
$this->assertSame(['ai', 'eps', 'ps'], $mt->getExtensions('application/postscript'));
|
||||||
|
$this->assertSame([], $mt->getExtensions('application/whatever-symfony'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetMimeTypes()
|
||||||
|
{
|
||||||
|
$mt = new MimeTypes();
|
||||||
|
$this->assertSame(['application/mbox'], $mt->getMimeTypes('mbox'));
|
||||||
|
$this->assertContains('application/postscript', $mt->getMimeTypes('ai'));
|
||||||
|
$this->assertContains('application/postscript', $mt->getMimeTypes('ps'));
|
||||||
|
$this->assertSame([], $mt->getMimeTypes('symfony'));
|
||||||
|
}
|
||||||
|
}
|
33
src/Symfony/Component/Mime/composer.json
Normal file
33
src/Symfony/Component/Mime/composer.json
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"name": "symfony/mime",
|
||||||
|
"type": "library",
|
||||||
|
"description": "A ",
|
||||||
|
"keywords": ["mime", "mime-type"],
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"php": "^7.1.3"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": { "Symfony\\Component\\Mime\\": "" },
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"minimum-stability": "dev",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "4.3-dev"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
src/Symfony/Component/Mime/phpunit.xml.dist
Normal file
31
src/Symfony/Component/Mime/phpunit.xml.dist
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.2/phpunit.xsd"
|
||||||
|
backupGlobals="false"
|
||||||
|
colors="true"
|
||||||
|
bootstrap="vendor/autoload.php"
|
||||||
|
failOnRisky="true"
|
||||||
|
failOnWarning="true"
|
||||||
|
>
|
||||||
|
<php>
|
||||||
|
<ini name="error_reporting" value="-1" />
|
||||||
|
</php>
|
||||||
|
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="Symfony MIME Component Test Suite">
|
||||||
|
<directory>./Tests/</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
|
||||||
|
<filter>
|
||||||
|
<whitelist>
|
||||||
|
<directory>./</directory>
|
||||||
|
<exclude>
|
||||||
|
<directory>./Resources</directory>
|
||||||
|
<directory>./Tests</directory>
|
||||||
|
<directory>./vendor</directory>
|
||||||
|
</exclude>
|
||||||
|
</whitelist>
|
||||||
|
</filter>
|
||||||
|
</phpunit>
|
@ -13,7 +13,9 @@ namespace Symfony\Component\Serializer\Normalizer;
|
|||||||
|
|
||||||
use Symfony\Component\HttpFoundation\File\File;
|
use Symfony\Component\HttpFoundation\File\File;
|
||||||
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser;
|
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser;
|
||||||
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface;
|
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface as DeprecatedMimeTypeGuesserInterface;
|
||||||
|
use Symfony\Component\Mime\MimeTypeGuesserInterface;
|
||||||
|
use Symfony\Component\Mime\MimeTypes;
|
||||||
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
||||||
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
|
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
|
||||||
|
|
||||||
@ -36,11 +38,23 @@ class DataUriNormalizer implements NormalizerInterface, DenormalizerInterface, C
|
|||||||
*/
|
*/
|
||||||
private $mimeTypeGuesser;
|
private $mimeTypeGuesser;
|
||||||
|
|
||||||
public function __construct(MimeTypeGuesserInterface $mimeTypeGuesser = null)
|
/**
|
||||||
|
* @param MimeTypeGuesserInterface
|
||||||
|
*/
|
||||||
|
public function __construct($mimeTypeGuesser = null)
|
||||||
{
|
{
|
||||||
if (null === $mimeTypeGuesser && class_exists('Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser')) {
|
if ($mimeTypeGuesser instanceof DeprecatedMimeTypeGuesserInterface) {
|
||||||
|
@trigger_error(sprintf('Passing a %s to "%s()" is deprecated since Symfony 4.3, pass a "%s" instead.', DeprecatedMimeTypeGuesserInterface::class, __METHOD__, MimeTypeGuesserInterface::class), E_USER_DEPRECATED);
|
||||||
|
} elseif (null === $mimeTypeGuesser) {
|
||||||
|
if (class_exists(MimeTypes::class)) {
|
||||||
|
$mimeTypeGuesser = MimeTypes::getDefault();
|
||||||
|
} else {
|
||||||
|
@trigger_error(sprintf('Passing null to "%s()" without symfony/mime installed is deprecated since Symfony 4.3, install symfony/mime.', __METHOD__), E_USER_DEPRECATED);
|
||||||
$mimeTypeGuesser = MimeTypeGuesser::getInstance();
|
$mimeTypeGuesser = MimeTypeGuesser::getInstance();
|
||||||
}
|
}
|
||||||
|
} elseif (!$mimeTypeGuesser instanceof MimeTypes) {
|
||||||
|
throw new \InvalidArgumentException(sprintf('Argument 1 passed to "%s()" must be an instance of "%s" or null, %s given.', __METHOD__, MimeTypes::class, \is_object($mimeTypeGuesser) ? \get_class($mimeTypeGuesser) : \gettype($mimeTypeGuesser)));
|
||||||
|
}
|
||||||
|
|
||||||
$this->mimeTypeGuesser = $mimeTypeGuesser;
|
$this->mimeTypeGuesser = $mimeTypeGuesser;
|
||||||
}
|
}
|
||||||
@ -140,7 +154,9 @@ class DataUriNormalizer implements NormalizerInterface, DenormalizerInterface, C
|
|||||||
return $object->getMimeType();
|
return $object->getMimeType();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->mimeTypeGuesser && $mimeType = $this->mimeTypeGuesser->guess($object->getPathname())) {
|
if ($this->mimeTypeGuesser instanceof DeprecatedMimeTypeGuesserInterface && $mimeType = $this->mimeTypeGuesser->guess($object->getPathname())) {
|
||||||
|
return $mimeType;
|
||||||
|
} elseif ($this->mimeTypeGuesser && $mimeType = $this->mimeTypeGuesser->guessMimeType($object->getPathname())) {
|
||||||
return $mimeType;
|
return $mimeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user