git subrepo commit (merge) mailcow/src/mailcow-dockerized
subrepo: subdir: "mailcow/src/mailcow-dockerized"
merged: "02ae5285"
upstream: origin: "https://github.com/mailcow/mailcow-dockerized.git"
branch: "master"
commit: "649a5c01"
git-subrepo: version: "0.4.3"
origin: "???"
commit: "???"
Change-Id: I870ad468fba026cc5abf3c5699ed1e12ff28b32b
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/ArrayLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/ArrayLoader.php
new file mode 100644
index 0000000..0758da8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/ArrayLoader.php
@@ -0,0 +1,58 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * ArrayLoader loads translations from a PHP array.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ArrayLoader implements LoaderInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, string $locale, string $domain = 'messages')
+ {
+ $resource = $this->flatten($resource);
+ $catalogue = new MessageCatalogue($locale);
+ $catalogue->add($resource, $domain);
+
+ return $catalogue;
+ }
+
+ /**
+ * Flattens an nested array of translations.
+ *
+ * The scheme used is:
+ * 'key' => ['key2' => ['key3' => 'value']]
+ * Becomes:
+ * 'key.key2.key3' => 'value'
+ */
+ private function flatten(array $messages): array
+ {
+ $result = [];
+ foreach ($messages as $key => $value) {
+ if (\is_array($value)) {
+ foreach ($this->flatten($value) as $k => $v) {
+ $result[$key.'.'.$k] = $v;
+ }
+ } else {
+ $result[$key] = $value;
+ }
+ }
+
+ return $result;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/CsvFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/CsvFileLoader.php
new file mode 100644
index 0000000..8d5d4db
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/CsvFileLoader.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+
+/**
+ * CsvFileLoader loads translations from CSV files.
+ *
+ * @author Saša Stamenković <umpirsky@gmail.com>
+ */
+class CsvFileLoader extends FileLoader
+{
+ private $delimiter = ';';
+ private $enclosure = '"';
+ private $escape = '\\';
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function loadResource(string $resource)
+ {
+ $messages = [];
+
+ try {
+ $file = new \SplFileObject($resource, 'rb');
+ } catch (\RuntimeException $e) {
+ throw new NotFoundResourceException(sprintf('Error opening file "%s".', $resource), 0, $e);
+ }
+
+ $file->setFlags(\SplFileObject::READ_CSV | \SplFileObject::SKIP_EMPTY);
+ $file->setCsvControl($this->delimiter, $this->enclosure, $this->escape);
+
+ foreach ($file as $data) {
+ if (false === $data) {
+ continue;
+ }
+
+ if ('#' !== substr($data[0], 0, 1) && isset($data[1]) && 2 === \count($data)) {
+ $messages[$data[0]] = $data[1];
+ }
+ }
+
+ return $messages;
+ }
+
+ /**
+ * Sets the delimiter, enclosure, and escape character for CSV.
+ */
+ public function setCsvControl(string $delimiter = ';', string $enclosure = '"', string $escape = '\\')
+ {
+ $this->delimiter = $delimiter;
+ $this->enclosure = $enclosure;
+ $this->escape = $escape;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/FileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/FileLoader.php
new file mode 100644
index 0000000..4725ea6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/FileLoader.php
@@ -0,0 +1,63 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Config\Resource\FileResource;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+
+/**
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+abstract class FileLoader extends ArrayLoader
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, string $locale, string $domain = 'messages')
+ {
+ if (!stream_is_local($resource)) {
+ throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ }
+
+ if (!file_exists($resource)) {
+ throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ }
+
+ $messages = $this->loadResource($resource);
+
+ // empty resource
+ if (null === $messages) {
+ $messages = [];
+ }
+
+ // not an array
+ if (!\is_array($messages)) {
+ throw new InvalidResourceException(sprintf('Unable to load file "%s".', $resource));
+ }
+
+ $catalogue = parent::load($messages, $locale, $domain);
+
+ if (class_exists(FileResource::class)) {
+ $catalogue->addResource(new FileResource($resource));
+ }
+
+ return $catalogue;
+ }
+
+ /**
+ * @return array
+ *
+ * @throws InvalidResourceException if stream content has an invalid format
+ */
+ abstract protected function loadResource(string $resource);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IcuDatFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IcuDatFileLoader.php
new file mode 100644
index 0000000..2a1aecc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IcuDatFileLoader.php
@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Config\Resource\FileResource;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * IcuResFileLoader loads translations from a resource bundle.
+ *
+ * @author stealth35
+ */
+class IcuDatFileLoader extends IcuResFileLoader
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, string $locale, string $domain = 'messages')
+ {
+ if (!stream_is_local($resource.'.dat')) {
+ throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ }
+
+ if (!file_exists($resource.'.dat')) {
+ throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ }
+
+ try {
+ $rb = new \ResourceBundle($locale, $resource);
+ } catch (\Exception $e) {
+ $rb = null;
+ }
+
+ if (!$rb) {
+ throw new InvalidResourceException(sprintf('Cannot load resource "%s".', $resource));
+ } elseif (intl_is_failure($rb->getErrorCode())) {
+ throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode());
+ }
+
+ $messages = $this->flatten($rb);
+ $catalogue = new MessageCatalogue($locale);
+ $catalogue->add($messages, $domain);
+
+ if (class_exists(FileResource::class)) {
+ $catalogue->addResource(new FileResource($resource.'.dat'));
+ }
+
+ return $catalogue;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IcuResFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IcuResFileLoader.php
new file mode 100644
index 0000000..64bbd3e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IcuResFileLoader.php
@@ -0,0 +1,91 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Config\Resource\DirectoryResource;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * IcuResFileLoader loads translations from a resource bundle.
+ *
+ * @author stealth35
+ */
+class IcuResFileLoader implements LoaderInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, string $locale, string $domain = 'messages')
+ {
+ if (!stream_is_local($resource)) {
+ throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ }
+
+ if (!is_dir($resource)) {
+ throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ }
+
+ try {
+ $rb = new \ResourceBundle($locale, $resource);
+ } catch (\Exception $e) {
+ $rb = null;
+ }
+
+ if (!$rb) {
+ throw new InvalidResourceException(sprintf('Cannot load resource "%s".', $resource));
+ } elseif (intl_is_failure($rb->getErrorCode())) {
+ throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode());
+ }
+
+ $messages = $this->flatten($rb);
+ $catalogue = new MessageCatalogue($locale);
+ $catalogue->add($messages, $domain);
+
+ if (class_exists(DirectoryResource::class)) {
+ $catalogue->addResource(new DirectoryResource($resource));
+ }
+
+ return $catalogue;
+ }
+
+ /**
+ * Flattens an ResourceBundle.
+ *
+ * The scheme used is:
+ * key { key2 { key3 { "value" } } }
+ * Becomes:
+ * 'key.key2.key3' => 'value'
+ *
+ * This function takes an array by reference and will modify it
+ *
+ * @param \ResourceBundle $rb The ResourceBundle that will be flattened
+ * @param array $messages Used internally for recursive calls
+ * @param string $path Current path being parsed, used internally for recursive calls
+ *
+ * @return array the flattened ResourceBundle
+ */
+ protected function flatten(\ResourceBundle $rb, array &$messages = [], string $path = null)
+ {
+ foreach ($rb as $key => $value) {
+ $nodePath = $path ? $path.'.'.$key : $key;
+ if ($value instanceof \ResourceBundle) {
+ $this->flatten($value, $messages, $nodePath);
+ } else {
+ $messages[$nodePath] = $value;
+ }
+ }
+
+ return $messages;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IniFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IniFileLoader.php
new file mode 100644
index 0000000..7398f77
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IniFileLoader.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+/**
+ * IniFileLoader loads translations from an ini file.
+ *
+ * @author stealth35
+ */
+class IniFileLoader extends FileLoader
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function loadResource(string $resource)
+ {
+ return parse_ini_file($resource, true);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/JsonFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/JsonFileLoader.php
new file mode 100644
index 0000000..5aefba0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/JsonFileLoader.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+
+/**
+ * JsonFileLoader loads translations from an json file.
+ *
+ * @author singles
+ */
+class JsonFileLoader extends FileLoader
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function loadResource(string $resource)
+ {
+ $messages = [];
+ if ($data = file_get_contents($resource)) {
+ $messages = json_decode($data, true);
+
+ if (0 < $errorCode = json_last_error()) {
+ throw new InvalidResourceException('Error parsing JSON: '.$this->getJSONErrorMessage($errorCode));
+ }
+ }
+
+ return $messages;
+ }
+
+ /**
+ * Translates JSON_ERROR_* constant into meaningful message.
+ */
+ private function getJSONErrorMessage(int $errorCode): string
+ {
+ switch ($errorCode) {
+ case \JSON_ERROR_DEPTH:
+ return 'Maximum stack depth exceeded';
+ case \JSON_ERROR_STATE_MISMATCH:
+ return 'Underflow or the modes mismatch';
+ case \JSON_ERROR_CTRL_CHAR:
+ return 'Unexpected control character found';
+ case \JSON_ERROR_SYNTAX:
+ return 'Syntax error, malformed JSON';
+ case \JSON_ERROR_UTF8:
+ return 'Malformed UTF-8 characters, possibly incorrectly encoded';
+ default:
+ return 'Unknown error';
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/LoaderInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/LoaderInterface.php
new file mode 100644
index 0000000..2073f2b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/LoaderInterface.php
@@ -0,0 +1,38 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * LoaderInterface is the interface implemented by all translation loaders.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface LoaderInterface
+{
+ /**
+ * Loads a locale.
+ *
+ * @param mixed $resource A resource
+ * @param string $locale A locale
+ * @param string $domain The domain
+ *
+ * @return MessageCatalogue A MessageCatalogue instance
+ *
+ * @throws NotFoundResourceException when the resource cannot be found
+ * @throws InvalidResourceException when the resource cannot be loaded
+ */
+ public function load($resource, string $locale, string $domain = 'messages');
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/MoFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/MoFileLoader.php
new file mode 100644
index 0000000..0ff6549
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/MoFileLoader.php
@@ -0,0 +1,140 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+
+/**
+ * @copyright Copyright (c) 2010, Union of RAD http://union-of-rad.org (http://lithify.me/)
+ */
+class MoFileLoader extends FileLoader
+{
+ /**
+ * Magic used for validating the format of an MO file as well as
+ * detecting if the machine used to create that file was little endian.
+ */
+ public const MO_LITTLE_ENDIAN_MAGIC = 0x950412de;
+
+ /**
+ * Magic used for validating the format of an MO file as well as
+ * detecting if the machine used to create that file was big endian.
+ */
+ public const MO_BIG_ENDIAN_MAGIC = 0xde120495;
+
+ /**
+ * The size of the header of an MO file in bytes.
+ */
+ public const MO_HEADER_SIZE = 28;
+
+ /**
+ * Parses machine object (MO) format, independent of the machine's endian it
+ * was created on. Both 32bit and 64bit systems are supported.
+ *
+ * {@inheritdoc}
+ */
+ protected function loadResource(string $resource)
+ {
+ $stream = fopen($resource, 'r');
+
+ $stat = fstat($stream);
+
+ if ($stat['size'] < self::MO_HEADER_SIZE) {
+ throw new InvalidResourceException('MO stream content has an invalid format.');
+ }
+ $magic = unpack('V1', fread($stream, 4));
+ $magic = hexdec(substr(dechex(current($magic)), -8));
+
+ if (self::MO_LITTLE_ENDIAN_MAGIC == $magic) {
+ $isBigEndian = false;
+ } elseif (self::MO_BIG_ENDIAN_MAGIC == $magic) {
+ $isBigEndian = true;
+ } else {
+ throw new InvalidResourceException('MO stream content has an invalid format.');
+ }
+
+ // formatRevision
+ $this->readLong($stream, $isBigEndian);
+ $count = $this->readLong($stream, $isBigEndian);
+ $offsetId = $this->readLong($stream, $isBigEndian);
+ $offsetTranslated = $this->readLong($stream, $isBigEndian);
+ // sizeHashes
+ $this->readLong($stream, $isBigEndian);
+ // offsetHashes
+ $this->readLong($stream, $isBigEndian);
+
+ $messages = [];
+
+ for ($i = 0; $i < $count; ++$i) {
+ $pluralId = null;
+ $translated = null;
+
+ fseek($stream, $offsetId + $i * 8);
+
+ $length = $this->readLong($stream, $isBigEndian);
+ $offset = $this->readLong($stream, $isBigEndian);
+
+ if ($length < 1) {
+ continue;
+ }
+
+ fseek($stream, $offset);
+ $singularId = fread($stream, $length);
+
+ if (str_contains($singularId, "\000")) {
+ [$singularId, $pluralId] = explode("\000", $singularId);
+ }
+
+ fseek($stream, $offsetTranslated + $i * 8);
+ $length = $this->readLong($stream, $isBigEndian);
+ $offset = $this->readLong($stream, $isBigEndian);
+
+ if ($length < 1) {
+ continue;
+ }
+
+ fseek($stream, $offset);
+ $translated = fread($stream, $length);
+
+ if (str_contains($translated, "\000")) {
+ $translated = explode("\000", $translated);
+ }
+
+ $ids = ['singular' => $singularId, 'plural' => $pluralId];
+ $item = compact('ids', 'translated');
+
+ if (!empty($item['ids']['singular'])) {
+ $id = $item['ids']['singular'];
+ if (isset($item['ids']['plural'])) {
+ $id .= '|'.$item['ids']['plural'];
+ }
+ $messages[$id] = stripcslashes(implode('|', (array) $item['translated']));
+ }
+ }
+
+ fclose($stream);
+
+ return array_filter($messages);
+ }
+
+ /**
+ * Reads an unsigned long from stream respecting endianness.
+ *
+ * @param resource $stream
+ */
+ private function readLong($stream, bool $isBigEndian): int
+ {
+ $result = unpack($isBigEndian ? 'N1' : 'V1', fread($stream, 4));
+ $result = current($result);
+
+ return (int) substr($result, -8);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/PhpFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/PhpFileLoader.php
new file mode 100644
index 0000000..85f1090
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/PhpFileLoader.php
@@ -0,0 +1,42 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+/**
+ * PhpFileLoader loads translations from PHP files returning an array of translations.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class PhpFileLoader extends FileLoader
+{
+ private static $cache = [];
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function loadResource(string $resource)
+ {
+ if ([] === self::$cache && \function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) || filter_var(ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN))) {
+ self::$cache = null;
+ }
+
+ if (null === self::$cache) {
+ return require $resource;
+ }
+
+ if (isset(self::$cache[$resource])) {
+ return self::$cache[$resource];
+ }
+
+ return self::$cache[$resource] = require $resource;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/PoFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/PoFileLoader.php
new file mode 100644
index 0000000..ee143e2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/PoFileLoader.php
@@ -0,0 +1,149 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+/**
+ * @copyright Copyright (c) 2010, Union of RAD https://github.com/UnionOfRAD/lithium
+ * @copyright Copyright (c) 2012, Clemens Tolboom
+ */
+class PoFileLoader extends FileLoader
+{
+ /**
+ * Parses portable object (PO) format.
+ *
+ * From https://www.gnu.org/software/gettext/manual/gettext.html#PO-Files
+ * we should be able to parse files having:
+ *
+ * white-space
+ * # translator-comments
+ * #. extracted-comments
+ * #: reference...
+ * #, flag...
+ * #| msgid previous-untranslated-string
+ * msgid untranslated-string
+ * msgstr translated-string
+ *
+ * extra or different lines are:
+ *
+ * #| msgctxt previous-context
+ * #| msgid previous-untranslated-string
+ * msgctxt context
+ *
+ * #| msgid previous-untranslated-string-singular
+ * #| msgid_plural previous-untranslated-string-plural
+ * msgid untranslated-string-singular
+ * msgid_plural untranslated-string-plural
+ * msgstr[0] translated-string-case-0
+ * ...
+ * msgstr[N] translated-string-case-n
+ *
+ * The definition states:
+ * - white-space and comments are optional.
+ * - msgid "" that an empty singleline defines a header.
+ *
+ * This parser sacrifices some features of the reference implementation the
+ * differences to that implementation are as follows.
+ * - No support for comments spanning multiple lines.
+ * - Translator and extracted comments are treated as being the same type.
+ * - Message IDs are allowed to have other encodings as just US-ASCII.
+ *
+ * Items with an empty id are ignored.
+ *
+ * {@inheritdoc}
+ */
+ protected function loadResource(string $resource)
+ {
+ $stream = fopen($resource, 'r');
+
+ $defaults = [
+ 'ids' => [],
+ 'translated' => null,
+ ];
+
+ $messages = [];
+ $item = $defaults;
+ $flags = [];
+
+ while ($line = fgets($stream)) {
+ $line = trim($line);
+
+ if ('' === $line) {
+ // Whitespace indicated current item is done
+ if (!\in_array('fuzzy', $flags)) {
+ $this->addMessage($messages, $item);
+ }
+ $item = $defaults;
+ $flags = [];
+ } elseif ('#,' === substr($line, 0, 2)) {
+ $flags = array_map('trim', explode(',', substr($line, 2)));
+ } elseif ('msgid "' === substr($line, 0, 7)) {
+ // We start a new msg so save previous
+ // TODO: this fails when comments or contexts are added
+ $this->addMessage($messages, $item);
+ $item = $defaults;
+ $item['ids']['singular'] = substr($line, 7, -1);
+ } elseif ('msgstr "' === substr($line, 0, 8)) {
+ $item['translated'] = substr($line, 8, -1);
+ } elseif ('"' === $line[0]) {
+ $continues = isset($item['translated']) ? 'translated' : 'ids';
+
+ if (\is_array($item[$continues])) {
+ end($item[$continues]);
+ $item[$continues][key($item[$continues])] .= substr($line, 1, -1);
+ } else {
+ $item[$continues] .= substr($line, 1, -1);
+ }
+ } elseif ('msgid_plural "' === substr($line, 0, 14)) {
+ $item['ids']['plural'] = substr($line, 14, -1);
+ } elseif ('msgstr[' === substr($line, 0, 7)) {
+ $size = strpos($line, ']');
+ $item['translated'][(int) substr($line, 7, 1)] = substr($line, $size + 3, -1);
+ }
+ }
+ // save last item
+ if (!\in_array('fuzzy', $flags)) {
+ $this->addMessage($messages, $item);
+ }
+ fclose($stream);
+
+ return $messages;
+ }
+
+ /**
+ * Save a translation item to the messages.
+ *
+ * A .po file could contain by error missing plural indexes. We need to
+ * fix these before saving them.
+ */
+ private function addMessage(array &$messages, array $item)
+ {
+ if (!empty($item['ids']['singular'])) {
+ $id = stripcslashes($item['ids']['singular']);
+ if (isset($item['ids']['plural'])) {
+ $id .= '|'.stripcslashes($item['ids']['plural']);
+ }
+
+ $translated = (array) $item['translated'];
+ // PO are by definition indexed so sort by index.
+ ksort($translated);
+ // Make sure every index is filled.
+ end($translated);
+ $count = key($translated);
+ // Fill missing spots with '-'.
+ $empties = array_fill(0, $count + 1, '-');
+ $translated += $empties;
+ ksort($translated);
+
+ $messages[$id] = stripcslashes(implode('|', $translated));
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/QtFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/QtFileLoader.php
new file mode 100644
index 0000000..9cf2fe9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/QtFileLoader.php
@@ -0,0 +1,82 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Config\Resource\FileResource;
+use Symfony\Component\Config\Util\XmlUtils;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Translation\Exception\RuntimeException;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * QtFileLoader loads translations from QT Translations XML files.
+ *
+ * @author Benjamin Eberlei <kontakt@beberlei.de>
+ */
+class QtFileLoader implements LoaderInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, string $locale, string $domain = 'messages')
+ {
+ if (!class_exists(XmlUtils::class)) {
+ throw new RuntimeException('Loading translations from the QT format requires the Symfony Config component.');
+ }
+
+ if (!stream_is_local($resource)) {
+ throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ }
+
+ if (!file_exists($resource)) {
+ throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ }
+
+ try {
+ $dom = XmlUtils::loadFile($resource);
+ } catch (\InvalidArgumentException $e) {
+ throw new InvalidResourceException(sprintf('Unable to load "%s".', $resource), $e->getCode(), $e);
+ }
+
+ $internalErrors = libxml_use_internal_errors(true);
+ libxml_clear_errors();
+
+ $xpath = new \DOMXPath($dom);
+ $nodes = $xpath->evaluate('//TS/context/name[text()="'.$domain.'"]');
+
+ $catalogue = new MessageCatalogue($locale);
+ if (1 == $nodes->length) {
+ $translations = $nodes->item(0)->nextSibling->parentNode->parentNode->getElementsByTagName('message');
+ foreach ($translations as $translation) {
+ $translationValue = (string) $translation->getElementsByTagName('translation')->item(0)->nodeValue;
+
+ if (!empty($translationValue)) {
+ $catalogue->set(
+ (string) $translation->getElementsByTagName('source')->item(0)->nodeValue,
+ $translationValue,
+ $domain
+ );
+ }
+ $translation = $translation->nextSibling;
+ }
+
+ if (class_exists(FileResource::class)) {
+ $catalogue->addResource(new FileResource($resource));
+ }
+ }
+
+ libxml_use_internal_errors($internalErrors);
+
+ return $catalogue;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/XliffFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/XliffFileLoader.php
new file mode 100644
index 0000000..35ad33e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/XliffFileLoader.php
@@ -0,0 +1,232 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Config\Resource\FileResource;
+use Symfony\Component\Config\Util\Exception\InvalidXmlException;
+use Symfony\Component\Config\Util\Exception\XmlParsingException;
+use Symfony\Component\Config\Util\XmlUtils;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Translation\Exception\RuntimeException;
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Util\XliffUtils;
+
+/**
+ * XliffFileLoader loads translations from XLIFF files.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class XliffFileLoader implements LoaderInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, string $locale, string $domain = 'messages')
+ {
+ if (!class_exists(XmlUtils::class)) {
+ throw new RuntimeException('Loading translations from the Xliff format requires the Symfony Config component.');
+ }
+
+ if (!$this->isXmlString($resource)) {
+ if (!stream_is_local($resource)) {
+ throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ }
+
+ if (!file_exists($resource)) {
+ throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ }
+
+ if (!is_file($resource)) {
+ throw new InvalidResourceException(sprintf('This is neither a file nor an XLIFF string "%s".', $resource));
+ }
+ }
+
+ try {
+ if ($this->isXmlString($resource)) {
+ $dom = XmlUtils::parse($resource);
+ } else {
+ $dom = XmlUtils::loadFile($resource);
+ }
+ } catch (\InvalidArgumentException | XmlParsingException | InvalidXmlException $e) {
+ throw new InvalidResourceException(sprintf('Unable to load "%s": ', $resource).$e->getMessage(), $e->getCode(), $e);
+ }
+
+ if ($errors = XliffUtils::validateSchema($dom)) {
+ throw new InvalidResourceException(sprintf('Invalid resource provided: "%s"; Errors: ', $resource).XliffUtils::getErrorsAsString($errors));
+ }
+
+ $catalogue = new MessageCatalogue($locale);
+ $this->extract($dom, $catalogue, $domain);
+
+ if (is_file($resource) && class_exists(FileResource::class)) {
+ $catalogue->addResource(new FileResource($resource));
+ }
+
+ return $catalogue;
+ }
+
+ private function extract(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain)
+ {
+ $xliffVersion = XliffUtils::getVersionNumber($dom);
+
+ if ('1.2' === $xliffVersion) {
+ $this->extractXliff1($dom, $catalogue, $domain);
+ }
+
+ if ('2.0' === $xliffVersion) {
+ $this->extractXliff2($dom, $catalogue, $domain);
+ }
+ }
+
+ /**
+ * Extract messages and metadata from DOMDocument into a MessageCatalogue.
+ */
+ private function extractXliff1(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain)
+ {
+ $xml = simplexml_import_dom($dom);
+ $encoding = $dom->encoding ? strtoupper($dom->encoding) : null;
+
+ $namespace = 'urn:oasis:names:tc:xliff:document:1.2';
+ $xml->registerXPathNamespace('xliff', $namespace);
+
+ foreach ($xml->xpath('//xliff:file') as $file) {
+ $fileAttributes = $file->attributes();
+
+ $file->registerXPathNamespace('xliff', $namespace);
+
+ foreach ($file->xpath('.//xliff:trans-unit') as $translation) {
+ $attributes = $translation->attributes();
+
+ if (!(isset($attributes['resname']) || isset($translation->source))) {
+ continue;
+ }
+
+ $source = isset($attributes['resname']) && $attributes['resname'] ? $attributes['resname'] : $translation->source;
+ // If the xlf file has another encoding specified, try to convert it because
+ // simple_xml will always return utf-8 encoded values
+ $target = $this->utf8ToCharset((string) ($translation->target ?? $translation->source), $encoding);
+
+ $catalogue->set((string) $source, $target, $domain);
+
+ $metadata = [
+ 'source' => (string) $translation->source,
+ 'file' => [
+ 'original' => (string) $fileAttributes['original'],
+ ],
+ ];
+ if ($notes = $this->parseNotesMetadata($translation->note, $encoding)) {
+ $metadata['notes'] = $notes;
+ }
+
+ if (isset($translation->target) && $translation->target->attributes()) {
+ $metadata['target-attributes'] = [];
+ foreach ($translation->target->attributes() as $key => $value) {
+ $metadata['target-attributes'][$key] = (string) $value;
+ }
+ }
+
+ if (isset($attributes['id'])) {
+ $metadata['id'] = (string) $attributes['id'];
+ }
+
+ $catalogue->setMetadata((string) $source, $metadata, $domain);
+ }
+ }
+ }
+
+ private function extractXliff2(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain)
+ {
+ $xml = simplexml_import_dom($dom);
+ $encoding = $dom->encoding ? strtoupper($dom->encoding) : null;
+
+ $xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:2.0');
+
+ foreach ($xml->xpath('//xliff:unit') as $unit) {
+ foreach ($unit->segment as $segment) {
+ $attributes = $unit->attributes();
+ $source = $attributes['name'] ?? $segment->source;
+
+ // If the xlf file has another encoding specified, try to convert it because
+ // simple_xml will always return utf-8 encoded values
+ $target = $this->utf8ToCharset((string) ($segment->target ?? $segment->source), $encoding);
+
+ $catalogue->set((string) $source, $target, $domain);
+
+ $metadata = [];
+ if (isset($segment->target) && $segment->target->attributes()) {
+ $metadata['target-attributes'] = [];
+ foreach ($segment->target->attributes() as $key => $value) {
+ $metadata['target-attributes'][$key] = (string) $value;
+ }
+ }
+
+ if (isset($unit->notes)) {
+ $metadata['notes'] = [];
+ foreach ($unit->notes->note as $noteNode) {
+ $note = [];
+ foreach ($noteNode->attributes() as $key => $value) {
+ $note[$key] = (string) $value;
+ }
+ $note['content'] = (string) $noteNode;
+ $metadata['notes'][] = $note;
+ }
+ }
+
+ $catalogue->setMetadata((string) $source, $metadata, $domain);
+ }
+ }
+ }
+
+ /**
+ * Convert a UTF8 string to the specified encoding.
+ */
+ private function utf8ToCharset(string $content, string $encoding = null): string
+ {
+ if ('UTF-8' !== $encoding && !empty($encoding)) {
+ return mb_convert_encoding($content, $encoding, 'UTF-8');
+ }
+
+ return $content;
+ }
+
+ private function parseNotesMetadata(\SimpleXMLElement $noteElement = null, string $encoding = null): array
+ {
+ $notes = [];
+
+ if (null === $noteElement) {
+ return $notes;
+ }
+
+ /** @var \SimpleXMLElement $xmlNote */
+ foreach ($noteElement as $xmlNote) {
+ $noteAttributes = $xmlNote->attributes();
+ $note = ['content' => $this->utf8ToCharset((string) $xmlNote, $encoding)];
+ if (isset($noteAttributes['priority'])) {
+ $note['priority'] = (int) $noteAttributes['priority'];
+ }
+
+ if (isset($noteAttributes['from'])) {
+ $note['from'] = (string) $noteAttributes['from'];
+ }
+
+ $notes[] = $note;
+ }
+
+ return $notes;
+ }
+
+ private function isXmlString(string $resource): bool
+ {
+ return 0 === strpos($resource, '<?xml');
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/YamlFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/YamlFileLoader.php
new file mode 100644
index 0000000..8588e18
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/YamlFileLoader.php
@@ -0,0 +1,54 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\LogicException;
+use Symfony\Component\Yaml\Exception\ParseException;
+use Symfony\Component\Yaml\Parser as YamlParser;
+use Symfony\Component\Yaml\Yaml;
+
+/**
+ * YamlFileLoader loads translations from Yaml files.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class YamlFileLoader extends FileLoader
+{
+ private $yamlParser;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function loadResource(string $resource)
+ {
+ if (null === $this->yamlParser) {
+ if (!class_exists(\Symfony\Component\Yaml\Parser::class)) {
+ throw new LogicException('Loading translations from the YAML format requires the Symfony Yaml component.');
+ }
+
+ $this->yamlParser = new YamlParser();
+ }
+
+ try {
+ $messages = $this->yamlParser->parseFile($resource, Yaml::PARSE_CONSTANT);
+ } catch (ParseException $e) {
+ throw new InvalidResourceException(sprintf('The file "%s" does not contain valid YAML: ', $resource).$e->getMessage(), 0, $e);
+ }
+
+ if (null !== $messages && !\is_array($messages)) {
+ throw new InvalidResourceException(sprintf('Unable to load file "%s".', $resource));
+ }
+
+ return $messages ?: [];
+ }
+}