PKdZVE  MimeTypesInterface.phpnu[ * * 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 */ interface MimeTypesInterface extends MimeTypeGuesserInterface { /** * Gets the extensions for the given MIME type in decreasing order of preference. * * @return string[] */ public function getExtensions(string $mimeType): array; /** * Gets the MIME types for the given extension in decreasing order of preference. * * @return string[] */ public function getMimeTypes(string $ext): array; } PKdZ {??.DependencyInjection/AddMimeTypeGuesserPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\DependencyInjection; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; /** * Registers custom mime types guessers. * * @author Fabien Potencier */ 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)]); } } } } PKdZC^^FileinfoMimeTypeGuesser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime; use Symfony\Component\Mime\Exception\InvalidArgumentException; use Symfony\Component\Mime\Exception\LogicException; /** * Guesses the MIME type using the PECL extension FileInfo. * * @author Bernhard Schussek */ class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface { private ?string $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; } $mimeType = $finfo->file($path); if ($mimeType && 0 === (\strlen($mimeType) % 2)) { $mimeStart = substr($mimeType, 0, \strlen($mimeType) >> 1); $mimeType = $mimeStart.$mimeStart === $mimeType ? $mimeStart : $mimeType; } return $mimeType; } } PKdZeRawMessage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime; use Symfony\Component\Mime\Exception\LogicException; /** * @author Fabien Potencier */ class RawMessage { private $message; public function __construct(iterable|string $message) { $this->message = $message; } public function toString(): string { if (\is_string($this->message)) { return $this->message; } if ($this->message instanceof \Traversable) { $this->message = iterator_to_array($this->message, false); } return $this->message = implode('', $this->message); } public function toIterable(): iterable { if (\is_string($this->message)) { yield $this->message; return; } $message = ''; foreach ($this->message as $chunk) { $message .= $chunk; yield $chunk; } $this->message = $message; } /** * @throws LogicException if the message is not valid */ public function ensureValidity() { } public function __serialize(): array { return [$this->toString()]; } public function __unserialize(array $data): void { [$this->message] = $data; } } PKdZvv composer.jsonnu[{ "name": "symfony/mime", "type": "library", "description": "Allows manipulating MIME messages", "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": ">=8.0.2", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3.1|^4", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "symfony/dependency-injection": "^5.4|^6.0", "symfony/property-access": "^5.4|^6.0", "symfony/property-info": "^5.4|^6.0", "symfony/serializer": "^5.4.14|~6.0.14|^6.1.6" }, "conflict": { "egulias/email-validator": "~3.0.0", "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", "symfony/mailer": "<5.4", "symfony/serializer": "<5.4.14|>=6.0,<6.0.14|>=6.1,<6.1.6" }, "autoload": { "psr-4": { "Symfony\\Component\\Mime\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "minimum-stability": "dev" } PKdZAnKK CHANGELOG.mdnu[CHANGELOG ========= 6.0 --- * Remove `Address::fromString()`, use `Address::create()` instead * Remove `Serializable` interface from `RawMessage` 5.2.0 ----- * Add support for DKIM * Deprecated `Address::fromString()`, use `Address::create()` instead 4.4.0 ----- * [BC BREAK] Removed `NamedAddress` (`Address` now supports a name) * Added PHPUnit constraints * Added `AbstractPart::asDebugString()` * Added `Address::fromString()` 4.3.3 ----- * [BC BREAK] Renamed method `Headers::getAll()` to `Headers::all()`. 4.3.0 ----- * Introduced the component as experimental PKdZQ::MimeTypeGuesserInterface.phpnu[ * * 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 */ interface MimeTypeGuesserInterface { /** * Returns true if this guesser is supported. */ public function isGuesserSupported(): bool; /** * Guesses the MIME type of the file with the given path. * * @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; } PKdZkHException/LogicException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Exception; /** * @author Fabien Potencier */ class LogicException extends \LogicException implements ExceptionInterface { } PKdZ'&Exception/InvalidArgumentException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Exception; /** * @author Fabien Potencier */ class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } PKdZЕ%Exception/AddressEncoderException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Exception; /** * @author Fabien Potencier */ class AddressEncoderException extends RfcComplianceException { } PKdZFz$Exception/RfcComplianceException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Exception; /** * @author Fabien Potencier */ class RfcComplianceException extends \InvalidArgumentException implements ExceptionInterface { } PKdZ{ Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Exception; /** * @author Fabien Potencier */ interface ExceptionInterface extends \Throwable { } PKdZr)Exception/RuntimeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Exception; /** * @author Fabien Potencier */ class RuntimeException extends \RuntimeException implements ExceptionInterface { } PKdZcEl Message.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime; use Symfony\Component\Mime\Exception\LogicException; use Symfony\Component\Mime\Header\Headers; use Symfony\Component\Mime\Part\AbstractPart; use Symfony\Component\Mime\Part\TextPart; /** * @author Fabien Potencier */ class Message extends RawMessage { private $headers; private $body; public function __construct(Headers $headers = null, AbstractPart $body = null) { $this->headers = $headers ? clone $headers : new Headers(); $this->body = $body; } public function __clone() { $this->headers = clone $this->headers; if (null !== $this->body) { $this->body = clone $this->body; } } /** * @return $this */ public function setBody(AbstractPart $body = null): static { $this->body = $body; return $this; } public function getBody(): ?AbstractPart { return $this->body; } /** * @return $this */ public function setHeaders(Headers $headers): static { $this->headers = $headers; return $this; } public function getHeaders(): Headers { return $this->headers; } public function getPreparedHeaders(): Headers { $headers = clone $this->headers; if (!$headers->has('From')) { if (!$headers->has('Sender')) { throw new LogicException('An email must have a "From" or a "Sender" header.'); } $headers->addMailboxListHeader('From', [$headers->get('Sender')->getAddress()]); } if (!$headers->has('MIME-Version')) { $headers->addTextHeader('MIME-Version', '1.0'); } if (!$headers->has('Date')) { $headers->addDateHeader('Date', new \DateTimeImmutable()); } // determine the "real" sender if (!$headers->has('Sender') && \count($froms = $headers->get('From')->getAddresses()) > 1) { $headers->addMailboxHeader('Sender', $froms[0]); } if (!$headers->has('Message-ID')) { $headers->addIdHeader('Message-ID', $this->generateMessageId()); } // remove the Bcc field which should NOT be part of the sent message $headers->remove('Bcc'); return $headers; } public function toString(): string { if (null === $body = $this->getBody()) { $body = new TextPart(''); } return $this->getPreparedHeaders()->toString().$body->toString(); } public function toIterable(): iterable { if (null === $body = $this->getBody()) { $body = new TextPart(''); } yield $this->getPreparedHeaders()->toString(); yield from $body->toIterable(); } public function ensureValidity() { if (!$this->headers->has('To') && !$this->headers->has('Cc') && !$this->headers->has('Bcc')) { throw new LogicException('An email must have a "To", "Cc", or "Bcc" header.'); } if (!$this->headers->has('From') && !$this->headers->has('Sender')) { throw new LogicException('An email must have a "From" or a "Sender" header.'); } parent::ensureValidity(); } public function generateMessageId(): string { if ($this->headers->has('Sender')) { $sender = $this->headers->get('Sender')->getAddress(); } elseif ($this->headers->has('From')) { $sender = $this->headers->get('From')->getAddresses()[0]; } else { throw new LogicException('An email must have a "From" or a "Sender" header.'); } return bin2hex(random_bytes(16)).strstr($sender->getAddress(), '@'); } public function __serialize(): array { return [$this->headers, $this->body]; } public function __unserialize(array $data): void { [$this->headers, $this->body] = $data; } } PKdZgא FileBinaryMimeTypeGuesser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime; use Symfony\Component\Mime\Exception\InvalidArgumentException; use Symfony\Component\Mime\Exception\LogicException; /** * Guesses the MIME type with the binary "file" (only available on *nix). * * @author Bernhard Schussek */ class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface { private string $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((str_starts_with($path, '-') ? './' : '').$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]; } } PKdZ'?Part/Multipart/MixedPart.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Part\Multipart; use Symfony\Component\Mime\Part\AbstractMultipartPart; /** * @author Fabien Potencier */ final class MixedPart extends AbstractMultipartPart { public function getMediaSubtype(): string { return 'mixed'; } } PKdZz~kkPart/Multipart/RelatedPart.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Part\Multipart; use Symfony\Component\Mime\Part\AbstractMultipartPart; use Symfony\Component\Mime\Part\AbstractPart; /** * @author Fabien Potencier */ final class RelatedPart extends AbstractMultipartPart { private $mainPart; public function __construct(AbstractPart $mainPart, AbstractPart $part, AbstractPart ...$parts) { $this->mainPart = $mainPart; $this->prepareParts($part, ...$parts); parent::__construct($part, ...$parts); } public function getParts(): array { return array_merge([$this->mainPart], parent::getParts()); } public function getMediaSubtype(): string { return 'related'; } private function generateContentId(): string { return bin2hex(random_bytes(16)).'@symfony'; } private function prepareParts(AbstractPart ...$parts): void { foreach ($parts as $part) { if (!$part->getHeaders()->has('Content-ID')) { $part->getHeaders()->setHeaderBody('Id', 'Content-ID', $this->generateContentId()); } } } } PKdZ;cPart/Multipart/DigestPart.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Part\Multipart; use Symfony\Component\Mime\Part\AbstractMultipartPart; use Symfony\Component\Mime\Part\MessagePart; /** * @author Fabien Potencier */ final class DigestPart extends AbstractMultipartPart { public function __construct(MessagePart ...$parts) { parent::__construct(...$parts); } public function getMediaSubtype(): string { return 'digest'; } } PKdZU. Part/Multipart/FormDataPart.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Part\Multipart; use Symfony\Component\Mime\Exception\InvalidArgumentException; use Symfony\Component\Mime\Part\AbstractMultipartPart; use Symfony\Component\Mime\Part\DataPart; use Symfony\Component\Mime\Part\TextPart; /** * Implements RFC 7578. * * @author Fabien Potencier */ final class FormDataPart extends AbstractMultipartPart { private $fields = []; /** * @param array $fields */ public function __construct(array $fields = []) { parent::__construct(); foreach ($fields as $name => $value) { if (!\is_string($value) && !\is_array($value) && !$value instanceof TextPart) { throw new InvalidArgumentException(sprintf('A form field value can only be a string, an array, or an instance of TextPart ("%s" given).', get_debug_type($value))); } $this->fields[$name] = $value; } // HTTP does not support \r\n in header values $this->getHeaders()->setMaxLineLength(\PHP_INT_MAX); } public function getMediaSubtype(): string { return 'form-data'; } public function getParts(): array { return $this->prepareFields($this->fields); } private function prepareFields(array $fields): array { $values = []; $prepare = function ($item, $key, $root = null) use (&$values, &$prepare) { if (\is_int($key) && \is_array($item)) { if (1 !== \count($item)) { throw new InvalidArgumentException(sprintf('Form field values with integer keys can only have one array element, the key being the field name and the value being the field value, %d provided.', \count($item))); } $key = key($item); $item = $item[$key]; } $fieldName = null !== $root ? sprintf('%s[%s]', $root, $key) : $key; if (\is_array($item)) { array_walk($item, $prepare, $fieldName); return; } $values[] = $this->preparePart($fieldName, $item); }; array_walk($fields, $prepare); return $values; } private function preparePart(string $name, string|TextPart $value): TextPart { if (\is_string($value)) { return $this->configurePart($name, new TextPart($value, 'utf-8', 'plain', '8bit')); } return $this->configurePart($name, $value); } private function configurePart(string $name, TextPart $part): TextPart { static $r; if (null === $r) { $r = new \ReflectionProperty(TextPart::class, 'encoding'); $r->setAccessible(true); } $part->setDisposition('form-data'); $part->setName($name); // HTTP does not support \r\n in header values $part->getHeaders()->setMaxLineLength(\PHP_INT_MAX); $r->setValue($part, '8bit'); return $part; } } PKdZS''"Part/Multipart/AlternativePart.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Part\Multipart; use Symfony\Component\Mime\Part\AbstractMultipartPart; /** * @author Fabien Potencier */ final class AlternativePart extends AbstractMultipartPart { public function getMediaSubtype(): string { return 'alternative'; } } PKdZaT ) ) Part/AbstractMultipartPart.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Part; use Symfony\Component\Mime\Header\Headers; /** * @author Fabien Potencier */ abstract class AbstractMultipartPart extends AbstractPart { private $boundary; private $parts = []; public function __construct(AbstractPart ...$parts) { parent::__construct(); foreach ($parts as $part) { $this->parts[] = $part; } } /** * @return AbstractPart[] */ public function getParts(): array { return $this->parts; } public function getMediaType(): string { return 'multipart'; } public function getPreparedHeaders(): Headers { $headers = parent::getPreparedHeaders(); $headers->setHeaderParameter('Content-Type', 'boundary', $this->getBoundary()); return $headers; } public function bodyToString(): string { $parts = $this->getParts(); $string = ''; foreach ($parts as $part) { $string .= '--'.$this->getBoundary()."\r\n".$part->toString()."\r\n"; } $string .= '--'.$this->getBoundary()."--\r\n"; return $string; } public function bodyToIterable(): iterable { $parts = $this->getParts(); foreach ($parts as $part) { yield '--'.$this->getBoundary()."\r\n"; yield from $part->toIterable(); yield "\r\n"; } yield '--'.$this->getBoundary()."--\r\n"; } public function asDebugString(): string { $str = parent::asDebugString(); foreach ($this->getParts() as $part) { $lines = explode("\n", $part->asDebugString()); $str .= "\n └ ".array_shift($lines); foreach ($lines as $line) { $str .= "\n |".$line; } } return $str; } private function getBoundary(): string { if (null === $this->boundary) { $this->boundary = strtr(base64_encode(random_bytes(6)), '+/', '-_'); } return $this->boundary; } } PKdZ"1 1 Part/SMimePart.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Part; use Symfony\Component\Mime\Header\Headers; /** * @author Sebastiaan Stok */ class SMimePart extends AbstractPart { /** @internal */ protected $_headers; private $body; private $type; private $subtype; private $parameters; public function __construct(iterable|string $body, string $type, string $subtype, array $parameters) { unset($this->_headers); parent::__construct(); $this->body = $body; $this->type = $type; $this->subtype = $subtype; $this->parameters = $parameters; } public function getMediaType(): string { return $this->type; } public function getMediaSubtype(): string { return $this->subtype; } public function bodyToString(): string { if (\is_string($this->body)) { return $this->body; } $body = ''; foreach ($this->body as $chunk) { $body .= $chunk; } $this->body = $body; return $body; } public function bodyToIterable(): iterable { if (\is_string($this->body)) { yield $this->body; return; } $body = ''; foreach ($this->body as $chunk) { $body .= $chunk; yield $chunk; } $this->body = $body; } public function getPreparedHeaders(): Headers { $headers = clone parent::getHeaders(); $headers->setHeaderBody('Parameterized', 'Content-Type', $this->getMediaType().'/'.$this->getMediaSubtype()); foreach ($this->parameters as $name => $value) { $headers->setHeaderParameter('Content-Type', $name, $value); } return $headers; } public function __sleep(): array { // convert iterables to strings for serialization if (is_iterable($this->body)) { $this->body = $this->bodyToString(); } $this->_headers = $this->getHeaders(); return ['_headers', 'body', 'type', 'subtype', 'parameters']; } public function __wakeup(): void { $r = new \ReflectionProperty(AbstractPart::class, 'headers'); $r->setAccessible(true); $r->setValue($this, $this->_headers); unset($this->_headers); } } PKdZPart/AbstractPart.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Part; use Symfony\Component\Mime\Header\Headers; /** * @author Fabien Potencier */ abstract class AbstractPart { private $headers; public function __construct() { $this->headers = new Headers(); } public function getHeaders(): Headers { return $this->headers; } public function getPreparedHeaders(): Headers { $headers = clone $this->headers; $headers->setHeaderBody('Parameterized', 'Content-Type', $this->getMediaType().'/'.$this->getMediaSubtype()); return $headers; } public function toString(): string { return $this->getPreparedHeaders()->toString()."\r\n".$this->bodyToString(); } public function toIterable(): iterable { yield $this->getPreparedHeaders()->toString(); yield "\r\n"; yield from $this->bodyToIterable(); } public function asDebugString(): string { return $this->getMediaType().'/'.$this->getMediaSubtype(); } abstract public function bodyToString(): string; abstract public function bodyToIterable(): iterable; abstract public function getMediaType(): string; abstract public function getMediaSubtype(): string; } PKdZzARPart/TextPart.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Part; use Symfony\Component\Mime\Encoder\Base64ContentEncoder; use Symfony\Component\Mime\Encoder\ContentEncoderInterface; use Symfony\Component\Mime\Encoder\EightBitContentEncoder; use Symfony\Component\Mime\Encoder\QpContentEncoder; use Symfony\Component\Mime\Exception\InvalidArgumentException; use Symfony\Component\Mime\Header\Headers; /** * @author Fabien Potencier */ class TextPart extends AbstractPart { /** @internal */ protected $_headers; private static $encoders = []; private $body; private $charset; private $subtype; /** * @var ?string */ private $disposition; private $name; private $encoding; private $seekable; /** * @param resource|string $body */ public function __construct($body, ?string $charset = 'utf-8', string $subtype = 'plain', string $encoding = null) { unset($this->_headers); parent::__construct(); if (!\is_string($body) && !\is_resource($body)) { throw new \TypeError(sprintf('The body of "%s" must be a string or a resource (got "%s").', self::class, get_debug_type($body))); } $this->body = $body; $this->charset = $charset; $this->subtype = $subtype; $this->seekable = \is_resource($body) ? stream_get_meta_data($body)['seekable'] && 0 === fseek($body, 0, \SEEK_CUR) : null; if (null === $encoding) { $this->encoding = $this->chooseEncoding(); } else { if ('quoted-printable' !== $encoding && 'base64' !== $encoding && '8bit' !== $encoding) { throw new InvalidArgumentException(sprintf('The encoding must be one of "quoted-printable", "base64", or "8bit" ("%s" given).', $encoding)); } $this->encoding = $encoding; } } public function getMediaType(): string { return 'text'; } public function getMediaSubtype(): string { return $this->subtype; } /** * @param string $disposition one of attachment, inline, or form-data * * @return $this */ public function setDisposition(string $disposition): static { $this->disposition = $disposition; return $this; } /** * Sets the name of the file (used by FormDataPart). * * @return $this */ public function setName(string $name): static { $this->name = $name; return $this; } public function getBody(): string { if (null === $this->seekable) { return $this->body; } if ($this->seekable) { rewind($this->body); } return stream_get_contents($this->body) ?: ''; } public function bodyToString(): string { return $this->getEncoder()->encodeString($this->getBody(), $this->charset); } public function bodyToIterable(): iterable { if (null !== $this->seekable) { if ($this->seekable) { rewind($this->body); } yield from $this->getEncoder()->encodeByteStream($this->body); } else { yield $this->getEncoder()->encodeString($this->body); } } public function getPreparedHeaders(): Headers { $headers = parent::getPreparedHeaders(); $headers->setHeaderBody('Parameterized', 'Content-Type', $this->getMediaType().'/'.$this->getMediaSubtype()); if ($this->charset) { $headers->setHeaderParameter('Content-Type', 'charset', $this->charset); } if ($this->name && 'form-data' !== $this->disposition) { $headers->setHeaderParameter('Content-Type', 'name', $this->name); } $headers->setHeaderBody('Text', 'Content-Transfer-Encoding', $this->encoding); if (!$headers->has('Content-Disposition') && null !== $this->disposition) { $headers->setHeaderBody('Parameterized', 'Content-Disposition', $this->disposition); if ($this->name) { $headers->setHeaderParameter('Content-Disposition', 'name', $this->name); } } return $headers; } public function asDebugString(): string { $str = parent::asDebugString(); if (null !== $this->charset) { $str .= ' charset: '.$this->charset; } if (null !== $this->disposition) { $str .= ' disposition: '.$this->disposition; } return $str; } private function getEncoder(): ContentEncoderInterface { if ('8bit' === $this->encoding) { return self::$encoders[$this->encoding] ?? (self::$encoders[$this->encoding] = new EightBitContentEncoder()); } if ('quoted-printable' === $this->encoding) { return self::$encoders[$this->encoding] ?? (self::$encoders[$this->encoding] = new QpContentEncoder()); } return self::$encoders[$this->encoding] ?? (self::$encoders[$this->encoding] = new Base64ContentEncoder()); } private function chooseEncoding(): string { if (null === $this->charset) { return 'base64'; } return 'quoted-printable'; } public function __sleep(): array { // convert resources to strings for serialization if (null !== $this->seekable) { $this->body = $this->getBody(); $this->seekable = null; } $this->_headers = $this->getHeaders(); return ['_headers', 'body', 'charset', 'subtype', 'disposition', 'name', 'encoding']; } public function __wakeup() { $r = new \ReflectionProperty(AbstractPart::class, 'headers'); $r->setAccessible(true); $r->setValue($this, $this->_headers); unset($this->_headers); } } PKdZsPart/MessagePart.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Part; use Symfony\Component\Mime\Message; use Symfony\Component\Mime\RawMessage; /** * @final * * @author Fabien Potencier */ class MessagePart extends DataPart { private $message; public function __construct(RawMessage $message) { if ($message instanceof Message) { $name = $message->getHeaders()->getHeaderBody('Subject').'.eml'; } else { $name = 'email.eml'; } parent::__construct('', $name); $this->message = $message; } public function getMediaType(): string { return 'message'; } public function getMediaSubtype(): string { return 'rfc822'; } public function getBody(): string { return $this->message->toString(); } public function bodyToString(): string { return $this->getBody(); } public function bodyToIterable(): iterable { return $this->message->toIterable(); } public function __sleep(): array { return ['message']; } public function __wakeup() { $this->__construct($this->message); } } PKdZ^Part/DataPart.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Part; use Symfony\Component\Mime\Exception\InvalidArgumentException; use Symfony\Component\Mime\Header\Headers; use Symfony\Component\Mime\MimeTypes; /** * @author Fabien Potencier */ class DataPart extends TextPart { /** @internal */ protected $_parent; private static $mimeTypes; private $filename; private $mediaType; private $cid; private $handle; /** * @param resource|string $body */ public function __construct($body, string $filename = null, string $contentType = null, string $encoding = null) { unset($this->_parent); if (null === $contentType) { $contentType = 'application/octet-stream'; } [$this->mediaType, $subtype] = explode('/', $contentType); parent::__construct($body, null, $subtype, $encoding); if (null !== $filename) { $this->filename = $filename; $this->setName($filename); } $this->setDisposition('attachment'); } public static function fromPath(string $path, string $name = null, string $contentType = null): self { if (null === $contentType) { $ext = strtolower(substr($path, strrpos($path, '.') + 1)); if (null === self::$mimeTypes) { self::$mimeTypes = new MimeTypes(); } $contentType = self::$mimeTypes->getMimeTypes($ext)[0] ?? 'application/octet-stream'; } if ((is_file($path) && !is_readable($path)) || is_dir($path)) { throw new InvalidArgumentException(sprintf('Path "%s" is not readable.', $path)); } if (false === $handle = @fopen($path, 'r', false)) { throw new InvalidArgumentException(sprintf('Unable to open path "%s".', $path)); } if (!is_file($path)) { $cache = fopen('php://temp', 'r+'); stream_copy_to_stream($handle, $cache); $handle = $cache; } $p = new self($handle, $name ?: basename($path), $contentType); $p->handle = $handle; return $p; } /** * @return $this */ public function asInline(): static { return $this->setDisposition('inline'); } public function getContentId(): string { return $this->cid ?: $this->cid = $this->generateContentId(); } public function hasContentId(): bool { return null !== $this->cid; } public function getMediaType(): string { return $this->mediaType; } public function getPreparedHeaders(): Headers { $headers = parent::getPreparedHeaders(); if (null !== $this->cid) { $headers->setHeaderBody('Id', 'Content-ID', $this->cid); } if (null !== $this->filename) { $headers->setHeaderParameter('Content-Disposition', 'filename', $this->filename); } return $headers; } public function asDebugString(): string { $str = parent::asDebugString(); if (null !== $this->filename) { $str .= ' filename: '.$this->filename; } return $str; } private function generateContentId(): string { return bin2hex(random_bytes(16)).'@symfony'; } public function __destruct() { if (null !== $this->handle && \is_resource($this->handle)) { fclose($this->handle); } } public function __sleep(): array { // converts the body to a string parent::__sleep(); $this->_parent = []; foreach (['body', 'charset', 'subtype', 'disposition', 'name', 'encoding'] as $name) { $r = new \ReflectionProperty(TextPart::class, $name); $r->setAccessible(true); $this->_parent[$name] = $r->getValue($this); } $this->_headers = $this->getHeaders(); return ['_headers', '_parent', 'filename', 'mediaType']; } public function __wakeup() { $r = new \ReflectionProperty(AbstractPart::class, 'headers'); $r->setAccessible(true); $r->setValue($this, $this->_headers); unset($this->_headers); if (!\is_array($this->_parent)) { throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } foreach (['body', 'charset', 'subtype', 'disposition', 'name', 'encoding'] as $name) { if (null !== $this->_parent[$name] && !\is_string($this->_parent[$name])) { throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } $r = new \ReflectionProperty(TextPart::class, $name); $r->setAccessible(true); $r->setValue($this, $this->_parent[$name]); } unset($this->_parent); } } PKdZ 8ic%c%CharacterStream.phpnu[ * * 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 * @author Xavier De Cock * * @internal */ final class CharacterStream { /** Pre-computed for optimization */ private const UTF8_LENGTH_MAP = [ "\x00" => 1, "\x01" => 1, "\x02" => 1, "\x03" => 1, "\x04" => 1, "\x05" => 1, "\x06" => 1, "\x07" => 1, "\x08" => 1, "\x09" => 1, "\x0a" => 1, "\x0b" => 1, "\x0c" => 1, "\x0d" => 1, "\x0e" => 1, "\x0f" => 1, "\x10" => 1, "\x11" => 1, "\x12" => 1, "\x13" => 1, "\x14" => 1, "\x15" => 1, "\x16" => 1, "\x17" => 1, "\x18" => 1, "\x19" => 1, "\x1a" => 1, "\x1b" => 1, "\x1c" => 1, "\x1d" => 1, "\x1e" => 1, "\x1f" => 1, "\x20" => 1, "\x21" => 1, "\x22" => 1, "\x23" => 1, "\x24" => 1, "\x25" => 1, "\x26" => 1, "\x27" => 1, "\x28" => 1, "\x29" => 1, "\x2a" => 1, "\x2b" => 1, "\x2c" => 1, "\x2d" => 1, "\x2e" => 1, "\x2f" => 1, "\x30" => 1, "\x31" => 1, "\x32" => 1, "\x33" => 1, "\x34" => 1, "\x35" => 1, "\x36" => 1, "\x37" => 1, "\x38" => 1, "\x39" => 1, "\x3a" => 1, "\x3b" => 1, "\x3c" => 1, "\x3d" => 1, "\x3e" => 1, "\x3f" => 1, "\x40" => 1, "\x41" => 1, "\x42" => 1, "\x43" => 1, "\x44" => 1, "\x45" => 1, "\x46" => 1, "\x47" => 1, "\x48" => 1, "\x49" => 1, "\x4a" => 1, "\x4b" => 1, "\x4c" => 1, "\x4d" => 1, "\x4e" => 1, "\x4f" => 1, "\x50" => 1, "\x51" => 1, "\x52" => 1, "\x53" => 1, "\x54" => 1, "\x55" => 1, "\x56" => 1, "\x57" => 1, "\x58" => 1, "\x59" => 1, "\x5a" => 1, "\x5b" => 1, "\x5c" => 1, "\x5d" => 1, "\x5e" => 1, "\x5f" => 1, "\x60" => 1, "\x61" => 1, "\x62" => 1, "\x63" => 1, "\x64" => 1, "\x65" => 1, "\x66" => 1, "\x67" => 1, "\x68" => 1, "\x69" => 1, "\x6a" => 1, "\x6b" => 1, "\x6c" => 1, "\x6d" => 1, "\x6e" => 1, "\x6f" => 1, "\x70" => 1, "\x71" => 1, "\x72" => 1, "\x73" => 1, "\x74" => 1, "\x75" => 1, "\x76" => 1, "\x77" => 1, "\x78" => 1, "\x79" => 1, "\x7a" => 1, "\x7b" => 1, "\x7c" => 1, "\x7d" => 1, "\x7e" => 1, "\x7f" => 1, "\x80" => 0, "\x81" => 0, "\x82" => 0, "\x83" => 0, "\x84" => 0, "\x85" => 0, "\x86" => 0, "\x87" => 0, "\x88" => 0, "\x89" => 0, "\x8a" => 0, "\x8b" => 0, "\x8c" => 0, "\x8d" => 0, "\x8e" => 0, "\x8f" => 0, "\x90" => 0, "\x91" => 0, "\x92" => 0, "\x93" => 0, "\x94" => 0, "\x95" => 0, "\x96" => 0, "\x97" => 0, "\x98" => 0, "\x99" => 0, "\x9a" => 0, "\x9b" => 0, "\x9c" => 0, "\x9d" => 0, "\x9e" => 0, "\x9f" => 0, "\xa0" => 0, "\xa1" => 0, "\xa2" => 0, "\xa3" => 0, "\xa4" => 0, "\xa5" => 0, "\xa6" => 0, "\xa7" => 0, "\xa8" => 0, "\xa9" => 0, "\xaa" => 0, "\xab" => 0, "\xac" => 0, "\xad" => 0, "\xae" => 0, "\xaf" => 0, "\xb0" => 0, "\xb1" => 0, "\xb2" => 0, "\xb3" => 0, "\xb4" => 0, "\xb5" => 0, "\xb6" => 0, "\xb7" => 0, "\xb8" => 0, "\xb9" => 0, "\xba" => 0, "\xbb" => 0, "\xbc" => 0, "\xbd" => 0, "\xbe" => 0, "\xbf" => 0, "\xc0" => 2, "\xc1" => 2, "\xc2" => 2, "\xc3" => 2, "\xc4" => 2, "\xc5" => 2, "\xc6" => 2, "\xc7" => 2, "\xc8" => 2, "\xc9" => 2, "\xca" => 2, "\xcb" => 2, "\xcc" => 2, "\xcd" => 2, "\xce" => 2, "\xcf" => 2, "\xd0" => 2, "\xd1" => 2, "\xd2" => 2, "\xd3" => 2, "\xd4" => 2, "\xd5" => 2, "\xd6" => 2, "\xd7" => 2, "\xd8" => 2, "\xd9" => 2, "\xda" => 2, "\xdb" => 2, "\xdc" => 2, "\xdd" => 2, "\xde" => 2, "\xdf" => 2, "\xe0" => 3, "\xe1" => 3, "\xe2" => 3, "\xe3" => 3, "\xe4" => 3, "\xe5" => 3, "\xe6" => 3, "\xe7" => 3, "\xe8" => 3, "\xe9" => 3, "\xea" => 3, "\xeb" => 3, "\xec" => 3, "\xed" => 3, "\xee" => 3, "\xef" => 3, "\xf0" => 4, "\xf1" => 4, "\xf2" => 4, "\xf3" => 4, "\xf4" => 4, "\xf5" => 4, "\xf6" => 4, "\xf7" => 4, "\xf8" => 5, "\xf9" => 5, "\xfa" => 5, "\xfb" => 5, "\xfc" => 6, "\xfd" => 6, "\xfe" => 0, "\xff" => 0, ]; private string $data = ''; private int $dataSize = 0; private array $map = []; private int $charCount = 0; private int $currentPos = 0; private int $fixedWidth = 0; /** * @param resource|string $input */ public function __construct($input, ?string $charset = 'utf-8') { $charset = strtolower(trim($charset)) ?: 'utf-8'; if ('utf-8' === $charset || 'utf8' === $charset) { $this->fixedWidth = 0; $this->map = ['p' => [], 'i' => []]; } else { switch ($charset) { // 16 bits case 'ucs2': case 'ucs-2': case 'utf16': case 'utf-16': $this->fixedWidth = 2; break; // 32 bits case 'ucs4': case 'ucs-4': case 'utf32': case 'utf-32': $this->fixedWidth = 4; break; // 7-8 bit charsets: (us-)?ascii, (iso|iec)-?8859-?[0-9]+, windows-?125[0-9], cp-?[0-9]+, ansi, macintosh, // koi-?7, koi-?8-?.+, mik, (cork|t1), v?iscii // and fallback default: $this->fixedWidth = 1; } } if (\is_resource($input)) { $blocks = 16372; while (false !== $read = fread($input, $blocks)) { $this->write($read); } } else { $this->write($input); } } public function read(int $length): ?string { if ($this->currentPos >= $this->charCount) { return null; } $length = ($this->currentPos + $length > $this->charCount) ? $this->charCount - $this->currentPos : $length; if ($this->fixedWidth > 0) { $len = $length * $this->fixedWidth; $ret = substr($this->data, $this->currentPos * $this->fixedWidth, $len); $this->currentPos += $length; } else { $end = $this->currentPos + $length; $end = $end > $this->charCount ? $this->charCount : $end; $ret = ''; $start = 0; if ($this->currentPos > 0) { $start = $this->map['p'][$this->currentPos - 1]; } $to = $start; for (; $this->currentPos < $end; ++$this->currentPos) { if (isset($this->map['i'][$this->currentPos])) { $ret .= substr($this->data, $start, $to - $start).'?'; $start = $this->map['p'][$this->currentPos]; } else { $to = $this->map['p'][$this->currentPos]; } } $ret .= substr($this->data, $start, $to - $start); } return $ret; } public function readBytes(int $length): ?array { if (null !== $read = $this->read($length)) { return array_map('ord', str_split($read, 1)); } return null; } public function setPointer(int $charOffset): void { if ($this->charCount < $charOffset) { $charOffset = $this->charCount; } $this->currentPos = $charOffset; } public function write(string $chars): void { $ignored = ''; $this->data .= $chars; if ($this->fixedWidth > 0) { $strlen = \strlen($chars); $ignoredL = $strlen % $this->fixedWidth; $ignored = $ignoredL ? substr($chars, -$ignoredL) : ''; $this->charCount += ($strlen - $ignoredL) / $this->fixedWidth; } else { $this->charCount += $this->getUtf8CharPositions($chars, $this->dataSize, $ignored); } $this->dataSize = \strlen($this->data) - \strlen($ignored); } private function getUtf8CharPositions(string $string, int $startOffset, string &$ignoredChars): int { $strlen = \strlen($string); $charPos = \count($this->map['p']); $foundChars = 0; $invalid = false; for ($i = 0; $i < $strlen; ++$i) { $char = $string[$i]; $size = self::UTF8_LENGTH_MAP[$char]; if (0 == $size) { /* char is invalid, we must wait for a resync */ $invalid = true; continue; } if ($invalid) { /* We mark the chars as invalid and start a new char */ $this->map['p'][$charPos + $foundChars] = $startOffset + $i; $this->map['i'][$charPos + $foundChars] = true; ++$foundChars; $invalid = false; } if (($i + $size) > $strlen) { $ignoredChars = substr($string, $i); break; } for ($j = 1; $j < $size; ++$j) { $char = $string[$i + $j]; if ($char > "\x7F" && $char < "\xC0") { // Valid - continue parsing } else { /* char is invalid, we must wait for a resync */ $invalid = true; continue 2; } } /* Ok we got a complete char here */ $this->map['p'][$charPos + $foundChars] = $startOffset + $i + $size; $i += $j - 1; ++$foundChars; } return $foundChars; } } PKdZlGyAyA Email.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime; use Symfony\Component\Mime\Exception\LogicException; use Symfony\Component\Mime\Part\AbstractPart; use Symfony\Component\Mime\Part\DataPart; use Symfony\Component\Mime\Part\Multipart\AlternativePart; use Symfony\Component\Mime\Part\Multipart\MixedPart; use Symfony\Component\Mime\Part\Multipart\RelatedPart; use Symfony\Component\Mime\Part\TextPart; /** * @author Fabien Potencier */ class Email extends Message { public const PRIORITY_HIGHEST = 1; public const PRIORITY_HIGH = 2; public const PRIORITY_NORMAL = 3; public const PRIORITY_LOW = 4; public const PRIORITY_LOWEST = 5; private const PRIORITY_MAP = [ self::PRIORITY_HIGHEST => 'Highest', self::PRIORITY_HIGH => 'High', self::PRIORITY_NORMAL => 'Normal', self::PRIORITY_LOW => 'Low', self::PRIORITY_LOWEST => 'Lowest', ]; /** * @var resource|string|null */ private $text; private ?string $textCharset = null; /** * @var resource|string|null */ private $html; private ?string $htmlCharset = null; private array $attachments = []; private ?AbstractPart $cachedBody = null; // Used to avoid wrong body hash in DKIM signatures with multiple parts (e.g. HTML + TEXT) due to multiple boundaries. /** * @return $this */ public function subject(string $subject): static { return $this->setHeaderBody('Text', 'Subject', $subject); } public function getSubject(): ?string { return $this->getHeaders()->getHeaderBody('Subject'); } /** * @return $this */ public function date(\DateTimeInterface $dateTime): static { return $this->setHeaderBody('Date', 'Date', $dateTime); } public function getDate(): ?\DateTimeImmutable { return $this->getHeaders()->getHeaderBody('Date'); } /** * @return $this */ public function returnPath(Address|string $address): static { return $this->setHeaderBody('Path', 'Return-Path', Address::create($address)); } public function getReturnPath(): ?Address { return $this->getHeaders()->getHeaderBody('Return-Path'); } /** * @return $this */ public function sender(Address|string $address): static { return $this->setHeaderBody('Mailbox', 'Sender', Address::create($address)); } public function getSender(): ?Address { return $this->getHeaders()->getHeaderBody('Sender'); } /** * @return $this */ public function addFrom(Address|string ...$addresses): static { return $this->addListAddressHeaderBody('From', $addresses); } /** * @return $this */ public function from(Address|string ...$addresses): static { return $this->setListAddressHeaderBody('From', $addresses); } /** * @return Address[] */ public function getFrom(): array { return $this->getHeaders()->getHeaderBody('From') ?: []; } /** * @return $this */ public function addReplyTo(Address|string ...$addresses): static { return $this->addListAddressHeaderBody('Reply-To', $addresses); } /** * @return $this */ public function replyTo(Address|string ...$addresses): static { return $this->setListAddressHeaderBody('Reply-To', $addresses); } /** * @return Address[] */ public function getReplyTo(): array { return $this->getHeaders()->getHeaderBody('Reply-To') ?: []; } /** * @return $this */ public function addTo(Address|string ...$addresses): static { return $this->addListAddressHeaderBody('To', $addresses); } /** * @return $this */ public function to(Address|string ...$addresses): static { return $this->setListAddressHeaderBody('To', $addresses); } /** * @return Address[] */ public function getTo(): array { return $this->getHeaders()->getHeaderBody('To') ?: []; } /** * @return $this */ public function addCc(Address|string ...$addresses): static { return $this->addListAddressHeaderBody('Cc', $addresses); } /** * @return $this */ public function cc(Address|string ...$addresses): static { return $this->setListAddressHeaderBody('Cc', $addresses); } /** * @return Address[] */ public function getCc(): array { return $this->getHeaders()->getHeaderBody('Cc') ?: []; } /** * @return $this */ public function addBcc(Address|string ...$addresses): static { return $this->addListAddressHeaderBody('Bcc', $addresses); } /** * @return $this */ public function bcc(Address|string ...$addresses): static { return $this->setListAddressHeaderBody('Bcc', $addresses); } /** * @return Address[] */ public function getBcc(): array { return $this->getHeaders()->getHeaderBody('Bcc') ?: []; } /** * Sets the priority of this message. * * The value is an integer where 1 is the highest priority and 5 is the lowest. * * @return $this */ public function priority(int $priority): static { if ($priority > 5) { $priority = 5; } elseif ($priority < 1) { $priority = 1; } return $this->setHeaderBody('Text', 'X-Priority', sprintf('%d (%s)', $priority, self::PRIORITY_MAP[$priority])); } /** * Get the priority of this message. * * The returned value is an integer where 1 is the highest priority and 5 * is the lowest. */ public function getPriority(): int { [$priority] = sscanf($this->getHeaders()->getHeaderBody('X-Priority') ?? '', '%[1-5]'); return $priority ?? 3; } /** * @param resource|string|null $body * * @return $this */ public function text($body, string $charset = 'utf-8'): static { if (null !== $body && !\is_string($body) && !\is_resource($body)) { throw new \TypeError(sprintf('The body must be a string, a resource or null (got "%s").', get_debug_type($body))); } $this->cachedBody = null; $this->text = $body; $this->textCharset = $charset; return $this; } /** * @return resource|string|null */ public function getTextBody() { return $this->text; } public function getTextCharset(): ?string { return $this->textCharset; } /** * @param resource|string|null $body * * @return $this */ public function html($body, string $charset = 'utf-8'): static { if (null !== $body && !\is_string($body) && !\is_resource($body)) { throw new \TypeError(sprintf('The body must be a string, a resource or null (got "%s").', get_debug_type($body))); } $this->cachedBody = null; $this->html = $body; $this->htmlCharset = $charset; return $this; } /** * @return resource|string|null */ public function getHtmlBody() { return $this->html; } public function getHtmlCharset(): ?string { return $this->htmlCharset; } /** * @param resource|string $body * * @return $this */ public function attach($body, string $name = null, string $contentType = null): static { if (!\is_string($body) && !\is_resource($body)) { throw new \TypeError(sprintf('The body must be a string or a resource (got "%s").', get_debug_type($body))); } $this->cachedBody = null; $this->attachments[] = ['body' => $body, 'name' => $name, 'content-type' => $contentType, 'inline' => false]; return $this; } /** * @return $this */ public function attachFromPath(string $path, string $name = null, string $contentType = null): static { $this->cachedBody = null; $this->attachments[] = ['path' => $path, 'name' => $name, 'content-type' => $contentType, 'inline' => false]; return $this; } /** * @param resource|string $body * * @return $this */ public function embed($body, string $name = null, string $contentType = null): static { if (!\is_string($body) && !\is_resource($body)) { throw new \TypeError(sprintf('The body must be a string or a resource (got "%s").', get_debug_type($body))); } $this->cachedBody = null; $this->attachments[] = ['body' => $body, 'name' => $name, 'content-type' => $contentType, 'inline' => true]; return $this; } /** * @return $this */ public function embedFromPath(string $path, string $name = null, string $contentType = null): static { $this->cachedBody = null; $this->attachments[] = ['path' => $path, 'name' => $name, 'content-type' => $contentType, 'inline' => true]; return $this; } /** * @return $this */ public function attachPart(DataPart $part): static { $this->cachedBody = null; $this->attachments[] = ['part' => $part]; return $this; } /** * @return array|DataPart[] */ public function getAttachments(): array { $parts = []; foreach ($this->attachments as $attachment) { $parts[] = $this->createDataPart($attachment); } return $parts; } public function getBody(): AbstractPart { if (null !== $body = parent::getBody()) { return $body; } return $this->generateBody(); } public function ensureValidity() { if (null === $this->text && null === $this->html && !$this->attachments) { throw new LogicException('A message must have a text or an HTML part or attachments.'); } parent::ensureValidity(); } /** * Generates an AbstractPart based on the raw body of a message. * * The most "complex" part generated by this method is when there is text and HTML bodies * with related images for the HTML part and some attachments: * * multipart/mixed * | * |------------> multipart/related * | | * | |------------> multipart/alternative * | | | * | | ------------> text/plain (with content) * | | | * | | ------------> text/html (with content) * | | * | ------------> image/png (with content) * | * ------------> application/pdf (with content) */ private function generateBody(): AbstractPart { if (null !== $this->cachedBody) { return $this->cachedBody; } $this->ensureValidity(); [$htmlPart, $otherParts, $relatedParts] = $this->prepareParts(); $part = null === $this->text ? null : new TextPart($this->text, $this->textCharset); if (null !== $htmlPart) { if (null !== $part) { $part = new AlternativePart($part, $htmlPart); } else { $part = $htmlPart; } } if ($relatedParts) { $part = new RelatedPart($part, ...$relatedParts); } if ($otherParts) { if ($part) { $part = new MixedPart($part, ...$otherParts); } else { $part = new MixedPart(...$otherParts); } } return $this->cachedBody = $part; } private function prepareParts(): ?array { $names = []; $htmlPart = null; $html = $this->html; if (null !== $html) { $htmlPart = new TextPart($html, $this->htmlCharset, 'html'); $html = $htmlPart->getBody(); preg_match_all('(]*src\s*=\s*(?:([\'"])cid:(.+?)\\1|cid:([^>\s]+)))i', $html, $names); $names = array_filter(array_unique(array_merge($names[2], $names[3]))); } // usage of reflection is a temporary workaround for missing getters that will be added in 6.2 $nameRef = new \ReflectionProperty(TextPart::class, 'name'); $nameRef->setAccessible(true); $otherParts = $relatedParts = []; foreach ($this->attachments as $attachment) { $part = $this->createDataPart($attachment); if (isset($attachment['part'])) { $attachment['name'] = $nameRef->getValue($part); } $related = false; foreach ($names as $name) { if ($name !== $attachment['name']) { continue; } if (isset($relatedParts[$name])) { continue 2; } $part->setDisposition('inline'); $html = str_replace('cid:'.$name, 'cid:'.$part->getContentId(), $html, $count); if ($count) { $related = true; } $part->setName($part->getContentId()); break; } if ($related) { $relatedParts[$attachment['name']] = $part; } else { $otherParts[] = $part; } } if (null !== $htmlPart) { $htmlPart = new TextPart($html, $this->htmlCharset, 'html'); } return [$htmlPart, $otherParts, array_values($relatedParts)]; } private function createDataPart(array $attachment): DataPart { if (isset($attachment['part'])) { return $attachment['part']; } if (isset($attachment['body'])) { $part = new DataPart($attachment['body'], $attachment['name'] ?? null, $attachment['content-type'] ?? null); } else { $part = DataPart::fromPath($attachment['path'] ?? '', $attachment['name'] ?? null, $attachment['content-type'] ?? null); } if ($attachment['inline']) { $part->asInline(); } return $part; } /** * @return $this */ private function setHeaderBody(string $type, string $name, $body): static { $this->getHeaders()->setHeaderBody($type, $name, $body); return $this; } private function addListAddressHeaderBody(string $name, array $addresses) { if (!$header = $this->getHeaders()->get($name)) { return $this->setListAddressHeaderBody($name, $addresses); } $header->addAddresses(Address::createArray($addresses)); return $this; } /** * @return $this */ private function setListAddressHeaderBody(string $name, array $addresses): static { $addresses = Address::createArray($addresses); $headers = $this->getHeaders(); if ($header = $headers->get($name)) { $header->setAddresses($addresses); } else { $headers->addMailboxListHeader($name, $addresses); } return $this; } /** * @internal */ public function __serialize(): array { if (\is_resource($this->text)) { $this->text = (new TextPart($this->text))->getBody(); } if (\is_resource($this->html)) { $this->html = (new TextPart($this->html))->getBody(); } foreach ($this->attachments as $i => $attachment) { if (isset($attachment['body']) && \is_resource($attachment['body'])) { $this->attachments[$i]['body'] = (new TextPart($attachment['body']))->getBody(); } } return [$this->text, $this->textCharset, $this->html, $this->htmlCharset, $this->attachments, parent::__serialize()]; } /** * @internal */ public function __unserialize(array $data): void { [$this->text, $this->textCharset, $this->html, $this->htmlCharset, $this->attachments, $parentData] = $data; parent::__unserialize($parentData); } } PKdZ Crypto/SMime.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Crypto; use Symfony\Component\Mime\Exception\RuntimeException; use Symfony\Component\Mime\Part\SMimePart; /** * @author Sebastiaan Stok * * @internal */ abstract class SMime { protected function normalizeFilePath(string $path): string { if (!file_exists($path)) { throw new RuntimeException(sprintf('File does not exist: "%s".', $path)); } return 'file://'.str_replace('\\', '/', realpath($path)); } protected function iteratorToFile(iterable $iterator, $stream): void { foreach ($iterator as $chunk) { fwrite($stream, $chunk); } } protected function convertMessageToSMimePart($stream, string $type, string $subtype): SMimePart { rewind($stream); $headers = ''; while (!feof($stream)) { $buffer = fread($stream, 78); $headers .= $buffer; // Detect ending of header list if (preg_match('/(\r\n\r\n|\n\n)/', $headers, $match)) { $headersPosEnd = strpos($headers, $headerBodySeparator = $match[0]); break; } } $headers = $this->getMessageHeaders(trim(substr($headers, 0, $headersPosEnd))); fseek($stream, $headersPosEnd + \strlen($headerBodySeparator)); return new SMimePart($this->getStreamIterator($stream), $type, $subtype, $this->getParametersFromHeader($headers['content-type'])); } protected function getStreamIterator($stream): iterable { while (!feof($stream)) { yield str_replace("\n", "\r\n", str_replace("\r\n", "\n", fread($stream, 16372))); } } private function getMessageHeaders(string $headerData): array { $headers = []; $headerLines = explode("\r\n", str_replace("\n", "\r\n", str_replace("\r\n", "\n", $headerData))); $currentHeaderName = ''; // Transform header lines into an associative array foreach ($headerLines as $headerLine) { // Empty lines between headers indicate a new mime-entity if ('' === $headerLine) { break; } // Handle headers that span multiple lines if (!str_contains($headerLine, ':')) { $headers[$currentHeaderName] .= ' '.trim($headerLine); continue; } $header = explode(':', $headerLine, 2); $currentHeaderName = strtolower($header[0]); $headers[$currentHeaderName] = trim($header[1]); } return $headers; } private function getParametersFromHeader(string $header): array { $params = []; preg_match_all('/(?P[a-z-0-9]+)=(?P"[^"]+"|(?:[^\s;]+|$))(?:\s+;)?/i', $header, $matches); foreach ($matches['value'] as $pos => $paramValue) { $params[$matches['name'][$pos]] = trim($paramValue, '"'); } return $params; } } PKdZW&Crypto/DkimOptions.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Crypto; /** * A helper providing autocompletion for available DkimSigner options. * * @author Fabien Potencier */ final class DkimOptions { private array $options = []; public function toArray(): array { return $this->options; } /** * @return $this */ public function algorithm(string $algo): static { $this->options['algorithm'] = $algo; return $this; } /** * @return $this */ public function signatureExpirationDelay(int $show): static { $this->options['signature_expiration_delay'] = $show; return $this; } /** * @return $this */ public function bodyMaxLength(int $max): static { $this->options['body_max_length'] = $max; return $this; } /** * @return $this */ public function bodyShowLength(bool $show): static { $this->options['body_show_length'] = $show; return $this; } /** * @return $this */ public function headerCanon(string $canon): static { $this->options['header_canon'] = $canon; return $this; } /** * @return $this */ public function bodyCanon(string $canon): static { $this->options['body_canon'] = $canon; return $this; } /** * @return $this */ public function headersToIgnore(array $headers): static { $this->options['headers_to_ignore'] = $headers; return $this; } } PKdZCrypto/DkimSigner.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Crypto; use Symfony\Component\Mime\Exception\InvalidArgumentException; use Symfony\Component\Mime\Exception\RuntimeException; use Symfony\Component\Mime\Header\UnstructuredHeader; use Symfony\Component\Mime\Message; use Symfony\Component\Mime\Part\AbstractPart; /** * @author Fabien Potencier * * RFC 6376 and 8301 */ final class DkimSigner { public const CANON_SIMPLE = 'simple'; public const CANON_RELAXED = 'relaxed'; public const ALGO_SHA256 = 'rsa-sha256'; public const ALGO_ED25519 = 'ed25519-sha256'; // RFC 8463 private $key; private string $domainName; private string $selector; private array $defaultOptions; /** * @param string $pk The private key as a string or the path to the file containing the private key, should be prefixed with file:// (in PEM format) * @param string $passphrase A passphrase of the private key (if any) */ public function __construct(string $pk, string $domainName, string $selector, array $defaultOptions = [], string $passphrase = '') { if (!\extension_loaded('openssl')) { throw new \LogicException('PHP extension "openssl" is required to use DKIM.'); } $this->key = openssl_pkey_get_private($pk, $passphrase) ?: throw new InvalidArgumentException('Unable to load DKIM private key: '.openssl_error_string()); $this->domainName = $domainName; $this->selector = $selector; $this->defaultOptions = $defaultOptions + [ 'algorithm' => self::ALGO_SHA256, 'signature_expiration_delay' => 0, 'body_max_length' => \PHP_INT_MAX, 'body_show_length' => false, 'header_canon' => self::CANON_RELAXED, 'body_canon' => self::CANON_RELAXED, 'headers_to_ignore' => [], ]; } public function sign(Message $message, array $options = []): Message { $options += $this->defaultOptions; if (!\in_array($options['algorithm'], [self::ALGO_SHA256, self::ALGO_ED25519], true)) { throw new InvalidArgumentException(sprintf('Invalid DKIM signing algorithm "%s".', $options['algorithm'])); } $headersToIgnore['return-path'] = true; $headersToIgnore['x-transport'] = true; foreach ($options['headers_to_ignore'] as $name) { $headersToIgnore[strtolower($name)] = true; } unset($headersToIgnore['from']); $signedHeaderNames = []; $headerCanonData = ''; $headers = $message->getPreparedHeaders(); foreach ($headers->getNames() as $name) { foreach ($headers->all($name) as $header) { if (isset($headersToIgnore[strtolower($header->getName())])) { continue; } if ('' !== $header->getBodyAsString()) { $headerCanonData .= $this->canonicalizeHeader($header->toString(), $options['header_canon']); $signedHeaderNames[] = $header->getName(); } } } [$bodyHash, $bodyLength] = $this->hashBody($message->getBody(), $options['body_canon'], $options['body_max_length']); $params = [ 'v' => '1', 'q' => 'dns/txt', 'a' => $options['algorithm'], 'bh' => base64_encode($bodyHash), 'd' => $this->domainName, 'h' => implode(': ', $signedHeaderNames), 'i' => '@'.$this->domainName, 's' => $this->selector, 't' => time(), 'c' => $options['header_canon'].'/'.$options['body_canon'], ]; if ($options['body_show_length']) { $params['l'] = $bodyLength; } if ($options['signature_expiration_delay']) { $params['x'] = $params['t'] + $options['signature_expiration_delay']; } $value = ''; foreach ($params as $k => $v) { $value .= $k.'='.$v.'; '; } $value = trim($value); $header = new UnstructuredHeader('DKIM-Signature', $value); $headerCanonData .= rtrim($this->canonicalizeHeader($header->toString()."\r\n b=", $options['header_canon'])); if (self::ALGO_SHA256 === $options['algorithm']) { if (!openssl_sign($headerCanonData, $signature, $this->key, \OPENSSL_ALGO_SHA256)) { throw new RuntimeException('Unable to sign DKIM hash: '.openssl_error_string()); } } else { throw new \RuntimeException(sprintf('The "%s" DKIM signing algorithm is not supported yet.', self::ALGO_ED25519)); } $header->setValue($value.' b='.trim(chunk_split(base64_encode($signature), 73, ' '))); $headers->add($header); return new Message($headers, $message->getBody()); } private function canonicalizeHeader(string $header, string $headerCanon): string { if (self::CANON_RELAXED !== $headerCanon) { return $header."\r\n"; } $exploded = explode(':', $header, 2); $name = strtolower(trim($exploded[0])); $value = str_replace("\r\n", '', $exploded[1]); $value = trim(preg_replace("/[ \t][ \t]+/", ' ', $value)); return $name.':'.$value."\r\n"; } private function hashBody(AbstractPart $body, string $bodyCanon, int $maxLength): array { $hash = hash_init('sha256'); $relaxed = self::CANON_RELAXED === $bodyCanon; $currentLine = ''; $emptyCounter = 0; $isSpaceSequence = false; $length = 0; foreach ($body->bodyToIterable() as $chunk) { $canon = ''; for ($i = 0, $len = \strlen($chunk); $i < $len; ++$i) { switch ($chunk[$i]) { case "\r": break; case "\n": // previous char is always \r if ($relaxed) { $isSpaceSequence = false; } if ('' === $currentLine) { ++$emptyCounter; } else { $currentLine = ''; $canon .= "\r\n"; } break; case ' ': case "\t": if ($relaxed) { $isSpaceSequence = true; break; } // no break default: if ($emptyCounter > 0) { $canon .= str_repeat("\r\n", $emptyCounter); $emptyCounter = 0; } if ($isSpaceSequence) { $currentLine .= ' '; $canon .= ' '; $isSpaceSequence = false; } $currentLine .= $chunk[$i]; $canon .= $chunk[$i]; } } if ($length + \strlen($canon) >= $maxLength) { $canon = substr($canon, 0, $maxLength - $length); $length += \strlen($canon); hash_update($hash, $canon); break; } $length += \strlen($canon); hash_update($hash, $canon); } // Add trailing Line return if last line is non empty if ('' !== $currentLine) { hash_update($hash, "\r\n"); $length += \strlen("\r\n"); } if (!$relaxed && 0 === $length) { hash_update($hash, "\r\n"); $length = 2; } return [hash_final($hash, true), $length]; } } PKdZ$TCrypto/SMimeEncrypter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Crypto; use Symfony\Component\Mime\Exception\RuntimeException; use Symfony\Component\Mime\Message; /** * @author Sebastiaan Stok */ final class SMimeEncrypter extends SMime { private string|array $certs; private int $cipher; /** * @param string|string[] $certificate The path (or array of paths) of the file(s) containing the X.509 certificate(s) * @param int|null $cipher A set of algorithms used to encrypt the message. Must be one of these PHP constants: https://www.php.net/manual/en/openssl.ciphers.php */ public function __construct(string|array $certificate, int $cipher = null) { if (!\extension_loaded('openssl')) { throw new \LogicException('PHP extension "openssl" is required to use SMime.'); } if (\is_array($certificate)) { $this->certs = array_map([$this, 'normalizeFilePath'], $certificate); } else { $this->certs = $this->normalizeFilePath($certificate); } $this->cipher = $cipher ?? \OPENSSL_CIPHER_AES_256_CBC; } public function encrypt(Message $message): Message { $bufferFile = tmpfile(); $outputFile = tmpfile(); $this->iteratorToFile($message->toIterable(), $bufferFile); if (!@openssl_pkcs7_encrypt(stream_get_meta_data($bufferFile)['uri'], stream_get_meta_data($outputFile)['uri'], $this->certs, [], 0, $this->cipher)) { throw new RuntimeException(sprintf('Failed to encrypt S/Mime message. Error: "%s".', openssl_error_string())); } $mimePart = $this->convertMessageToSMimePart($outputFile, 'application', 'pkcs7-mime'); $mimePart->getHeaders() ->addTextHeader('Content-Transfer-Encoding', 'base64') ->addParameterizedHeader('Content-Disposition', 'attachment', ['name' => 'smime.p7m']) ; return new Message($message->getHeaders(), $mimePart); } } PKdZ\ Crypto/SMimeSigner.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Crypto; use Symfony\Component\Mime\Exception\RuntimeException; use Symfony\Component\Mime\Message; /** * @author Sebastiaan Stok */ final class SMimeSigner extends SMime { private string $signCertificate; private string|array $signPrivateKey; private int $signOptions; private ?string $extraCerts; /** * @param string $certificate The path of the file containing the signing certificate (in PEM format) * @param string $privateKey The path of the file containing the private key (in PEM format) * @param string|null $privateKeyPassphrase A passphrase of the private key (if any) * @param string|null $extraCerts The path of the file containing intermediate certificates (in PEM format) needed by the signing certificate * @param int|null $signOptions Bitwise operator options for openssl_pkcs7_sign() (@see https://secure.php.net/manual/en/openssl.pkcs7.flags.php) */ public function __construct(string $certificate, string $privateKey, string $privateKeyPassphrase = null, string $extraCerts = null, int $signOptions = null) { if (!\extension_loaded('openssl')) { throw new \LogicException('PHP extension "openssl" is required to use SMime.'); } $this->signCertificate = $this->normalizeFilePath($certificate); if (null !== $privateKeyPassphrase) { $this->signPrivateKey = [$this->normalizeFilePath($privateKey), $privateKeyPassphrase]; } else { $this->signPrivateKey = $this->normalizeFilePath($privateKey); } $this->signOptions = $signOptions ?? \PKCS7_DETACHED; $this->extraCerts = $extraCerts ? realpath($extraCerts) : null; } public function sign(Message $message): Message { $bufferFile = tmpfile(); $outputFile = tmpfile(); $this->iteratorToFile($message->getBody()->toIterable(), $bufferFile); if (!@openssl_pkcs7_sign(stream_get_meta_data($bufferFile)['uri'], stream_get_meta_data($outputFile)['uri'], $this->signCertificate, $this->signPrivateKey, [], $this->signOptions, $this->extraCerts)) { throw new RuntimeException(sprintf('Failed to sign S/Mime message. Error: "%s".', openssl_error_string())); } return new Message($message->getHeaders(), $this->convertMessageToSMimePart($outputFile, 'multipart', 'signed')); } } PKdZ# README.mdnu[MIME Component ============== The MIME component allows manipulating MIME messages. 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) PKdZ&Khh(Test/Constraint/EmailAddressContains.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Test\Constraint; use PHPUnit\Framework\Constraint\Constraint; use Symfony\Component\Mime\Header\MailboxHeader; use Symfony\Component\Mime\Header\MailboxListHeader; use Symfony\Component\Mime\RawMessage; final class EmailAddressContains extends Constraint { private string $headerName; private string $expectedValue; public function __construct(string $headerName, string $expectedValue) { $this->headerName = $headerName; $this->expectedValue = $expectedValue; } /** * {@inheritdoc} */ public function toString(): string { return sprintf('contains address "%s" with value "%s"', $this->headerName, $this->expectedValue); } /** * @param RawMessage $message * * {@inheritdoc} */ protected function matches($message): bool { if (RawMessage::class === \get_class($message)) { throw new \LogicException('Unable to test a message address on a RawMessage instance.'); } $header = $message->getHeaders()->get($this->headerName); if ($header instanceof MailboxHeader) { return $this->expectedValue === $header->getAddress()->getAddress(); } elseif ($header instanceof MailboxListHeader) { foreach ($header->getAddresses() as $address) { if ($this->expectedValue === $address->getAddress()) { return true; } } return false; } throw new \LogicException('Unable to test a message address on a non-address header.'); } /** * @param RawMessage $message * * {@inheritdoc} */ protected function failureDescription($message): string { return sprintf('the Email %s (value is %s)', $this->toString(), $message->getHeaders()->get($this->headerName)->getBodyAsString()); } } PKdZME )Test/Constraint/EmailHtmlBodyContains.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Test\Constraint; use PHPUnit\Framework\Constraint\Constraint; use Symfony\Component\Mime\Message; use Symfony\Component\Mime\RawMessage; final class EmailHtmlBodyContains extends Constraint { private string $expectedText; public function __construct(string $expectedText) { $this->expectedText = $expectedText; } /** * {@inheritdoc} */ public function toString(): string { return sprintf('contains "%s"', $this->expectedText); } /** * {@inheritdoc} * * @param RawMessage $message */ protected function matches($message): bool { if (RawMessage::class === \get_class($message) || Message::class === \get_class($message)) { throw new \LogicException('Unable to test a message HTML body on a RawMessage or Message instance.'); } return false !== mb_strpos($message->getHtmlBody(), $this->expectedText); } /** * {@inheritdoc} * * @param RawMessage $message */ protected function failureDescription($message): string { return 'the Email HTML body '.$this->toString(); } } PKdZGdg88#Test/Constraint/EmailHeaderSame.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Test\Constraint; use PHPUnit\Framework\Constraint\Constraint; use Symfony\Component\Mime\Header\UnstructuredHeader; use Symfony\Component\Mime\RawMessage; final class EmailHeaderSame extends Constraint { private string $headerName; private string $expectedValue; public function __construct(string $headerName, string $expectedValue) { $this->headerName = $headerName; $this->expectedValue = $expectedValue; } /** * {@inheritdoc} */ public function toString(): string { return sprintf('has header "%s" with value "%s"', $this->headerName, $this->expectedValue); } /** * @param RawMessage $message * * {@inheritdoc} */ protected function matches($message): bool { if (RawMessage::class === \get_class($message)) { throw new \LogicException('Unable to test a message header on a RawMessage instance.'); } return $this->expectedValue === $this->getHeaderValue($message); } /** * @param RawMessage $message * * {@inheritdoc} */ protected function failureDescription($message): string { return sprintf('the Email %s (value is %s)', $this->toString(), $this->getHeaderValue($message) ?? 'null'); } private function getHeaderValue($message): ?string { if (null === $header = $message->getHeaders()->get($this->headerName)) { return null; } return $header instanceof UnstructuredHeader ? $header->getValue() : $header->getBodyAsString(); } } PKdZ:pz5)Test/Constraint/EmailTextBodyContains.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Test\Constraint; use PHPUnit\Framework\Constraint\Constraint; use Symfony\Component\Mime\Message; use Symfony\Component\Mime\RawMessage; final class EmailTextBodyContains extends Constraint { private string $expectedText; public function __construct(string $expectedText) { $this->expectedText = $expectedText; } /** * {@inheritdoc} */ public function toString(): string { return sprintf('contains "%s"', $this->expectedText); } /** * {@inheritdoc} * * @param RawMessage $message */ protected function matches($message): bool { if (RawMessage::class === \get_class($message) || Message::class === \get_class($message)) { throw new \LogicException('Unable to test a message text body on a RawMessage or Message instance.'); } return false !== mb_strpos($message->getTextBody(), $this->expectedText); } /** * {@inheritdoc} * * @param RawMessage $message */ protected function failureDescription($message): string { return 'the Email text body '.$this->toString(); } } PKdZģg0(Test/Constraint/EmailAttachmentCount.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Test\Constraint; use PHPUnit\Framework\Constraint\Constraint; use Symfony\Component\Mime\Message; use Symfony\Component\Mime\RawMessage; final class EmailAttachmentCount extends Constraint { private int $expectedValue; private ?string $transport; public function __construct(int $expectedValue, string $transport = null) { $this->expectedValue = $expectedValue; $this->transport = $transport; } /** * {@inheritdoc} */ public function toString(): string { return sprintf('has sent "%d" attachment(s)', $this->expectedValue); } /** * @param RawMessage $message * * {@inheritdoc} */ protected function matches($message): bool { if (RawMessage::class === \get_class($message) || Message::class === \get_class($message)) { throw new \LogicException('Unable to test a message attachment on a RawMessage or Message instance.'); } return $this->expectedValue === \count($message->getAttachments()); } /** * @param RawMessage $message * * {@inheritdoc} */ protected function failureDescription($message): string { return 'the Email '.$this->toString(); } } PKdZ "Test/Constraint/EmailHasHeader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Test\Constraint; use PHPUnit\Framework\Constraint\Constraint; use Symfony\Component\Mime\RawMessage; final class EmailHasHeader extends Constraint { private string $headerName; public function __construct(string $headerName) { $this->headerName = $headerName; } /** * {@inheritdoc} */ public function toString(): string { return sprintf('has header "%s"', $this->headerName); } /** * @param RawMessage $message * * {@inheritdoc} */ protected function matches($message): bool { if (RawMessage::class === \get_class($message)) { throw new \LogicException('Unable to test a message header on a RawMessage instance.'); } return $message->getHeaders()->has($this->headerName); } /** * @param RawMessage $message * * {@inheritdoc} */ protected function failureDescription($message): string { return 'the Email '.$this->toString(); } } PKdZCEncoder/EncoderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Encoder; /** * @author Chris Corbyn */ interface EncoderInterface { /** * Encode a given string to produce an encoded string. * * @param int $firstLineOffset if first line needs to be shorter * @param int $maxLineLength - 0 indicates the default length for this encoding */ public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string; } PKdZiq &Encoder/MimeHeaderEncoderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Encoder; /** * @author Chris Corbyn */ interface MimeHeaderEncoderInterface { /** * Get the MIME name of this content encoding scheme. */ public function getName(): string; } PKdZ'Encoder/QpContentEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Encoder; /** * @author Lars Strojny */ final class QpContentEncoder implements ContentEncoderInterface { public function encodeByteStream($stream, int $maxLineLength = 0): iterable { if (!\is_resource($stream)) { throw new \TypeError(sprintf('Method "%s" takes a stream as a first argument.', __METHOD__)); } // we don't use PHP stream filters here as the content should be small enough yield $this->encodeString(stream_get_contents($stream), 'utf-8', 0, $maxLineLength); } public function getName(): string { return 'quoted-printable'; } public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string { return $this->standardize(quoted_printable_encode($string)); } /** * Make sure CRLF is correct and HT/SPACE are in valid places. */ private function standardize(string $string): string { // transform CR or LF to CRLF $string = preg_replace('~=0D(?!=0A)|(? * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Encoder; use Symfony\Component\Mime\CharacterStream; /** * @author Chris Corbyn */ class QpEncoder implements EncoderInterface { /** * Pre-computed QP for HUGE optimization. */ private const QP_MAP = [ 0 => '=00', 1 => '=01', 2 => '=02', 3 => '=03', 4 => '=04', 5 => '=05', 6 => '=06', 7 => '=07', 8 => '=08', 9 => '=09', 10 => '=0A', 11 => '=0B', 12 => '=0C', 13 => '=0D', 14 => '=0E', 15 => '=0F', 16 => '=10', 17 => '=11', 18 => '=12', 19 => '=13', 20 => '=14', 21 => '=15', 22 => '=16', 23 => '=17', 24 => '=18', 25 => '=19', 26 => '=1A', 27 => '=1B', 28 => '=1C', 29 => '=1D', 30 => '=1E', 31 => '=1F', 32 => '=20', 33 => '=21', 34 => '=22', 35 => '=23', 36 => '=24', 37 => '=25', 38 => '=26', 39 => '=27', 40 => '=28', 41 => '=29', 42 => '=2A', 43 => '=2B', 44 => '=2C', 45 => '=2D', 46 => '=2E', 47 => '=2F', 48 => '=30', 49 => '=31', 50 => '=32', 51 => '=33', 52 => '=34', 53 => '=35', 54 => '=36', 55 => '=37', 56 => '=38', 57 => '=39', 58 => '=3A', 59 => '=3B', 60 => '=3C', 61 => '=3D', 62 => '=3E', 63 => '=3F', 64 => '=40', 65 => '=41', 66 => '=42', 67 => '=43', 68 => '=44', 69 => '=45', 70 => '=46', 71 => '=47', 72 => '=48', 73 => '=49', 74 => '=4A', 75 => '=4B', 76 => '=4C', 77 => '=4D', 78 => '=4E', 79 => '=4F', 80 => '=50', 81 => '=51', 82 => '=52', 83 => '=53', 84 => '=54', 85 => '=55', 86 => '=56', 87 => '=57', 88 => '=58', 89 => '=59', 90 => '=5A', 91 => '=5B', 92 => '=5C', 93 => '=5D', 94 => '=5E', 95 => '=5F', 96 => '=60', 97 => '=61', 98 => '=62', 99 => '=63', 100 => '=64', 101 => '=65', 102 => '=66', 103 => '=67', 104 => '=68', 105 => '=69', 106 => '=6A', 107 => '=6B', 108 => '=6C', 109 => '=6D', 110 => '=6E', 111 => '=6F', 112 => '=70', 113 => '=71', 114 => '=72', 115 => '=73', 116 => '=74', 117 => '=75', 118 => '=76', 119 => '=77', 120 => '=78', 121 => '=79', 122 => '=7A', 123 => '=7B', 124 => '=7C', 125 => '=7D', 126 => '=7E', 127 => '=7F', 128 => '=80', 129 => '=81', 130 => '=82', 131 => '=83', 132 => '=84', 133 => '=85', 134 => '=86', 135 => '=87', 136 => '=88', 137 => '=89', 138 => '=8A', 139 => '=8B', 140 => '=8C', 141 => '=8D', 142 => '=8E', 143 => '=8F', 144 => '=90', 145 => '=91', 146 => '=92', 147 => '=93', 148 => '=94', 149 => '=95', 150 => '=96', 151 => '=97', 152 => '=98', 153 => '=99', 154 => '=9A', 155 => '=9B', 156 => '=9C', 157 => '=9D', 158 => '=9E', 159 => '=9F', 160 => '=A0', 161 => '=A1', 162 => '=A2', 163 => '=A3', 164 => '=A4', 165 => '=A5', 166 => '=A6', 167 => '=A7', 168 => '=A8', 169 => '=A9', 170 => '=AA', 171 => '=AB', 172 => '=AC', 173 => '=AD', 174 => '=AE', 175 => '=AF', 176 => '=B0', 177 => '=B1', 178 => '=B2', 179 => '=B3', 180 => '=B4', 181 => '=B5', 182 => '=B6', 183 => '=B7', 184 => '=B8', 185 => '=B9', 186 => '=BA', 187 => '=BB', 188 => '=BC', 189 => '=BD', 190 => '=BE', 191 => '=BF', 192 => '=C0', 193 => '=C1', 194 => '=C2', 195 => '=C3', 196 => '=C4', 197 => '=C5', 198 => '=C6', 199 => '=C7', 200 => '=C8', 201 => '=C9', 202 => '=CA', 203 => '=CB', 204 => '=CC', 205 => '=CD', 206 => '=CE', 207 => '=CF', 208 => '=D0', 209 => '=D1', 210 => '=D2', 211 => '=D3', 212 => '=D4', 213 => '=D5', 214 => '=D6', 215 => '=D7', 216 => '=D8', 217 => '=D9', 218 => '=DA', 219 => '=DB', 220 => '=DC', 221 => '=DD', 222 => '=DE', 223 => '=DF', 224 => '=E0', 225 => '=E1', 226 => '=E2', 227 => '=E3', 228 => '=E4', 229 => '=E5', 230 => '=E6', 231 => '=E7', 232 => '=E8', 233 => '=E9', 234 => '=EA', 235 => '=EB', 236 => '=EC', 237 => '=ED', 238 => '=EE', 239 => '=EF', 240 => '=F0', 241 => '=F1', 242 => '=F2', 243 => '=F3', 244 => '=F4', 245 => '=F5', 246 => '=F6', 247 => '=F7', 248 => '=F8', 249 => '=F9', 250 => '=FA', 251 => '=FB', 252 => '=FC', 253 => '=FD', 254 => '=FE', 255 => '=FF', ]; private static array $safeMapShare = []; /** * A map of non-encoded ascii characters. * * @var string[] * * @internal */ protected array $safeMap = []; public function __construct() { $id = static::class; if (!isset(self::$safeMapShare[$id])) { $this->initSafeMap(); self::$safeMapShare[$id] = $this->safeMap; } else { $this->safeMap = self::$safeMapShare[$id]; } } protected function initSafeMap(): void { foreach (array_merge([0x09, 0x20], range(0x21, 0x3C), range(0x3E, 0x7E)) as $byte) { $this->safeMap[$byte] = \chr($byte); } } /** * {@inheritdoc} * * Takes an unencoded string and produces a QP encoded string from it. * * QP encoded strings have a maximum line length of 76 characters. * If the first line needs to be shorter, indicate the difference with * $firstLineOffset. */ public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string { if ($maxLineLength > 76 || $maxLineLength <= 0) { $maxLineLength = 76; } $thisLineLength = $maxLineLength - $firstLineOffset; $lines = []; $lNo = 0; $lines[$lNo] = ''; $currentLine = &$lines[$lNo++]; $size = $lineLen = 0; $charStream = new CharacterStream($string, $charset); // Fetching more than 4 chars at one is slower, as is fetching fewer bytes // Conveniently 4 chars is the UTF-8 safe number since UTF-8 has up to 6 // bytes per char and (6 * 4 * 3 = 72 chars per line) * =NN is 3 bytes while (null !== $bytes = $charStream->readBytes(4)) { $enc = $this->encodeByteSequence($bytes, $size); $i = strpos($enc, '=0D=0A'); $newLineLength = $lineLen + (false === $i ? $size : $i); if ($currentLine && $newLineLength >= $thisLineLength) { $lines[$lNo] = ''; $currentLine = &$lines[$lNo++]; $thisLineLength = $maxLineLength; $lineLen = 0; } $currentLine .= $enc; if (false === $i) { $lineLen += $size; } else { // 6 is the length of '=0D=0A'. $lineLen = $size - strrpos($enc, '=0D=0A') - 6; } } return $this->standardize(implode("=\r\n", $lines)); } /** * Encode the given byte array into a verbatim QP form. */ private function encodeByteSequence(array $bytes, int &$size): string { $ret = ''; $size = 0; foreach ($bytes as $b) { if (isset($this->safeMap[$b])) { $ret .= $this->safeMap[$b]; ++$size; } else { $ret .= self::QP_MAP[$b]; $size += 3; } } return $ret; } /** * Make sure CRLF is correct and HT/SPACE are in valid places. */ private function standardize(string $string): string { $string = str_replace(["\t=0D=0A", ' =0D=0A', '=0D=0A'], ["=09\r\n", "=20\r\n", "\r\n"], $string); switch ($end = \ord(substr($string, -1))) { case 0x09: case 0x20: $string = substr_replace($string, self::QP_MAP[$end], -1); } return $string; } } PKdZr LEncoder/IdnAddressEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Encoder; /** * An IDN email address encoder. * * Encodes the domain part of an address using IDN. This is compatible will all * SMTP servers. * * Note: It leaves the local part as is. In case there are non-ASCII characters * in the local part then it depends on the SMTP Server if this is supported. * * @author Christian Schmidt */ final class IdnAddressEncoder implements AddressEncoderInterface { /** * Encodes the domain part of an address using IDN. */ public function encodeString(string $address): string { $i = strrpos($address, '@'); if (false !== $i) { $local = substr($address, 0, $i); $domain = substr($address, $i + 1); if (preg_match('/[^\x00-\x7F]/', $domain)) { $address = sprintf('%s@%s', $local, idn_to_ascii($domain, \IDNA_DEFAULT | \IDNA_USE_STD3_RULES | \IDNA_CHECK_BIDI | \IDNA_CHECK_CONTEXTJ | \IDNA_NONTRANSITIONAL_TO_ASCII, \INTL_IDNA_VARIANT_UTS46)); } } return $address; } } PKdZ[9Encoder/Rfc2231Encoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Encoder; use Symfony\Component\Mime\CharacterStream; /** * @author Chris Corbyn */ final class Rfc2231Encoder implements EncoderInterface { /** * Takes an unencoded string and produces a string encoded according to RFC 2231 from it. */ public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string { $lines = []; $lineCount = 0; $lines[] = ''; $currentLine = &$lines[$lineCount++]; if (0 >= $maxLineLength) { $maxLineLength = 75; } $charStream = new CharacterStream($string, $charset); $thisLineLength = $maxLineLength - $firstLineOffset; while (null !== $char = $charStream->read(4)) { $encodedChar = rawurlencode($char); if ('' !== $currentLine && \strlen($currentLine.$encodedChar) > $thisLineLength) { $lines[] = ''; $currentLine = &$lines[$lineCount++]; $thisLineLength = $maxLineLength; } $currentLine .= $encodedChar; } return implode("\r\n", $lines); } } PKdZ`// Encoder/Base64ContentEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Encoder; use Symfony\Component\Mime\Exception\RuntimeException; /** * @author Fabien Potencier */ final class Base64ContentEncoder extends Base64Encoder implements ContentEncoderInterface { public function encodeByteStream($stream, int $maxLineLength = 0): iterable { if (!\is_resource($stream)) { throw new \TypeError(sprintf('Method "%s" takes a stream as a first argument.', __METHOD__)); } $filter = stream_filter_append($stream, 'convert.base64-encode', \STREAM_FILTER_READ, [ 'line-length' => 0 >= $maxLineLength || 76 < $maxLineLength ? 76 : $maxLineLength, 'line-break-chars' => "\r\n", ]); if (!\is_resource($filter)) { throw new RuntimeException('Unable to set the base64 content encoder to the filter.'); } while (!feof($stream)) { yield fread($stream, 16372); } stream_filter_remove($filter); } public function getName(): string { return 'base64'; } } PKdZ"z33Encoder/QpMimeHeaderEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Encoder; /** * @author Chris Corbyn */ final class QpMimeHeaderEncoder extends QpEncoder implements MimeHeaderEncoderInterface { protected function initSafeMap(): void { foreach (array_merge( range(0x61, 0x7A), range(0x41, 0x5A), range(0x30, 0x39), [0x20, 0x21, 0x2A, 0x2B, 0x2D, 0x2F] ) as $byte) { $this->safeMap[$byte] = \chr($byte); } } public function getName(): string { return 'Q'; } public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string { return str_replace([' ', '=20', "=\r\n"], ['_', '_', "\r\n"], parent::encodeString($string, $charset, $firstLineOffset, $maxLineLength) ); } } PKdZƑ}Encoder/Base64Encoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Encoder; /** * @author Chris Corbyn */ class Base64Encoder implements EncoderInterface { /** * Takes an unencoded string and produces a Base64 encoded string from it. * * Base64 encoded strings have a maximum line length of 76 characters. * If the first line needs to be shorter, indicate the difference with * $firstLineOffset. */ public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string { if (0 >= $maxLineLength || 76 < $maxLineLength) { $maxLineLength = 76; } $encodedString = base64_encode($string); $firstLine = ''; if (0 !== $firstLineOffset) { $firstLine = substr($encodedString, 0, $maxLineLength - $firstLineOffset)."\r\n"; $encodedString = substr($encodedString, $maxLineLength - $firstLineOffset); } return $firstLine.trim(chunk_split($encodedString, $maxLineLength, "\r\n")); } } PKdZ͒#Encoder/ContentEncoderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Encoder; /** * @author Chris Corbyn */ interface ContentEncoderInterface extends EncoderInterface { /** * Encodes the stream to a Generator. * * @param resource $stream */ public function encodeByteStream($stream, int $maxLineLength = 0): iterable; /** * Gets the MIME name of this content encoding scheme. */ public function getName(): string; } PKdZ%#Encoder/AddressEncoderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Encoder; use Symfony\Component\Mime\Exception\AddressEncoderException; /** * @author Christian Schmidt */ interface AddressEncoderInterface { /** * Encodes an email address. * * @throws AddressEncoderException if the email cannot be represented in * the encoding implemented by this class */ public function encodeString(string $address): string; } PKdZ&jC#Encoder/Base64MimeHeaderEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Encoder; /** * @author Chris Corbyn */ final class Base64MimeHeaderEncoder extends Base64Encoder implements MimeHeaderEncoderInterface { public function getName(): string { return 'B'; } /** * Takes an unencoded string and produces a Base64 encoded string from it. * * If the charset is iso-2022-jp, it uses mb_encode_mimeheader instead of * default encodeString, otherwise pass to the parent method. */ public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string { if ('iso-2022-jp' === strtolower($charset)) { $old = mb_internal_encoding(); mb_internal_encoding('utf-8'); $newstring = mb_encode_mimeheader($string, 'iso-2022-jp', $this->getName(), "\r\n"); mb_internal_encoding($old); return $newstring; } return parent::encodeString($string, $charset, $firstLineOffset, $maxLineLength); } } PKdZ{5BB"Encoder/EightBitContentEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Encoder; /** * @author Fabien Potencier */ final class EightBitContentEncoder implements ContentEncoderInterface { public function encodeByteStream($stream, int $maxLineLength = 0): iterable { while (!feof($stream)) { yield fread($stream, 16372); } } public function getName(): string { return '8bit'; } public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string { return $string; } } PKdZYh[))LICENSEnu[Copyright (c) 2010-2023 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. PKdZ;/S Address.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime; use Egulias\EmailValidator\EmailValidator; use Egulias\EmailValidator\Validation\MessageIDValidation; use Egulias\EmailValidator\Validation\RFCValidation; use Symfony\Component\Mime\Encoder\IdnAddressEncoder; use Symfony\Component\Mime\Exception\InvalidArgumentException; use Symfony\Component\Mime\Exception\LogicException; use Symfony\Component\Mime\Exception\RfcComplianceException; /** * @author Fabien Potencier */ final class Address { /** * A regex that matches a structure like 'Name '. * It matches anything between the first < and last > as email address. * This allows to use a single string to construct an Address, which can be convenient to use in * config, and allows to have more readable config. * This does not try to cover all edge cases for address. */ private const FROM_STRING_PATTERN = '~(?[^<]*)<(?.*)>[^>]*~'; private static EmailValidator $validator; private static IdnAddressEncoder $encoder; private string $address; private string $name; public function __construct(string $address, string $name = '') { if (!class_exists(EmailValidator::class)) { throw new LogicException(sprintf('The "%s" class cannot be used as it needs "%s"; try running "composer require egulias/email-validator".', __CLASS__, EmailValidator::class)); } self::$validator ??= new EmailValidator(); $this->address = trim($address); $this->name = trim(str_replace(["\n", "\r"], '', $name)); if (!self::$validator->isValid($this->address, class_exists(MessageIDValidation::class) ? new MessageIDValidation() : new RFCValidation())) { throw new RfcComplianceException(sprintf('Email "%s" does not comply with addr-spec of RFC 2822.', $address)); } } public function getAddress(): string { return $this->address; } public function getName(): string { return $this->name; } public function getEncodedAddress(): string { self::$encoder ??= new IdnAddressEncoder(); return self::$encoder->encodeString($this->address); } public function toString(): string { return ($n = $this->getEncodedName()) ? $n.' <'.$this->getEncodedAddress().'>' : $this->getEncodedAddress(); } public function getEncodedName(): string { if ('' === $this->getName()) { return ''; } return sprintf('"%s"', preg_replace('/"/u', '\"', $this->getName())); } public static function create(self|string $address): self { if ($address instanceof self) { return $address; } if (false === strpos($address, '<')) { return new self($address); } if (!preg_match(self::FROM_STRING_PATTERN, $address, $matches)) { throw new InvalidArgumentException(sprintf('Could not parse "%s" to a "%s" instance.', $address, self::class)); } return new self($matches['addrSpec'], trim($matches['displayName'], ' \'"')); } /** * @param array $addresses * * @return Address[] */ public static function createArray(array $addresses): array { $addrs = []; foreach ($addresses as $address) { $addrs[] = self::create($address); } return $addrs; } } PKdZ#?Header/UnstructuredHeader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Header; /** * A Simple MIME Header. * * @author Chris Corbyn */ class UnstructuredHeader extends AbstractHeader { private string $value; public function __construct(string $name, string $value) { parent::__construct($name); $this->setValue($value); } /** * @param string $body */ public function setBody(mixed $body) { $this->setValue($body); } public function getBody(): string { return $this->getValue(); } /** * Get the (unencoded) value of this header. */ public function getValue(): string { return $this->value; } /** * Set the (unencoded) value of this header. */ public function setValue(string $value) { $this->value = $value; } /** * Get the value of this header prepared for rendering. */ public function getBodyAsString(): string { return $this->encodeWords($this, $this->value); } } PKdZ#;O O Header/MailboxListHeader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Header; use Symfony\Component\Mime\Address; use Symfony\Component\Mime\Exception\RfcComplianceException; /** * A Mailbox list MIME Header for something like From, To, Cc, and Bcc (one or more named addresses). * * @author Chris Corbyn */ final class MailboxListHeader extends AbstractHeader { private array $addresses = []; /** * @param Address[] $addresses */ public function __construct(string $name, array $addresses) { parent::__construct($name); $this->setAddresses($addresses); } /** * @param Address[] $body * * @throws RfcComplianceException */ public function setBody(mixed $body) { $this->setAddresses($body); } /** * @throws RfcComplianceException * * @return Address[] */ public function getBody(): array { return $this->getAddresses(); } /** * Sets a list of addresses to be shown in this Header. * * @param Address[] $addresses * * @throws RfcComplianceException */ public function setAddresses(array $addresses) { $this->addresses = []; $this->addAddresses($addresses); } /** * Sets a list of addresses to be shown in this Header. * * @param Address[] $addresses * * @throws RfcComplianceException */ public function addAddresses(array $addresses) { foreach ($addresses as $address) { $this->addAddress($address); } } /** * @throws RfcComplianceException */ public function addAddress(Address $address) { $this->addresses[] = $address; } /** * @return Address[] */ public function getAddresses(): array { return $this->addresses; } /** * Gets the full mailbox list of this Header as an array of valid RFC 2822 strings. * * @throws RfcComplianceException * * @return string[] */ public function getAddressStrings(): array { $strings = []; foreach ($this->addresses as $address) { $str = $address->getEncodedAddress(); if ($name = $address->getName()) { $str = $this->createPhrase($this, $name, $this->getCharset(), !$strings).' <'.$str.'>'; } $strings[] = $str; } return $strings; } public function getBodyAsString(): string { return implode(', ', $this->getAddressStrings()); } /** * Redefine the encoding requirements for addresses. * * All "specials" must be encoded as the full header value will not be quoted * * @see RFC 2822 3.2.1 */ protected function tokenNeedsEncoding(string $token): bool { return preg_match('/[()<>\[\]:;@\,."]/', $token) || parent::tokenNeedsEncoding($token); } } PKdZr pHeader/ParameterizedHeader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Header; use Symfony\Component\Mime\Encoder\Rfc2231Encoder; /** * @author Chris Corbyn */ final class ParameterizedHeader extends UnstructuredHeader { /** * RFC 2231's definition of a token. * * @var string */ public const TOKEN_REGEX = '(?:[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E]+)'; private $encoder = null; private array $parameters = []; public function __construct(string $name, string $value, array $parameters = []) { parent::__construct($name, $value); foreach ($parameters as $k => $v) { $this->setParameter($k, $v); } if ('content-type' !== strtolower($name)) { $this->encoder = new Rfc2231Encoder(); } } public function setParameter(string $parameter, ?string $value) { $this->setParameters(array_merge($this->getParameters(), [$parameter => $value])); } public function getParameter(string $parameter): string { return $this->getParameters()[$parameter] ?? ''; } /** * @param string[] $parameters */ public function setParameters(array $parameters) { $this->parameters = $parameters; } /** * @return string[] */ public function getParameters(): array { return $this->parameters; } public function getBodyAsString(): string { $body = parent::getBodyAsString(); foreach ($this->parameters as $name => $value) { if (null !== $value) { $body .= '; '.$this->createParameter($name, $value); } } return $body; } /** * Generate a list of all tokens in the final header. * * This doesn't need to be overridden in theory, but it is for implementation * reasons to prevent potential breakage of attributes. */ protected function toTokens(string $string = null): array { $tokens = parent::toTokens(parent::getBodyAsString()); // Try creating any parameters foreach ($this->parameters as $name => $value) { if (null !== $value) { // Add the semi-colon separator $tokens[\count($tokens) - 1] .= ';'; $tokens = array_merge($tokens, $this->generateTokenLines(' '.$this->createParameter($name, $value))); } } return $tokens; } /** * Render an RFC 2047 compliant header parameter from the $name and $value. */ private function createParameter(string $name, string $value): string { $origValue = $value; $encoded = false; // Allow room for parameter name, indices, "=" and DQUOTEs $maxValueLength = $this->getMaxLineLength() - \strlen($name.'=*N"";') - 1; $firstLineOffset = 0; // If it's not already a valid parameter value... if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) { // TODO: text, or something else?? // ... and it's not ascii if (!preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x7F]*$/D', $value)) { $encoded = true; // Allow space for the indices, charset and language $maxValueLength = $this->getMaxLineLength() - \strlen($name.'*N*="";') - 1; $firstLineOffset = \strlen($this->getCharset()."'".$this->getLanguage()."'"); } if (\in_array($name, ['name', 'filename'], true) && 'form-data' === $this->getValue() && 'content-disposition' === strtolower($this->getName()) && preg_match('//u', $value)) { // WHATWG HTML living standard 4.10.21.8 2 specifies: // For field names and filenames for file fields, the result of the // encoding in the previous bullet point must be escaped by replacing // any 0x0A (LF) bytes with the byte sequence `%0A`, 0x0D (CR) with `%0D` // and 0x22 (") with `%22`. // The user agent must not perform any other escapes. $value = str_replace(['"', "\r", "\n"], ['%22', '%0D', '%0A'], $value); if (\strlen($value) <= $maxValueLength) { return $name.'="'.$value.'"'; } $value = $origValue; } } // Encode if we need to if ($encoded || \strlen($value) > $maxValueLength) { if (null !== $this->encoder) { $value = $this->encoder->encodeString($origValue, $this->getCharset(), $firstLineOffset, $maxValueLength); } else { // We have to go against RFC 2183/2231 in some areas for interoperability $value = $this->getTokenAsEncodedWord($origValue); $encoded = false; } } $valueLines = $this->encoder ? explode("\r\n", $value) : [$value]; // Need to add indices if (\count($valueLines) > 1) { $paramLines = []; foreach ($valueLines as $i => $line) { $paramLines[] = $name.'*'.$i.$this->getEndOfParameterValue($line, true, 0 === $i); } return implode(";\r\n ", $paramLines); } else { return $name.$this->getEndOfParameterValue($valueLines[0], $encoded, true); } } /** * Returns the parameter value from the "=" and beyond. * * @param string $value to append */ private function getEndOfParameterValue(string $value, bool $encoded = false, bool $firstLine = false): string { $forceHttpQuoting = 'form-data' === $this->getValue() && 'content-disposition' === strtolower($this->getName()); if ($forceHttpQuoting || !preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) { $value = '"'.$value.'"'; } $prepend = '='; if ($encoded) { $prepend = '*='; if ($firstLine) { $prepend = '*='.$this->getCharset()."'".$this->getLanguage()."'"; } } return $prepend.$value; } } PKdZ0k> > Header/IdentificationHeader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Header; use Symfony\Component\Mime\Address; use Symfony\Component\Mime\Exception\RfcComplianceException; /** * An ID MIME Header for something like Message-ID or Content-ID (one or more addresses). * * @author Chris Corbyn */ final class IdentificationHeader extends AbstractHeader { private array $ids = []; private array $idsAsAddresses = []; public function __construct(string $name, string|array $ids) { parent::__construct($name); $this->setId($ids); } /** * @param string|string[] $body a string ID or an array of IDs * * @throws RfcComplianceException */ public function setBody(mixed $body) { $this->setId($body); } public function getBody(): array { return $this->getIds(); } /** * Set the ID used in the value of this header. * * @param string|string[] $id * * @throws RfcComplianceException */ public function setId(string|array $id) { $this->setIds(\is_array($id) ? $id : [$id]); } /** * Get the ID used in the value of this Header. * * If multiple IDs are set only the first is returned. */ public function getId(): ?string { return $this->ids[0] ?? null; } /** * Set a collection of IDs to use in the value of this Header. * * @param string[] $ids * * @throws RfcComplianceException */ public function setIds(array $ids) { $this->ids = []; $this->idsAsAddresses = []; foreach ($ids as $id) { $this->idsAsAddresses[] = new Address($id); $this->ids[] = $id; } } /** * Get the list of IDs used in this Header. * * @return string[] */ public function getIds(): array { return $this->ids; } public function getBodyAsString(): string { $addrs = []; foreach ($this->idsAsAddresses as $address) { $addrs[] = '<'.$address->toString().'>'; } return implode(' ', $addrs); } } PKdZQ7?)?)Header/AbstractHeader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Header; use Symfony\Component\Mime\Encoder\QpMimeHeaderEncoder; /** * An abstract base MIME Header. * * @author Chris Corbyn */ abstract class AbstractHeader implements HeaderInterface { public const PHRASE_PATTERN = '(?:(?:(?:(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?[a-zA-Z0-9!#\$%&\'\*\+\-\/=\?\^_`\{\}\|~]+(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?)|(?:(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?"((?:(?:[ \t]*(?:\r\n))?[ \t])?(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21\x23-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])))*(?:(?:[ \t]*(?:\r\n))?[ \t])?"(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?))+?)'; private static QpMimeHeaderEncoder $encoder; private string $name; private int $lineLength = 76; private ?string $lang = null; private string $charset = 'utf-8'; public function __construct(string $name) { $this->name = $name; } public function setCharset(string $charset) { $this->charset = $charset; } public function getCharset(): ?string { return $this->charset; } /** * Set the language used in this Header. * * For example, for US English, 'en-us'. */ public function setLanguage(string $lang) { $this->lang = $lang; } public function getLanguage(): ?string { return $this->lang; } public function getName(): string { return $this->name; } public function setMaxLineLength(int $lineLength) { $this->lineLength = $lineLength; } public function getMaxLineLength(): int { return $this->lineLength; } public function toString(): string { return $this->tokensToString($this->toTokens()); } /** * Produces a compliant, formatted RFC 2822 'phrase' based on the string given. * * @param string $string as displayed * @param bool $shorten the first line to make remove for header name */ protected function createPhrase(HeaderInterface $header, string $string, string $charset, bool $shorten = false): string { // Treat token as exactly what was given $phraseStr = $string; // If it's not valid if (!preg_match('/^'.self::PHRASE_PATTERN.'$/D', $phraseStr)) { // .. but it is just ascii text, try escaping some characters // and make it a quoted-string if (preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x7F]*$/D', $phraseStr)) { foreach (['\\', '"'] as $char) { $phraseStr = str_replace($char, '\\'.$char, $phraseStr); } $phraseStr = '"'.$phraseStr.'"'; } else { // ... otherwise it needs encoding // Determine space remaining on line if first line if ($shorten) { $usedLength = \strlen($header->getName().': '); } else { $usedLength = 0; } $phraseStr = $this->encodeWords($header, $string, $usedLength); } } elseif (str_contains($phraseStr, '(')) { foreach (['\\', '"'] as $char) { $phraseStr = str_replace($char, '\\'.$char, $phraseStr); } $phraseStr = '"'.$phraseStr.'"'; } return $phraseStr; } /** * Encode needed word tokens within a string of input. */ protected function encodeWords(HeaderInterface $header, string $input, int $usedLength = -1): string { $value = ''; $tokens = $this->getEncodableWordTokens($input); foreach ($tokens as $token) { // See RFC 2822, Sect 2.2 (really 2.2 ??) if ($this->tokenNeedsEncoding($token)) { // Don't encode starting WSP $firstChar = substr($token, 0, 1); switch ($firstChar) { case ' ': case "\t": $value .= $firstChar; $token = substr($token, 1); } if (-1 == $usedLength) { $usedLength = \strlen($header->getName().': ') + \strlen($value); } $value .= $this->getTokenAsEncodedWord($token, $usedLength); } else { $value .= $token; } } return $value; } protected function tokenNeedsEncoding(string $token): bool { return (bool) preg_match('~[\x00-\x08\x10-\x19\x7F-\xFF\r\n]~', $token); } /** * Splits a string into tokens in blocks of words which can be encoded quickly. * * @return string[] */ protected function getEncodableWordTokens(string $string): array { $tokens = []; $encodedToken = ''; // Split at all whitespace boundaries foreach (preg_split('~(?=[\t ])~', $string) as $token) { if ($this->tokenNeedsEncoding($token)) { $encodedToken .= $token; } else { if ('' !== $encodedToken) { $tokens[] = $encodedToken; $encodedToken = ''; } $tokens[] = $token; } } if ('' !== $encodedToken) { $tokens[] = $encodedToken; } return $tokens; } /** * Get a token as an encoded word for safe insertion into headers. */ protected function getTokenAsEncodedWord(string $token, int $firstLineOffset = 0): string { self::$encoder ??= new QpMimeHeaderEncoder(); // Adjust $firstLineOffset to account for space needed for syntax $charsetDecl = $this->charset; if (null !== $this->lang) { $charsetDecl .= '*'.$this->lang; } $encodingWrapperLength = \strlen('=?'.$charsetDecl.'?'.self::$encoder->getName().'??='); if ($firstLineOffset >= 75) { // Does this logic need to be here? $firstLineOffset = 0; } $encodedTextLines = explode("\r\n", self::$encoder->encodeString($token, $this->charset, $firstLineOffset, 75 - $encodingWrapperLength) ); if ('iso-2022-jp' !== strtolower($this->charset)) { // special encoding for iso-2022-jp using mb_encode_mimeheader foreach ($encodedTextLines as $lineNum => $line) { $encodedTextLines[$lineNum] = '=?'.$charsetDecl.'?'.self::$encoder->getName().'?'.$line.'?='; } } return implode("\r\n ", $encodedTextLines); } /** * Generates tokens from the given string which include CRLF as individual tokens. * * @return string[] */ protected function generateTokenLines(string $token): array { return preg_split('~(\r\n)~', $token, -1, \PREG_SPLIT_DELIM_CAPTURE); } /** * Generate a list of all tokens in the final header. */ protected function toTokens(string $string = null): array { if (null === $string) { $string = $this->getBodyAsString(); } $tokens = []; // Generate atoms; split at all invisible boundaries followed by WSP foreach (preg_split('~(?=[ \t])~', $string) as $token) { $newTokens = $this->generateTokenLines($token); foreach ($newTokens as $newToken) { $tokens[] = $newToken; } } return $tokens; } /** * Takes an array of tokens which appear in the header and turns them into * an RFC 2822 compliant string, adding FWSP where needed. * * @param string[] $tokens */ private function tokensToString(array $tokens): string { $lineCount = 0; $headerLines = []; $headerLines[] = $this->name.': '; $currentLine = &$headerLines[$lineCount++]; // Build all tokens back into compliant header foreach ($tokens as $i => $token) { // Line longer than specified maximum or token was just a new line if (("\r\n" === $token) || ($i > 0 && \strlen($currentLine.$token) > $this->lineLength) && '' !== $currentLine) { $headerLines[] = ''; $currentLine = &$headerLines[$lineCount++]; } // Append token to the line if ("\r\n" !== $token) { $currentLine .= $token; } } // Implode with FWS (RFC 2822, 2.2.3) return implode("\r\n", $headerLines); } } PKdZëF!!Header/Headers.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Header; use Symfony\Component\Mime\Address; use Symfony\Component\Mime\Exception\LogicException; /** * A collection of headers. * * @author Fabien Potencier */ final class Headers { private const UNIQUE_HEADERS = [ 'date', 'from', 'sender', 'reply-to', 'to', 'cc', 'bcc', 'message-id', 'in-reply-to', 'references', 'subject', ]; private const HEADER_CLASS_MAP = [ 'date' => DateHeader::class, 'from' => MailboxListHeader::class, 'sender' => MailboxHeader::class, 'reply-to' => MailboxListHeader::class, 'to' => MailboxListHeader::class, 'cc' => MailboxListHeader::class, 'bcc' => MailboxListHeader::class, 'message-id' => IdentificationHeader::class, 'in-reply-to' => UnstructuredHeader::class, // `In-Reply-To` and `References` are less strict than RFC 2822 (3.6.4) to allow users entering the original email's ... 'references' => UnstructuredHeader::class, // ... `Message-ID`, even if that is no valid `msg-id` 'return-path' => PathHeader::class, ]; /** * @var HeaderInterface[][] */ private array $headers = []; private int $lineLength = 76; public function __construct(HeaderInterface ...$headers) { foreach ($headers as $header) { $this->add($header); } } public function __clone() { foreach ($this->headers as $name => $collection) { foreach ($collection as $i => $header) { $this->headers[$name][$i] = clone $header; } } } public function setMaxLineLength(int $lineLength) { $this->lineLength = $lineLength; foreach ($this->all() as $header) { $header->setMaxLineLength($lineLength); } } public function getMaxLineLength(): int { return $this->lineLength; } /** * @param array $addresses * * @return $this */ public function addMailboxListHeader(string $name, array $addresses): static { return $this->add(new MailboxListHeader($name, Address::createArray($addresses))); } /** * @return $this */ public function addMailboxHeader(string $name, Address|string $address): static { return $this->add(new MailboxHeader($name, Address::create($address))); } /** * @return $this */ public function addIdHeader(string $name, string|array $ids): static { return $this->add(new IdentificationHeader($name, $ids)); } /** * @return $this */ public function addPathHeader(string $name, Address|string $path): static { return $this->add(new PathHeader($name, $path instanceof Address ? $path : new Address($path))); } /** * @return $this */ public function addDateHeader(string $name, \DateTimeInterface $dateTime): static { return $this->add(new DateHeader($name, $dateTime)); } /** * @return $this */ public function addTextHeader(string $name, string $value): static { return $this->add(new UnstructuredHeader($name, $value)); } /** * @return $this */ public function addParameterizedHeader(string $name, string $value, array $params = []): static { return $this->add(new ParameterizedHeader($name, $value, $params)); } /** * @return $this */ public function addHeader(string $name, mixed $argument, array $more = []): static { $parts = explode('\\', self::HEADER_CLASS_MAP[strtolower($name)] ?? UnstructuredHeader::class); $method = 'add'.ucfirst(array_pop($parts)); if ('addUnstructuredHeader' === $method) { $method = 'addTextHeader'; } elseif ('addIdentificationHeader' === $method) { $method = 'addIdHeader'; } return $this->$method($name, $argument, $more); } public function has(string $name): bool { return isset($this->headers[strtolower($name)]); } /** * @return $this */ public function add(HeaderInterface $header): static { self::checkHeaderClass($header); $header->setMaxLineLength($this->lineLength); $name = strtolower($header->getName()); if (\in_array($name, self::UNIQUE_HEADERS, true) && isset($this->headers[$name]) && \count($this->headers[$name]) > 0) { throw new LogicException(sprintf('Impossible to set header "%s" as it\'s already defined and must be unique.', $header->getName())); } $this->headers[$name][] = $header; return $this; } public function get(string $name): ?HeaderInterface { $name = strtolower($name); if (!isset($this->headers[$name])) { return null; } $values = array_values($this->headers[$name]); return array_shift($values); } public function all(string $name = null): iterable { if (null === $name) { foreach ($this->headers as $name => $collection) { foreach ($collection as $header) { yield $name => $header; } } } elseif (isset($this->headers[strtolower($name)])) { foreach ($this->headers[strtolower($name)] as $header) { yield $header; } } } public function getNames(): array { return array_keys($this->headers); } public function remove(string $name): void { unset($this->headers[strtolower($name)]); } public static function isUniqueHeader(string $name): bool { return \in_array(strtolower($name), self::UNIQUE_HEADERS, true); } /** * @throws LogicException if the header name and class are not compatible */ public static function checkHeaderClass(HeaderInterface $header): void { $name = strtolower($header->getName()); if (($c = self::HEADER_CLASS_MAP[$name] ?? null) && !$header instanceof $c) { throw new LogicException(sprintf('The "%s" header must be an instance of "%s" (got "%s").', $header->getName(), $c, get_debug_type($header))); } } public function toString(): string { $string = ''; foreach ($this->toArray() as $str) { $string .= $str."\r\n"; } return $string; } public function toArray(): array { $arr = []; foreach ($this->all() as $header) { if ('' !== $header->getBodyAsString()) { $arr[] = $header->toString(); } } return $arr; } public function getHeaderBody(string $name) { return $this->has($name) ? $this->get($name)->getBody() : null; } /** * @internal */ public function setHeaderBody(string $type, string $name, mixed $body): void { if ($this->has($name)) { $this->get($name)->setBody($body); } else { $this->{'add'.$type.'Header'}($name, $body); } } public function getHeaderParameter(string $name, string $parameter): ?string { if (!$this->has($name)) { return null; } $header = $this->get($name); if (!$header instanceof ParameterizedHeader) { throw new LogicException(sprintf('Unable to get parameter "%s" on header "%s" as the header is not of class "%s".', $parameter, $name, ParameterizedHeader::class)); } return $header->getParameter($parameter); } /** * @internal */ public function setHeaderParameter(string $name, string $parameter, ?string $value): void { if (!$this->has($name)) { throw new LogicException(sprintf('Unable to set parameter "%s" on header "%s" as the header is not defined.', $parameter, $name)); } $header = $this->get($name); if (!$header instanceof ParameterizedHeader) { throw new LogicException(sprintf('Unable to set parameter "%s" on header "%s" as the header is not of class "%s".', $parameter, $name, ParameterizedHeader::class)); } $header->setParameter($parameter, $value); } } PKdZ b#Header/PathHeader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Header; use Symfony\Component\Mime\Address; use Symfony\Component\Mime\Exception\RfcComplianceException; /** * A Path Header, such a Return-Path (one address). * * @author Chris Corbyn */ final class PathHeader extends AbstractHeader { private $address; public function __construct(string $name, Address $address) { parent::__construct($name); $this->setAddress($address); } /** * @param Address $body * * @throws RfcComplianceException */ public function setBody(mixed $body) { $this->setAddress($body); } public function getBody(): Address { return $this->getAddress(); } public function setAddress(Address $address) { $this->address = $address; } public function getAddress(): Address { return $this->address; } public function getBodyAsString(): string { return '<'.$this->address->toString().'>'; } } PKdZHeader/DateHeader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Header; /** * A Date MIME Header. * * @author Chris Corbyn */ final class DateHeader extends AbstractHeader { private \DateTimeImmutable $dateTime; public function __construct(string $name, \DateTimeInterface $date) { parent::__construct($name); $this->setDateTime($date); } /** * @param \DateTimeInterface $body */ public function setBody(mixed $body) { $this->setDateTime($body); } public function getBody(): \DateTimeImmutable { return $this->getDateTime(); } public function getDateTime(): \DateTimeImmutable { return $this->dateTime; } /** * Set the date-time of the Date in this Header. * * If a DateTime instance is provided, it is converted to DateTimeImmutable. */ public function setDateTime(\DateTimeInterface $dateTime) { if ($dateTime instanceof \DateTime) { $immutable = new \DateTimeImmutable('@'.$dateTime->getTimestamp()); $dateTime = $immutable->setTimezone($dateTime->getTimezone()); } $this->dateTime = $dateTime; } public function getBodyAsString(): string { return $this->dateTime->format(\DateTime::RFC2822); } } PKdZ#9jjHeader/HeaderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Header; /** * A MIME Header. * * @author Chris Corbyn */ interface HeaderInterface { /** * Sets the body. * * The type depends on the Header concrete class. */ public function setBody(mixed $body); /** * Gets the body. * * The return type depends on the Header concrete class. */ public function getBody(): mixed; public function setCharset(string $charset); public function getCharset(): ?string; public function setLanguage(string $lang); public function getLanguage(): ?string; public function getName(): string; public function setMaxLineLength(int $lineLength); public function getMaxLineLength(): int; /** * Gets this Header rendered as a compliant string. */ public function toString(): string; /** * Gets the header's body, prepared for folding into a final header value. * * This is not necessarily RFC 2822 compliant since folding white space is * not added at this stage (see {@link toString()} for that). */ public function getBodyAsString(): string; } PKdZ1ޜHeader/MailboxHeader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime\Header; use Symfony\Component\Mime\Address; use Symfony\Component\Mime\Exception\RfcComplianceException; /** * A Mailbox MIME Header for something like Sender (one named address). * * @author Fabien Potencier */ final class MailboxHeader extends AbstractHeader { private $address; public function __construct(string $name, Address $address) { parent::__construct($name); $this->setAddress($address); } /** * @param Address $body * * @throws RfcComplianceException */ public function setBody(mixed $body) { $this->setAddress($body); } /** * @throws RfcComplianceException */ public function getBody(): Address { return $this->getAddress(); } /** * @throws RfcComplianceException */ public function setAddress(Address $address) { $this->address = $address; } public function getAddress(): Address { return $this->address; } public function getBodyAsString(): string { $str = $this->address->getEncodedAddress(); if ($name = $this->address->getName()) { $str = $this->createPhrase($this, $name, $this->getCharset(), true).' <'.$str.'>'; } return $str; } /** * Redefine the encoding requirements for an address. * * All "specials" must be encoded as the full header value will not be quoted * * @see RFC 2822 3.2.1 */ protected function tokenNeedsEncoding(string $token): bool { return preg_match('/[()<>\[\]:;@\,."]/', $token) || parent::tokenNeedsEncoding($token); } } PKdZ^ccMessageConverter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime; use Symfony\Component\Mime\Exception\RuntimeException; use Symfony\Component\Mime\Part\DataPart; use Symfony\Component\Mime\Part\Multipart\AlternativePart; use Symfony\Component\Mime\Part\Multipart\MixedPart; use Symfony\Component\Mime\Part\Multipart\RelatedPart; use Symfony\Component\Mime\Part\TextPart; /** * @author Fabien Potencier */ final class MessageConverter { /** * @throws RuntimeException when unable to convert the message to an email */ public static function toEmail(Message $message): Email { if ($message instanceof Email) { return $message; } // try to convert to a "simple" Email instance $body = $message->getBody(); if ($body instanceof TextPart) { return self::createEmailFromTextPart($message, $body); } if ($body instanceof AlternativePart) { return self::createEmailFromAlternativePart($message, $body); } if ($body instanceof RelatedPart) { return self::createEmailFromRelatedPart($message, $body); } if ($body instanceof MixedPart) { $parts = $body->getParts(); if ($parts[0] instanceof RelatedPart) { $email = self::createEmailFromRelatedPart($message, $parts[0]); } elseif ($parts[0] instanceof AlternativePart) { $email = self::createEmailFromAlternativePart($message, $parts[0]); } elseif ($parts[0] instanceof TextPart) { $email = self::createEmailFromTextPart($message, $parts[0]); } else { throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', get_debug_type($message))); } return self::attachParts($email, \array_slice($parts, 1)); } throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', get_debug_type($message))); } private static function createEmailFromTextPart(Message $message, TextPart $part): Email { if ('text' === $part->getMediaType() && 'plain' === $part->getMediaSubtype()) { return (new Email(clone $message->getHeaders()))->text($part->getBody(), $part->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8'); } if ('text' === $part->getMediaType() && 'html' === $part->getMediaSubtype()) { return (new Email(clone $message->getHeaders()))->html($part->getBody(), $part->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8'); } throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', get_debug_type($message))); } private static function createEmailFromAlternativePart(Message $message, AlternativePart $part): Email { $parts = $part->getParts(); if ( 2 === \count($parts) && $parts[0] instanceof TextPart && 'text' === $parts[0]->getMediaType() && 'plain' === $parts[0]->getMediaSubtype() && $parts[1] instanceof TextPart && 'text' === $parts[1]->getMediaType() && 'html' === $parts[1]->getMediaSubtype() ) { return (new Email(clone $message->getHeaders())) ->text($parts[0]->getBody(), $parts[0]->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8') ->html($parts[1]->getBody(), $parts[1]->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8') ; } throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', get_debug_type($message))); } private static function createEmailFromRelatedPart(Message $message, RelatedPart $part): Email { $parts = $part->getParts(); if ($parts[0] instanceof AlternativePart) { $email = self::createEmailFromAlternativePart($message, $parts[0]); } elseif ($parts[0] instanceof TextPart) { $email = self::createEmailFromTextPart($message, $parts[0]); } else { throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', get_debug_type($message))); } return self::attachParts($email, \array_slice($parts, 1)); } private static function attachParts(Email $email, array $parts): Email { foreach ($parts as $part) { if (!$part instanceof DataPart) { throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', get_debug_type($email))); } $headers = $part->getPreparedHeaders(); $method = 'inline' === $headers->getHeaderBody('Content-Disposition') ? 'embed' : 'attach'; $name = $headers->getHeaderParameter('Content-Disposition', 'filename'); $email->$method($part->getBody(), $name, $part->getMediaType().'/'.$part->getMediaSubtype()); } return $email; } } PKdZ  MimeTypes.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Mime; use Symfony\Component\Mime\Exception\LogicException; /** * Manages MIME types and file extensions. * * For MIME type guessing, you can register custom guessers * by calling the registerGuesser() method. * Custom guessers are always called before any default ones: * * $guesser = new MimeTypes(); * $guesser->registerGuesser(new MyCustomMimeTypeGuesser()); * * If you want to change the order of the default guessers, just re-register your * preferred one as a custom one. The last registered guesser is preferred over * previously registered ones. * * Re-registering a built-in guesser also allows you to configure it: * * $guesser = new MimeTypes(); * $guesser->registerGuesser(new FileinfoMimeTypeGuesser('/path/to/magic/file')); * * @author Fabien Potencier */ final class MimeTypes implements MimeTypesInterface { private array $extensions = []; private array $mimeTypes = []; /** * @var MimeTypeGuesserInterface[] */ private array $guessers = []; private static MimeTypes $default; public function __construct(array $map = []) { foreach ($map as $mimeType => $extensions) { $this->extensions[$mimeType] = $extensions; foreach ($extensions as $extension) { $this->mimeTypes[$extension][] = $mimeType; } } $this->registerGuesser(new FileBinaryMimeTypeGuesser()); $this->registerGuesser(new FileinfoMimeTypeGuesser()); } public static function setDefault(self $default) { self::$default = $default; } public static function getDefault(): self { return self::$default ?? self::$default = new self(); } /** * Registers a MIME type guesser. * * The last registered guesser has precedence over the other ones. */ public function registerGuesser(MimeTypeGuesserInterface $guesser) { array_unshift($this->guessers, $guesser); } /** * {@inheritdoc} */ public function getExtensions(string $mimeType): array { if ($this->extensions) { $extensions = $this->extensions[$mimeType] ?? $this->extensions[$lcMimeType = strtolower($mimeType)] ?? null; } return $extensions ?? self::MAP[$mimeType] ?? self::MAP[$lcMimeType ?? strtolower($mimeType)] ?? []; } /** * {@inheritdoc} */ public function getMimeTypes(string $ext): array { if ($this->mimeTypes) { $mimeTypes = $this->mimeTypes[$ext] ?? $this->mimeTypes[$lcExt = strtolower($ext)] ?? null; } return $mimeTypes ?? self::REVERSE_MAP[$ext] ?? self::REVERSE_MAP[$lcExt ?? strtolower($ext)] ?? []; } /** * {@inheritdoc} */ public function isGuesserSupported(): bool { foreach ($this->guessers as $guesser) { if ($guesser->isGuesserSupported()) { return true; } } return false; } /** * {@inheritdoc} * * The file is passed to each registered MIME type guesser in reverse order * of their registration (last registered is queried first). Once a guesser * returns a value that is not null, this method terminates and returns the * value. */ public function guessMimeType(string $path): ?string { foreach ($this->guessers as $guesser) { if (!$guesser->isGuesserSupported()) { continue; } if (null !== $mimeType = $guesser->guessMimeType($path)) { return $mimeType; } } if (!$this->isGuesserSupported()) { throw new LogicException('Unable to guess the MIME type as no guessers are available (have you enabled the php_fileinfo extension?).'); } return null; } /** * A map of MIME types and their default extensions. * * Updated from upstream on 2021-09-03 * * @see Resources/bin/update_mime_types.php */ private const MAP = [ 'application/acrobat' => ['pdf'], 'application/andrew-inset' => ['ez'], 'application/annodex' => ['anx'], 'application/applixware' => ['aw'], 'application/atom+xml' => ['atom'], 'application/atomcat+xml' => ['atomcat'], 'application/atomdeleted+xml' => ['atomdeleted'], 'application/atomsvc+xml' => ['atomsvc'], 'application/atsc-dwd+xml' => ['dwd'], 'application/atsc-held+xml' => ['held'], 'application/atsc-rsat+xml' => ['rsat'], 'application/bdoc' => ['bdoc'], 'application/bzip2' => ['bz2', 'bz'], 'application/calendar+xml' => ['xcs'], 'application/ccxml+xml' => ['ccxml'], 'application/cdfx+xml' => ['cdfx'], 'application/cdmi-capability' => ['cdmia'], 'application/cdmi-container' => ['cdmic'], 'application/cdmi-domain' => ['cdmid'], 'application/cdmi-object' => ['cdmio'], 'application/cdmi-queue' => ['cdmiq'], 'application/cdr' => ['cdr'], 'application/coreldraw' => ['cdr'], 'application/csv' => ['csv'], 'application/cu-seeme' => ['cu'], 'application/dash+xml' => ['mpd'], 'application/davmount+xml' => ['davmount'], 'application/dbase' => ['dbf'], 'application/dbf' => ['dbf'], 'application/dicom' => ['dcm'], 'application/docbook+xml' => ['dbk', 'docbook'], 'application/dssc+der' => ['dssc'], 'application/dssc+xml' => ['xdssc'], 'application/ecmascript' => ['ecma', 'es'], 'application/emf' => ['emf'], 'application/emma+xml' => ['emma'], 'application/emotionml+xml' => ['emotionml'], 'application/epub+zip' => ['epub'], 'application/exi' => ['exi'], 'application/fdt+xml' => ['fdt'], 'application/font-tdpfr' => ['pfr'], 'application/font-woff' => ['woff'], 'application/futuresplash' => ['swf', 'spl'], 'application/geo+json' => ['geojson', 'geo.json'], 'application/gml+xml' => ['gml'], 'application/gnunet-directory' => ['gnd'], 'application/gpx' => ['gpx'], 'application/gpx+xml' => ['gpx'], 'application/gxf' => ['gxf'], 'application/gzip' => ['gz'], 'application/hjson' => ['hjson'], 'application/hyperstudio' => ['stk'], 'application/ico' => ['ico'], 'application/ics' => ['vcs', 'ics'], 'application/illustrator' => ['ai'], 'application/inkml+xml' => ['ink', 'inkml'], 'application/ipfix' => ['ipfix'], 'application/its+xml' => ['its'], 'application/java' => ['class'], 'application/java-archive' => ['jar', 'war', 'ear'], 'application/java-byte-code' => ['class'], 'application/java-serialized-object' => ['ser'], 'application/java-vm' => ['class'], 'application/javascript' => ['js', 'mjs', 'jsm'], 'application/jrd+json' => ['jrd'], 'application/json' => ['json', 'map'], 'application/json-patch+json' => ['json-patch'], 'application/json5' => ['json5'], 'application/jsonml+json' => ['jsonml'], 'application/ld+json' => ['jsonld'], 'application/lgr+xml' => ['lgr'], 'application/lost+xml' => ['lostxml'], 'application/lotus123' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], 'application/m3u' => ['m3u', 'm3u8', 'vlc'], 'application/mac-binhex40' => ['hqx'], 'application/mac-compactpro' => ['cpt'], 'application/mads+xml' => ['mads'], 'application/manifest+json' => ['webmanifest'], 'application/marc' => ['mrc'], 'application/marcxml+xml' => ['mrcx'], 'application/mathematica' => ['ma', 'nb', 'mb'], 'application/mathml+xml' => ['mathml', 'mml'], 'application/mbox' => ['mbox'], 'application/mdb' => ['mdb'], 'application/mediaservercontrol+xml' => ['mscml'], 'application/metalink+xml' => ['metalink'], 'application/metalink4+xml' => ['meta4'], 'application/mets+xml' => ['mets'], 'application/mmt-aei+xml' => ['maei'], 'application/mmt-usd+xml' => ['musd'], 'application/mods+xml' => ['mods'], 'application/mp21' => ['m21', 'mp21'], 'application/mp4' => ['mp4s', 'm4p'], 'application/mrb-consumer+xml' => ['xdf'], 'application/mrb-publish+xml' => ['xdf'], 'application/ms-tnef' => ['tnef', 'tnf'], 'application/msaccess' => ['mdb'], 'application/msexcel' => ['xls', 'xlc', 'xll', 'xlm', 'xlw', 'xla', 'xlt', 'xld'], 'application/mspowerpoint' => ['ppz', 'ppt', 'pps', 'pot'], 'application/msword' => ['doc', 'dot'], 'application/msword-template' => ['dot'], 'application/mxf' => ['mxf'], 'application/n-quads' => ['nq'], 'application/n-triples' => ['nt'], 'application/nappdf' => ['pdf'], 'application/node' => ['cjs'], 'application/octet-stream' => ['bin', 'dms', 'lrf', 'mar', 'so', 'dist', 'distz', 'pkg', 'bpk', 'dump', 'elc', 'deploy', 'exe', 'dll', 'deb', 'dmg', 'iso', 'img', 'msi', 'msp', 'msm', 'buffer'], 'application/oda' => ['oda'], 'application/oebps-package+xml' => ['opf'], 'application/ogg' => ['ogx'], 'application/omdoc+xml' => ['omdoc'], 'application/onenote' => ['onetoc', 'onetoc2', 'onetmp', 'onepkg'], 'application/ovf' => ['ova'], 'application/owl+xml' => ['owx'], 'application/oxps' => ['oxps'], 'application/p2p-overlay+xml' => ['relo'], 'application/patch-ops-error+xml' => ['xer'], 'application/pcap' => ['pcap', 'cap', 'dmp'], 'application/pdf' => ['pdf'], 'application/pgp' => ['pgp', 'gpg', 'asc'], 'application/pgp-encrypted' => ['pgp', 'gpg', 'asc'], 'application/pgp-keys' => ['skr', 'pkr', 'asc', 'pgp', 'gpg', 'key'], 'application/pgp-signature' => ['asc', 'sig', 'pgp', 'gpg'], 'application/photoshop' => ['psd'], 'application/pics-rules' => ['prf'], 'application/pkcs10' => ['p10'], 'application/pkcs12' => ['p12', 'pfx'], 'application/pkcs7-mime' => ['p7m', 'p7c'], 'application/pkcs7-signature' => ['p7s'], 'application/pkcs8' => ['p8'], 'application/pkcs8-encrypted' => ['p8e'], 'application/pkix-attr-cert' => ['ac'], 'application/pkix-cert' => ['cer'], 'application/pkix-crl' => ['crl'], 'application/pkix-pkipath' => ['pkipath'], 'application/pkixcmp' => ['pki'], 'application/pls' => ['pls'], 'application/pls+xml' => ['pls'], 'application/postscript' => ['ai', 'eps', 'ps'], 'application/powerpoint' => ['ppz', 'ppt', 'pps', 'pot'], 'application/provenance+xml' => ['provx'], 'application/prs.cww' => ['cww'], 'application/pskc+xml' => ['pskcxml'], 'application/ram' => ['ram'], 'application/raml+yaml' => ['raml'], 'application/rdf+xml' => ['rdf', 'owl', 'rdfs'], 'application/reginfo+xml' => ['rif'], 'application/relax-ng-compact-syntax' => ['rnc'], 'application/resource-lists+xml' => ['rl'], 'application/resource-lists-diff+xml' => ['rld'], 'application/rls-services+xml' => ['rs'], 'application/route-apd+xml' => ['rapd'], 'application/route-s-tsid+xml' => ['sls'], 'application/route-usd+xml' => ['rusd'], 'application/rpki-ghostbusters' => ['gbr'], 'application/rpki-manifest' => ['mft'], 'application/rpki-roa' => ['roa'], 'application/rsd+xml' => ['rsd'], 'application/rss+xml' => ['rss'], 'application/rtf' => ['rtf'], 'application/sbml+xml' => ['sbml'], 'application/schema+json' => ['json'], 'application/scvp-cv-request' => ['scq'], 'application/scvp-cv-response' => ['scs'], 'application/scvp-vp-request' => ['spq'], 'application/scvp-vp-response' => ['spp'], 'application/sdp' => ['sdp'], 'application/senml+xml' => ['senmlx'], 'application/sensml+xml' => ['sensmlx'], 'application/set-payment-initiation' => ['setpay'], 'application/set-registration-initiation' => ['setreg'], 'application/shf+xml' => ['shf'], 'application/sieve' => ['siv', 'sieve'], 'application/smil' => ['smil', 'smi', 'sml', 'kino'], 'application/smil+xml' => ['smi', 'smil', 'sml', 'kino'], 'application/sparql-query' => ['rq'], 'application/sparql-results+xml' => ['srx'], 'application/sql' => ['sql'], 'application/srgs' => ['gram'], 'application/srgs+xml' => ['grxml'], 'application/sru+xml' => ['sru'], 'application/ssdl+xml' => ['ssdl'], 'application/ssml+xml' => ['ssml'], 'application/stuffit' => ['sit', 'hqx'], 'application/swid+xml' => ['swidtag'], 'application/tei+xml' => ['tei', 'teicorpus'], 'application/tga' => ['tga', 'icb', 'tpic', 'vda', 'vst'], 'application/thraud+xml' => ['tfi'], 'application/timestamped-data' => ['tsd'], 'application/toml' => ['toml'], 'application/trig' => ['trig'], 'application/ttml+xml' => ['ttml'], 'application/ubjson' => ['ubj'], 'application/urc-ressheet+xml' => ['rsheet'], 'application/urc-targetdesc+xml' => ['td'], 'application/vnd.1000minds.decision-model+xml' => ['1km'], 'application/vnd.3gpp.pic-bw-large' => ['plb'], 'application/vnd.3gpp.pic-bw-small' => ['psb'], 'application/vnd.3gpp.pic-bw-var' => ['pvb'], 'application/vnd.3gpp2.tcap' => ['tcap'], 'application/vnd.3m.post-it-notes' => ['pwn'], 'application/vnd.accpac.simply.aso' => ['aso'], 'application/vnd.accpac.simply.imp' => ['imp'], 'application/vnd.acucobol' => ['acu'], 'application/vnd.acucorp' => ['atc', 'acutc'], 'application/vnd.adobe.air-application-installer-package+zip' => ['air'], 'application/vnd.adobe.flash.movie' => ['swf', 'spl'], 'application/vnd.adobe.formscentral.fcdt' => ['fcdt'], 'application/vnd.adobe.fxp' => ['fxp', 'fxpl'], 'application/vnd.adobe.illustrator' => ['ai'], 'application/vnd.adobe.xdp+xml' => ['xdp'], 'application/vnd.adobe.xfdf' => ['xfdf'], 'application/vnd.ahead.space' => ['ahead'], 'application/vnd.airzip.filesecure.azf' => ['azf'], 'application/vnd.airzip.filesecure.azs' => ['azs'], 'application/vnd.amazon.ebook' => ['azw'], 'application/vnd.amazon.mobi8-ebook' => ['azw3', 'kfx'], 'application/vnd.americandynamics.acc' => ['acc'], 'application/vnd.amiga.ami' => ['ami'], 'application/vnd.android.package-archive' => ['apk'], 'application/vnd.anser-web-certificate-issue-initiation' => ['cii'], 'application/vnd.anser-web-funds-transfer-initiation' => ['fti'], 'application/vnd.antix.game-component' => ['atx'], 'application/vnd.appimage' => ['appimage'], 'application/vnd.apple.installer+xml' => ['mpkg'], 'application/vnd.apple.keynote' => ['key', 'keynote'], 'application/vnd.apple.mpegurl' => ['m3u8', 'm3u'], 'application/vnd.apple.numbers' => ['numbers'], 'application/vnd.apple.pages' => ['pages'], 'application/vnd.apple.pkpass' => ['pkpass'], 'application/vnd.aristanetworks.swi' => ['swi'], 'application/vnd.astraea-software.iota' => ['iota'], 'application/vnd.audiograph' => ['aep'], 'application/vnd.balsamiq.bmml+xml' => ['bmml'], 'application/vnd.blueice.multipass' => ['mpm'], 'application/vnd.bmi' => ['bmi'], 'application/vnd.businessobjects' => ['rep'], 'application/vnd.chemdraw+xml' => ['cdxml'], 'application/vnd.chess-pgn' => ['pgn'], 'application/vnd.chipnuts.karaoke-mmd' => ['mmd'], 'application/vnd.cinderella' => ['cdy'], 'application/vnd.citationstyles.style+xml' => ['csl'], 'application/vnd.claymore' => ['cla'], 'application/vnd.cloanto.rp9' => ['rp9'], 'application/vnd.clonk.c4group' => ['c4g', 'c4d', 'c4f', 'c4p', 'c4u'], 'application/vnd.cluetrust.cartomobile-config' => ['c11amc'], 'application/vnd.cluetrust.cartomobile-config-pkg' => ['c11amz'], 'application/vnd.coffeescript' => ['coffee'], 'application/vnd.comicbook+zip' => ['cbz'], 'application/vnd.comicbook-rar' => ['cbr'], 'application/vnd.commonspace' => ['csp'], 'application/vnd.contact.cmsg' => ['cdbcmsg'], 'application/vnd.corel-draw' => ['cdr'], 'application/vnd.cosmocaller' => ['cmc'], 'application/vnd.crick.clicker' => ['clkx'], 'application/vnd.crick.clicker.keyboard' => ['clkk'], 'application/vnd.crick.clicker.palette' => ['clkp'], 'application/vnd.crick.clicker.template' => ['clkt'], 'application/vnd.crick.clicker.wordbank' => ['clkw'], 'application/vnd.criticaltools.wbs+xml' => ['wbs'], 'application/vnd.ctc-posml' => ['pml'], 'application/vnd.cups-ppd' => ['ppd'], 'application/vnd.curl.car' => ['car'], 'application/vnd.curl.pcurl' => ['pcurl'], 'application/vnd.dart' => ['dart'], 'application/vnd.data-vision.rdz' => ['rdz'], 'application/vnd.dbf' => ['dbf'], 'application/vnd.debian.binary-package' => ['deb', 'udeb'], 'application/vnd.dece.data' => ['uvf', 'uvvf', 'uvd', 'uvvd'], 'application/vnd.dece.ttml+xml' => ['uvt', 'uvvt'], 'application/vnd.dece.unspecified' => ['uvx', 'uvvx'], 'application/vnd.dece.zip' => ['uvz', 'uvvz'], 'application/vnd.denovo.fcselayout-link' => ['fe_launch'], 'application/vnd.dna' => ['dna'], 'application/vnd.dolby.mlp' => ['mlp'], 'application/vnd.dpgraph' => ['dpg'], 'application/vnd.dreamfactory' => ['dfac'], 'application/vnd.ds-keypoint' => ['kpxx'], 'application/vnd.dvb.ait' => ['ait'], 'application/vnd.dvb.service' => ['svc'], 'application/vnd.dynageo' => ['geo'], 'application/vnd.ecowin.chart' => ['mag'], 'application/vnd.emusic-emusic_package' => ['emp'], 'application/vnd.enliven' => ['nml'], 'application/vnd.epson.esf' => ['esf'], 'application/vnd.epson.msf' => ['msf'], 'application/vnd.epson.quickanime' => ['qam'], 'application/vnd.epson.salt' => ['slt'], 'application/vnd.epson.ssf' => ['ssf'], 'application/vnd.eszigno3+xml' => ['es3', 'et3'], 'application/vnd.etsi.asic-e+zip' => ['asice'], 'application/vnd.ezpix-album' => ['ez2'], 'application/vnd.ezpix-package' => ['ez3'], 'application/vnd.fdf' => ['fdf'], 'application/vnd.fdsn.mseed' => ['mseed'], 'application/vnd.fdsn.seed' => ['seed', 'dataless'], 'application/vnd.flatpak' => ['flatpak', 'xdgapp'], 'application/vnd.flatpak.ref' => ['flatpakref'], 'application/vnd.flatpak.repo' => ['flatpakrepo'], 'application/vnd.flographit' => ['gph'], 'application/vnd.fluxtime.clip' => ['ftc'], 'application/vnd.framemaker' => ['fm', 'frame', 'maker', 'book'], 'application/vnd.frogans.fnc' => ['fnc'], 'application/vnd.frogans.ltf' => ['ltf'], 'application/vnd.fsc.weblaunch' => ['fsc'], 'application/vnd.fujitsu.oasys' => ['oas'], 'application/vnd.fujitsu.oasys2' => ['oa2'], 'application/vnd.fujitsu.oasys3' => ['oa3'], 'application/vnd.fujitsu.oasysgp' => ['fg5'], 'application/vnd.fujitsu.oasysprs' => ['bh2'], 'application/vnd.fujixerox.ddd' => ['ddd'], 'application/vnd.fujixerox.docuworks' => ['xdw'], 'application/vnd.fujixerox.docuworks.binder' => ['xbd'], 'application/vnd.fuzzysheet' => ['fzs'], 'application/vnd.genomatix.tuxedo' => ['txd'], 'application/vnd.geo+json' => ['geojson', 'geo.json'], 'application/vnd.geogebra.file' => ['ggb'], 'application/vnd.geogebra.tool' => ['ggt'], 'application/vnd.geometry-explorer' => ['gex', 'gre'], 'application/vnd.geonext' => ['gxt'], 'application/vnd.geoplan' => ['g2w'], 'application/vnd.geospace' => ['g3w'], 'application/vnd.gmx' => ['gmx'], 'application/vnd.google-apps.document' => ['gdoc'], 'application/vnd.google-apps.presentation' => ['gslides'], 'application/vnd.google-apps.spreadsheet' => ['gsheet'], 'application/vnd.google-earth.kml+xml' => ['kml'], 'application/vnd.google-earth.kmz' => ['kmz'], 'application/vnd.grafeq' => ['gqf', 'gqs'], 'application/vnd.groove-account' => ['gac'], 'application/vnd.groove-help' => ['ghf'], 'application/vnd.groove-identity-message' => ['gim'], 'application/vnd.groove-injector' => ['grv'], 'application/vnd.groove-tool-message' => ['gtm'], 'application/vnd.groove-tool-template' => ['tpl'], 'application/vnd.groove-vcard' => ['vcg'], 'application/vnd.haansoft-hwp' => ['hwp'], 'application/vnd.haansoft-hwt' => ['hwt'], 'application/vnd.hal+xml' => ['hal'], 'application/vnd.handheld-entertainment+xml' => ['zmm'], 'application/vnd.hbci' => ['hbci'], 'application/vnd.hhe.lesson-player' => ['les'], 'application/vnd.hp-hpgl' => ['hpgl'], 'application/vnd.hp-hpid' => ['hpid'], 'application/vnd.hp-hps' => ['hps'], 'application/vnd.hp-jlyt' => ['jlt'], 'application/vnd.hp-pcl' => ['pcl'], 'application/vnd.hp-pclxl' => ['pclxl'], 'application/vnd.hydrostatix.sof-data' => ['sfd-hdstx'], 'application/vnd.ibm.minipay' => ['mpy'], 'application/vnd.ibm.modcap' => ['afp', 'listafp', 'list3820'], 'application/vnd.ibm.rights-management' => ['irm'], 'application/vnd.ibm.secure-container' => ['sc'], 'application/vnd.iccprofile' => ['icc', 'icm'], 'application/vnd.igloader' => ['igl'], 'application/vnd.immervision-ivp' => ['ivp'], 'application/vnd.immervision-ivu' => ['ivu'], 'application/vnd.insors.igm' => ['igm'], 'application/vnd.intercon.formnet' => ['xpw', 'xpx'], 'application/vnd.intergeo' => ['i2g'], 'application/vnd.intu.qbo' => ['qbo'], 'application/vnd.intu.qfx' => ['qfx'], 'application/vnd.ipunplugged.rcprofile' => ['rcprofile'], 'application/vnd.irepository.package+xml' => ['irp'], 'application/vnd.is-xpr' => ['xpr'], 'application/vnd.isac.fcs' => ['fcs'], 'application/vnd.jam' => ['jam'], 'application/vnd.jcp.javame.midlet-rms' => ['rms'], 'application/vnd.jisp' => ['jisp'], 'application/vnd.joost.joda-archive' => ['joda'], 'application/vnd.kahootz' => ['ktz', 'ktr'], 'application/vnd.kde.karbon' => ['karbon'], 'application/vnd.kde.kchart' => ['chrt'], 'application/vnd.kde.kformula' => ['kfo'], 'application/vnd.kde.kivio' => ['flw'], 'application/vnd.kde.kontour' => ['kon'], 'application/vnd.kde.kpresenter' => ['kpr', 'kpt'], 'application/vnd.kde.kspread' => ['ksp'], 'application/vnd.kde.kword' => ['kwd', 'kwt'], 'application/vnd.kenameaapp' => ['htke'], 'application/vnd.kidspiration' => ['kia'], 'application/vnd.kinar' => ['kne', 'knp'], 'application/vnd.koan' => ['skp', 'skd', 'skt', 'skm'], 'application/vnd.kodak-descriptor' => ['sse'], 'application/vnd.las.las+xml' => ['lasxml'], 'application/vnd.llamagraphics.life-balance.desktop' => ['lbd'], 'application/vnd.llamagraphics.life-balance.exchange+xml' => ['lbe'], 'application/vnd.lotus-1-2-3' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], 'application/vnd.lotus-approach' => ['apr'], 'application/vnd.lotus-freelance' => ['pre'], 'application/vnd.lotus-notes' => ['nsf'], 'application/vnd.lotus-organizer' => ['org'], 'application/vnd.lotus-screencam' => ['scm'], 'application/vnd.lotus-wordpro' => ['lwp'], 'application/vnd.macports.portpkg' => ['portpkg'], 'application/vnd.mapbox-vector-tile' => ['mvt'], 'application/vnd.mcd' => ['mcd'], 'application/vnd.medcalcdata' => ['mc1'], 'application/vnd.mediastation.cdkey' => ['cdkey'], 'application/vnd.mfer' => ['mwf'], 'application/vnd.mfmp' => ['mfm'], 'application/vnd.micrografx.flo' => ['flo'], 'application/vnd.micrografx.igx' => ['igx'], 'application/vnd.mif' => ['mif'], 'application/vnd.mobius.daf' => ['daf'], 'application/vnd.mobius.dis' => ['dis'], 'application/vnd.mobius.mbk' => ['mbk'], 'application/vnd.mobius.mqy' => ['mqy'], 'application/vnd.mobius.msl' => ['msl'], 'application/vnd.mobius.plc' => ['plc'], 'application/vnd.mobius.txf' => ['txf'], 'application/vnd.mophun.application' => ['mpn'], 'application/vnd.mophun.certificate' => ['mpc'], 'application/vnd.mozilla.xul+xml' => ['xul'], 'application/vnd.ms-access' => ['mdb'], 'application/vnd.ms-artgalry' => ['cil'], 'application/vnd.ms-asf' => ['asf'], 'application/vnd.ms-cab-compressed' => ['cab'], 'application/vnd.ms-excel' => ['xls', 'xlm', 'xla', 'xlc', 'xlt', 'xlw', 'xll', 'xld'], 'application/vnd.ms-excel.addin.macroenabled.12' => ['xlam'], 'application/vnd.ms-excel.sheet.binary.macroenabled.12' => ['xlsb'], 'application/vnd.ms-excel.sheet.macroenabled.12' => ['xlsm'], 'application/vnd.ms-excel.template.macroenabled.12' => ['xltm'], 'application/vnd.ms-fontobject' => ['eot'], 'application/vnd.ms-htmlhelp' => ['chm'], 'application/vnd.ms-ims' => ['ims'], 'application/vnd.ms-lrm' => ['lrm'], 'application/vnd.ms-officetheme' => ['thmx'], 'application/vnd.ms-outlook' => ['msg'], 'application/vnd.ms-pki.seccat' => ['cat'], 'application/vnd.ms-pki.stl' => ['stl'], 'application/vnd.ms-powerpoint' => ['ppt', 'pps', 'pot', 'ppz'], 'application/vnd.ms-powerpoint.addin.macroenabled.12' => ['ppam'], 'application/vnd.ms-powerpoint.presentation.macroenabled.12' => ['pptm'], 'application/vnd.ms-powerpoint.slide.macroenabled.12' => ['sldm'], 'application/vnd.ms-powerpoint.slideshow.macroenabled.12' => ['ppsm'], 'application/vnd.ms-powerpoint.template.macroenabled.12' => ['potm'], 'application/vnd.ms-project' => ['mpp', 'mpt'], 'application/vnd.ms-publisher' => ['pub'], 'application/vnd.ms-tnef' => ['tnef', 'tnf'], 'application/vnd.ms-visio.drawing.macroenabled.main+xml' => ['vsdm'], 'application/vnd.ms-visio.drawing.main+xml' => ['vsdx'], 'application/vnd.ms-visio.stencil.macroenabled.main+xml' => ['vssm'], 'application/vnd.ms-visio.stencil.main+xml' => ['vssx'], 'application/vnd.ms-visio.template.macroenabled.main+xml' => ['vstm'], 'application/vnd.ms-visio.template.main+xml' => ['vstx'], 'application/vnd.ms-word' => ['doc'], 'application/vnd.ms-word.document.macroenabled.12' => ['docm'], 'application/vnd.ms-word.template.macroenabled.12' => ['dotm'], 'application/vnd.ms-works' => ['wps', 'wks', 'wcm', 'wdb', 'xlr'], 'application/vnd.ms-wpl' => ['wpl'], 'application/vnd.ms-xpsdocument' => ['xps'], 'application/vnd.msaccess' => ['mdb'], 'application/vnd.mseq' => ['mseq'], 'application/vnd.musician' => ['mus'], 'application/vnd.muvee.style' => ['msty'], 'application/vnd.mynfc' => ['taglet'], 'application/vnd.neurolanguage.nlu' => ['nlu'], 'application/vnd.nintendo.snes.rom' => ['sfc', 'smc'], 'application/vnd.nitf' => ['ntf', 'nitf'], 'application/vnd.noblenet-directory' => ['nnd'], 'application/vnd.noblenet-sealer' => ['nns'], 'application/vnd.noblenet-web' => ['nnw'], 'application/vnd.nokia.n-gage.ac+xml' => ['ac'], 'application/vnd.nokia.n-gage.data' => ['ngdat'], 'application/vnd.nokia.n-gage.symbian.install' => ['n-gage'], 'application/vnd.nokia.radio-preset' => ['rpst'], 'application/vnd.nokia.radio-presets' => ['rpss'], 'application/vnd.novadigm.edm' => ['edm'], 'application/vnd.novadigm.edx' => ['edx'], 'application/vnd.novadigm.ext' => ['ext'], 'application/vnd.oasis.docbook+xml' => ['dbk', 'docbook'], 'application/vnd.oasis.opendocument.chart' => ['odc'], 'application/vnd.oasis.opendocument.chart-template' => ['otc'], 'application/vnd.oasis.opendocument.database' => ['odb'], 'application/vnd.oasis.opendocument.formula' => ['odf'], 'application/vnd.oasis.opendocument.formula-template' => ['odft', 'otf'], 'application/vnd.oasis.opendocument.graphics' => ['odg'], 'application/vnd.oasis.opendocument.graphics-flat-xml' => ['fodg'], 'application/vnd.oasis.opendocument.graphics-template' => ['otg'], 'application/vnd.oasis.opendocument.image' => ['odi'], 'application/vnd.oasis.opendocument.image-template' => ['oti'], 'application/vnd.oasis.opendocument.presentation' => ['odp'], 'application/vnd.oasis.opendocument.presentation-flat-xml' => ['fodp'], 'application/vnd.oasis.opendocument.presentation-template' => ['otp'], 'application/vnd.oasis.opendocument.spreadsheet' => ['ods'], 'application/vnd.oasis.opendocument.spreadsheet-flat-xml' => ['fods'], 'application/vnd.oasis.opendocument.spreadsheet-template' => ['ots'], 'application/vnd.oasis.opendocument.text' => ['odt'], 'application/vnd.oasis.opendocument.text-flat-xml' => ['fodt'], 'application/vnd.oasis.opendocument.text-master' => ['odm'], 'application/vnd.oasis.opendocument.text-template' => ['ott'], 'application/vnd.oasis.opendocument.text-web' => ['oth'], 'application/vnd.olpc-sugar' => ['xo'], 'application/vnd.oma.dd2+xml' => ['dd2'], 'application/vnd.openblox.game+xml' => ['obgx'], 'application/vnd.openofficeorg.extension' => ['oxt'], 'application/vnd.openstreetmap.data+xml' => ['osm'], 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => ['pptx'], 'application/vnd.openxmlformats-officedocument.presentationml.slide' => ['sldx'], 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => ['ppsx'], 'application/vnd.openxmlformats-officedocument.presentationml.template' => ['potx'], 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => ['xlsx'], 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => ['xltx'], 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => ['docx'], 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => ['dotx'], 'application/vnd.osgeo.mapguide.package' => ['mgp'], 'application/vnd.osgi.dp' => ['dp'], 'application/vnd.osgi.subsystem' => ['esa'], 'application/vnd.palm' => ['pdb', 'pqa', 'oprc', 'prc'], 'application/vnd.pawaafile' => ['paw'], 'application/vnd.pg.format' => ['str'], 'application/vnd.pg.osasli' => ['ei6'], 'application/vnd.picsel' => ['efif'], 'application/vnd.pmi.widget' => ['wg'], 'application/vnd.pocketlearn' => ['plf'], 'application/vnd.powerbuilder6' => ['pbd'], 'application/vnd.previewsystems.box' => ['box'], 'application/vnd.proteus.magazine' => ['mgz'], 'application/vnd.publishare-delta-tree' => ['qps'], 'application/vnd.pvi.ptid1' => ['ptid'], 'application/vnd.quark.quarkxpress' => ['qxd', 'qxt', 'qwd', 'qwt', 'qxl', 'qxb'], 'application/vnd.rar' => ['rar'], 'application/vnd.realvnc.bed' => ['bed'], 'application/vnd.recordare.musicxml' => ['mxl'], 'application/vnd.recordare.musicxml+xml' => ['musicxml'], 'application/vnd.rig.cryptonote' => ['cryptonote'], 'application/vnd.rim.cod' => ['cod'], 'application/vnd.rn-realmedia' => ['rm', 'rmj', 'rmm', 'rms', 'rmx', 'rmvb'], 'application/vnd.rn-realmedia-vbr' => ['rmvb', 'rm', 'rmj', 'rmm', 'rms', 'rmx'], 'application/vnd.route66.link66+xml' => ['link66'], 'application/vnd.sailingtracker.track' => ['st'], 'application/vnd.sdp' => ['sdp'], 'application/vnd.seemail' => ['see'], 'application/vnd.sema' => ['sema'], 'application/vnd.semd' => ['semd'], 'application/vnd.semf' => ['semf'], 'application/vnd.shana.informed.formdata' => ['ifm'], 'application/vnd.shana.informed.formtemplate' => ['itp'], 'application/vnd.shana.informed.interchange' => ['iif'], 'application/vnd.shana.informed.package' => ['ipk'], 'application/vnd.simtech-mindmapper' => ['twd', 'twds'], 'application/vnd.smaf' => ['mmf', 'smaf'], 'application/vnd.smart.teacher' => ['teacher'], 'application/vnd.snap' => ['snap'], 'application/vnd.software602.filler.form+xml' => ['fo'], 'application/vnd.solent.sdkm+xml' => ['sdkm', 'sdkd'], 'application/vnd.spotfire.dxp' => ['dxp'], 'application/vnd.spotfire.sfs' => ['sfs'], 'application/vnd.sqlite3' => ['sqlite3'], 'application/vnd.squashfs' => ['sqsh'], 'application/vnd.stardivision.calc' => ['sdc'], 'application/vnd.stardivision.chart' => ['sds'], 'application/vnd.stardivision.draw' => ['sda'], 'application/vnd.stardivision.impress' => ['sdd', 'sdp'], 'application/vnd.stardivision.mail' => ['smd'], 'application/vnd.stardivision.math' => ['smf'], 'application/vnd.stardivision.writer' => ['sdw', 'vor', 'sgl'], 'application/vnd.stardivision.writer-global' => ['sgl', 'sdw', 'vor'], 'application/vnd.stepmania.package' => ['smzip'], 'application/vnd.stepmania.stepchart' => ['sm'], 'application/vnd.sun.wadl+xml' => ['wadl'], 'application/vnd.sun.xml.base' => ['odb'], 'application/vnd.sun.xml.calc' => ['sxc'], 'application/vnd.sun.xml.calc.template' => ['stc'], 'application/vnd.sun.xml.draw' => ['sxd'], 'application/vnd.sun.xml.draw.template' => ['std'], 'application/vnd.sun.xml.impress' => ['sxi'], 'application/vnd.sun.xml.impress.template' => ['sti'], 'application/vnd.sun.xml.math' => ['sxm'], 'application/vnd.sun.xml.writer' => ['sxw'], 'application/vnd.sun.xml.writer.global' => ['sxg'], 'application/vnd.sun.xml.writer.template' => ['stw'], 'application/vnd.sus-calendar' => ['sus', 'susp'], 'application/vnd.svd' => ['svd'], 'application/vnd.symbian.install' => ['sis', 'sisx'], 'application/vnd.syncml+xml' => ['xsm'], 'application/vnd.syncml.dm+wbxml' => ['bdm'], 'application/vnd.syncml.dm+xml' => ['xdm'], 'application/vnd.syncml.dmddf+xml' => ['ddf'], 'application/vnd.tao.intent-module-archive' => ['tao'], 'application/vnd.tcpdump.pcap' => ['pcap', 'cap', 'dmp'], 'application/vnd.tmobile-livetv' => ['tmo'], 'application/vnd.trid.tpt' => ['tpt'], 'application/vnd.triscape.mxs' => ['mxs'], 'application/vnd.trueapp' => ['tra'], 'application/vnd.ufdl' => ['ufd', 'ufdl'], 'application/vnd.uiq.theme' => ['utz'], 'application/vnd.umajin' => ['umj'], 'application/vnd.unity' => ['unityweb'], 'application/vnd.uoml+xml' => ['uoml'], 'application/vnd.vcx' => ['vcx'], 'application/vnd.visio' => ['vsd', 'vst', 'vss', 'vsw'], 'application/vnd.visionary' => ['vis'], 'application/vnd.vsf' => ['vsf'], 'application/vnd.wap.wbxml' => ['wbxml'], 'application/vnd.wap.wmlc' => ['wmlc'], 'application/vnd.wap.wmlscriptc' => ['wmlsc'], 'application/vnd.webturbo' => ['wtb'], 'application/vnd.wolfram.player' => ['nbp'], 'application/vnd.wordperfect' => ['wpd', 'wp', 'wp4', 'wp5', 'wp6', 'wpp'], 'application/vnd.wqd' => ['wqd'], 'application/vnd.wt.stf' => ['stf'], 'application/vnd.xara' => ['xar'], 'application/vnd.xdgapp' => ['flatpak', 'xdgapp'], 'application/vnd.xfdl' => ['xfdl'], 'application/vnd.yamaha.hv-dic' => ['hvd'], 'application/vnd.yamaha.hv-script' => ['hvs'], 'application/vnd.yamaha.hv-voice' => ['hvp'], 'application/vnd.yamaha.openscoreformat' => ['osf'], 'application/vnd.yamaha.openscoreformat.osfpvg+xml' => ['osfpvg'], 'application/vnd.yamaha.smaf-audio' => ['saf'], 'application/vnd.yamaha.smaf-phrase' => ['spf'], 'application/vnd.yellowriver-custom-menu' => ['cmp'], 'application/vnd.youtube.yt' => ['yt'], 'application/vnd.zul' => ['zir', 'zirz'], 'application/vnd.zzazz.deck+xml' => ['zaz'], 'application/voicexml+xml' => ['vxml'], 'application/wasm' => ['wasm'], 'application/widget' => ['wgt'], 'application/winhlp' => ['hlp'], 'application/wk1' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], 'application/wmf' => ['wmf'], 'application/wordperfect' => ['wp', 'wp4', 'wp5', 'wp6', 'wpd', 'wpp'], 'application/wsdl+xml' => ['wsdl'], 'application/wspolicy+xml' => ['wspolicy'], 'application/wwf' => ['wwf'], 'application/x-123' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], 'application/x-7z-compressed' => ['7z', '7z.001'], 'application/x-abiword' => ['abw', 'abw.CRASHED', 'abw.gz', 'zabw'], 'application/x-ace' => ['ace'], 'application/x-ace-compressed' => ['ace'], 'application/x-alz' => ['alz'], 'application/x-amiga-disk-format' => ['adf'], 'application/x-amipro' => ['sam'], 'application/x-annodex' => ['anx'], 'application/x-aportisdoc' => ['pdb', 'pdc'], 'application/x-apple-diskimage' => ['dmg'], 'application/x-apple-systemprofiler+xml' => ['spx'], 'application/x-appleworks-document' => ['cwk'], 'application/x-applix-spreadsheet' => ['as'], 'application/x-applix-word' => ['aw'], 'application/x-archive' => ['a', 'ar'], 'application/x-arj' => ['arj'], 'application/x-asp' => ['asp'], 'application/x-atari-2600-rom' => ['a26'], 'application/x-atari-7800-rom' => ['a78'], 'application/x-atari-lynx-rom' => ['lnx'], 'application/x-authorware-bin' => ['aab', 'x32', 'u32', 'vox'], 'application/x-authorware-map' => ['aam'], 'application/x-authorware-seg' => ['aas'], 'application/x-awk' => ['awk'], 'application/x-bcpio' => ['bcpio'], 'application/x-bdoc' => ['bdoc'], 'application/x-bittorrent' => ['torrent'], 'application/x-blender' => ['blender', 'blend', 'BLEND'], 'application/x-blorb' => ['blb', 'blorb'], 'application/x-bps-patch' => ['bps'], 'application/x-bsdiff' => ['bsdiff'], 'application/x-bz2' => ['bz2'], 'application/x-bzdvi' => ['dvi.bz2'], 'application/x-bzip' => ['bz', 'bz2'], 'application/x-bzip-compressed-tar' => ['tar.bz2', 'tar.bz', 'tbz2', 'tbz', 'tb2'], 'application/x-bzip2' => ['bz2', 'boz', 'bz'], 'application/x-bzpdf' => ['pdf.bz2'], 'application/x-bzpostscript' => ['ps.bz2'], 'application/x-cb7' => ['cb7'], 'application/x-cbr' => ['cbr', 'cba', 'cbt', 'cbz', 'cb7'], 'application/x-cbt' => ['cbt'], 'application/x-cbz' => ['cbz'], 'application/x-ccmx' => ['ccmx'], 'application/x-cd-image' => ['iso', 'iso9660'], 'application/x-cdlink' => ['vcd'], 'application/x-cdr' => ['cdr'], 'application/x-cdrdao-toc' => ['toc'], 'application/x-cfs-compressed' => ['cfs'], 'application/x-chat' => ['chat'], 'application/x-chess-pgn' => ['pgn'], 'application/x-chm' => ['chm'], 'application/x-chrome-extension' => ['crx'], 'application/x-cisco-vpn-settings' => ['pcf'], 'application/x-cocoa' => ['cco'], 'application/x-compress' => ['Z'], 'application/x-compressed-iso' => ['cso'], 'application/x-compressed-tar' => ['tar.gz', 'tgz'], 'application/x-conference' => ['nsc'], 'application/x-coreldraw' => ['cdr'], 'application/x-cpio' => ['cpio'], 'application/x-cpio-compressed' => ['cpio.gz'], 'application/x-csh' => ['csh'], 'application/x-cue' => ['cue'], 'application/x-dar' => ['dar'], 'application/x-dbase' => ['dbf'], 'application/x-dbf' => ['dbf'], 'application/x-dc-rom' => ['dc'], 'application/x-deb' => ['deb', 'udeb'], 'application/x-debian-package' => ['deb', 'udeb'], 'application/x-designer' => ['ui'], 'application/x-desktop' => ['desktop', 'kdelnk'], 'application/x-dgc-compressed' => ['dgc'], 'application/x-dia-diagram' => ['dia'], 'application/x-dia-shape' => ['shape'], 'application/x-director' => ['dir', 'dcr', 'dxr', 'cst', 'cct', 'cxt', 'w3d', 'fgd', 'swa'], 'application/x-discjuggler-cd-image' => ['cdi'], 'application/x-docbook+xml' => ['dbk', 'docbook'], 'application/x-doom' => ['wad'], 'application/x-doom-wad' => ['wad'], 'application/x-dreamcast-rom' => ['iso'], 'application/x-dtbncx+xml' => ['ncx'], 'application/x-dtbook+xml' => ['dtb'], 'application/x-dtbresource+xml' => ['res'], 'application/x-dvi' => ['dvi'], 'application/x-e-theme' => ['etheme'], 'application/x-egon' => ['egon'], 'application/x-emf' => ['emf'], 'application/x-envoy' => ['evy'], 'application/x-eva' => ['eva'], 'application/x-fd-file' => ['fd', 'qd'], 'application/x-fds-disk' => ['fds'], 'application/x-fictionbook' => ['fb2'], 'application/x-fictionbook+xml' => ['fb2'], 'application/x-flash-video' => ['flv'], 'application/x-fluid' => ['fl'], 'application/x-font-afm' => ['afm'], 'application/x-font-bdf' => ['bdf'], 'application/x-font-ghostscript' => ['gsf'], 'application/x-font-linux-psf' => ['psf'], 'application/x-font-otf' => ['otf'], 'application/x-font-pcf' => ['pcf', 'pcf.Z', 'pcf.gz'], 'application/x-font-snf' => ['snf'], 'application/x-font-speedo' => ['spd'], 'application/x-font-truetype' => ['ttf'], 'application/x-font-ttf' => ['ttf'], 'application/x-font-ttx' => ['ttx'], 'application/x-font-type1' => ['pfa', 'pfb', 'pfm', 'afm', 'gsf'], 'application/x-font-woff' => ['woff'], 'application/x-frame' => ['fm'], 'application/x-freearc' => ['arc'], 'application/x-futuresplash' => ['spl'], 'application/x-gameboy-color-rom' => ['gbc', 'cgb'], 'application/x-gameboy-rom' => ['gb', 'sgb'], 'application/x-gamecube-iso-image' => ['iso'], 'application/x-gamecube-rom' => ['iso'], 'application/x-gamegear-rom' => ['gg'], 'application/x-gba-rom' => ['gba', 'agb'], 'application/x-gca-compressed' => ['gca'], 'application/x-gd-rom-cue' => ['gdi'], 'application/x-gedcom' => ['ged', 'gedcom'], 'application/x-genesis-32x-rom' => ['32x', 'mdx'], 'application/x-genesis-rom' => ['gen', 'smd', 'sgd'], 'application/x-gettext' => ['po'], 'application/x-gettext-translation' => ['gmo', 'mo'], 'application/x-glade' => ['glade'], 'application/x-glulx' => ['ulx'], 'application/x-gnome-app-info' => ['desktop', 'kdelnk'], 'application/x-gnucash' => ['gnucash', 'gnc', 'xac'], 'application/x-gnumeric' => ['gnumeric'], 'application/x-gnuplot' => ['gp', 'gplt', 'gnuplot'], 'application/x-go-sgf' => ['sgf'], 'application/x-gpx' => ['gpx'], 'application/x-gpx+xml' => ['gpx'], 'application/x-gramps-xml' => ['gramps'], 'application/x-graphite' => ['gra'], 'application/x-gtar' => ['gtar', 'tar', 'gem'], 'application/x-gtk-builder' => ['ui'], 'application/x-gz-font-linux-psf' => ['psf.gz'], 'application/x-gzdvi' => ['dvi.gz'], 'application/x-gzip' => ['gz'], 'application/x-gzpdf' => ['pdf.gz'], 'application/x-gzpostscript' => ['ps.gz'], 'application/x-hdf' => ['hdf', 'hdf4', 'h4', 'hdf5', 'h5'], 'application/x-hfe-file' => ['hfe'], 'application/x-hfe-floppy-image' => ['hfe'], 'application/x-httpd-php' => ['php'], 'application/x-hwp' => ['hwp'], 'application/x-hwt' => ['hwt'], 'application/x-ica' => ['ica'], 'application/x-install-instructions' => ['install'], 'application/x-ips-patch' => ['ips'], 'application/x-ipynb+json' => ['ipynb'], 'application/x-iso9660-appimage' => ['appimage'], 'application/x-iso9660-image' => ['iso', 'iso9660'], 'application/x-it87' => ['it87'], 'application/x-iwork-keynote-sffkey' => ['key'], 'application/x-iwork-numbers-sffnumbers' => ['numbers'], 'application/x-iwork-pages-sffpages' => ['pages'], 'application/x-jar' => ['jar'], 'application/x-java' => ['class'], 'application/x-java-archive' => ['jar'], 'application/x-java-archive-diff' => ['jardiff'], 'application/x-java-class' => ['class'], 'application/x-java-jce-keystore' => ['jceks'], 'application/x-java-jnlp-file' => ['jnlp'], 'application/x-java-keystore' => ['jks', 'ks'], 'application/x-java-pack200' => ['pack'], 'application/x-java-vm' => ['class'], 'application/x-javascript' => ['js', 'jsm', 'mjs'], 'application/x-jbuilder-project' => ['jpr', 'jpx'], 'application/x-karbon' => ['karbon'], 'application/x-kchart' => ['chrt'], 'application/x-keepass2' => ['kdbx'], 'application/x-kexi-connectiondata' => ['kexic'], 'application/x-kexiproject-shortcut' => ['kexis'], 'application/x-kexiproject-sqlite' => ['kexi'], 'application/x-kexiproject-sqlite2' => ['kexi'], 'application/x-kexiproject-sqlite3' => ['kexi'], 'application/x-kformula' => ['kfo'], 'application/x-killustrator' => ['kil'], 'application/x-kivio' => ['flw'], 'application/x-kontour' => ['kon'], 'application/x-kpovmodeler' => ['kpm'], 'application/x-kpresenter' => ['kpr', 'kpt'], 'application/x-krita' => ['kra', 'krz'], 'application/x-kspread' => ['ksp'], 'application/x-kugar' => ['kud'], 'application/x-kword' => ['kwd', 'kwt'], 'application/x-latex' => ['latex'], 'application/x-lha' => ['lha', 'lzh'], 'application/x-lhz' => ['lhz'], 'application/x-linguist' => ['ts'], 'application/x-lotus123' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], 'application/x-lrzip' => ['lrz'], 'application/x-lrzip-compressed-tar' => ['tar.lrz', 'tlrz'], 'application/x-lua-bytecode' => ['luac'], 'application/x-lyx' => ['lyx'], 'application/x-lz4' => ['lz4'], 'application/x-lz4-compressed-tar' => ['tar.lz4'], 'application/x-lzh-compressed' => ['lzh', 'lha'], 'application/x-lzip' => ['lz'], 'application/x-lzip-compressed-tar' => ['tar.lz'], 'application/x-lzma' => ['lzma'], 'application/x-lzma-compressed-tar' => ['tar.lzma', 'tlz'], 'application/x-lzop' => ['lzo'], 'application/x-lzpdf' => ['pdf.lz'], 'application/x-m4' => ['m4'], 'application/x-magicpoint' => ['mgp'], 'application/x-makeself' => ['run'], 'application/x-mame-chd' => ['chd'], 'application/x-markaby' => ['mab'], 'application/x-mathematica' => ['nb'], 'application/x-mdb' => ['mdb'], 'application/x-mie' => ['mie'], 'application/x-mif' => ['mif'], 'application/x-mimearchive' => ['mhtml', 'mht'], 'application/x-mobi8-ebook' => ['azw3', 'kfx'], 'application/x-mobipocket-ebook' => ['prc', 'mobi'], 'application/x-ms-application' => ['application'], 'application/x-ms-asx' => ['asx', 'wax', 'wvx', 'wmx'], 'application/x-ms-dos-executable' => ['exe'], 'application/x-ms-shortcut' => ['lnk'], 'application/x-ms-wim' => ['wim', 'swm'], 'application/x-ms-wmd' => ['wmd'], 'application/x-ms-wmz' => ['wmz'], 'application/x-ms-xbap' => ['xbap'], 'application/x-msaccess' => ['mdb'], 'application/x-msbinder' => ['obd'], 'application/x-mscardfile' => ['crd'], 'application/x-msclip' => ['clp'], 'application/x-msdos-program' => ['exe'], 'application/x-msdownload' => ['exe', 'dll', 'com', 'bat', 'msi'], 'application/x-msexcel' => ['xls', 'xlc', 'xll', 'xlm', 'xlw', 'xla', 'xlt', 'xld'], 'application/x-msi' => ['msi'], 'application/x-msmediaview' => ['mvb', 'm13', 'm14'], 'application/x-msmetafile' => ['wmf', 'wmz', 'emf', 'emz'], 'application/x-msmoney' => ['mny'], 'application/x-mspowerpoint' => ['ppz', 'ppt', 'pps', 'pot'], 'application/x-mspublisher' => ['pub'], 'application/x-msschedule' => ['scd'], 'application/x-msterminal' => ['trm'], 'application/x-mswinurl' => ['url'], 'application/x-msword' => ['doc'], 'application/x-mswrite' => ['wri'], 'application/x-msx-rom' => ['msx'], 'application/x-n64-rom' => ['n64', 'z64', 'v64'], 'application/x-navi-animation' => ['ani'], 'application/x-neo-geo-pocket-color-rom' => ['ngc'], 'application/x-neo-geo-pocket-rom' => ['ngp'], 'application/x-nes-rom' => ['nes', 'nez', 'unf', 'unif'], 'application/x-netcdf' => ['nc', 'cdf'], 'application/x-netshow-channel' => ['nsc'], 'application/x-nintendo-3ds-executable' => ['3dsx'], 'application/x-nintendo-3ds-rom' => ['3ds', 'cci'], 'application/x-nintendo-ds-rom' => ['nds'], 'application/x-ns-proxy-autoconfig' => ['pac'], 'application/x-nzb' => ['nzb'], 'application/x-object' => ['o', 'mod'], 'application/x-ogg' => ['ogx'], 'application/x-oleo' => ['oleo'], 'application/x-pagemaker' => ['p65', 'pm', 'pm6', 'pmd'], 'application/x-pak' => ['pak'], 'application/x-palm-database' => ['prc', 'pdb', 'pqa', 'oprc'], 'application/x-par2' => ['PAR2', 'par2'], 'application/x-partial-download' => ['wkdownload', 'crdownload', 'part'], 'application/x-pc-engine-rom' => ['pce'], 'application/x-pcap' => ['pcap', 'cap', 'dmp'], 'application/x-pdf' => ['pdf'], 'application/x-perl' => ['pl', 'pm', 'PL', 'al', 'perl', 'pod', 't'], 'application/x-photoshop' => ['psd'], 'application/x-php' => ['php', 'php3', 'php4', 'php5', 'phps'], 'application/x-pilot' => ['prc', 'pdb'], 'application/x-pkcs12' => ['p12', 'pfx'], 'application/x-pkcs7-certificates' => ['p7b', 'spc'], 'application/x-pkcs7-certreqresp' => ['p7r'], 'application/x-planperfect' => ['pln'], 'application/x-pocket-word' => ['psw'], 'application/x-pw' => ['pw'], 'application/x-pyspread-bz-spreadsheet' => ['pys'], 'application/x-pyspread-spreadsheet' => ['pysu'], 'application/x-python-bytecode' => ['pyc', 'pyo'], 'application/x-qed-disk' => ['qed'], 'application/x-qemu-disk' => ['qcow2', 'qcow'], 'application/x-qpress' => ['qp'], 'application/x-qtiplot' => ['qti', 'qti.gz'], 'application/x-quattropro' => ['wb1', 'wb2', 'wb3'], 'application/x-quicktime-media-link' => ['qtl'], 'application/x-quicktimeplayer' => ['qtl'], 'application/x-qw' => ['qif'], 'application/x-rar' => ['rar'], 'application/x-rar-compressed' => ['rar'], 'application/x-raw-disk-image' => ['raw-disk-image', 'img'], 'application/x-raw-disk-image-xz-compressed' => ['raw-disk-image.xz', 'img.xz'], 'application/x-raw-floppy-disk-image' => ['fd', 'qd'], 'application/x-redhat-package-manager' => ['rpm'], 'application/x-reject' => ['rej'], 'application/x-research-info-systems' => ['ris'], 'application/x-rnc' => ['rnc'], 'application/x-rpm' => ['rpm'], 'application/x-ruby' => ['rb'], 'application/x-sami' => ['smi', 'sami'], 'application/x-sap-file' => ['sap'], 'application/x-saturn-rom' => ['iso'], 'application/x-sdp' => ['sdp'], 'application/x-sea' => ['sea'], 'application/x-sega-cd-rom' => ['iso'], 'application/x-sega-pico-rom' => ['iso'], 'application/x-sg1000-rom' => ['sg'], 'application/x-sh' => ['sh'], 'application/x-shar' => ['shar'], 'application/x-shared-library-la' => ['la'], 'application/x-sharedlib' => ['so'], 'application/x-shellscript' => ['sh'], 'application/x-shockwave-flash' => ['swf', 'spl'], 'application/x-shorten' => ['shn'], 'application/x-siag' => ['siag'], 'application/x-silverlight-app' => ['xap'], 'application/x-sit' => ['sit'], 'application/x-smaf' => ['mmf', 'smaf'], 'application/x-sms-rom' => ['sms'], 'application/x-snes-rom' => ['sfc', 'smc'], 'application/x-source-rpm' => ['src.rpm', 'spm'], 'application/x-spss-por' => ['por'], 'application/x-spss-sav' => ['sav', 'zsav'], 'application/x-spss-savefile' => ['sav', 'zsav'], 'application/x-sql' => ['sql'], 'application/x-sqlite2' => ['sqlite2'], 'application/x-sqlite3' => ['sqlite3'], 'application/x-srt' => ['srt'], 'application/x-stuffit' => ['sit'], 'application/x-stuffitx' => ['sitx'], 'application/x-subrip' => ['srt'], 'application/x-sv4cpio' => ['sv4cpio'], 'application/x-sv4crc' => ['sv4crc'], 'application/x-t3vm-image' => ['t3'], 'application/x-t602' => ['602'], 'application/x-tads' => ['gam'], 'application/x-tar' => ['tar', 'gtar', 'gem'], 'application/x-targa' => ['tga', 'icb', 'tpic', 'vda', 'vst'], 'application/x-tarz' => ['tar.Z', 'taz'], 'application/x-tcl' => ['tcl', 'tk'], 'application/x-tex' => ['tex', 'ltx', 'sty', 'cls', 'dtx', 'ins', 'latex'], 'application/x-tex-gf' => ['gf'], 'application/x-tex-pk' => ['pk'], 'application/x-tex-tfm' => ['tfm'], 'application/x-texinfo' => ['texinfo', 'texi'], 'application/x-tga' => ['tga', 'icb', 'tpic', 'vda', 'vst'], 'application/x-tgif' => ['obj'], 'application/x-theme' => ['theme'], 'application/x-thomson-cartridge-memo7' => ['m7'], 'application/x-thomson-cassette' => ['k7'], 'application/x-thomson-sap-image' => ['sap'], 'application/x-trash' => ['bak', 'old', 'sik'], 'application/x-trig' => ['trig'], 'application/x-troff' => ['tr', 'roff', 't'], 'application/x-troff-man' => ['man'], 'application/x-tzo' => ['tar.lzo', 'tzo'], 'application/x-ufraw' => ['ufraw'], 'application/x-ustar' => ['ustar'], 'application/x-vdi-disk' => ['vdi'], 'application/x-vhd-disk' => ['vhd', 'vpc'], 'application/x-vhdx-disk' => ['vhdx'], 'application/x-virtual-boy-rom' => ['vb'], 'application/x-virtualbox-hdd' => ['hdd'], 'application/x-virtualbox-ova' => ['ova'], 'application/x-virtualbox-ovf' => ['ovf'], 'application/x-virtualbox-vbox' => ['vbox'], 'application/x-virtualbox-vbox-extpack' => ['vbox-extpack'], 'application/x-virtualbox-vdi' => ['vdi'], 'application/x-virtualbox-vhd' => ['vhd', 'vpc'], 'application/x-virtualbox-vhdx' => ['vhdx'], 'application/x-virtualbox-vmdk' => ['vmdk'], 'application/x-vmdk-disk' => ['vmdk'], 'application/x-vnd.kde.kexi' => ['kexi'], 'application/x-wais-source' => ['src'], 'application/x-wbfs' => ['iso'], 'application/x-web-app-manifest+json' => ['webapp'], 'application/x-wia' => ['iso'], 'application/x-wii-iso-image' => ['iso'], 'application/x-wii-rom' => ['iso'], 'application/x-wii-wad' => ['wad'], 'application/x-windows-themepack' => ['themepack'], 'application/x-wmf' => ['wmf'], 'application/x-wonderswan-color-rom' => ['wsc'], 'application/x-wonderswan-rom' => ['ws'], 'application/x-wordperfect' => ['wp', 'wp4', 'wp5', 'wp6', 'wpd', 'wpp'], 'application/x-wpg' => ['wpg'], 'application/x-wwf' => ['wwf'], 'application/x-x509-ca-cert' => ['der', 'crt', 'pem', 'cert'], 'application/x-xar' => ['xar', 'pkg'], 'application/x-xbel' => ['xbel'], 'application/x-xfig' => ['fig'], 'application/x-xliff' => ['xlf', 'xliff'], 'application/x-xliff+xml' => ['xlf'], 'application/x-xpinstall' => ['xpi'], 'application/x-xspf+xml' => ['xspf'], 'application/x-xz' => ['xz'], 'application/x-xz-compressed-tar' => ['tar.xz', 'txz'], 'application/x-xzpdf' => ['pdf.xz'], 'application/x-yaml' => ['yaml', 'yml'], 'application/x-zip' => ['zip'], 'application/x-zip-compressed' => ['zip'], 'application/x-zip-compressed-fb2' => ['fb2.zip'], 'application/x-zmachine' => ['z1', 'z2', 'z3', 'z4', 'z5', 'z6', 'z7', 'z8'], 'application/x-zoo' => ['zoo'], 'application/x-zstd-compressed-tar' => ['tar.zst', 'tzst'], 'application/xaml+xml' => ['xaml'], 'application/xcap-att+xml' => ['xav'], 'application/xcap-caps+xml' => ['xca'], 'application/xcap-diff+xml' => ['xdf'], 'application/xcap-el+xml' => ['xel'], 'application/xcap-error+xml' => ['xer'], 'application/xcap-ns+xml' => ['xns'], 'application/xenc+xml' => ['xenc'], 'application/xhtml+xml' => ['xhtml', 'xht', 'html', 'htm'], 'application/xliff+xml' => ['xlf', 'xliff'], 'application/xml' => ['xml', 'xsl', 'xsd', 'rng', 'xbl'], 'application/xml-dtd' => ['dtd'], 'application/xml-external-parsed-entity' => ['ent'], 'application/xop+xml' => ['xop'], 'application/xproc+xml' => ['xpl'], 'application/xps' => ['xps'], 'application/xslt+xml' => ['xsl', 'xslt'], 'application/xspf+xml' => ['xspf'], 'application/xv+xml' => ['mxml', 'xhvml', 'xvml', 'xvm'], 'application/yang' => ['yang'], 'application/yin+xml' => ['yin'], 'application/zip' => ['zip'], 'application/zlib' => ['zz'], 'application/zstd' => ['zst'], 'audio/3gpp' => ['3gpp', '3gp', '3ga'], 'audio/3gpp-encrypted' => ['3gp', '3gpp', '3ga'], 'audio/3gpp2' => ['3g2', '3gp2', '3gpp2'], 'audio/aac' => ['aac', 'adts', 'ass'], 'audio/ac3' => ['ac3'], 'audio/adpcm' => ['adp'], 'audio/amr' => ['amr'], 'audio/amr-encrypted' => ['amr'], 'audio/amr-wb' => ['awb'], 'audio/amr-wb-encrypted' => ['awb'], 'audio/annodex' => ['axa'], 'audio/basic' => ['au', 'snd'], 'audio/flac' => ['flac'], 'audio/imelody' => ['imy', 'ime'], 'audio/m3u' => ['m3u', 'm3u8', 'vlc'], 'audio/m4a' => ['m4a', 'f4a'], 'audio/midi' => ['mid', 'midi', 'kar', 'rmi'], 'audio/mobile-xmf' => ['mxmf', 'xmf'], 'audio/mp2' => ['mp2'], 'audio/mp3' => ['mp3', 'mpga'], 'audio/mp4' => ['m4a', 'mp4a', 'f4a'], 'audio/mpeg' => ['mp3', 'mpga', 'mp2', 'mp2a', 'm2a', 'm3a'], 'audio/mpegurl' => ['m3u', 'm3u8', 'vlc'], 'audio/ogg' => ['ogg', 'oga', 'spx', 'opus'], 'audio/prs.sid' => ['sid', 'psid'], 'audio/s3m' => ['s3m'], 'audio/scpls' => ['pls'], 'audio/silk' => ['sil'], 'audio/tta' => ['tta'], 'audio/usac' => ['loas', 'xhe'], 'audio/vnd.audible' => ['aa', 'aax'], 'audio/vnd.audible.aax' => ['aax'], 'audio/vnd.dece.audio' => ['uva', 'uvva'], 'audio/vnd.digital-winds' => ['eol'], 'audio/vnd.dra' => ['dra'], 'audio/vnd.dts' => ['dts'], 'audio/vnd.dts.hd' => ['dtshd'], 'audio/vnd.lucent.voice' => ['lvp'], 'audio/vnd.m-realaudio' => ['ra', 'rax'], 'audio/vnd.ms-playready.media.pya' => ['pya'], 'audio/vnd.nuera.ecelp4800' => ['ecelp4800'], 'audio/vnd.nuera.ecelp7470' => ['ecelp7470'], 'audio/vnd.nuera.ecelp9600' => ['ecelp9600'], 'audio/vnd.rip' => ['rip'], 'audio/vnd.rn-realaudio' => ['ra', 'rax'], 'audio/vnd.wave' => ['wav'], 'audio/vorbis' => ['oga', 'ogg'], 'audio/wav' => ['wav'], 'audio/wave' => ['wav'], 'audio/webm' => ['weba'], 'audio/wma' => ['wma'], 'audio/x-aac' => ['aac', 'adts', 'ass'], 'audio/x-aifc' => ['aifc', 'aiffc'], 'audio/x-aiff' => ['aif', 'aiff', 'aifc'], 'audio/x-aiffc' => ['aifc', 'aiffc'], 'audio/x-amzxml' => ['amz'], 'audio/x-annodex' => ['axa'], 'audio/x-ape' => ['ape'], 'audio/x-caf' => ['caf'], 'audio/x-dts' => ['dts'], 'audio/x-dtshd' => ['dtshd'], 'audio/x-flac' => ['flac'], 'audio/x-flac+ogg' => ['oga', 'ogg'], 'audio/x-gsm' => ['gsm'], 'audio/x-hx-aac-adts' => ['aac', 'adts', 'ass'], 'audio/x-imelody' => ['imy', 'ime'], 'audio/x-iriver-pla' => ['pla'], 'audio/x-it' => ['it'], 'audio/x-m3u' => ['m3u', 'm3u8', 'vlc'], 'audio/x-m4a' => ['m4a', 'f4a'], 'audio/x-m4b' => ['m4b', 'f4b'], 'audio/x-m4r' => ['m4r'], 'audio/x-matroska' => ['mka'], 'audio/x-midi' => ['mid', 'midi', 'kar'], 'audio/x-minipsf' => ['minipsf'], 'audio/x-mo3' => ['mo3'], 'audio/x-mod' => ['mod', 'ult', 'uni', 'm15', 'mtm', '669', 'med'], 'audio/x-mp2' => ['mp2'], 'audio/x-mp3' => ['mp3', 'mpga'], 'audio/x-mp3-playlist' => ['m3u', 'm3u8', 'vlc'], 'audio/x-mpeg' => ['mp3', 'mpga'], 'audio/x-mpegurl' => ['m3u', 'm3u8', 'vlc'], 'audio/x-mpg' => ['mp3', 'mpga'], 'audio/x-ms-asx' => ['asx', 'wax', 'wvx', 'wmx'], 'audio/x-ms-wax' => ['wax'], 'audio/x-ms-wma' => ['wma'], 'audio/x-ms-wmv' => ['wmv'], 'audio/x-musepack' => ['mpc', 'mpp', 'mp+'], 'audio/x-ogg' => ['oga', 'ogg', 'opus'], 'audio/x-oggflac' => ['oga', 'ogg'], 'audio/x-opus+ogg' => ['opus'], 'audio/x-pn-audibleaudio' => ['aa', 'aax'], 'audio/x-pn-realaudio' => ['ram', 'ra', 'rax'], 'audio/x-pn-realaudio-plugin' => ['rmp'], 'audio/x-psf' => ['psf'], 'audio/x-psflib' => ['psflib'], 'audio/x-realaudio' => ['ra'], 'audio/x-rn-3gpp-amr' => ['3gp', '3gpp', '3ga'], 'audio/x-rn-3gpp-amr-encrypted' => ['3gp', '3gpp', '3ga'], 'audio/x-rn-3gpp-amr-wb' => ['3gp', '3gpp', '3ga'], 'audio/x-rn-3gpp-amr-wb-encrypted' => ['3gp', '3gpp', '3ga'], 'audio/x-s3m' => ['s3m'], 'audio/x-scpls' => ['pls'], 'audio/x-shorten' => ['shn'], 'audio/x-speex' => ['spx'], 'audio/x-speex+ogg' => ['oga', 'ogg', 'spx'], 'audio/x-stm' => ['stm'], 'audio/x-tta' => ['tta'], 'audio/x-voc' => ['voc'], 'audio/x-vorbis' => ['oga', 'ogg'], 'audio/x-vorbis+ogg' => ['oga', 'ogg'], 'audio/x-wav' => ['wav'], 'audio/x-wavpack' => ['wv', 'wvp'], 'audio/x-wavpack-correction' => ['wvc'], 'audio/x-xi' => ['xi'], 'audio/x-xm' => ['xm'], 'audio/x-xmf' => ['xmf'], 'audio/xm' => ['xm'], 'audio/xmf' => ['xmf'], 'chemical/x-cdx' => ['cdx'], 'chemical/x-cif' => ['cif'], 'chemical/x-cmdf' => ['cmdf'], 'chemical/x-cml' => ['cml'], 'chemical/x-csml' => ['csml'], 'chemical/x-xyz' => ['xyz'], 'flv-application/octet-stream' => ['flv'], 'font/collection' => ['ttc'], 'font/otf' => ['otf'], 'font/ttf' => ['ttf'], 'font/woff' => ['woff'], 'font/woff2' => ['woff2'], 'image/aces' => ['exr'], 'image/apng' => ['apng'], 'image/astc' => ['astc'], 'image/avif' => ['avif', 'avifs'], 'image/avif-sequence' => ['avif', 'avifs'], 'image/bmp' => ['bmp', 'dib'], 'image/cdr' => ['cdr'], 'image/cgm' => ['cgm'], 'image/dicom-rle' => ['drle'], 'image/emf' => ['emf'], 'image/fax-g3' => ['g3'], 'image/fits' => ['fits'], 'image/g3fax' => ['g3'], 'image/gif' => ['gif'], 'image/heic' => ['heic', 'heif'], 'image/heic-sequence' => ['heics', 'heic', 'heif'], 'image/heif' => ['heif', 'heic'], 'image/heif-sequence' => ['heifs', 'heic', 'heif'], 'image/hej2k' => ['hej2'], 'image/hsj2' => ['hsj2'], 'image/ico' => ['ico'], 'image/icon' => ['ico'], 'image/ief' => ['ief'], 'image/jls' => ['jls'], 'image/jp2' => ['jp2', 'jpg2'], 'image/jpeg' => ['jpg', 'jpeg', 'jpe'], 'image/jpeg2000' => ['jp2', 'jpg2'], 'image/jpeg2000-image' => ['jp2', 'jpg2'], 'image/jph' => ['jph'], 'image/jphc' => ['jhc'], 'image/jpm' => ['jpm', 'jpgm'], 'image/jpx' => ['jpx', 'jpf'], 'image/jxl' => ['jxl'], 'image/jxr' => ['jxr'], 'image/jxra' => ['jxra'], 'image/jxrs' => ['jxrs'], 'image/jxs' => ['jxs'], 'image/jxsc' => ['jxsc'], 'image/jxsi' => ['jxsi'], 'image/jxss' => ['jxss'], 'image/ktx' => ['ktx'], 'image/ktx2' => ['ktx2'], 'image/openraster' => ['ora'], 'image/pdf' => ['pdf'], 'image/photoshop' => ['psd'], 'image/pjpeg' => ['jpg', 'jpeg', 'jpe'], 'image/png' => ['png'], 'image/prs.btif' => ['btif'], 'image/prs.pti' => ['pti'], 'image/psd' => ['psd'], 'image/rle' => ['rle'], 'image/sgi' => ['sgi'], 'image/svg' => ['svg'], 'image/svg+xml' => ['svg', 'svgz'], 'image/svg+xml-compressed' => ['svgz'], 'image/t38' => ['t38'], 'image/targa' => ['tga', 'icb', 'tpic', 'vda', 'vst'], 'image/tga' => ['tga', 'icb', 'tpic', 'vda', 'vst'], 'image/tiff' => ['tif', 'tiff'], 'image/tiff-fx' => ['tfx'], 'image/vnd.adobe.photoshop' => ['psd'], 'image/vnd.airzip.accelerator.azv' => ['azv'], 'image/vnd.dece.graphic' => ['uvi', 'uvvi', 'uvg', 'uvvg'], 'image/vnd.djvu' => ['djvu', 'djv'], 'image/vnd.djvu+multipage' => ['djvu', 'djv'], 'image/vnd.dvb.subtitle' => ['sub'], 'image/vnd.dwg' => ['dwg'], 'image/vnd.dxf' => ['dxf'], 'image/vnd.fastbidsheet' => ['fbs'], 'image/vnd.fpx' => ['fpx'], 'image/vnd.fst' => ['fst'], 'image/vnd.fujixerox.edmics-mmr' => ['mmr'], 'image/vnd.fujixerox.edmics-rlc' => ['rlc'], 'image/vnd.microsoft.icon' => ['ico'], 'image/vnd.ms-dds' => ['dds'], 'image/vnd.ms-modi' => ['mdi'], 'image/vnd.ms-photo' => ['wdp'], 'image/vnd.net-fpx' => ['npx'], 'image/vnd.pco.b16' => ['b16'], 'image/vnd.rn-realpix' => ['rp'], 'image/vnd.tencent.tap' => ['tap'], 'image/vnd.valve.source.texture' => ['vtf'], 'image/vnd.wap.wbmp' => ['wbmp'], 'image/vnd.xiff' => ['xif'], 'image/vnd.zbrush.pcx' => ['pcx'], 'image/webp' => ['webp'], 'image/wmf' => ['wmf'], 'image/x-3ds' => ['3ds'], 'image/x-adobe-dng' => ['dng'], 'image/x-applix-graphics' => ['ag'], 'image/x-bmp' => ['bmp', 'dib'], 'image/x-bzeps' => ['eps.bz2', 'epsi.bz2', 'epsf.bz2'], 'image/x-canon-cr2' => ['cr2'], 'image/x-canon-cr3' => ['cr3'], 'image/x-canon-crw' => ['crw'], 'image/x-cdr' => ['cdr'], 'image/x-cmu-raster' => ['ras'], 'image/x-cmx' => ['cmx'], 'image/x-compressed-xcf' => ['xcf.gz', 'xcf.bz2'], 'image/x-dds' => ['dds'], 'image/x-djvu' => ['djvu', 'djv'], 'image/x-emf' => ['emf'], 'image/x-eps' => ['eps', 'epsi', 'epsf'], 'image/x-exr' => ['exr'], 'image/x-fits' => ['fits'], 'image/x-freehand' => ['fh', 'fhc', 'fh4', 'fh5', 'fh7'], 'image/x-fuji-raf' => ['raf'], 'image/x-gimp-gbr' => ['gbr'], 'image/x-gimp-gih' => ['gih'], 'image/x-gimp-pat' => ['pat'], 'image/x-gzeps' => ['eps.gz', 'epsi.gz', 'epsf.gz'], 'image/x-icb' => ['tga', 'icb', 'tpic', 'vda', 'vst'], 'image/x-icns' => ['icns'], 'image/x-ico' => ['ico'], 'image/x-icon' => ['ico'], 'image/x-iff' => ['iff', 'ilbm', 'lbm'], 'image/x-ilbm' => ['iff', 'ilbm', 'lbm'], 'image/x-jng' => ['jng'], 'image/x-jp2-codestream' => ['j2c', 'j2k', 'jpc'], 'image/x-jpeg2000-image' => ['jp2', 'jpg2'], 'image/x-kodak-dcr' => ['dcr'], 'image/x-kodak-k25' => ['k25'], 'image/x-kodak-kdc' => ['kdc'], 'image/x-lwo' => ['lwo', 'lwob'], 'image/x-lws' => ['lws'], 'image/x-macpaint' => ['pntg'], 'image/x-minolta-mrw' => ['mrw'], 'image/x-mrsid-image' => ['sid'], 'image/x-ms-bmp' => ['bmp', 'dib'], 'image/x-msod' => ['msod'], 'image/x-nikon-nef' => ['nef'], 'image/x-nikon-nrw' => ['nrw'], 'image/x-olympus-orf' => ['orf'], 'image/x-panasonic-raw' => ['raw'], 'image/x-panasonic-raw2' => ['rw2'], 'image/x-panasonic-rw' => ['raw'], 'image/x-panasonic-rw2' => ['rw2'], 'image/x-pcx' => ['pcx'], 'image/x-pentax-pef' => ['pef'], 'image/x-photo-cd' => ['pcd'], 'image/x-photoshop' => ['psd'], 'image/x-pict' => ['pic', 'pct', 'pict', 'pict1', 'pict2'], 'image/x-portable-anymap' => ['pnm'], 'image/x-portable-bitmap' => ['pbm'], 'image/x-portable-graymap' => ['pgm'], 'image/x-portable-pixmap' => ['ppm'], 'image/x-psd' => ['psd'], 'image/x-quicktime' => ['qtif', 'qif'], 'image/x-rgb' => ['rgb'], 'image/x-sgi' => ['sgi'], 'image/x-sigma-x3f' => ['x3f'], 'image/x-skencil' => ['sk', 'sk1'], 'image/x-sony-arw' => ['arw'], 'image/x-sony-sr2' => ['sr2'], 'image/x-sony-srf' => ['srf'], 'image/x-sun-raster' => ['sun'], 'image/x-targa' => ['tga', 'icb', 'tpic', 'vda', 'vst'], 'image/x-tga' => ['tga', 'icb', 'tpic', 'vda', 'vst'], 'image/x-win-bitmap' => ['cur'], 'image/x-win-metafile' => ['wmf'], 'image/x-wmf' => ['wmf'], 'image/x-xbitmap' => ['xbm'], 'image/x-xcf' => ['xcf'], 'image/x-xfig' => ['fig'], 'image/x-xpixmap' => ['xpm'], 'image/x-xpm' => ['xpm'], 'image/x-xwindowdump' => ['xwd'], 'image/x.djvu' => ['djvu', 'djv'], 'message/disposition-notification' => ['disposition-notification'], 'message/global' => ['u8msg'], 'message/global-delivery-status' => ['u8dsn'], 'message/global-disposition-notification' => ['u8mdn'], 'message/global-headers' => ['u8hdr'], 'message/rfc822' => ['eml', 'mime'], 'message/vnd.wfa.wsc' => ['wsc'], 'model/3mf' => ['3mf'], 'model/gltf+json' => ['gltf'], 'model/gltf-binary' => ['glb'], 'model/iges' => ['igs', 'iges'], 'model/mesh' => ['msh', 'mesh', 'silo'], 'model/mtl' => ['mtl'], 'model/obj' => ['obj'], 'model/step+zip' => ['stpz'], 'model/step-xml+zip' => ['stpxz'], 'model/stl' => ['stl'], 'model/vnd.collada+xml' => ['dae'], 'model/vnd.dwf' => ['dwf'], 'model/vnd.gdl' => ['gdl'], 'model/vnd.gtw' => ['gtw'], 'model/vnd.mts' => ['mts'], 'model/vnd.opengex' => ['ogex'], 'model/vnd.parasolid.transmit.binary' => ['x_b'], 'model/vnd.parasolid.transmit.text' => ['x_t'], 'model/vnd.sap.vds' => ['vds'], 'model/vnd.usdz+zip' => ['usdz'], 'model/vnd.valve.source.compiled-map' => ['bsp'], 'model/vnd.vtu' => ['vtu'], 'model/vrml' => ['wrl', 'vrml', 'vrm'], 'model/x.stl-ascii' => ['stl'], 'model/x.stl-binary' => ['stl'], 'model/x3d+binary' => ['x3db', 'x3dbz'], 'model/x3d+fastinfoset' => ['x3db'], 'model/x3d+vrml' => ['x3dv', 'x3dvz'], 'model/x3d+xml' => ['x3d', 'x3dz'], 'model/x3d-vrml' => ['x3dv'], 'text/cache-manifest' => ['appcache', 'manifest'], 'text/calendar' => ['ics', 'ifb', 'vcs'], 'text/coffeescript' => ['coffee', 'litcoffee'], 'text/crystal' => ['cr'], 'text/css' => ['css'], 'text/csv' => ['csv'], 'text/csv-schema' => ['csvs'], 'text/directory' => ['vcard', 'vcf', 'vct', 'gcrd'], 'text/ecmascript' => ['es'], 'text/gedcom' => ['ged', 'gedcom'], 'text/google-video-pointer' => ['gvp'], 'text/html' => ['html', 'htm', 'shtml'], 'text/ico' => ['ico'], 'text/jade' => ['jade'], 'text/javascript' => ['js', 'jsm', 'mjs'], 'text/jsx' => ['jsx'], 'text/less' => ['less'], 'text/markdown' => ['md', 'markdown', 'mkd'], 'text/mathml' => ['mml'], 'text/mdx' => ['mdx'], 'text/n3' => ['n3'], 'text/org' => ['org'], 'text/plain' => ['txt', 'text', 'conf', 'def', 'list', 'log', 'in', 'ini', 'asc'], 'text/prs.lines.tag' => ['dsc'], 'text/rdf' => ['rdf', 'rdfs', 'owl'], 'text/richtext' => ['rtx'], 'text/rss' => ['rss'], 'text/rtf' => ['rtf'], 'text/rust' => ['rs'], 'text/sgml' => ['sgml', 'sgm'], 'text/shex' => ['shex'], 'text/slim' => ['slim', 'slm'], 'text/spdx' => ['spdx'], 'text/spreadsheet' => ['sylk', 'slk'], 'text/stylus' => ['stylus', 'styl'], 'text/tab-separated-values' => ['tsv'], 'text/tcl' => ['tcl', 'tk'], 'text/troff' => ['t', 'tr', 'roff', 'man', 'me', 'ms'], 'text/turtle' => ['ttl'], 'text/uri-list' => ['uri', 'uris', 'urls'], 'text/vbs' => ['vbs'], 'text/vbscript' => ['vbs'], 'text/vcard' => ['vcard', 'vcf', 'vct', 'gcrd'], 'text/vnd.curl' => ['curl'], 'text/vnd.curl.dcurl' => ['dcurl'], 'text/vnd.curl.mcurl' => ['mcurl'], 'text/vnd.curl.scurl' => ['scurl'], 'text/vnd.dvb.subtitle' => ['sub'], 'text/vnd.fly' => ['fly'], 'text/vnd.fmi.flexstor' => ['flx'], 'text/vnd.graphviz' => ['gv', 'dot'], 'text/vnd.in3d.3dml' => ['3dml'], 'text/vnd.in3d.spot' => ['spot'], 'text/vnd.qt.linguist' => ['ts'], 'text/vnd.rn-realtext' => ['rt'], 'text/vnd.senx.warpscript' => ['mc2'], 'text/vnd.sun.j2me.app-descriptor' => ['jad'], 'text/vnd.trolltech.linguist' => ['ts'], 'text/vnd.wap.wml' => ['wml'], 'text/vnd.wap.wmlscript' => ['wmls'], 'text/vtt' => ['vtt'], 'text/x-adasrc' => ['adb', 'ads'], 'text/x-asm' => ['s', 'asm'], 'text/x-bibtex' => ['bib'], 'text/x-c' => ['c', 'cc', 'cxx', 'cpp', 'h', 'hh', 'dic'], 'text/x-c++hdr' => ['hh', 'hp', 'hpp', 'h++', 'hxx'], 'text/x-c++src' => ['cpp', 'cxx', 'cc', 'C', 'c++'], 'text/x-chdr' => ['h'], 'text/x-cmake' => ['cmake'], 'text/x-cobol' => ['cbl', 'cob'], 'text/x-comma-separated-values' => ['csv'], 'text/x-common-lisp' => ['asd', 'fasl', 'lisp', 'ros'], 'text/x-component' => ['htc'], 'text/x-crystal' => ['cr'], 'text/x-csharp' => ['cs'], 'text/x-csrc' => ['c'], 'text/x-csv' => ['csv'], 'text/x-dart' => ['dart'], 'text/x-dbus-service' => ['service'], 'text/x-dcl' => ['dcl'], 'text/x-diff' => ['diff', 'patch'], 'text/x-dsl' => ['dsl'], 'text/x-dsrc' => ['d', 'di'], 'text/x-dtd' => ['dtd'], 'text/x-eiffel' => ['e', 'eif'], 'text/x-elixir' => ['ex', 'exs'], 'text/x-emacs-lisp' => ['el'], 'text/x-erlang' => ['erl'], 'text/x-fortran' => ['f', 'for', 'f77', 'f90', 'f95'], 'text/x-genie' => ['gs'], 'text/x-gettext-translation' => ['po'], 'text/x-gettext-translation-template' => ['pot'], 'text/x-gherkin' => ['feature'], 'text/x-go' => ['go'], 'text/x-google-video-pointer' => ['gvp'], 'text/x-gradle' => ['gradle'], 'text/x-groovy' => ['groovy', 'gvy', 'gy', 'gsh'], 'text/x-handlebars-template' => ['hbs'], 'text/x-haskell' => ['hs'], 'text/x-idl' => ['idl'], 'text/x-imelody' => ['imy', 'ime'], 'text/x-iptables' => ['iptables'], 'text/x-java' => ['java'], 'text/x-java-source' => ['java'], 'text/x-kaitai-struct' => ['ksy'], 'text/x-kotlin' => ['kt'], 'text/x-ldif' => ['ldif'], 'text/x-lilypond' => ['ly'], 'text/x-literate-haskell' => ['lhs'], 'text/x-log' => ['log'], 'text/x-lua' => ['lua'], 'text/x-lyx' => ['lyx'], 'text/x-makefile' => ['mk', 'mak'], 'text/x-markdown' => ['md', 'mkd', 'markdown'], 'text/x-matlab' => ['m'], 'text/x-microdvd' => ['sub'], 'text/x-moc' => ['moc'], 'text/x-modelica' => ['mo'], 'text/x-mof' => ['mof'], 'text/x-mpsub' => ['sub'], 'text/x-mrml' => ['mrml', 'mrl'], 'text/x-ms-regedit' => ['reg'], 'text/x-mup' => ['mup', 'not'], 'text/x-nfo' => ['nfo'], 'text/x-objcsrc' => ['m'], 'text/x-ocaml' => ['ml', 'mli'], 'text/x-ocl' => ['ocl'], 'text/x-octave' => ['m'], 'text/x-ooc' => ['ooc'], 'text/x-opencl-src' => ['cl'], 'text/x-opml' => ['opml'], 'text/x-opml+xml' => ['opml'], 'text/x-org' => ['org'], 'text/x-pascal' => ['p', 'pas'], 'text/x-patch' => ['diff', 'patch'], 'text/x-perl' => ['pl', 'PL', 'pm', 'al', 'perl', 'pod', 't'], 'text/x-po' => ['po'], 'text/x-pot' => ['pot'], 'text/x-processing' => ['pde'], 'text/x-python' => ['py', 'pyx', 'wsgi'], 'text/x-python3' => ['py', 'py3', 'py3x', 'pyi'], 'text/x-qml' => ['qml', 'qmltypes', 'qmlproject'], 'text/x-reject' => ['rej'], 'text/x-rpm-spec' => ['spec'], 'text/x-rst' => ['rst'], 'text/x-sagemath' => ['sage'], 'text/x-sass' => ['sass'], 'text/x-scala' => ['scala', 'sc'], 'text/x-scheme' => ['scm', 'ss'], 'text/x-scss' => ['scss'], 'text/x-setext' => ['etx'], 'text/x-sfv' => ['sfv'], 'text/x-sh' => ['sh'], 'text/x-sql' => ['sql'], 'text/x-ssa' => ['ssa', 'ass'], 'text/x-subviewer' => ['sub'], 'text/x-suse-ymp' => ['ymp'], 'text/x-svhdr' => ['svh'], 'text/x-svsrc' => ['sv'], 'text/x-systemd-unit' => ['automount', 'device', 'mount', 'path', 'scope', 'service', 'slice', 'socket', 'swap', 'target', 'timer'], 'text/x-tcl' => ['tcl', 'tk'], 'text/x-tex' => ['tex', 'ltx', 'sty', 'cls', 'dtx', 'ins', 'latex'], 'text/x-texinfo' => ['texi', 'texinfo'], 'text/x-troff' => ['tr', 'roff', 't'], 'text/x-troff-me' => ['me'], 'text/x-troff-mm' => ['mm'], 'text/x-troff-ms' => ['ms'], 'text/x-twig' => ['twig'], 'text/x-txt2tags' => ['t2t'], 'text/x-uil' => ['uil'], 'text/x-uuencode' => ['uu', 'uue'], 'text/x-vala' => ['vala', 'vapi'], 'text/x-vcalendar' => ['vcs', 'ics'], 'text/x-vcard' => ['vcf', 'vcard', 'vct', 'gcrd'], 'text/x-verilog' => ['v'], 'text/x-vhdl' => ['vhd', 'vhdl'], 'text/x-xmi' => ['xmi'], 'text/x-xslfo' => ['fo', 'xslfo'], 'text/x-yaml' => ['yaml', 'yml'], 'text/x.gcode' => ['gcode'], 'text/xml' => ['xml', 'xbl', 'xsd', 'rng'], 'text/xml-external-parsed-entity' => ['ent'], 'text/yaml' => ['yaml', 'yml'], 'video/3gp' => ['3gp', '3gpp', '3ga'], 'video/3gpp' => ['3gp', '3gpp', '3ga'], 'video/3gpp-encrypted' => ['3gp', '3gpp', '3ga'], 'video/3gpp2' => ['3g2', '3gp2', '3gpp2'], 'video/annodex' => ['axv'], 'video/avi' => ['avi', 'avf', 'divx'], 'video/divx' => ['avi', 'avf', 'divx'], 'video/dv' => ['dv'], 'video/fli' => ['fli', 'flc'], 'video/flv' => ['flv'], 'video/h261' => ['h261'], 'video/h263' => ['h263'], 'video/h264' => ['h264'], 'video/iso.segment' => ['m4s'], 'video/jpeg' => ['jpgv'], 'video/jpm' => ['jpm', 'jpgm'], 'video/mj2' => ['mj2', 'mjp2'], 'video/mp2t' => ['ts', 'm2t', 'm2ts', 'mts', 'cpi', 'clpi', 'mpl', 'mpls', 'bdm', 'bdmv'], 'video/mp4' => ['mp4', 'mp4v', 'mpg4', 'm4v', 'f4v', 'lrv'], 'video/mp4v-es' => ['mp4', 'm4v', 'f4v', 'lrv'], 'video/mpeg' => ['mpeg', 'mpg', 'mpe', 'm1v', 'm2v', 'mp2', 'vob'], 'video/mpeg-system' => ['mpeg', 'mpg', 'mp2', 'mpe', 'vob'], 'video/msvideo' => ['avi', 'avf', 'divx'], 'video/ogg' => ['ogv', 'ogg'], 'video/quicktime' => ['mov', 'qt', 'moov', 'qtvr'], 'video/vivo' => ['viv', 'vivo'], 'video/vnd.dece.hd' => ['uvh', 'uvvh'], 'video/vnd.dece.mobile' => ['uvm', 'uvvm'], 'video/vnd.dece.pd' => ['uvp', 'uvvp'], 'video/vnd.dece.sd' => ['uvs', 'uvvs'], 'video/vnd.dece.video' => ['uvv', 'uvvv'], 'video/vnd.divx' => ['avi', 'avf', 'divx'], 'video/vnd.dvb.file' => ['dvb'], 'video/vnd.fvt' => ['fvt'], 'video/vnd.mpegurl' => ['mxu', 'm4u', 'm1u'], 'video/vnd.ms-playready.media.pyv' => ['pyv'], 'video/vnd.radgamettools.bink' => ['bik', 'bk2'], 'video/vnd.radgamettools.smacker' => ['smk'], 'video/vnd.rn-realvideo' => ['rv', 'rvx'], 'video/vnd.uvvu.mp4' => ['uvu', 'uvvu'], 'video/vnd.vivo' => ['viv', 'vivo'], 'video/webm' => ['webm'], 'video/x-anim' => ['anim[1-9j]'], 'video/x-annodex' => ['axv'], 'video/x-avi' => ['avi', 'avf', 'divx'], 'video/x-f4v' => ['f4v'], 'video/x-fli' => ['fli', 'flc'], 'video/x-flic' => ['fli', 'flc'], 'video/x-flv' => ['flv'], 'video/x-javafx' => ['fxm'], 'video/x-m4v' => ['m4v', 'mp4', 'f4v', 'lrv'], 'video/x-matroska' => ['mkv', 'mk3d', 'mks'], 'video/x-matroska-3d' => ['mk3d'], 'video/x-mjpeg' => ['mjpeg', 'mjpg'], 'video/x-mng' => ['mng'], 'video/x-mpeg' => ['mpeg', 'mpg', 'mp2', 'mpe', 'vob'], 'video/x-mpeg-system' => ['mpeg', 'mpg', 'mp2', 'mpe', 'vob'], 'video/x-mpeg2' => ['mpeg', 'mpg', 'mp2', 'mpe', 'vob'], 'video/x-mpegurl' => ['m1u', 'm4u', 'mxu'], 'video/x-ms-asf' => ['asf', 'asx'], 'video/x-ms-asf-plugin' => ['asf'], 'video/x-ms-vob' => ['vob'], 'video/x-ms-wax' => ['asx', 'wax', 'wvx', 'wmx'], 'video/x-ms-wm' => ['wm', 'asf'], 'video/x-ms-wmv' => ['wmv'], 'video/x-ms-wmx' => ['wmx', 'asx', 'wax', 'wvx'], 'video/x-ms-wvx' => ['wvx', 'asx', 'wax', 'wmx'], 'video/x-msvideo' => ['avi', 'avf', 'divx'], 'video/x-nsv' => ['nsv'], 'video/x-ogg' => ['ogv', 'ogg'], 'video/x-ogm' => ['ogm'], 'video/x-ogm+ogg' => ['ogm'], 'video/x-real-video' => ['rv', 'rvx'], 'video/x-sgi-movie' => ['movie'], 'video/x-smv' => ['smv'], 'video/x-theora' => ['ogg'], 'video/x-theora+ogg' => ['ogg'], 'x-conference/x-cooltalk' => ['ice'], 'x-epoc/x-sisx-app' => ['sisx'], 'zz-application/zz-winassoc-123' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], 'zz-application/zz-winassoc-cab' => ['cab'], 'zz-application/zz-winassoc-cdr' => ['cdr'], 'zz-application/zz-winassoc-doc' => ['doc'], 'zz-application/zz-winassoc-hlp' => ['hlp'], 'zz-application/zz-winassoc-mdb' => ['mdb'], 'zz-application/zz-winassoc-uu' => ['uue'], 'zz-application/zz-winassoc-xls' => ['xls', 'xlc', 'xll', 'xlm', 'xlw', 'xla', 'xlt', 'xld'], ]; private const REVERSE_MAP = [ '1km' => ['application/vnd.1000minds.decision-model+xml'], '32x' => ['application/x-genesis-32x-rom'], '3dml' => ['text/vnd.in3d.3dml'], '3ds' => ['application/x-nintendo-3ds-rom', 'image/x-3ds'], '3dsx' => ['application/x-nintendo-3ds-executable'], '3g2' => ['audio/3gpp2', 'video/3gpp2'], '3ga' => ['audio/3gpp', 'audio/3gpp-encrypted', 'audio/x-rn-3gpp-amr', 'audio/x-rn-3gpp-amr-encrypted', 'audio/x-rn-3gpp-amr-wb', 'audio/x-rn-3gpp-amr-wb-encrypted', 'video/3gp', 'video/3gpp', 'video/3gpp-encrypted'], '3gp' => ['audio/3gpp', 'audio/3gpp-encrypted', 'audio/x-rn-3gpp-amr', 'audio/x-rn-3gpp-amr-encrypted', 'audio/x-rn-3gpp-amr-wb', 'audio/x-rn-3gpp-amr-wb-encrypted', 'video/3gp', 'video/3gpp', 'video/3gpp-encrypted'], '3gp2' => ['audio/3gpp2', 'video/3gpp2'], '3gpp' => ['audio/3gpp', 'audio/3gpp-encrypted', 'audio/x-rn-3gpp-amr', 'audio/x-rn-3gpp-amr-encrypted', 'audio/x-rn-3gpp-amr-wb', 'audio/x-rn-3gpp-amr-wb-encrypted', 'video/3gp', 'video/3gpp', 'video/3gpp-encrypted'], '3gpp2' => ['audio/3gpp2', 'video/3gpp2'], '3mf' => ['model/3mf'], '7z' => ['application/x-7z-compressed'], '7z.001' => ['application/x-7z-compressed'], 'BLEND' => ['application/x-blender'], 'C' => ['text/x-c++src'], 'PAR2' => ['application/x-par2'], 'PL' => ['application/x-perl', 'text/x-perl'], 'Z' => ['application/x-compress'], 'a' => ['application/x-archive'], 'a26' => ['application/x-atari-2600-rom'], 'a78' => ['application/x-atari-7800-rom'], 'aa' => ['audio/vnd.audible', 'audio/x-pn-audibleaudio'], 'aab' => ['application/x-authorware-bin'], 'aac' => ['audio/aac', 'audio/x-aac', 'audio/x-hx-aac-adts'], 'aam' => ['application/x-authorware-map'], 'aas' => ['application/x-authorware-seg'], 'aax' => ['audio/vnd.audible', 'audio/vnd.audible.aax', 'audio/x-pn-audibleaudio'], 'abw' => ['application/x-abiword'], 'abw.CRASHED' => ['application/x-abiword'], 'abw.gz' => ['application/x-abiword'], 'ac' => ['application/pkix-attr-cert', 'application/vnd.nokia.n-gage.ac+xml'], 'ac3' => ['audio/ac3'], 'acc' => ['application/vnd.americandynamics.acc'], 'ace' => ['application/x-ace', 'application/x-ace-compressed'], 'acu' => ['application/vnd.acucobol'], 'acutc' => ['application/vnd.acucorp'], 'adb' => ['text/x-adasrc'], 'adf' => ['application/x-amiga-disk-format'], 'adp' => ['audio/adpcm'], 'ads' => ['text/x-adasrc'], 'adts' => ['audio/aac', 'audio/x-aac', 'audio/x-hx-aac-adts'], 'aep' => ['application/vnd.audiograph'], 'afm' => ['application/x-font-afm', 'application/x-font-type1'], 'afp' => ['application/vnd.ibm.modcap'], 'ag' => ['image/x-applix-graphics'], 'agb' => ['application/x-gba-rom'], 'ahead' => ['application/vnd.ahead.space'], 'ai' => ['application/illustrator', 'application/postscript', 'application/vnd.adobe.illustrator'], 'aif' => ['audio/x-aiff'], 'aifc' => ['audio/x-aifc', 'audio/x-aiff', 'audio/x-aiffc'], 'aiff' => ['audio/x-aiff'], 'aiffc' => ['audio/x-aifc', 'audio/x-aiffc'], 'air' => ['application/vnd.adobe.air-application-installer-package+zip'], 'ait' => ['application/vnd.dvb.ait'], 'al' => ['application/x-perl', 'text/x-perl'], 'alz' => ['application/x-alz'], 'ami' => ['application/vnd.amiga.ami'], 'amr' => ['audio/amr', 'audio/amr-encrypted'], 'amz' => ['audio/x-amzxml'], 'ani' => ['application/x-navi-animation'], 'anim[1-9j]' => ['video/x-anim'], 'anx' => ['application/annodex', 'application/x-annodex'], 'ape' => ['audio/x-ape'], 'apk' => ['application/vnd.android.package-archive'], 'apng' => ['image/apng'], 'appcache' => ['text/cache-manifest'], 'appimage' => ['application/vnd.appimage', 'application/x-iso9660-appimage'], 'application' => ['application/x-ms-application'], 'apr' => ['application/vnd.lotus-approach'], 'ar' => ['application/x-archive'], 'arc' => ['application/x-freearc'], 'arj' => ['application/x-arj'], 'arw' => ['image/x-sony-arw'], 'as' => ['application/x-applix-spreadsheet'], 'asc' => ['application/pgp', 'application/pgp-encrypted', 'application/pgp-keys', 'application/pgp-signature', 'text/plain'], 'asd' => ['text/x-common-lisp'], 'asf' => ['application/vnd.ms-asf', 'video/x-ms-asf', 'video/x-ms-asf-plugin', 'video/x-ms-wm'], 'asice' => ['application/vnd.etsi.asic-e+zip'], 'asm' => ['text/x-asm'], 'aso' => ['application/vnd.accpac.simply.aso'], 'asp' => ['application/x-asp'], 'ass' => ['audio/aac', 'audio/x-aac', 'audio/x-hx-aac-adts', 'text/x-ssa'], 'astc' => ['image/astc'], 'asx' => ['application/x-ms-asx', 'audio/x-ms-asx', 'video/x-ms-asf', 'video/x-ms-wax', 'video/x-ms-wmx', 'video/x-ms-wvx'], 'atc' => ['application/vnd.acucorp'], 'atom' => ['application/atom+xml'], 'atomcat' => ['application/atomcat+xml'], 'atomdeleted' => ['application/atomdeleted+xml'], 'atomsvc' => ['application/atomsvc+xml'], 'atx' => ['application/vnd.antix.game-component'], 'au' => ['audio/basic'], 'automount' => ['text/x-systemd-unit'], 'avf' => ['video/avi', 'video/divx', 'video/msvideo', 'video/vnd.divx', 'video/x-avi', 'video/x-msvideo'], 'avi' => ['video/avi', 'video/divx', 'video/msvideo', 'video/vnd.divx', 'video/x-avi', 'video/x-msvideo'], 'avif' => ['image/avif', 'image/avif-sequence'], 'avifs' => ['image/avif', 'image/avif-sequence'], 'aw' => ['application/applixware', 'application/x-applix-word'], 'awb' => ['audio/amr-wb', 'audio/amr-wb-encrypted'], 'awk' => ['application/x-awk'], 'axa' => ['audio/annodex', 'audio/x-annodex'], 'axv' => ['video/annodex', 'video/x-annodex'], 'azf' => ['application/vnd.airzip.filesecure.azf'], 'azs' => ['application/vnd.airzip.filesecure.azs'], 'azv' => ['image/vnd.airzip.accelerator.azv'], 'azw' => ['application/vnd.amazon.ebook'], 'azw3' => ['application/vnd.amazon.mobi8-ebook', 'application/x-mobi8-ebook'], 'b16' => ['image/vnd.pco.b16'], 'bak' => ['application/x-trash'], 'bat' => ['application/x-msdownload'], 'bcpio' => ['application/x-bcpio'], 'bdf' => ['application/x-font-bdf'], 'bdm' => ['application/vnd.syncml.dm+wbxml', 'video/mp2t'], 'bdmv' => ['video/mp2t'], 'bdoc' => ['application/bdoc', 'application/x-bdoc'], 'bed' => ['application/vnd.realvnc.bed'], 'bh2' => ['application/vnd.fujitsu.oasysprs'], 'bib' => ['text/x-bibtex'], 'bik' => ['video/vnd.radgamettools.bink'], 'bin' => ['application/octet-stream'], 'bk2' => ['video/vnd.radgamettools.bink'], 'blb' => ['application/x-blorb'], 'blend' => ['application/x-blender'], 'blender' => ['application/x-blender'], 'blorb' => ['application/x-blorb'], 'bmi' => ['application/vnd.bmi'], 'bmml' => ['application/vnd.balsamiq.bmml+xml'], 'bmp' => ['image/bmp', 'image/x-bmp', 'image/x-ms-bmp'], 'book' => ['application/vnd.framemaker'], 'box' => ['application/vnd.previewsystems.box'], 'boz' => ['application/x-bzip2'], 'bps' => ['application/x-bps-patch'], 'bsdiff' => ['application/x-bsdiff'], 'bsp' => ['model/vnd.valve.source.compiled-map'], 'btif' => ['image/prs.btif'], 'bz' => ['application/bzip2', 'application/x-bzip', 'application/x-bzip2'], 'bz2' => ['application/x-bz2', 'application/bzip2', 'application/x-bzip', 'application/x-bzip2'], 'c' => ['text/x-c', 'text/x-csrc'], 'c++' => ['text/x-c++src'], 'c11amc' => ['application/vnd.cluetrust.cartomobile-config'], 'c11amz' => ['application/vnd.cluetrust.cartomobile-config-pkg'], 'c4d' => ['application/vnd.clonk.c4group'], 'c4f' => ['application/vnd.clonk.c4group'], 'c4g' => ['application/vnd.clonk.c4group'], 'c4p' => ['application/vnd.clonk.c4group'], 'c4u' => ['application/vnd.clonk.c4group'], 'cab' => ['application/vnd.ms-cab-compressed', 'zz-application/zz-winassoc-cab'], 'caf' => ['audio/x-caf'], 'cap' => ['application/pcap', 'application/vnd.tcpdump.pcap', 'application/x-pcap'], 'car' => ['application/vnd.curl.car'], 'cat' => ['application/vnd.ms-pki.seccat'], 'cb7' => ['application/x-cb7', 'application/x-cbr'], 'cba' => ['application/x-cbr'], 'cbl' => ['text/x-cobol'], 'cbr' => ['application/vnd.comicbook-rar', 'application/x-cbr'], 'cbt' => ['application/x-cbr', 'application/x-cbt'], 'cbz' => ['application/vnd.comicbook+zip', 'application/x-cbr', 'application/x-cbz'], 'cc' => ['text/x-c', 'text/x-c++src'], 'cci' => ['application/x-nintendo-3ds-rom'], 'ccmx' => ['application/x-ccmx'], 'cco' => ['application/x-cocoa'], 'cct' => ['application/x-director'], 'ccxml' => ['application/ccxml+xml'], 'cdbcmsg' => ['application/vnd.contact.cmsg'], 'cdf' => ['application/x-netcdf'], 'cdfx' => ['application/cdfx+xml'], 'cdi' => ['application/x-discjuggler-cd-image'], 'cdkey' => ['application/vnd.mediastation.cdkey'], 'cdmia' => ['application/cdmi-capability'], 'cdmic' => ['application/cdmi-container'], 'cdmid' => ['application/cdmi-domain'], 'cdmio' => ['application/cdmi-object'], 'cdmiq' => ['application/cdmi-queue'], 'cdr' => ['application/cdr', 'application/coreldraw', 'application/vnd.corel-draw', 'application/x-cdr', 'application/x-coreldraw', 'image/cdr', 'image/x-cdr', 'zz-application/zz-winassoc-cdr'], 'cdx' => ['chemical/x-cdx'], 'cdxml' => ['application/vnd.chemdraw+xml'], 'cdy' => ['application/vnd.cinderella'], 'cer' => ['application/pkix-cert'], 'cert' => ['application/x-x509-ca-cert'], 'cfs' => ['application/x-cfs-compressed'], 'cgb' => ['application/x-gameboy-color-rom'], 'cgm' => ['image/cgm'], 'chat' => ['application/x-chat'], 'chd' => ['application/x-mame-chd'], 'chm' => ['application/vnd.ms-htmlhelp', 'application/x-chm'], 'chrt' => ['application/vnd.kde.kchart', 'application/x-kchart'], 'cif' => ['chemical/x-cif'], 'cii' => ['application/vnd.anser-web-certificate-issue-initiation'], 'cil' => ['application/vnd.ms-artgalry'], 'cjs' => ['application/node'], 'cl' => ['text/x-opencl-src'], 'cla' => ['application/vnd.claymore'], 'class' => ['application/java', 'application/java-byte-code', 'application/java-vm', 'application/x-java', 'application/x-java-class', 'application/x-java-vm'], 'clkk' => ['application/vnd.crick.clicker.keyboard'], 'clkp' => ['application/vnd.crick.clicker.palette'], 'clkt' => ['application/vnd.crick.clicker.template'], 'clkw' => ['application/vnd.crick.clicker.wordbank'], 'clkx' => ['application/vnd.crick.clicker'], 'clp' => ['application/x-msclip'], 'clpi' => ['video/mp2t'], 'cls' => ['application/x-tex', 'text/x-tex'], 'cmake' => ['text/x-cmake'], 'cmc' => ['application/vnd.cosmocaller'], 'cmdf' => ['chemical/x-cmdf'], 'cml' => ['chemical/x-cml'], 'cmp' => ['application/vnd.yellowriver-custom-menu'], 'cmx' => ['image/x-cmx'], 'cob' => ['text/x-cobol'], 'cod' => ['application/vnd.rim.cod'], 'coffee' => ['application/vnd.coffeescript', 'text/coffeescript'], 'com' => ['application/x-msdownload'], 'conf' => ['text/plain'], 'cpi' => ['video/mp2t'], 'cpio' => ['application/x-cpio'], 'cpio.gz' => ['application/x-cpio-compressed'], 'cpp' => ['text/x-c', 'text/x-c++src'], 'cpt' => ['application/mac-compactpro'], 'cr' => ['text/crystal', 'text/x-crystal'], 'cr2' => ['image/x-canon-cr2'], 'cr3' => ['image/x-canon-cr3'], 'crd' => ['application/x-mscardfile'], 'crdownload' => ['application/x-partial-download'], 'crl' => ['application/pkix-crl'], 'crt' => ['application/x-x509-ca-cert'], 'crw' => ['image/x-canon-crw'], 'crx' => ['application/x-chrome-extension'], 'cryptonote' => ['application/vnd.rig.cryptonote'], 'cs' => ['text/x-csharp'], 'csh' => ['application/x-csh'], 'csl' => ['application/vnd.citationstyles.style+xml'], 'csml' => ['chemical/x-csml'], 'cso' => ['application/x-compressed-iso'], 'csp' => ['application/vnd.commonspace'], 'css' => ['text/css'], 'cst' => ['application/x-director'], 'csv' => ['text/csv', 'application/csv', 'text/x-comma-separated-values', 'text/x-csv'], 'csvs' => ['text/csv-schema'], 'cu' => ['application/cu-seeme'], 'cue' => ['application/x-cue'], 'cur' => ['image/x-win-bitmap'], 'curl' => ['text/vnd.curl'], 'cwk' => ['application/x-appleworks-document'], 'cww' => ['application/prs.cww'], 'cxt' => ['application/x-director'], 'cxx' => ['text/x-c', 'text/x-c++src'], 'd' => ['text/x-dsrc'], 'dae' => ['model/vnd.collada+xml'], 'daf' => ['application/vnd.mobius.daf'], 'dar' => ['application/x-dar'], 'dart' => ['application/vnd.dart', 'text/x-dart'], 'dataless' => ['application/vnd.fdsn.seed'], 'davmount' => ['application/davmount+xml'], 'dbf' => ['application/dbase', 'application/dbf', 'application/vnd.dbf', 'application/x-dbase', 'application/x-dbf'], 'dbk' => ['application/docbook+xml', 'application/vnd.oasis.docbook+xml', 'application/x-docbook+xml'], 'dc' => ['application/x-dc-rom'], 'dcl' => ['text/x-dcl'], 'dcm' => ['application/dicom'], 'dcr' => ['application/x-director', 'image/x-kodak-dcr'], 'dcurl' => ['text/vnd.curl.dcurl'], 'dd2' => ['application/vnd.oma.dd2+xml'], 'ddd' => ['application/vnd.fujixerox.ddd'], 'ddf' => ['application/vnd.syncml.dmddf+xml'], 'dds' => ['image/vnd.ms-dds', 'image/x-dds'], 'deb' => ['application/vnd.debian.binary-package', 'application/x-deb', 'application/x-debian-package'], 'def' => ['text/plain'], 'der' => ['application/x-x509-ca-cert'], 'desktop' => ['application/x-desktop', 'application/x-gnome-app-info'], 'device' => ['text/x-systemd-unit'], 'dfac' => ['application/vnd.dreamfactory'], 'dgc' => ['application/x-dgc-compressed'], 'di' => ['text/x-dsrc'], 'dia' => ['application/x-dia-diagram'], 'dib' => ['image/bmp', 'image/x-bmp', 'image/x-ms-bmp'], 'dic' => ['text/x-c'], 'diff' => ['text/x-diff', 'text/x-patch'], 'dir' => ['application/x-director'], 'dis' => ['application/vnd.mobius.dis'], 'disposition-notification' => ['message/disposition-notification'], 'divx' => ['video/avi', 'video/divx', 'video/msvideo', 'video/vnd.divx', 'video/x-avi', 'video/x-msvideo'], 'djv' => ['image/vnd.djvu', 'image/vnd.djvu+multipage', 'image/x-djvu', 'image/x.djvu'], 'djvu' => ['image/vnd.djvu', 'image/vnd.djvu+multipage', 'image/x-djvu', 'image/x.djvu'], 'dll' => ['application/x-msdownload'], 'dmg' => ['application/x-apple-diskimage'], 'dmp' => ['application/pcap', 'application/vnd.tcpdump.pcap', 'application/x-pcap'], 'dna' => ['application/vnd.dna'], 'dng' => ['image/x-adobe-dng'], 'doc' => ['application/msword', 'application/vnd.ms-word', 'application/x-msword', 'zz-application/zz-winassoc-doc'], 'docbook' => ['application/docbook+xml', 'application/vnd.oasis.docbook+xml', 'application/x-docbook+xml'], 'docm' => ['application/vnd.ms-word.document.macroenabled.12'], 'docx' => ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'], 'dot' => ['application/msword', 'application/msword-template', 'text/vnd.graphviz'], 'dotm' => ['application/vnd.ms-word.template.macroenabled.12'], 'dotx' => ['application/vnd.openxmlformats-officedocument.wordprocessingml.template'], 'dp' => ['application/vnd.osgi.dp'], 'dpg' => ['application/vnd.dpgraph'], 'dra' => ['audio/vnd.dra'], 'drle' => ['image/dicom-rle'], 'dsc' => ['text/prs.lines.tag'], 'dsl' => ['text/x-dsl'], 'dssc' => ['application/dssc+der'], 'dtb' => ['application/x-dtbook+xml'], 'dtd' => ['application/xml-dtd', 'text/x-dtd'], 'dts' => ['audio/vnd.dts', 'audio/x-dts'], 'dtshd' => ['audio/vnd.dts.hd', 'audio/x-dtshd'], 'dtx' => ['application/x-tex', 'text/x-tex'], 'dv' => ['video/dv'], 'dvb' => ['video/vnd.dvb.file'], 'dvi' => ['application/x-dvi'], 'dvi.bz2' => ['application/x-bzdvi'], 'dvi.gz' => ['application/x-gzdvi'], 'dwd' => ['application/atsc-dwd+xml'], 'dwf' => ['model/vnd.dwf'], 'dwg' => ['image/vnd.dwg'], 'dxf' => ['image/vnd.dxf'], 'dxp' => ['application/vnd.spotfire.dxp'], 'dxr' => ['application/x-director'], 'e' => ['text/x-eiffel'], 'ear' => ['application/java-archive'], 'ecelp4800' => ['audio/vnd.nuera.ecelp4800'], 'ecelp7470' => ['audio/vnd.nuera.ecelp7470'], 'ecelp9600' => ['audio/vnd.nuera.ecelp9600'], 'ecma' => ['application/ecmascript'], 'edm' => ['application/vnd.novadigm.edm'], 'edx' => ['application/vnd.novadigm.edx'], 'efif' => ['application/vnd.picsel'], 'egon' => ['application/x-egon'], 'ei6' => ['application/vnd.pg.osasli'], 'eif' => ['text/x-eiffel'], 'el' => ['text/x-emacs-lisp'], 'emf' => ['application/emf', 'application/x-emf', 'application/x-msmetafile', 'image/emf', 'image/x-emf'], 'eml' => ['message/rfc822'], 'emma' => ['application/emma+xml'], 'emotionml' => ['application/emotionml+xml'], 'emp' => ['application/vnd.emusic-emusic_package'], 'emz' => ['application/x-msmetafile'], 'ent' => ['application/xml-external-parsed-entity', 'text/xml-external-parsed-entity'], 'eol' => ['audio/vnd.digital-winds'], 'eot' => ['application/vnd.ms-fontobject'], 'eps' => ['application/postscript', 'image/x-eps'], 'eps.bz2' => ['image/x-bzeps'], 'eps.gz' => ['image/x-gzeps'], 'epsf' => ['image/x-eps'], 'epsf.bz2' => ['image/x-bzeps'], 'epsf.gz' => ['image/x-gzeps'], 'epsi' => ['image/x-eps'], 'epsi.bz2' => ['image/x-bzeps'], 'epsi.gz' => ['image/x-gzeps'], 'epub' => ['application/epub+zip'], 'erl' => ['text/x-erlang'], 'es' => ['application/ecmascript', 'text/ecmascript'], 'es3' => ['application/vnd.eszigno3+xml'], 'esa' => ['application/vnd.osgi.subsystem'], 'esf' => ['application/vnd.epson.esf'], 'et3' => ['application/vnd.eszigno3+xml'], 'etheme' => ['application/x-e-theme'], 'etx' => ['text/x-setext'], 'eva' => ['application/x-eva'], 'evy' => ['application/x-envoy'], 'ex' => ['text/x-elixir'], 'exe' => ['application/x-ms-dos-executable', 'application/x-msdos-program', 'application/x-msdownload'], 'exi' => ['application/exi'], 'exr' => ['image/aces', 'image/x-exr'], 'exs' => ['text/x-elixir'], 'ext' => ['application/vnd.novadigm.ext'], 'ez' => ['application/andrew-inset'], 'ez2' => ['application/vnd.ezpix-album'], 'ez3' => ['application/vnd.ezpix-package'], 'f' => ['text/x-fortran'], 'f4a' => ['audio/m4a', 'audio/mp4', 'audio/x-m4a'], 'f4b' => ['audio/x-m4b'], 'f4v' => ['video/mp4', 'video/mp4v-es', 'video/x-f4v', 'video/x-m4v'], 'f77' => ['text/x-fortran'], 'f90' => ['text/x-fortran'], 'f95' => ['text/x-fortran'], 'fasl' => ['text/x-common-lisp'], 'fb2' => ['application/x-fictionbook', 'application/x-fictionbook+xml'], 'fb2.zip' => ['application/x-zip-compressed-fb2'], 'fbs' => ['image/vnd.fastbidsheet'], 'fcdt' => ['application/vnd.adobe.formscentral.fcdt'], 'fcs' => ['application/vnd.isac.fcs'], 'fd' => ['application/x-fd-file', 'application/x-raw-floppy-disk-image'], 'fdf' => ['application/vnd.fdf'], 'fds' => ['application/x-fds-disk'], 'fdt' => ['application/fdt+xml'], 'fe_launch' => ['application/vnd.denovo.fcselayout-link'], 'feature' => ['text/x-gherkin'], 'fg5' => ['application/vnd.fujitsu.oasysgp'], 'fgd' => ['application/x-director'], 'fh' => ['image/x-freehand'], 'fh4' => ['image/x-freehand'], 'fh5' => ['image/x-freehand'], 'fh7' => ['image/x-freehand'], 'fhc' => ['image/x-freehand'], 'fig' => ['application/x-xfig', 'image/x-xfig'], 'fits' => ['image/fits', 'image/x-fits'], 'fl' => ['application/x-fluid'], 'flac' => ['audio/flac', 'audio/x-flac'], 'flatpak' => ['application/vnd.flatpak', 'application/vnd.xdgapp'], 'flatpakref' => ['application/vnd.flatpak.ref'], 'flatpakrepo' => ['application/vnd.flatpak.repo'], 'flc' => ['video/fli', 'video/x-fli', 'video/x-flic'], 'fli' => ['video/fli', 'video/x-fli', 'video/x-flic'], 'flo' => ['application/vnd.micrografx.flo'], 'flv' => ['video/x-flv', 'application/x-flash-video', 'flv-application/octet-stream', 'video/flv'], 'flw' => ['application/vnd.kde.kivio', 'application/x-kivio'], 'flx' => ['text/vnd.fmi.flexstor'], 'fly' => ['text/vnd.fly'], 'fm' => ['application/vnd.framemaker', 'application/x-frame'], 'fnc' => ['application/vnd.frogans.fnc'], 'fo' => ['application/vnd.software602.filler.form+xml', 'text/x-xslfo'], 'fodg' => ['application/vnd.oasis.opendocument.graphics-flat-xml'], 'fodp' => ['application/vnd.oasis.opendocument.presentation-flat-xml'], 'fods' => ['application/vnd.oasis.opendocument.spreadsheet-flat-xml'], 'fodt' => ['application/vnd.oasis.opendocument.text-flat-xml'], 'for' => ['text/x-fortran'], 'fpx' => ['image/vnd.fpx'], 'frame' => ['application/vnd.framemaker'], 'fsc' => ['application/vnd.fsc.weblaunch'], 'fst' => ['image/vnd.fst'], 'ftc' => ['application/vnd.fluxtime.clip'], 'fti' => ['application/vnd.anser-web-funds-transfer-initiation'], 'fvt' => ['video/vnd.fvt'], 'fxm' => ['video/x-javafx'], 'fxp' => ['application/vnd.adobe.fxp'], 'fxpl' => ['application/vnd.adobe.fxp'], 'fzs' => ['application/vnd.fuzzysheet'], 'g2w' => ['application/vnd.geoplan'], 'g3' => ['image/fax-g3', 'image/g3fax'], 'g3w' => ['application/vnd.geospace'], 'gac' => ['application/vnd.groove-account'], 'gam' => ['application/x-tads'], 'gb' => ['application/x-gameboy-rom'], 'gba' => ['application/x-gba-rom'], 'gbc' => ['application/x-gameboy-color-rom'], 'gbr' => ['application/rpki-ghostbusters', 'image/x-gimp-gbr'], 'gca' => ['application/x-gca-compressed'], 'gcode' => ['text/x.gcode'], 'gcrd' => ['text/directory', 'text/vcard', 'text/x-vcard'], 'gdi' => ['application/x-gd-rom-cue'], 'gdl' => ['model/vnd.gdl'], 'gdoc' => ['application/vnd.google-apps.document'], 'ged' => ['application/x-gedcom', 'text/gedcom'], 'gedcom' => ['application/x-gedcom', 'text/gedcom'], 'gem' => ['application/x-gtar', 'application/x-tar'], 'gen' => ['application/x-genesis-rom'], 'geo' => ['application/vnd.dynageo'], 'geo.json' => ['application/geo+json', 'application/vnd.geo+json'], 'geojson' => ['application/geo+json', 'application/vnd.geo+json'], 'gex' => ['application/vnd.geometry-explorer'], 'gf' => ['application/x-tex-gf'], 'gg' => ['application/x-gamegear-rom'], 'ggb' => ['application/vnd.geogebra.file'], 'ggt' => ['application/vnd.geogebra.tool'], 'ghf' => ['application/vnd.groove-help'], 'gif' => ['image/gif'], 'gih' => ['image/x-gimp-gih'], 'gim' => ['application/vnd.groove-identity-message'], 'glade' => ['application/x-glade'], 'glb' => ['model/gltf-binary'], 'gltf' => ['model/gltf+json'], 'gml' => ['application/gml+xml'], 'gmo' => ['application/x-gettext-translation'], 'gmx' => ['application/vnd.gmx'], 'gnc' => ['application/x-gnucash'], 'gnd' => ['application/gnunet-directory'], 'gnucash' => ['application/x-gnucash'], 'gnumeric' => ['application/x-gnumeric'], 'gnuplot' => ['application/x-gnuplot'], 'go' => ['text/x-go'], 'gp' => ['application/x-gnuplot'], 'gpg' => ['application/pgp', 'application/pgp-encrypted', 'application/pgp-keys', 'application/pgp-signature'], 'gph' => ['application/vnd.flographit'], 'gplt' => ['application/x-gnuplot'], 'gpx' => ['application/gpx', 'application/gpx+xml', 'application/x-gpx', 'application/x-gpx+xml'], 'gqf' => ['application/vnd.grafeq'], 'gqs' => ['application/vnd.grafeq'], 'gra' => ['application/x-graphite'], 'gradle' => ['text/x-gradle'], 'gram' => ['application/srgs'], 'gramps' => ['application/x-gramps-xml'], 'gre' => ['application/vnd.geometry-explorer'], 'groovy' => ['text/x-groovy'], 'grv' => ['application/vnd.groove-injector'], 'grxml' => ['application/srgs+xml'], 'gs' => ['text/x-genie'], 'gsf' => ['application/x-font-ghostscript', 'application/x-font-type1'], 'gsh' => ['text/x-groovy'], 'gsheet' => ['application/vnd.google-apps.spreadsheet'], 'gslides' => ['application/vnd.google-apps.presentation'], 'gsm' => ['audio/x-gsm'], 'gtar' => ['application/x-gtar', 'application/x-tar'], 'gtm' => ['application/vnd.groove-tool-message'], 'gtw' => ['model/vnd.gtw'], 'gv' => ['text/vnd.graphviz'], 'gvp' => ['text/google-video-pointer', 'text/x-google-video-pointer'], 'gvy' => ['text/x-groovy'], 'gxf' => ['application/gxf'], 'gxt' => ['application/vnd.geonext'], 'gy' => ['text/x-groovy'], 'gz' => ['application/x-gzip', 'application/gzip'], 'h' => ['text/x-c', 'text/x-chdr'], 'h++' => ['text/x-c++hdr'], 'h261' => ['video/h261'], 'h263' => ['video/h263'], 'h264' => ['video/h264'], 'h4' => ['application/x-hdf'], 'h5' => ['application/x-hdf'], 'hal' => ['application/vnd.hal+xml'], 'hbci' => ['application/vnd.hbci'], 'hbs' => ['text/x-handlebars-template'], 'hdd' => ['application/x-virtualbox-hdd'], 'hdf' => ['application/x-hdf'], 'hdf4' => ['application/x-hdf'], 'hdf5' => ['application/x-hdf'], 'heic' => ['image/heic', 'image/heic-sequence', 'image/heif', 'image/heif-sequence'], 'heics' => ['image/heic-sequence'], 'heif' => ['image/heic', 'image/heic-sequence', 'image/heif', 'image/heif-sequence'], 'heifs' => ['image/heif-sequence'], 'hej2' => ['image/hej2k'], 'held' => ['application/atsc-held+xml'], 'hfe' => ['application/x-hfe-file', 'application/x-hfe-floppy-image'], 'hh' => ['text/x-c', 'text/x-c++hdr'], 'hjson' => ['application/hjson'], 'hlp' => ['application/winhlp', 'zz-application/zz-winassoc-hlp'], 'hp' => ['text/x-c++hdr'], 'hpgl' => ['application/vnd.hp-hpgl'], 'hpid' => ['application/vnd.hp-hpid'], 'hpp' => ['text/x-c++hdr'], 'hps' => ['application/vnd.hp-hps'], 'hqx' => ['application/stuffit', 'application/mac-binhex40'], 'hs' => ['text/x-haskell'], 'hsj2' => ['image/hsj2'], 'htc' => ['text/x-component'], 'htke' => ['application/vnd.kenameaapp'], 'htm' => ['text/html', 'application/xhtml+xml'], 'html' => ['text/html', 'application/xhtml+xml'], 'hvd' => ['application/vnd.yamaha.hv-dic'], 'hvp' => ['application/vnd.yamaha.hv-voice'], 'hvs' => ['application/vnd.yamaha.hv-script'], 'hwp' => ['application/vnd.haansoft-hwp', 'application/x-hwp'], 'hwt' => ['application/vnd.haansoft-hwt', 'application/x-hwt'], 'hxx' => ['text/x-c++hdr'], 'i2g' => ['application/vnd.intergeo'], 'ica' => ['application/x-ica'], 'icb' => ['application/tga', 'application/x-targa', 'application/x-tga', 'image/targa', 'image/tga', 'image/x-icb', 'image/x-targa', 'image/x-tga'], 'icc' => ['application/vnd.iccprofile'], 'ice' => ['x-conference/x-cooltalk'], 'icm' => ['application/vnd.iccprofile'], 'icns' => ['image/x-icns'], 'ico' => ['application/ico', 'image/ico', 'image/icon', 'image/vnd.microsoft.icon', 'image/x-ico', 'image/x-icon', 'text/ico'], 'ics' => ['application/ics', 'text/calendar', 'text/x-vcalendar'], 'idl' => ['text/x-idl'], 'ief' => ['image/ief'], 'ifb' => ['text/calendar'], 'iff' => ['image/x-iff', 'image/x-ilbm'], 'ifm' => ['application/vnd.shana.informed.formdata'], 'iges' => ['model/iges'], 'igl' => ['application/vnd.igloader'], 'igm' => ['application/vnd.insors.igm'], 'igs' => ['model/iges'], 'igx' => ['application/vnd.micrografx.igx'], 'iif' => ['application/vnd.shana.informed.interchange'], 'ilbm' => ['image/x-iff', 'image/x-ilbm'], 'ime' => ['audio/imelody', 'audio/x-imelody', 'text/x-imelody'], 'img' => ['application/x-raw-disk-image'], 'img.xz' => ['application/x-raw-disk-image-xz-compressed'], 'imp' => ['application/vnd.accpac.simply.imp'], 'ims' => ['application/vnd.ms-ims'], 'imy' => ['audio/imelody', 'audio/x-imelody', 'text/x-imelody'], 'in' => ['text/plain'], 'ini' => ['text/plain'], 'ink' => ['application/inkml+xml'], 'inkml' => ['application/inkml+xml'], 'ins' => ['application/x-tex', 'text/x-tex'], 'install' => ['application/x-install-instructions'], 'iota' => ['application/vnd.astraea-software.iota'], 'ipfix' => ['application/ipfix'], 'ipk' => ['application/vnd.shana.informed.package'], 'ips' => ['application/x-ips-patch'], 'iptables' => ['text/x-iptables'], 'ipynb' => ['application/x-ipynb+json'], 'irm' => ['application/vnd.ibm.rights-management'], 'irp' => ['application/vnd.irepository.package+xml'], 'iso' => ['application/x-cd-image', 'application/x-dreamcast-rom', 'application/x-gamecube-iso-image', 'application/x-gamecube-rom', 'application/x-iso9660-image', 'application/x-saturn-rom', 'application/x-sega-cd-rom', 'application/x-sega-pico-rom', 'application/x-wbfs', 'application/x-wia', 'application/x-wii-iso-image', 'application/x-wii-rom'], 'iso9660' => ['application/x-cd-image', 'application/x-iso9660-image'], 'it' => ['audio/x-it'], 'it87' => ['application/x-it87'], 'itp' => ['application/vnd.shana.informed.formtemplate'], 'its' => ['application/its+xml'], 'ivp' => ['application/vnd.immervision-ivp'], 'ivu' => ['application/vnd.immervision-ivu'], 'j2c' => ['image/x-jp2-codestream'], 'j2k' => ['image/x-jp2-codestream'], 'jad' => ['text/vnd.sun.j2me.app-descriptor'], 'jade' => ['text/jade'], 'jam' => ['application/vnd.jam'], 'jar' => ['application/x-java-archive', 'application/java-archive', 'application/x-jar'], 'jardiff' => ['application/x-java-archive-diff'], 'java' => ['text/x-java', 'text/x-java-source'], 'jceks' => ['application/x-java-jce-keystore'], 'jhc' => ['image/jphc'], 'jisp' => ['application/vnd.jisp'], 'jks' => ['application/x-java-keystore'], 'jls' => ['image/jls'], 'jlt' => ['application/vnd.hp-jlyt'], 'jng' => ['image/x-jng'], 'jnlp' => ['application/x-java-jnlp-file'], 'joda' => ['application/vnd.joost.joda-archive'], 'jp2' => ['image/jp2', 'image/jpeg2000', 'image/jpeg2000-image', 'image/x-jpeg2000-image'], 'jpc' => ['image/x-jp2-codestream'], 'jpe' => ['image/jpeg', 'image/pjpeg'], 'jpeg' => ['image/jpeg', 'image/pjpeg'], 'jpf' => ['image/jpx'], 'jpg' => ['image/jpeg', 'image/pjpeg'], 'jpg2' => ['image/jp2', 'image/jpeg2000', 'image/jpeg2000-image', 'image/x-jpeg2000-image'], 'jpgm' => ['image/jpm', 'video/jpm'], 'jpgv' => ['video/jpeg'], 'jph' => ['image/jph'], 'jpm' => ['image/jpm', 'video/jpm'], 'jpr' => ['application/x-jbuilder-project'], 'jpx' => ['application/x-jbuilder-project', 'image/jpx'], 'jrd' => ['application/jrd+json'], 'js' => ['text/javascript', 'application/javascript', 'application/x-javascript'], 'jsm' => ['application/javascript', 'application/x-javascript', 'text/javascript'], 'json' => ['application/json', 'application/schema+json'], 'json-patch' => ['application/json-patch+json'], 'json5' => ['application/json5'], 'jsonld' => ['application/ld+json'], 'jsonml' => ['application/jsonml+json'], 'jsx' => ['text/jsx'], 'jxl' => ['image/jxl'], 'jxr' => ['image/jxr'], 'jxra' => ['image/jxra'], 'jxrs' => ['image/jxrs'], 'jxs' => ['image/jxs'], 'jxsc' => ['image/jxsc'], 'jxsi' => ['image/jxsi'], 'jxss' => ['image/jxss'], 'k25' => ['image/x-kodak-k25'], 'k7' => ['application/x-thomson-cassette'], 'kar' => ['audio/midi', 'audio/x-midi'], 'karbon' => ['application/vnd.kde.karbon', 'application/x-karbon'], 'kdbx' => ['application/x-keepass2'], 'kdc' => ['image/x-kodak-kdc'], 'kdelnk' => ['application/x-desktop', 'application/x-gnome-app-info'], 'kexi' => ['application/x-kexiproject-sqlite', 'application/x-kexiproject-sqlite2', 'application/x-kexiproject-sqlite3', 'application/x-vnd.kde.kexi'], 'kexic' => ['application/x-kexi-connectiondata'], 'kexis' => ['application/x-kexiproject-shortcut'], 'key' => ['application/vnd.apple.keynote', 'application/pgp-keys', 'application/x-iwork-keynote-sffkey'], 'keynote' => ['application/vnd.apple.keynote'], 'kfo' => ['application/vnd.kde.kformula', 'application/x-kformula'], 'kfx' => ['application/vnd.amazon.mobi8-ebook', 'application/x-mobi8-ebook'], 'kia' => ['application/vnd.kidspiration'], 'kil' => ['application/x-killustrator'], 'kino' => ['application/smil', 'application/smil+xml'], 'kml' => ['application/vnd.google-earth.kml+xml'], 'kmz' => ['application/vnd.google-earth.kmz'], 'kne' => ['application/vnd.kinar'], 'knp' => ['application/vnd.kinar'], 'kon' => ['application/vnd.kde.kontour', 'application/x-kontour'], 'kpm' => ['application/x-kpovmodeler'], 'kpr' => ['application/vnd.kde.kpresenter', 'application/x-kpresenter'], 'kpt' => ['application/vnd.kde.kpresenter', 'application/x-kpresenter'], 'kpxx' => ['application/vnd.ds-keypoint'], 'kra' => ['application/x-krita'], 'krz' => ['application/x-krita'], 'ks' => ['application/x-java-keystore'], 'ksp' => ['application/vnd.kde.kspread', 'application/x-kspread'], 'ksy' => ['text/x-kaitai-struct'], 'kt' => ['text/x-kotlin'], 'ktr' => ['application/vnd.kahootz'], 'ktx' => ['image/ktx'], 'ktx2' => ['image/ktx2'], 'ktz' => ['application/vnd.kahootz'], 'kud' => ['application/x-kugar'], 'kwd' => ['application/vnd.kde.kword', 'application/x-kword'], 'kwt' => ['application/vnd.kde.kword', 'application/x-kword'], 'la' => ['application/x-shared-library-la'], 'lasxml' => ['application/vnd.las.las+xml'], 'latex' => ['application/x-latex', 'application/x-tex', 'text/x-tex'], 'lbd' => ['application/vnd.llamagraphics.life-balance.desktop'], 'lbe' => ['application/vnd.llamagraphics.life-balance.exchange+xml'], 'lbm' => ['image/x-iff', 'image/x-ilbm'], 'ldif' => ['text/x-ldif'], 'les' => ['application/vnd.hhe.lesson-player'], 'less' => ['text/less'], 'lgr' => ['application/lgr+xml'], 'lha' => ['application/x-lha', 'application/x-lzh-compressed'], 'lhs' => ['text/x-literate-haskell'], 'lhz' => ['application/x-lhz'], 'link66' => ['application/vnd.route66.link66+xml'], 'lisp' => ['text/x-common-lisp'], 'list' => ['text/plain'], 'list3820' => ['application/vnd.ibm.modcap'], 'listafp' => ['application/vnd.ibm.modcap'], 'litcoffee' => ['text/coffeescript'], 'lnk' => ['application/x-ms-shortcut'], 'lnx' => ['application/x-atari-lynx-rom'], 'loas' => ['audio/usac'], 'log' => ['text/plain', 'text/x-log'], 'lostxml' => ['application/lost+xml'], 'lrm' => ['application/vnd.ms-lrm'], 'lrv' => ['video/mp4', 'video/mp4v-es', 'video/x-m4v'], 'lrz' => ['application/x-lrzip'], 'ltf' => ['application/vnd.frogans.ltf'], 'ltx' => ['application/x-tex', 'text/x-tex'], 'lua' => ['text/x-lua'], 'luac' => ['application/x-lua-bytecode'], 'lvp' => ['audio/vnd.lucent.voice'], 'lwo' => ['image/x-lwo'], 'lwob' => ['image/x-lwo'], 'lwp' => ['application/vnd.lotus-wordpro'], 'lws' => ['image/x-lws'], 'ly' => ['text/x-lilypond'], 'lyx' => ['application/x-lyx', 'text/x-lyx'], 'lz' => ['application/x-lzip'], 'lz4' => ['application/x-lz4'], 'lzh' => ['application/x-lha', 'application/x-lzh-compressed'], 'lzma' => ['application/x-lzma'], 'lzo' => ['application/x-lzop'], 'm' => ['text/x-matlab', 'text/x-objcsrc', 'text/x-octave'], 'm13' => ['application/x-msmediaview'], 'm14' => ['application/x-msmediaview'], 'm15' => ['audio/x-mod'], 'm1u' => ['video/vnd.mpegurl', 'video/x-mpegurl'], 'm1v' => ['video/mpeg'], 'm21' => ['application/mp21'], 'm2a' => ['audio/mpeg'], 'm2t' => ['video/mp2t'], 'm2ts' => ['video/mp2t'], 'm2v' => ['video/mpeg'], 'm3a' => ['audio/mpeg'], 'm3u' => ['audio/x-mpegurl', 'application/m3u', 'application/vnd.apple.mpegurl', 'audio/m3u', 'audio/mpegurl', 'audio/x-m3u', 'audio/x-mp3-playlist'], 'm3u8' => ['application/m3u', 'application/vnd.apple.mpegurl', 'audio/m3u', 'audio/mpegurl', 'audio/x-m3u', 'audio/x-mp3-playlist', 'audio/x-mpegurl'], 'm4' => ['application/x-m4'], 'm4a' => ['audio/mp4', 'audio/m4a', 'audio/x-m4a'], 'm4b' => ['audio/x-m4b'], 'm4p' => ['application/mp4'], 'm4r' => ['audio/x-m4r'], 'm4s' => ['video/iso.segment'], 'm4u' => ['video/vnd.mpegurl', 'video/x-mpegurl'], 'm4v' => ['video/mp4', 'video/mp4v-es', 'video/x-m4v'], 'm7' => ['application/x-thomson-cartridge-memo7'], 'ma' => ['application/mathematica'], 'mab' => ['application/x-markaby'], 'mads' => ['application/mads+xml'], 'maei' => ['application/mmt-aei+xml'], 'mag' => ['application/vnd.ecowin.chart'], 'mak' => ['text/x-makefile'], 'maker' => ['application/vnd.framemaker'], 'man' => ['application/x-troff-man', 'text/troff'], 'manifest' => ['text/cache-manifest'], 'map' => ['application/json'], 'markdown' => ['text/markdown', 'text/x-markdown'], 'mathml' => ['application/mathml+xml'], 'mb' => ['application/mathematica'], 'mbk' => ['application/vnd.mobius.mbk'], 'mbox' => ['application/mbox'], 'mc1' => ['application/vnd.medcalcdata'], 'mc2' => ['text/vnd.senx.warpscript'], 'mcd' => ['application/vnd.mcd'], 'mcurl' => ['text/vnd.curl.mcurl'], 'md' => ['text/markdown', 'text/x-markdown'], 'mdb' => ['application/x-msaccess', 'application/mdb', 'application/msaccess', 'application/vnd.ms-access', 'application/vnd.msaccess', 'application/x-mdb', 'zz-application/zz-winassoc-mdb'], 'mdi' => ['image/vnd.ms-modi'], 'mdx' => ['application/x-genesis-32x-rom', 'text/mdx'], 'me' => ['text/troff', 'text/x-troff-me'], 'med' => ['audio/x-mod'], 'mesh' => ['model/mesh'], 'meta4' => ['application/metalink4+xml'], 'metalink' => ['application/metalink+xml'], 'mets' => ['application/mets+xml'], 'mfm' => ['application/vnd.mfmp'], 'mft' => ['application/rpki-manifest'], 'mgp' => ['application/vnd.osgeo.mapguide.package', 'application/x-magicpoint'], 'mgz' => ['application/vnd.proteus.magazine'], 'mht' => ['application/x-mimearchive'], 'mhtml' => ['application/x-mimearchive'], 'mid' => ['audio/midi', 'audio/x-midi'], 'midi' => ['audio/midi', 'audio/x-midi'], 'mie' => ['application/x-mie'], 'mif' => ['application/vnd.mif', 'application/x-mif'], 'mime' => ['message/rfc822'], 'minipsf' => ['audio/x-minipsf'], 'mj2' => ['video/mj2'], 'mjp2' => ['video/mj2'], 'mjpeg' => ['video/x-mjpeg'], 'mjpg' => ['video/x-mjpeg'], 'mjs' => ['application/javascript', 'application/x-javascript', 'text/javascript'], 'mk' => ['text/x-makefile'], 'mk3d' => ['video/x-matroska', 'video/x-matroska-3d'], 'mka' => ['audio/x-matroska'], 'mkd' => ['text/markdown', 'text/x-markdown'], 'mks' => ['video/x-matroska'], 'mkv' => ['video/x-matroska'], 'ml' => ['text/x-ocaml'], 'mli' => ['text/x-ocaml'], 'mlp' => ['application/vnd.dolby.mlp'], 'mm' => ['text/x-troff-mm'], 'mmd' => ['application/vnd.chipnuts.karaoke-mmd'], 'mmf' => ['application/vnd.smaf', 'application/x-smaf'], 'mml' => ['application/mathml+xml', 'text/mathml'], 'mmr' => ['image/vnd.fujixerox.edmics-mmr'], 'mng' => ['video/x-mng'], 'mny' => ['application/x-msmoney'], 'mo' => ['application/x-gettext-translation', 'text/x-modelica'], 'mo3' => ['audio/x-mo3'], 'mobi' => ['application/x-mobipocket-ebook'], 'moc' => ['text/x-moc'], 'mod' => ['application/x-object', 'audio/x-mod'], 'mods' => ['application/mods+xml'], 'mof' => ['text/x-mof'], 'moov' => ['video/quicktime'], 'mount' => ['text/x-systemd-unit'], 'mov' => ['video/quicktime'], 'movie' => ['video/x-sgi-movie'], 'mp+' => ['audio/x-musepack'], 'mp2' => ['audio/mp2', 'audio/mpeg', 'audio/x-mp2', 'video/mpeg', 'video/mpeg-system', 'video/x-mpeg', 'video/x-mpeg-system', 'video/x-mpeg2'], 'mp21' => ['application/mp21'], 'mp2a' => ['audio/mpeg'], 'mp3' => ['audio/mpeg', 'audio/mp3', 'audio/x-mp3', 'audio/x-mpeg', 'audio/x-mpg'], 'mp4' => ['video/mp4', 'video/mp4v-es', 'video/x-m4v'], 'mp4a' => ['audio/mp4'], 'mp4s' => ['application/mp4'], 'mp4v' => ['video/mp4'], 'mpc' => ['application/vnd.mophun.certificate', 'audio/x-musepack'], 'mpd' => ['application/dash+xml'], 'mpe' => ['video/mpeg', 'video/mpeg-system', 'video/x-mpeg', 'video/x-mpeg-system', 'video/x-mpeg2'], 'mpeg' => ['video/mpeg', 'video/mpeg-system', 'video/x-mpeg', 'video/x-mpeg-system', 'video/x-mpeg2'], 'mpg' => ['video/mpeg', 'video/mpeg-system', 'video/x-mpeg', 'video/x-mpeg-system', 'video/x-mpeg2'], 'mpg4' => ['video/mp4'], 'mpga' => ['audio/mp3', 'audio/mpeg', 'audio/x-mp3', 'audio/x-mpeg', 'audio/x-mpg'], 'mpkg' => ['application/vnd.apple.installer+xml'], 'mpl' => ['video/mp2t'], 'mpls' => ['video/mp2t'], 'mpm' => ['application/vnd.blueice.multipass'], 'mpn' => ['application/vnd.mophun.application'], 'mpp' => ['application/vnd.ms-project', 'audio/x-musepack'], 'mpt' => ['application/vnd.ms-project'], 'mpy' => ['application/vnd.ibm.minipay'], 'mqy' => ['application/vnd.mobius.mqy'], 'mrc' => ['application/marc'], 'mrcx' => ['application/marcxml+xml'], 'mrl' => ['text/x-mrml'], 'mrml' => ['text/x-mrml'], 'mrw' => ['image/x-minolta-mrw'], 'ms' => ['text/troff', 'text/x-troff-ms'], 'mscml' => ['application/mediaservercontrol+xml'], 'mseed' => ['application/vnd.fdsn.mseed'], 'mseq' => ['application/vnd.mseq'], 'msf' => ['application/vnd.epson.msf'], 'msg' => ['application/vnd.ms-outlook'], 'msh' => ['model/mesh'], 'msi' => ['application/x-msdownload', 'application/x-msi'], 'msl' => ['application/vnd.mobius.msl'], 'msod' => ['image/x-msod'], 'msty' => ['application/vnd.muvee.style'], 'msx' => ['application/x-msx-rom'], 'mtl' => ['model/mtl'], 'mtm' => ['audio/x-mod'], 'mts' => ['model/vnd.mts', 'video/mp2t'], 'mup' => ['text/x-mup'], 'mus' => ['application/vnd.musician'], 'musd' => ['application/mmt-usd+xml'], 'musicxml' => ['application/vnd.recordare.musicxml+xml'], 'mvb' => ['application/x-msmediaview'], 'mvt' => ['application/vnd.mapbox-vector-tile'], 'mwf' => ['application/vnd.mfer'], 'mxf' => ['application/mxf'], 'mxl' => ['application/vnd.recordare.musicxml'], 'mxmf' => ['audio/mobile-xmf'], 'mxml' => ['application/xv+xml'], 'mxs' => ['application/vnd.triscape.mxs'], 'mxu' => ['video/vnd.mpegurl', 'video/x-mpegurl'], 'n-gage' => ['application/vnd.nokia.n-gage.symbian.install'], 'n3' => ['text/n3'], 'n64' => ['application/x-n64-rom'], 'nb' => ['application/mathematica', 'application/x-mathematica'], 'nbp' => ['application/vnd.wolfram.player'], 'nc' => ['application/x-netcdf'], 'ncx' => ['application/x-dtbncx+xml'], 'nds' => ['application/x-nintendo-ds-rom'], 'nef' => ['image/x-nikon-nef'], 'nes' => ['application/x-nes-rom'], 'nez' => ['application/x-nes-rom'], 'nfo' => ['text/x-nfo'], 'ngc' => ['application/x-neo-geo-pocket-color-rom'], 'ngdat' => ['application/vnd.nokia.n-gage.data'], 'ngp' => ['application/x-neo-geo-pocket-rom'], 'nitf' => ['application/vnd.nitf'], 'nlu' => ['application/vnd.neurolanguage.nlu'], 'nml' => ['application/vnd.enliven'], 'nnd' => ['application/vnd.noblenet-directory'], 'nns' => ['application/vnd.noblenet-sealer'], 'nnw' => ['application/vnd.noblenet-web'], 'not' => ['text/x-mup'], 'npx' => ['image/vnd.net-fpx'], 'nq' => ['application/n-quads'], 'nrw' => ['image/x-nikon-nrw'], 'nsc' => ['application/x-conference', 'application/x-netshow-channel'], 'nsf' => ['application/vnd.lotus-notes'], 'nsv' => ['video/x-nsv'], 'nt' => ['application/n-triples'], 'ntf' => ['application/vnd.nitf'], 'numbers' => ['application/vnd.apple.numbers', 'application/x-iwork-numbers-sffnumbers'], 'nzb' => ['application/x-nzb'], 'o' => ['application/x-object'], 'oa2' => ['application/vnd.fujitsu.oasys2'], 'oa3' => ['application/vnd.fujitsu.oasys3'], 'oas' => ['application/vnd.fujitsu.oasys'], 'obd' => ['application/x-msbinder'], 'obgx' => ['application/vnd.openblox.game+xml'], 'obj' => ['application/x-tgif', 'model/obj'], 'ocl' => ['text/x-ocl'], 'oda' => ['application/oda'], 'odb' => ['application/vnd.oasis.opendocument.database', 'application/vnd.sun.xml.base'], 'odc' => ['application/vnd.oasis.opendocument.chart'], 'odf' => ['application/vnd.oasis.opendocument.formula'], 'odft' => ['application/vnd.oasis.opendocument.formula-template'], 'odg' => ['application/vnd.oasis.opendocument.graphics'], 'odi' => ['application/vnd.oasis.opendocument.image'], 'odm' => ['application/vnd.oasis.opendocument.text-master'], 'odp' => ['application/vnd.oasis.opendocument.presentation'], 'ods' => ['application/vnd.oasis.opendocument.spreadsheet'], 'odt' => ['application/vnd.oasis.opendocument.text'], 'oga' => ['audio/ogg', 'audio/vorbis', 'audio/x-flac+ogg', 'audio/x-ogg', 'audio/x-oggflac', 'audio/x-speex+ogg', 'audio/x-vorbis', 'audio/x-vorbis+ogg'], 'ogex' => ['model/vnd.opengex'], 'ogg' => ['audio/ogg', 'audio/vorbis', 'audio/x-flac+ogg', 'audio/x-ogg', 'audio/x-oggflac', 'audio/x-speex+ogg', 'audio/x-vorbis', 'audio/x-vorbis+ogg', 'video/ogg', 'video/x-ogg', 'video/x-theora', 'video/x-theora+ogg'], 'ogm' => ['video/x-ogm', 'video/x-ogm+ogg'], 'ogv' => ['video/ogg', 'video/x-ogg'], 'ogx' => ['application/ogg', 'application/x-ogg'], 'old' => ['application/x-trash'], 'oleo' => ['application/x-oleo'], 'omdoc' => ['application/omdoc+xml'], 'onepkg' => ['application/onenote'], 'onetmp' => ['application/onenote'], 'onetoc' => ['application/onenote'], 'onetoc2' => ['application/onenote'], 'ooc' => ['text/x-ooc'], 'opf' => ['application/oebps-package+xml'], 'opml' => ['text/x-opml', 'text/x-opml+xml'], 'oprc' => ['application/vnd.palm', 'application/x-palm-database'], 'opus' => ['audio/ogg', 'audio/x-ogg', 'audio/x-opus+ogg'], 'ora' => ['image/openraster'], 'orf' => ['image/x-olympus-orf'], 'org' => ['application/vnd.lotus-organizer', 'text/org', 'text/x-org'], 'osf' => ['application/vnd.yamaha.openscoreformat'], 'osfpvg' => ['application/vnd.yamaha.openscoreformat.osfpvg+xml'], 'osm' => ['application/vnd.openstreetmap.data+xml'], 'otc' => ['application/vnd.oasis.opendocument.chart-template'], 'otf' => ['application/vnd.oasis.opendocument.formula-template', 'application/x-font-otf', 'font/otf'], 'otg' => ['application/vnd.oasis.opendocument.graphics-template'], 'oth' => ['application/vnd.oasis.opendocument.text-web'], 'oti' => ['application/vnd.oasis.opendocument.image-template'], 'otp' => ['application/vnd.oasis.opendocument.presentation-template'], 'ots' => ['application/vnd.oasis.opendocument.spreadsheet-template'], 'ott' => ['application/vnd.oasis.opendocument.text-template'], 'ova' => ['application/ovf', 'application/x-virtualbox-ova'], 'ovf' => ['application/x-virtualbox-ovf'], 'owl' => ['application/rdf+xml', 'text/rdf'], 'owx' => ['application/owl+xml'], 'oxps' => ['application/oxps'], 'oxt' => ['application/vnd.openofficeorg.extension'], 'p' => ['text/x-pascal'], 'p10' => ['application/pkcs10'], 'p12' => ['application/pkcs12', 'application/x-pkcs12'], 'p65' => ['application/x-pagemaker'], 'p7b' => ['application/x-pkcs7-certificates'], 'p7c' => ['application/pkcs7-mime'], 'p7m' => ['application/pkcs7-mime'], 'p7r' => ['application/x-pkcs7-certreqresp'], 'p7s' => ['application/pkcs7-signature'], 'p8' => ['application/pkcs8'], 'p8e' => ['application/pkcs8-encrypted'], 'pac' => ['application/x-ns-proxy-autoconfig'], 'pack' => ['application/x-java-pack200'], 'pages' => ['application/vnd.apple.pages', 'application/x-iwork-pages-sffpages'], 'pak' => ['application/x-pak'], 'par2' => ['application/x-par2'], 'part' => ['application/x-partial-download'], 'pas' => ['text/x-pascal'], 'pat' => ['image/x-gimp-pat'], 'patch' => ['text/x-diff', 'text/x-patch'], 'path' => ['text/x-systemd-unit'], 'paw' => ['application/vnd.pawaafile'], 'pbd' => ['application/vnd.powerbuilder6'], 'pbm' => ['image/x-portable-bitmap'], 'pcap' => ['application/pcap', 'application/vnd.tcpdump.pcap', 'application/x-pcap'], 'pcd' => ['image/x-photo-cd'], 'pce' => ['application/x-pc-engine-rom'], 'pcf' => ['application/x-cisco-vpn-settings', 'application/x-font-pcf'], 'pcf.Z' => ['application/x-font-pcf'], 'pcf.gz' => ['application/x-font-pcf'], 'pcl' => ['application/vnd.hp-pcl'], 'pclxl' => ['application/vnd.hp-pclxl'], 'pct' => ['image/x-pict'], 'pcurl' => ['application/vnd.curl.pcurl'], 'pcx' => ['image/vnd.zbrush.pcx', 'image/x-pcx'], 'pdb' => ['application/vnd.palm', 'application/x-aportisdoc', 'application/x-palm-database', 'application/x-pilot'], 'pdc' => ['application/x-aportisdoc'], 'pde' => ['text/x-processing'], 'pdf' => ['application/pdf', 'application/acrobat', 'application/nappdf', 'application/x-pdf', 'image/pdf'], 'pdf.bz2' => ['application/x-bzpdf'], 'pdf.gz' => ['application/x-gzpdf'], 'pdf.lz' => ['application/x-lzpdf'], 'pdf.xz' => ['application/x-xzpdf'], 'pef' => ['image/x-pentax-pef'], 'pem' => ['application/x-x509-ca-cert'], 'perl' => ['application/x-perl', 'text/x-perl'], 'pfa' => ['application/x-font-type1'], 'pfb' => ['application/x-font-type1'], 'pfm' => ['application/x-font-type1'], 'pfr' => ['application/font-tdpfr'], 'pfx' => ['application/pkcs12', 'application/x-pkcs12'], 'pgm' => ['image/x-portable-graymap'], 'pgn' => ['application/vnd.chess-pgn', 'application/x-chess-pgn'], 'pgp' => ['application/pgp', 'application/pgp-encrypted', 'application/pgp-keys', 'application/pgp-signature'], 'php' => ['application/x-php', 'application/x-httpd-php'], 'php3' => ['application/x-php'], 'php4' => ['application/x-php'], 'php5' => ['application/x-php'], 'phps' => ['application/x-php'], 'pic' => ['image/x-pict'], 'pict' => ['image/x-pict'], 'pict1' => ['image/x-pict'], 'pict2' => ['image/x-pict'], 'pk' => ['application/x-tex-pk'], 'pkg' => ['application/x-xar'], 'pki' => ['application/pkixcmp'], 'pkipath' => ['application/pkix-pkipath'], 'pkpass' => ['application/vnd.apple.pkpass'], 'pkr' => ['application/pgp-keys'], 'pl' => ['application/x-perl', 'text/x-perl'], 'pla' => ['audio/x-iriver-pla'], 'plb' => ['application/vnd.3gpp.pic-bw-large'], 'plc' => ['application/vnd.mobius.plc'], 'plf' => ['application/vnd.pocketlearn'], 'pln' => ['application/x-planperfect'], 'pls' => ['application/pls', 'application/pls+xml', 'audio/scpls', 'audio/x-scpls'], 'pm' => ['application/x-pagemaker', 'application/x-perl', 'text/x-perl'], 'pm6' => ['application/x-pagemaker'], 'pmd' => ['application/x-pagemaker'], 'pml' => ['application/vnd.ctc-posml'], 'png' => ['image/png'], 'pnm' => ['image/x-portable-anymap'], 'pntg' => ['image/x-macpaint'], 'po' => ['application/x-gettext', 'text/x-gettext-translation', 'text/x-po'], 'pod' => ['application/x-perl', 'text/x-perl'], 'por' => ['application/x-spss-por'], 'portpkg' => ['application/vnd.macports.portpkg'], 'pot' => ['application/mspowerpoint', 'application/powerpoint', 'application/vnd.ms-powerpoint', 'application/x-mspowerpoint', 'text/x-gettext-translation-template', 'text/x-pot'], 'potm' => ['application/vnd.ms-powerpoint.template.macroenabled.12'], 'potx' => ['application/vnd.openxmlformats-officedocument.presentationml.template'], 'ppam' => ['application/vnd.ms-powerpoint.addin.macroenabled.12'], 'ppd' => ['application/vnd.cups-ppd'], 'ppm' => ['image/x-portable-pixmap'], 'pps' => ['application/mspowerpoint', 'application/powerpoint', 'application/vnd.ms-powerpoint', 'application/x-mspowerpoint'], 'ppsm' => ['application/vnd.ms-powerpoint.slideshow.macroenabled.12'], 'ppsx' => ['application/vnd.openxmlformats-officedocument.presentationml.slideshow'], 'ppt' => ['application/vnd.ms-powerpoint', 'application/mspowerpoint', 'application/powerpoint', 'application/x-mspowerpoint'], 'pptm' => ['application/vnd.ms-powerpoint.presentation.macroenabled.12'], 'pptx' => ['application/vnd.openxmlformats-officedocument.presentationml.presentation'], 'ppz' => ['application/mspowerpoint', 'application/powerpoint', 'application/vnd.ms-powerpoint', 'application/x-mspowerpoint'], 'pqa' => ['application/vnd.palm', 'application/x-palm-database'], 'prc' => ['application/vnd.palm', 'application/x-mobipocket-ebook', 'application/x-palm-database', 'application/x-pilot'], 'pre' => ['application/vnd.lotus-freelance'], 'prf' => ['application/pics-rules'], 'provx' => ['application/provenance+xml'], 'ps' => ['application/postscript'], 'ps.bz2' => ['application/x-bzpostscript'], 'ps.gz' => ['application/x-gzpostscript'], 'psb' => ['application/vnd.3gpp.pic-bw-small'], 'psd' => ['application/photoshop', 'application/x-photoshop', 'image/photoshop', 'image/psd', 'image/vnd.adobe.photoshop', 'image/x-photoshop', 'image/x-psd'], 'psf' => ['application/x-font-linux-psf', 'audio/x-psf'], 'psf.gz' => ['application/x-gz-font-linux-psf'], 'psflib' => ['audio/x-psflib'], 'psid' => ['audio/prs.sid'], 'pskcxml' => ['application/pskc+xml'], 'psw' => ['application/x-pocket-word'], 'pti' => ['image/prs.pti'], 'ptid' => ['application/vnd.pvi.ptid1'], 'pub' => ['application/vnd.ms-publisher', 'application/x-mspublisher'], 'pvb' => ['application/vnd.3gpp.pic-bw-var'], 'pw' => ['application/x-pw'], 'pwn' => ['application/vnd.3m.post-it-notes'], 'py' => ['text/x-python', 'text/x-python3'], 'py3' => ['text/x-python3'], 'py3x' => ['text/x-python3'], 'pya' => ['audio/vnd.ms-playready.media.pya'], 'pyc' => ['application/x-python-bytecode'], 'pyi' => ['text/x-python3'], 'pyo' => ['application/x-python-bytecode'], 'pys' => ['application/x-pyspread-bz-spreadsheet'], 'pysu' => ['application/x-pyspread-spreadsheet'], 'pyv' => ['video/vnd.ms-playready.media.pyv'], 'pyx' => ['text/x-python'], 'qam' => ['application/vnd.epson.quickanime'], 'qbo' => ['application/vnd.intu.qbo'], 'qcow' => ['application/x-qemu-disk'], 'qcow2' => ['application/x-qemu-disk'], 'qd' => ['application/x-fd-file', 'application/x-raw-floppy-disk-image'], 'qed' => ['application/x-qed-disk'], 'qfx' => ['application/vnd.intu.qfx'], 'qif' => ['application/x-qw', 'image/x-quicktime'], 'qml' => ['text/x-qml'], 'qmlproject' => ['text/x-qml'], 'qmltypes' => ['text/x-qml'], 'qp' => ['application/x-qpress'], 'qps' => ['application/vnd.publishare-delta-tree'], 'qt' => ['video/quicktime'], 'qti' => ['application/x-qtiplot'], 'qti.gz' => ['application/x-qtiplot'], 'qtif' => ['image/x-quicktime'], 'qtl' => ['application/x-quicktime-media-link', 'application/x-quicktimeplayer'], 'qtvr' => ['video/quicktime'], 'qwd' => ['application/vnd.quark.quarkxpress'], 'qwt' => ['application/vnd.quark.quarkxpress'], 'qxb' => ['application/vnd.quark.quarkxpress'], 'qxd' => ['application/vnd.quark.quarkxpress'], 'qxl' => ['application/vnd.quark.quarkxpress'], 'qxt' => ['application/vnd.quark.quarkxpress'], 'ra' => ['audio/vnd.m-realaudio', 'audio/vnd.rn-realaudio', 'audio/x-pn-realaudio', 'audio/x-realaudio'], 'raf' => ['image/x-fuji-raf'], 'ram' => ['application/ram', 'audio/x-pn-realaudio'], 'raml' => ['application/raml+yaml'], 'rapd' => ['application/route-apd+xml'], 'rar' => ['application/x-rar-compressed', 'application/vnd.rar', 'application/x-rar'], 'ras' => ['image/x-cmu-raster'], 'raw' => ['image/x-panasonic-raw', 'image/x-panasonic-rw'], 'raw-disk-image' => ['application/x-raw-disk-image'], 'raw-disk-image.xz' => ['application/x-raw-disk-image-xz-compressed'], 'rax' => ['audio/vnd.m-realaudio', 'audio/vnd.rn-realaudio', 'audio/x-pn-realaudio'], 'rb' => ['application/x-ruby'], 'rcprofile' => ['application/vnd.ipunplugged.rcprofile'], 'rdf' => ['application/rdf+xml', 'text/rdf'], 'rdfs' => ['application/rdf+xml', 'text/rdf'], 'rdz' => ['application/vnd.data-vision.rdz'], 'reg' => ['text/x-ms-regedit'], 'rej' => ['application/x-reject', 'text/x-reject'], 'relo' => ['application/p2p-overlay+xml'], 'rep' => ['application/vnd.businessobjects'], 'res' => ['application/x-dtbresource+xml'], 'rgb' => ['image/x-rgb'], 'rif' => ['application/reginfo+xml'], 'rip' => ['audio/vnd.rip'], 'ris' => ['application/x-research-info-systems'], 'rl' => ['application/resource-lists+xml'], 'rlc' => ['image/vnd.fujixerox.edmics-rlc'], 'rld' => ['application/resource-lists-diff+xml'], 'rle' => ['image/rle'], 'rm' => ['application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], 'rmi' => ['audio/midi'], 'rmj' => ['application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], 'rmm' => ['application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], 'rmp' => ['audio/x-pn-realaudio-plugin'], 'rms' => ['application/vnd.jcp.javame.midlet-rms', 'application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], 'rmvb' => ['application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], 'rmx' => ['application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], 'rnc' => ['application/relax-ng-compact-syntax', 'application/x-rnc'], 'rng' => ['application/xml', 'text/xml'], 'roa' => ['application/rpki-roa'], 'roff' => ['application/x-troff', 'text/troff', 'text/x-troff'], 'ros' => ['text/x-common-lisp'], 'rp' => ['image/vnd.rn-realpix'], 'rp9' => ['application/vnd.cloanto.rp9'], 'rpm' => ['application/x-redhat-package-manager', 'application/x-rpm'], 'rpss' => ['application/vnd.nokia.radio-presets'], 'rpst' => ['application/vnd.nokia.radio-preset'], 'rq' => ['application/sparql-query'], 'rs' => ['application/rls-services+xml', 'text/rust'], 'rsat' => ['application/atsc-rsat+xml'], 'rsd' => ['application/rsd+xml'], 'rsheet' => ['application/urc-ressheet+xml'], 'rss' => ['application/rss+xml', 'text/rss'], 'rst' => ['text/x-rst'], 'rt' => ['text/vnd.rn-realtext'], 'rtf' => ['application/rtf', 'text/rtf'], 'rtx' => ['text/richtext'], 'run' => ['application/x-makeself'], 'rusd' => ['application/route-usd+xml'], 'rv' => ['video/vnd.rn-realvideo', 'video/x-real-video'], 'rvx' => ['video/vnd.rn-realvideo', 'video/x-real-video'], 'rw2' => ['image/x-panasonic-raw2', 'image/x-panasonic-rw2'], 's' => ['text/x-asm'], 's3m' => ['audio/s3m', 'audio/x-s3m'], 'saf' => ['application/vnd.yamaha.smaf-audio'], 'sage' => ['text/x-sagemath'], 'sam' => ['application/x-amipro'], 'sami' => ['application/x-sami'], 'sap' => ['application/x-sap-file', 'application/x-thomson-sap-image'], 'sass' => ['text/x-sass'], 'sav' => ['application/x-spss-sav', 'application/x-spss-savefile'], 'sbml' => ['application/sbml+xml'], 'sc' => ['application/vnd.ibm.secure-container', 'text/x-scala'], 'scala' => ['text/x-scala'], 'scd' => ['application/x-msschedule'], 'scm' => ['application/vnd.lotus-screencam', 'text/x-scheme'], 'scope' => ['text/x-systemd-unit'], 'scq' => ['application/scvp-cv-request'], 'scs' => ['application/scvp-cv-response'], 'scss' => ['text/x-scss'], 'scurl' => ['text/vnd.curl.scurl'], 'sda' => ['application/vnd.stardivision.draw'], 'sdc' => ['application/vnd.stardivision.calc'], 'sdd' => ['application/vnd.stardivision.impress'], 'sdkd' => ['application/vnd.solent.sdkm+xml'], 'sdkm' => ['application/vnd.solent.sdkm+xml'], 'sdp' => ['application/sdp', 'application/vnd.sdp', 'application/vnd.stardivision.impress', 'application/x-sdp'], 'sds' => ['application/vnd.stardivision.chart'], 'sdw' => ['application/vnd.stardivision.writer', 'application/vnd.stardivision.writer-global'], 'sea' => ['application/x-sea'], 'see' => ['application/vnd.seemail'], 'seed' => ['application/vnd.fdsn.seed'], 'sema' => ['application/vnd.sema'], 'semd' => ['application/vnd.semd'], 'semf' => ['application/vnd.semf'], 'senmlx' => ['application/senml+xml'], 'sensmlx' => ['application/sensml+xml'], 'ser' => ['application/java-serialized-object'], 'service' => ['text/x-dbus-service', 'text/x-systemd-unit'], 'setpay' => ['application/set-payment-initiation'], 'setreg' => ['application/set-registration-initiation'], 'sfc' => ['application/vnd.nintendo.snes.rom', 'application/x-snes-rom'], 'sfd-hdstx' => ['application/vnd.hydrostatix.sof-data'], 'sfs' => ['application/vnd.spotfire.sfs'], 'sfv' => ['text/x-sfv'], 'sg' => ['application/x-sg1000-rom'], 'sgb' => ['application/x-gameboy-rom'], 'sgd' => ['application/x-genesis-rom'], 'sgf' => ['application/x-go-sgf'], 'sgi' => ['image/sgi', 'image/x-sgi'], 'sgl' => ['application/vnd.stardivision.writer', 'application/vnd.stardivision.writer-global'], 'sgm' => ['text/sgml'], 'sgml' => ['text/sgml'], 'sh' => ['application/x-sh', 'application/x-shellscript', 'text/x-sh'], 'shape' => ['application/x-dia-shape'], 'shar' => ['application/x-shar'], 'shex' => ['text/shex'], 'shf' => ['application/shf+xml'], 'shn' => ['application/x-shorten', 'audio/x-shorten'], 'shtml' => ['text/html'], 'siag' => ['application/x-siag'], 'sid' => ['audio/prs.sid', 'image/x-mrsid-image'], 'sieve' => ['application/sieve'], 'sig' => ['application/pgp-signature'], 'sik' => ['application/x-trash'], 'sil' => ['audio/silk'], 'silo' => ['model/mesh'], 'sis' => ['application/vnd.symbian.install'], 'sisx' => ['application/vnd.symbian.install', 'x-epoc/x-sisx-app'], 'sit' => ['application/x-stuffit', 'application/stuffit', 'application/x-sit'], 'sitx' => ['application/x-stuffitx'], 'siv' => ['application/sieve'], 'sk' => ['image/x-skencil'], 'sk1' => ['image/x-skencil'], 'skd' => ['application/vnd.koan'], 'skm' => ['application/vnd.koan'], 'skp' => ['application/vnd.koan'], 'skr' => ['application/pgp-keys'], 'skt' => ['application/vnd.koan'], 'sldm' => ['application/vnd.ms-powerpoint.slide.macroenabled.12'], 'sldx' => ['application/vnd.openxmlformats-officedocument.presentationml.slide'], 'slice' => ['text/x-systemd-unit'], 'slim' => ['text/slim'], 'slk' => ['text/spreadsheet'], 'slm' => ['text/slim'], 'sls' => ['application/route-s-tsid+xml'], 'slt' => ['application/vnd.epson.salt'], 'sm' => ['application/vnd.stepmania.stepchart'], 'smaf' => ['application/vnd.smaf', 'application/x-smaf'], 'smc' => ['application/vnd.nintendo.snes.rom', 'application/x-snes-rom'], 'smd' => ['application/vnd.stardivision.mail', 'application/x-genesis-rom'], 'smf' => ['application/vnd.stardivision.math'], 'smi' => ['application/smil', 'application/smil+xml', 'application/x-sami'], 'smil' => ['application/smil', 'application/smil+xml'], 'smk' => ['video/vnd.radgamettools.smacker'], 'sml' => ['application/smil', 'application/smil+xml'], 'sms' => ['application/x-sms-rom'], 'smv' => ['video/x-smv'], 'smzip' => ['application/vnd.stepmania.package'], 'snap' => ['application/vnd.snap'], 'snd' => ['audio/basic'], 'snf' => ['application/x-font-snf'], 'so' => ['application/x-sharedlib'], 'socket' => ['text/x-systemd-unit'], 'spc' => ['application/x-pkcs7-certificates'], 'spd' => ['application/x-font-speedo'], 'spdx' => ['text/spdx'], 'spec' => ['text/x-rpm-spec'], 'spf' => ['application/vnd.yamaha.smaf-phrase'], 'spl' => ['application/futuresplash', 'application/vnd.adobe.flash.movie', 'application/x-futuresplash', 'application/x-shockwave-flash'], 'spm' => ['application/x-source-rpm'], 'spot' => ['text/vnd.in3d.spot'], 'spp' => ['application/scvp-vp-response'], 'spq' => ['application/scvp-vp-request'], 'spx' => ['application/x-apple-systemprofiler+xml', 'audio/ogg', 'audio/x-speex', 'audio/x-speex+ogg'], 'sql' => ['application/sql', 'application/x-sql', 'text/x-sql'], 'sqlite2' => ['application/x-sqlite2'], 'sqlite3' => ['application/vnd.sqlite3', 'application/x-sqlite3'], 'sqsh' => ['application/vnd.squashfs'], 'sr2' => ['image/x-sony-sr2'], 'src' => ['application/x-wais-source'], 'src.rpm' => ['application/x-source-rpm'], 'srf' => ['image/x-sony-srf'], 'srt' => ['application/x-srt', 'application/x-subrip'], 'sru' => ['application/sru+xml'], 'srx' => ['application/sparql-results+xml'], 'ss' => ['text/x-scheme'], 'ssa' => ['text/x-ssa'], 'ssdl' => ['application/ssdl+xml'], 'sse' => ['application/vnd.kodak-descriptor'], 'ssf' => ['application/vnd.epson.ssf'], 'ssml' => ['application/ssml+xml'], 'st' => ['application/vnd.sailingtracker.track'], 'stc' => ['application/vnd.sun.xml.calc.template'], 'std' => ['application/vnd.sun.xml.draw.template'], 'stf' => ['application/vnd.wt.stf'], 'sti' => ['application/vnd.sun.xml.impress.template'], 'stk' => ['application/hyperstudio'], 'stl' => ['application/vnd.ms-pki.stl', 'model/stl', 'model/x.stl-ascii', 'model/x.stl-binary'], 'stm' => ['audio/x-stm'], 'stpxz' => ['model/step-xml+zip'], 'stpz' => ['model/step+zip'], 'str' => ['application/vnd.pg.format'], 'stw' => ['application/vnd.sun.xml.writer.template'], 'sty' => ['application/x-tex', 'text/x-tex'], 'styl' => ['text/stylus'], 'stylus' => ['text/stylus'], 'sub' => ['image/vnd.dvb.subtitle', 'text/vnd.dvb.subtitle', 'text/x-microdvd', 'text/x-mpsub', 'text/x-subviewer'], 'sun' => ['image/x-sun-raster'], 'sus' => ['application/vnd.sus-calendar'], 'susp' => ['application/vnd.sus-calendar'], 'sv' => ['text/x-svsrc'], 'sv4cpio' => ['application/x-sv4cpio'], 'sv4crc' => ['application/x-sv4crc'], 'svc' => ['application/vnd.dvb.service'], 'svd' => ['application/vnd.svd'], 'svg' => ['image/svg+xml', 'image/svg'], 'svgz' => ['image/svg+xml', 'image/svg+xml-compressed'], 'svh' => ['text/x-svhdr'], 'swa' => ['application/x-director'], 'swap' => ['text/x-systemd-unit'], 'swf' => ['application/futuresplash', 'application/vnd.adobe.flash.movie', 'application/x-shockwave-flash'], 'swi' => ['application/vnd.aristanetworks.swi'], 'swidtag' => ['application/swid+xml'], 'swm' => ['application/x-ms-wim'], 'sxc' => ['application/vnd.sun.xml.calc'], 'sxd' => ['application/vnd.sun.xml.draw'], 'sxg' => ['application/vnd.sun.xml.writer.global'], 'sxi' => ['application/vnd.sun.xml.impress'], 'sxm' => ['application/vnd.sun.xml.math'], 'sxw' => ['application/vnd.sun.xml.writer'], 'sylk' => ['text/spreadsheet'], 't' => ['application/x-perl', 'application/x-troff', 'text/troff', 'text/x-perl', 'text/x-troff'], 't2t' => ['text/x-txt2tags'], 't3' => ['application/x-t3vm-image'], 't38' => ['image/t38'], 'taglet' => ['application/vnd.mynfc'], 'tao' => ['application/vnd.tao.intent-module-archive'], 'tap' => ['image/vnd.tencent.tap'], 'tar' => ['application/x-tar', 'application/x-gtar'], 'tar.Z' => ['application/x-tarz'], 'tar.bz' => ['application/x-bzip-compressed-tar'], 'tar.bz2' => ['application/x-bzip-compressed-tar'], 'tar.gz' => ['application/x-compressed-tar'], 'tar.lrz' => ['application/x-lrzip-compressed-tar'], 'tar.lz' => ['application/x-lzip-compressed-tar'], 'tar.lz4' => ['application/x-lz4-compressed-tar'], 'tar.lzma' => ['application/x-lzma-compressed-tar'], 'tar.lzo' => ['application/x-tzo'], 'tar.xz' => ['application/x-xz-compressed-tar'], 'tar.zst' => ['application/x-zstd-compressed-tar'], 'target' => ['text/x-systemd-unit'], 'taz' => ['application/x-tarz'], 'tb2' => ['application/x-bzip-compressed-tar'], 'tbz' => ['application/x-bzip-compressed-tar'], 'tbz2' => ['application/x-bzip-compressed-tar'], 'tcap' => ['application/vnd.3gpp2.tcap'], 'tcl' => ['application/x-tcl', 'text/tcl', 'text/x-tcl'], 'td' => ['application/urc-targetdesc+xml'], 'teacher' => ['application/vnd.smart.teacher'], 'tei' => ['application/tei+xml'], 'teicorpus' => ['application/tei+xml'], 'tex' => ['application/x-tex', 'text/x-tex'], 'texi' => ['application/x-texinfo', 'text/x-texinfo'], 'texinfo' => ['application/x-texinfo', 'text/x-texinfo'], 'text' => ['text/plain'], 'tfi' => ['application/thraud+xml'], 'tfm' => ['application/x-tex-tfm'], 'tfx' => ['image/tiff-fx'], 'tga' => ['application/tga', 'application/x-targa', 'application/x-tga', 'image/targa', 'image/tga', 'image/x-icb', 'image/x-targa', 'image/x-tga'], 'tgz' => ['application/x-compressed-tar'], 'theme' => ['application/x-theme'], 'themepack' => ['application/x-windows-themepack'], 'thmx' => ['application/vnd.ms-officetheme'], 'tif' => ['image/tiff'], 'tiff' => ['image/tiff'], 'timer' => ['text/x-systemd-unit'], 'tk' => ['application/x-tcl', 'text/tcl', 'text/x-tcl'], 'tlrz' => ['application/x-lrzip-compressed-tar'], 'tlz' => ['application/x-lzma-compressed-tar'], 'tmo' => ['application/vnd.tmobile-livetv'], 'tnef' => ['application/ms-tnef', 'application/vnd.ms-tnef'], 'tnf' => ['application/ms-tnef', 'application/vnd.ms-tnef'], 'toc' => ['application/x-cdrdao-toc'], 'toml' => ['application/toml'], 'torrent' => ['application/x-bittorrent'], 'tpic' => ['application/tga', 'application/x-targa', 'application/x-tga', 'image/targa', 'image/tga', 'image/x-icb', 'image/x-targa', 'image/x-tga'], 'tpl' => ['application/vnd.groove-tool-template'], 'tpt' => ['application/vnd.trid.tpt'], 'tr' => ['application/x-troff', 'text/troff', 'text/x-troff'], 'tra' => ['application/vnd.trueapp'], 'trig' => ['application/trig', 'application/x-trig'], 'trm' => ['application/x-msterminal'], 'ts' => ['application/x-linguist', 'text/vnd.qt.linguist', 'text/vnd.trolltech.linguist', 'video/mp2t'], 'tsd' => ['application/timestamped-data'], 'tsv' => ['text/tab-separated-values'], 'tta' => ['audio/tta', 'audio/x-tta'], 'ttc' => ['font/collection'], 'ttf' => ['application/x-font-truetype', 'application/x-font-ttf', 'font/ttf'], 'ttl' => ['text/turtle'], 'ttml' => ['application/ttml+xml'], 'ttx' => ['application/x-font-ttx'], 'twd' => ['application/vnd.simtech-mindmapper'], 'twds' => ['application/vnd.simtech-mindmapper'], 'twig' => ['text/x-twig'], 'txd' => ['application/vnd.genomatix.tuxedo'], 'txf' => ['application/vnd.mobius.txf'], 'txt' => ['text/plain'], 'txz' => ['application/x-xz-compressed-tar'], 'tzo' => ['application/x-tzo'], 'tzst' => ['application/x-zstd-compressed-tar'], 'u32' => ['application/x-authorware-bin'], 'u8dsn' => ['message/global-delivery-status'], 'u8hdr' => ['message/global-headers'], 'u8mdn' => ['message/global-disposition-notification'], 'u8msg' => ['message/global'], 'ubj' => ['application/ubjson'], 'udeb' => ['application/vnd.debian.binary-package', 'application/x-deb', 'application/x-debian-package'], 'ufd' => ['application/vnd.ufdl'], 'ufdl' => ['application/vnd.ufdl'], 'ufraw' => ['application/x-ufraw'], 'ui' => ['application/x-designer', 'application/x-gtk-builder'], 'uil' => ['text/x-uil'], 'ult' => ['audio/x-mod'], 'ulx' => ['application/x-glulx'], 'umj' => ['application/vnd.umajin'], 'unf' => ['application/x-nes-rom'], 'uni' => ['audio/x-mod'], 'unif' => ['application/x-nes-rom'], 'unityweb' => ['application/vnd.unity'], 'uoml' => ['application/vnd.uoml+xml'], 'uri' => ['text/uri-list'], 'uris' => ['text/uri-list'], 'url' => ['application/x-mswinurl'], 'urls' => ['text/uri-list'], 'usdz' => ['model/vnd.usdz+zip'], 'ustar' => ['application/x-ustar'], 'utz' => ['application/vnd.uiq.theme'], 'uu' => ['text/x-uuencode'], 'uue' => ['text/x-uuencode', 'zz-application/zz-winassoc-uu'], 'uva' => ['audio/vnd.dece.audio'], 'uvd' => ['application/vnd.dece.data'], 'uvf' => ['application/vnd.dece.data'], 'uvg' => ['image/vnd.dece.graphic'], 'uvh' => ['video/vnd.dece.hd'], 'uvi' => ['image/vnd.dece.graphic'], 'uvm' => ['video/vnd.dece.mobile'], 'uvp' => ['video/vnd.dece.pd'], 'uvs' => ['video/vnd.dece.sd'], 'uvt' => ['application/vnd.dece.ttml+xml'], 'uvu' => ['video/vnd.uvvu.mp4'], 'uvv' => ['video/vnd.dece.video'], 'uvva' => ['audio/vnd.dece.audio'], 'uvvd' => ['application/vnd.dece.data'], 'uvvf' => ['application/vnd.dece.data'], 'uvvg' => ['image/vnd.dece.graphic'], 'uvvh' => ['video/vnd.dece.hd'], 'uvvi' => ['image/vnd.dece.graphic'], 'uvvm' => ['video/vnd.dece.mobile'], 'uvvp' => ['video/vnd.dece.pd'], 'uvvs' => ['video/vnd.dece.sd'], 'uvvt' => ['application/vnd.dece.ttml+xml'], 'uvvu' => ['video/vnd.uvvu.mp4'], 'uvvv' => ['video/vnd.dece.video'], 'uvvx' => ['application/vnd.dece.unspecified'], 'uvvz' => ['application/vnd.dece.zip'], 'uvx' => ['application/vnd.dece.unspecified'], 'uvz' => ['application/vnd.dece.zip'], 'v' => ['text/x-verilog'], 'v64' => ['application/x-n64-rom'], 'vala' => ['text/x-vala'], 'vapi' => ['text/x-vala'], 'vb' => ['application/x-virtual-boy-rom'], 'vbox' => ['application/x-virtualbox-vbox'], 'vbox-extpack' => ['application/x-virtualbox-vbox-extpack'], 'vbs' => ['text/vbs', 'text/vbscript'], 'vcard' => ['text/directory', 'text/vcard', 'text/x-vcard'], 'vcd' => ['application/x-cdlink'], 'vcf' => ['text/x-vcard', 'text/directory', 'text/vcard'], 'vcg' => ['application/vnd.groove-vcard'], 'vcs' => ['application/ics', 'text/calendar', 'text/x-vcalendar'], 'vct' => ['text/directory', 'text/vcard', 'text/x-vcard'], 'vcx' => ['application/vnd.vcx'], 'vda' => ['application/tga', 'application/x-targa', 'application/x-tga', 'image/targa', 'image/tga', 'image/x-icb', 'image/x-targa', 'image/x-tga'], 'vdi' => ['application/x-vdi-disk', 'application/x-virtualbox-vdi'], 'vds' => ['model/vnd.sap.vds'], 'vhd' => ['application/x-vhd-disk', 'application/x-virtualbox-vhd', 'text/x-vhdl'], 'vhdl' => ['text/x-vhdl'], 'vhdx' => ['application/x-vhdx-disk', 'application/x-virtualbox-vhdx'], 'vis' => ['application/vnd.visionary'], 'viv' => ['video/vivo', 'video/vnd.vivo'], 'vivo' => ['video/vivo', 'video/vnd.vivo'], 'vlc' => ['application/m3u', 'audio/m3u', 'audio/mpegurl', 'audio/x-m3u', 'audio/x-mp3-playlist', 'audio/x-mpegurl'], 'vmdk' => ['application/x-virtualbox-vmdk', 'application/x-vmdk-disk'], 'vob' => ['video/mpeg', 'video/mpeg-system', 'video/x-mpeg', 'video/x-mpeg-system', 'video/x-mpeg2', 'video/x-ms-vob'], 'voc' => ['audio/x-voc'], 'vor' => ['application/vnd.stardivision.writer', 'application/vnd.stardivision.writer-global'], 'vox' => ['application/x-authorware-bin'], 'vpc' => ['application/x-vhd-disk', 'application/x-virtualbox-vhd'], 'vrm' => ['model/vrml'], 'vrml' => ['model/vrml'], 'vsd' => ['application/vnd.visio'], 'vsdm' => ['application/vnd.ms-visio.drawing.macroenabled.main+xml'], 'vsdx' => ['application/vnd.ms-visio.drawing.main+xml'], 'vsf' => ['application/vnd.vsf'], 'vss' => ['application/vnd.visio'], 'vssm' => ['application/vnd.ms-visio.stencil.macroenabled.main+xml'], 'vssx' => ['application/vnd.ms-visio.stencil.main+xml'], 'vst' => ['application/tga', 'application/vnd.visio', 'application/x-targa', 'application/x-tga', 'image/targa', 'image/tga', 'image/x-icb', 'image/x-targa', 'image/x-tga'], 'vstm' => ['application/vnd.ms-visio.template.macroenabled.main+xml'], 'vstx' => ['application/vnd.ms-visio.template.main+xml'], 'vsw' => ['application/vnd.visio'], 'vtf' => ['image/vnd.valve.source.texture'], 'vtt' => ['text/vtt'], 'vtu' => ['model/vnd.vtu'], 'vxml' => ['application/voicexml+xml'], 'w3d' => ['application/x-director'], 'wad' => ['application/x-doom', 'application/x-doom-wad', 'application/x-wii-wad'], 'wadl' => ['application/vnd.sun.wadl+xml'], 'war' => ['application/java-archive'], 'wasm' => ['application/wasm'], 'wav' => ['audio/wav', 'audio/vnd.wave', 'audio/wave', 'audio/x-wav'], 'wax' => ['application/x-ms-asx', 'audio/x-ms-asx', 'audio/x-ms-wax', 'video/x-ms-wax', 'video/x-ms-wmx', 'video/x-ms-wvx'], 'wb1' => ['application/x-quattropro'], 'wb2' => ['application/x-quattropro'], 'wb3' => ['application/x-quattropro'], 'wbmp' => ['image/vnd.wap.wbmp'], 'wbs' => ['application/vnd.criticaltools.wbs+xml'], 'wbxml' => ['application/vnd.wap.wbxml'], 'wcm' => ['application/vnd.ms-works'], 'wdb' => ['application/vnd.ms-works'], 'wdp' => ['image/vnd.ms-photo'], 'weba' => ['audio/webm'], 'webapp' => ['application/x-web-app-manifest+json'], 'webm' => ['video/webm'], 'webmanifest' => ['application/manifest+json'], 'webp' => ['image/webp'], 'wg' => ['application/vnd.pmi.widget'], 'wgt' => ['application/widget'], 'wim' => ['application/x-ms-wim'], 'wk1' => ['application/lotus123', 'application/vnd.lotus-1-2-3', 'application/wk1', 'application/x-123', 'application/x-lotus123', 'zz-application/zz-winassoc-123'], 'wk3' => ['application/lotus123', 'application/vnd.lotus-1-2-3', 'application/wk1', 'application/x-123', 'application/x-lotus123', 'zz-application/zz-winassoc-123'], 'wk4' => ['application/lotus123', 'application/vnd.lotus-1-2-3', 'application/wk1', 'application/x-123', 'application/x-lotus123', 'zz-application/zz-winassoc-123'], 'wkdownload' => ['application/x-partial-download'], 'wks' => ['application/lotus123', 'application/vnd.lotus-1-2-3', 'application/vnd.ms-works', 'application/wk1', 'application/x-123', 'application/x-lotus123', 'zz-application/zz-winassoc-123'], 'wm' => ['video/x-ms-wm'], 'wma' => ['audio/x-ms-wma', 'audio/wma'], 'wmd' => ['application/x-ms-wmd'], 'wmf' => ['application/wmf', 'application/x-msmetafile', 'application/x-wmf', 'image/wmf', 'image/x-win-metafile', 'image/x-wmf'], 'wml' => ['text/vnd.wap.wml'], 'wmlc' => ['application/vnd.wap.wmlc'], 'wmls' => ['text/vnd.wap.wmlscript'], 'wmlsc' => ['application/vnd.wap.wmlscriptc'], 'wmv' => ['audio/x-ms-wmv', 'video/x-ms-wmv'], 'wmx' => ['application/x-ms-asx', 'audio/x-ms-asx', 'video/x-ms-wax', 'video/x-ms-wmx', 'video/x-ms-wvx'], 'wmz' => ['application/x-ms-wmz', 'application/x-msmetafile'], 'woff' => ['application/font-woff', 'application/x-font-woff', 'font/woff'], 'woff2' => ['font/woff2'], 'wp' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], 'wp4' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], 'wp5' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], 'wp6' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], 'wpd' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], 'wpg' => ['application/x-wpg'], 'wpl' => ['application/vnd.ms-wpl'], 'wpp' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], 'wps' => ['application/vnd.ms-works'], 'wqd' => ['application/vnd.wqd'], 'wri' => ['application/x-mswrite'], 'wrl' => ['model/vrml'], 'ws' => ['application/x-wonderswan-rom'], 'wsc' => ['application/x-wonderswan-color-rom', 'message/vnd.wfa.wsc'], 'wsdl' => ['application/wsdl+xml'], 'wsgi' => ['text/x-python'], 'wspolicy' => ['application/wspolicy+xml'], 'wtb' => ['application/vnd.webturbo'], 'wv' => ['audio/x-wavpack'], 'wvc' => ['audio/x-wavpack-correction'], 'wvp' => ['audio/x-wavpack'], 'wvx' => ['application/x-ms-asx', 'audio/x-ms-asx', 'video/x-ms-wax', 'video/x-ms-wmx', 'video/x-ms-wvx'], 'wwf' => ['application/wwf', 'application/x-wwf'], 'x32' => ['application/x-authorware-bin'], 'x3d' => ['model/x3d+xml'], 'x3db' => ['model/x3d+binary', 'model/x3d+fastinfoset'], 'x3dbz' => ['model/x3d+binary'], 'x3dv' => ['model/x3d+vrml', 'model/x3d-vrml'], 'x3dvz' => ['model/x3d+vrml'], 'x3dz' => ['model/x3d+xml'], 'x3f' => ['image/x-sigma-x3f'], 'x_b' => ['model/vnd.parasolid.transmit.binary'], 'x_t' => ['model/vnd.parasolid.transmit.text'], 'xac' => ['application/x-gnucash'], 'xaml' => ['application/xaml+xml'], 'xap' => ['application/x-silverlight-app'], 'xar' => ['application/vnd.xara', 'application/x-xar'], 'xav' => ['application/xcap-att+xml'], 'xbap' => ['application/x-ms-xbap'], 'xbd' => ['application/vnd.fujixerox.docuworks.binder'], 'xbel' => ['application/x-xbel'], 'xbl' => ['application/xml', 'text/xml'], 'xbm' => ['image/x-xbitmap'], 'xca' => ['application/xcap-caps+xml'], 'xcf' => ['image/x-xcf'], 'xcf.bz2' => ['image/x-compressed-xcf'], 'xcf.gz' => ['image/x-compressed-xcf'], 'xcs' => ['application/calendar+xml'], 'xdf' => ['application/mrb-consumer+xml', 'application/mrb-publish+xml', 'application/xcap-diff+xml'], 'xdgapp' => ['application/vnd.flatpak', 'application/vnd.xdgapp'], 'xdm' => ['application/vnd.syncml.dm+xml'], 'xdp' => ['application/vnd.adobe.xdp+xml'], 'xdssc' => ['application/dssc+xml'], 'xdw' => ['application/vnd.fujixerox.docuworks'], 'xel' => ['application/xcap-el+xml'], 'xenc' => ['application/xenc+xml'], 'xer' => ['application/patch-ops-error+xml', 'application/xcap-error+xml'], 'xfdf' => ['application/vnd.adobe.xfdf'], 'xfdl' => ['application/vnd.xfdl'], 'xhe' => ['audio/usac'], 'xht' => ['application/xhtml+xml'], 'xhtml' => ['application/xhtml+xml'], 'xhvml' => ['application/xv+xml'], 'xi' => ['audio/x-xi'], 'xif' => ['image/vnd.xiff'], 'xla' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], 'xlam' => ['application/vnd.ms-excel.addin.macroenabled.12'], 'xlc' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], 'xld' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], 'xlf' => ['application/x-xliff', 'application/x-xliff+xml', 'application/xliff+xml'], 'xliff' => ['application/x-xliff', 'application/xliff+xml'], 'xll' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], 'xlm' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], 'xlr' => ['application/vnd.ms-works'], 'xls' => ['application/vnd.ms-excel', 'application/msexcel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], 'xlsb' => ['application/vnd.ms-excel.sheet.binary.macroenabled.12'], 'xlsm' => ['application/vnd.ms-excel.sheet.macroenabled.12'], 'xlsx' => ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'], 'xlt' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], 'xltm' => ['application/vnd.ms-excel.template.macroenabled.12'], 'xltx' => ['application/vnd.openxmlformats-officedocument.spreadsheetml.template'], 'xlw' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], 'xm' => ['audio/x-xm', 'audio/xm'], 'xmf' => ['audio/mobile-xmf', 'audio/x-xmf', 'audio/xmf'], 'xmi' => ['text/x-xmi'], 'xml' => ['application/xml', 'text/xml'], 'xns' => ['application/xcap-ns+xml'], 'xo' => ['application/vnd.olpc-sugar'], 'xop' => ['application/xop+xml'], 'xpi' => ['application/x-xpinstall'], 'xpl' => ['application/xproc+xml'], 'xpm' => ['image/x-xpixmap', 'image/x-xpm'], 'xpr' => ['application/vnd.is-xpr'], 'xps' => ['application/vnd.ms-xpsdocument', 'application/xps'], 'xpw' => ['application/vnd.intercon.formnet'], 'xpx' => ['application/vnd.intercon.formnet'], 'xsd' => ['application/xml', 'text/xml'], 'xsl' => ['application/xml', 'application/xslt+xml'], 'xslfo' => ['text/x-xslfo'], 'xslt' => ['application/xslt+xml'], 'xsm' => ['application/vnd.syncml+xml'], 'xspf' => ['application/x-xspf+xml', 'application/xspf+xml'], 'xul' => ['application/vnd.mozilla.xul+xml'], 'xvm' => ['application/xv+xml'], 'xvml' => ['application/xv+xml'], 'xwd' => ['image/x-xwindowdump'], 'xyz' => ['chemical/x-xyz'], 'xz' => ['application/x-xz'], 'yaml' => ['application/x-yaml', 'text/x-yaml', 'text/yaml'], 'yang' => ['application/yang'], 'yin' => ['application/yin+xml'], 'yml' => ['application/x-yaml', 'text/x-yaml', 'text/yaml'], 'ymp' => ['text/x-suse-ymp'], 'yt' => ['application/vnd.youtube.yt'], 'z1' => ['application/x-zmachine'], 'z2' => ['application/x-zmachine'], 'z3' => ['application/x-zmachine'], 'z4' => ['application/x-zmachine'], 'z5' => ['application/x-zmachine'], 'z6' => ['application/x-zmachine'], 'z64' => ['application/x-n64-rom'], 'z7' => ['application/x-zmachine'], 'z8' => ['application/x-zmachine'], 'zabw' => ['application/x-abiword'], 'zaz' => ['application/vnd.zzazz.deck+xml'], 'zip' => ['application/zip', 'application/x-zip', 'application/x-zip-compressed'], 'zir' => ['application/vnd.zul'], 'zirz' => ['application/vnd.zul'], 'zmm' => ['application/vnd.handheld-entertainment+xml'], 'zoo' => ['application/x-zoo'], 'zsav' => ['application/x-spss-sav', 'application/x-spss-savefile'], 'zst' => ['application/zstd'], 'zz' => ['application/zlib'], '123' => ['application/lotus123', 'application/vnd.lotus-1-2-3', 'application/wk1', 'application/x-123', 'application/x-lotus123', 'zz-application/zz-winassoc-123'], '602' => ['application/x-t602'], '669' => ['audio/x-mod'], ]; } PKdZ  #Resources/bin/update_mime_types.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ if ('cli' !== \PHP_SAPI) { throw new Exception('This script must be run from the command line.'); } // load new map $data = json_decode(file_get_contents('https://cdn.jsdelivr.net/gh/jshttp/mime-db@v1.49.0/db.json'), true); $new = []; foreach ($data as $mimeType => $mimeTypeInformation) { if (!array_key_exists('extensions', $mimeTypeInformation)) { continue; } $new[$mimeType] = $mimeTypeInformation['extensions']; } $xml = simplexml_load_string(file_get_contents('https://gitlab.freedesktop.org/xdg/shared-mime-info/-/raw/master/data/freedesktop.org.xml.in')); 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]); } $data = $pre; // reverse map // we prefill the extensions with some preferences for content-types $exts = [ 'asice' => ['application/vnd.etsi.asic-e+zip'], 'bz2' => ['application/x-bz2'], 'csv' => ['text/csv'], 'ecma' => ['application/ecmascript'], 'flv' => ['video/x-flv'], 'gif' => ['image/gif'], 'gz' => ['application/x-gzip'], 'htm' => ['text/html'], 'html' => ['text/html'], 'jar' => ['application/x-java-archive'], 'jpg' => ['image/jpeg'], 'js' => ['text/javascript'], 'keynote' => ['application/vnd.apple.keynote'], 'key' => ['application/vnd.apple.keynote'], 'm3u' => ['audio/x-mpegurl'], 'm4a' => ['audio/mp4'], 'md' => ['text/markdown', 'text/x-markdown'], 'mdb' => ['application/x-msaccess'], 'mid' => ['audio/midi'], 'mov' => ['video/quicktime'], 'mp3' => ['audio/mpeg'], 'ogg' => ['audio/ogg'], 'pdf' => ['application/pdf'], 'php' => ['application/x-php'], 'ppt' => ['application/vnd.ms-powerpoint'], 'rar' => ['application/x-rar-compressed'], 'hqx' => ['application/stuffit'], 'sit' => ['application/x-stuffit', 'application/stuffit'], 'svg' => ['image/svg+xml'], 'tar' => ['application/x-tar'], 'tif' => ['image/tiff'], 'ttf' => ['application/x-font-truetype'], 'vcf' => ['text/x-vcard'], 'wav' => ['audio/wav'], 'wma' => ['audio/x-ms-wma'], 'wmv' => ['audio/x-ms-wmv'], 'xls' => ['application/vnd.ms-excel'], 'zip' => ['application/zip'], ]; // we merge the 2 maps (we never remove old mime types) $map = array_replace_recursive($current, $new); foreach ($exts as $ext => $types) { foreach ($types as $mt) { if (!isset($map[$mt])) { $map += [$mt => [$ext]]; } } } ksort($map); foreach ($map as $mimeType => $extensions) { foreach ($exts as $ext => $types) { if (in_array($mimeType, $types, true)) { array_unshift($extensions, $ext); } } $data .= sprintf(" '%s' => ['%s'],\n", $mimeType, implode("', '", array_unique($extensions))); } $data .= $post; foreach ($map as $mimeType => $extensions) { foreach ($extensions as $extension) { if ('application/octet-stream' === $mimeType && 'bin' !== $extension) { continue; } $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"; PKdZӆ)BodyRendererInterface.phpnu[ * * 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 */ interface BodyRendererInterface { public function render(Message $message): void; } PKdZVE  MimeTypesInterface.phpnu[PKdZ {??.ODependencyInjection/AddMimeTypeGuesserPass.phpnu[PKdZC^^FileinfoMimeTypeGuesser.phpnu[PKdZeRawMessage.phpnu[PKdZvv composer.jsonnu[PKdZAnKK tCHANGELOG.mdnu[PKdZQ::MimeTypeGuesserInterface.phpnu[PKdZkH!Exception/LogicException.phpnu[PKdZ'&p#Exception/InvalidArgumentException.phpnu[PKdZЕ%}%Exception/AddressEncoderException.phpnu[PKdZFz$g'Exception/RfcComplianceException.phpnu[PKdZ{ p)Exception/ExceptionInterface.phpnu[PKdZr)H+Exception/RuntimeException.phpnu[PKdZcEl =-Message.phpnu[PKdZgא >FileBinaryMimeTypeGuesser.phpnu[PKdZ'?5HPart/Multipart/MixedPart.phpnu[PKdZz~kkJPart/Multipart/RelatedPart.phpnu[PKdZ;cUPPart/Multipart/DigestPart.phpnu[PKdZU. XSPart/Multipart/FormDataPart.phpnu[PKdZS''"p`Part/Multipart/AlternativePart.phpnu[PKdZaT ) ) bPart/AbstractMultipartPart.phpnu[PKdZ"1 1 `lPart/SMimePart.phpnu[PKdZvPart/AbstractPart.phpnu[PKdZzAR}Part/TextPart.phpnu[PKdZs"Part/MessagePart.phpnu[PKdZ^Part/DataPart.phpnu[PKdZ 8ic%c%CharacterStream.phpnu[PKdZlGyAyA Email.phpnu[PKdZ iCrypto/SMime.phpnu[PKdZW&h#Crypto/DkimOptions.phpnu[PKdZ*Crypto/DkimSigner.phpnu[PKdZ$TJCrypto/SMimeEncrypter.phpnu[PKdZ\ SCrypto/SMimeSigner.phpnu[PKdZ# ^README.mdnu[PKdZ&Khh(`Test/Constraint/EmailAddressContains.phpnu[PKdZME )iTest/Constraint/EmailHtmlBodyContains.phpnu[PKdZGdg88#eoTest/Constraint/EmailHeaderSame.phpnu[PKdZ:pz5)vTest/Constraint/EmailTextBodyContains.phpnu[PKdZģg0(|Test/Constraint/EmailAttachmentCount.phpnu[PKdZ "Test/Constraint/EmailHasHeader.phpnu[PKdZCfEncoder/EncoderInterface.phpnu[PKdZiq &Encoder/MimeHeaderEncoderInterface.phpnu[PKdZ'Encoder/QpContentEncoder.phpnu[PKdZ<ھYEncoder/QpEncoder.phpnu[PKdZr L1Encoder/IdnAddressEncoder.phpnu[PKdZ[9Encoder/Rfc2231Encoder.phpnu[PKdZ`// }Encoder/Base64ContentEncoder.phpnu[PKdZ"z33Encoder/QpMimeHeaderEncoder.phpnu[PKdZƑ}~Encoder/Base64Encoder.phpnu[PKdZ͒#Encoder/ContentEncoderInterface.phpnu[PKdZ%#Encoder/AddressEncoderInterface.phpnu[PKdZ&jC#Encoder/Base64MimeHeaderEncoder.phpnu[PKdZ{5BB"Encoder/EightBitContentEncoder.phpnu[PKdZYh[))LICENSEnu[PKdZ;/S  Address.phpnu[PKdZ#?Header/UnstructuredHeader.phpnu[PKdZ#;O O  Header/MailboxListHeader.phpnu[PKdZr pHeader/ParameterizedHeader.phpnu[PKdZ0k> > Header/IdentificationHeader.phpnu[PKdZQ7?)?)W%Header/AbstractHeader.phpnu[PKdZëF!!NHeader/Headers.phpnu[PKdZ b#pHeader/PathHeader.phpnu[PKdZuHeader/DateHeader.phpnu[PKdZ#9jj |Header/HeaderInterface.phpnu[PKdZ1ޜHeader/MailboxHeader.phpnu[PKdZ^ccMessageConverter.phpnu[PKdZ  JMimeTypes.phpnu[PKdZ  #7bResources/bin/update_mime_types.phpnu[PKdZӆ)uBodyRendererInterface.phpnu[PKEEU~w