From 1a0e91e912b7f2c755b214a655a491e9c9499854 Mon Sep 17 00:00:00 2001 From: rhertogh Date: Mon, 24 Jul 2023 08:56:04 +0200 Subject: [PATCH 01/25] Fix #19906: Fixed multiline strings in the `\yii\console\widgets\Table` widget --- framework/CHANGELOG.md | 1 + framework/console/widgets/Table.php | 24 ++- tests/framework/console/widgets/TableTest.php | 144 ++++++++++++++++++ 3 files changed, 167 insertions(+), 2 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 894b1ad2a5..dca3886227 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -10,6 +10,7 @@ Yii Framework 2 Change Log - Enh #19853: Added support for default value for `\yii\helpers\Console::select()` (rhertogh) - Bug #19868: Added whitespace sanitation for tests, due to updates in ICU 72 (schmunk42) - Enh #19884: Added support Enums in Query Builder (sk1t0n) +- Bug #19906: Fixed multiline strings in the `\yii\console\widgets\Table` widget (rhertogh) 2.0.48.1 May 24, 2023 diff --git a/framework/console/widgets/Table.php b/framework/console/widgets/Table.php index 4862e88b6b..658cf5fd55 100644 --- a/framework/console/widgets/Table.php +++ b/framework/console/widgets/Table.php @@ -252,18 +252,32 @@ class Table extends Widget if ($index !== 0) { $buffer .= $spanMiddle . ' '; } + + $arrayFromMultilineString = false; + if (is_string($cell)) { + $cellLines = explode(PHP_EOL, $cell); + if (count($cellLines) > 1) { + $cell = $cellLines; + $arrayFromMultilineString = true; + } + } + if (is_array($cell)) { if (empty($renderedChunkTexts[$index])) { $renderedChunkTexts[$index] = ''; $start = 0; - $prefix = $this->listPrefix; + $prefix = $arrayFromMultilineString ? '' : $this->listPrefix; if (!isset($arrayPointer[$index])) { $arrayPointer[$index] = 0; } } else { $start = mb_strwidth($renderedChunkTexts[$index], Yii::$app->charset); } - $chunk = Console::ansiColorizedSubstr($cell[$arrayPointer[$index]], $start, $cellSize - 4); + $chunk = Console::ansiColorizedSubstr( + $cell[$arrayPointer[$index]], + $start, + $cellSize - 2 - Console::ansiStrwidth($prefix) + ); $renderedChunkTexts[$index] .= Console::stripAnsiFormat($chunk); $fullChunkText = Console::stripAnsiFormat($cell[$arrayPointer[$index]]); if (isset($cell[$arrayPointer[$index] + 1]) && $renderedChunkTexts[$index] === $fullChunkText) { @@ -339,6 +353,9 @@ class Table extends Widget if (is_array($val)) { return max(array_map('yii\helpers\Console::ansiStrwidth', $val)) + Console::ansiStrwidth($this->listPrefix); } + if (is_string($val)) { + return max(array_map('yii\helpers\Console::ansiStrwidth', explode(PHP_EOL, $val))); + } return Console::ansiStrwidth($val); }, $column)) + 2; $this->columnWidths[] = $columnWidth; @@ -388,6 +405,9 @@ class Table extends Widget if (is_array($val)) { return array_map('yii\helpers\Console::ansiStrwidth', $val); } + if (is_string($val)) { + return array_map('yii\helpers\Console::ansiStrwidth', explode(PHP_EOL, $val)); + } return Console::ansiStrwidth($val); }, $row)); return max($rowsPerCell); diff --git a/tests/framework/console/widgets/TableTest.php b/tests/framework/console/widgets/TableTest.php index 95e7c60e46..b5bf6f2c6d 100644 --- a/tests/framework/console/widgets/TableTest.php +++ b/tests/framework/console/widgets/TableTest.php @@ -58,6 +58,121 @@ class TableTest extends TestCase ║ testcontent21 │ testcontent22 │ testcontent23 ║ ╚═══════════════╧═══════════════╧═══════════════╝ +EXPECTED; + + $tableContent = $table + ->setHeaders($headers) + ->setRows($rows) + ->setScreenWidth(200) + ->run(); + $this->assertEqualsWithoutLE($expected, $tableContent); + } + + public function getMultiLineTableData() + { + return [ + [ + ['test1', 'test2', 'test3' . PHP_EOL . 'multiline'], + [ + ['test' . PHP_EOL . 'content1', 'testcontent2', 'test' . PHP_EOL . 'content3'], + [ + 'testcontent21', + 'testcontent22' . PHP_EOL + . 'loooooooooooooooooooooooooooooooooooong' . PHP_EOL + . 'content', + 'testcontent23' . PHP_EOL + . 'loooooooooooooooooooooooooooooooooooong content' + ], + ] + ], + [ + ['key1' => 'test1', 'key2' => 'test2', 'key3' => 'test3' . PHP_EOL . 'multiline'], + [ + [ + 'key1' => 'test' . PHP_EOL . 'content1', + 'key2' => 'testcontent2', + 'key3' => 'test' . PHP_EOL . 'content3' + ], + [ + 'key1' => 'testcontent21', + 'key2' => 'testcontent22' . PHP_EOL + . 'loooooooooooooooooooooooooooooooooooong' . PHP_EOL + . 'content', + 'key3' => 'testcontent23' . PHP_EOL + . 'loooooooooooooooooooooooooooooooooooong content' + ], + ] + ] + ]; + } + + /** + * @dataProvider getMultiLineTableData + */ + public function testMultiLineTable($headers, $rows) + { + $table = new Table(); + + $expected = <<<'EXPECTED' +╔═════════════╤═════════════════════════════════════╤═════════════════════════════════════════════╗ +║ test1 │ test2 │ test3 ║ +║ │ │ multiline ║ +╟─────────────┼─────────────────────────────────────┼─────────────────────────────────────────────╢ +║ test │ testcontent2 │ test ║ +║ content1 │ │ content3 ║ +╟─────────────┼─────────────────────────────────────┼─────────────────────────────────────────────╢ +║ testcontent │ testcontent22 │ testcontent23 ║ +║ 21 │ loooooooooooooooooooooooooooooooooo │ loooooooooooooooooooooooooooooooooooong con ║ +║ │ oong │ tent ║ +║ │ content │ ║ +╚═════════════╧═════════════════════════════════════╧═════════════════════════════════════════════╝ + +EXPECTED; + + $tableContent = $table + ->setHeaders($headers) + ->setRows($rows) + ->setScreenWidth(100) + ->run(); + $this->assertEqualsWithoutLE($expected, $tableContent); + } + + public function getNumericTableData() + { + return [ + [ + [1, 2, 3], + [ + [1, 1.2, -1.3], + [-2, 2.2, 2.3], + ] + ], + [ + ['key1' => 1, 'key2' => 2, 'key3' => 3], + [ + ['key1' => 1, 'key2' => 1.2, 'key3' => -1.3], + ['key1' => -2, 'key2' => 2.2, 'key3' => 2.3], + ] + ] + ]; + } + + /** + * @dataProvider getNumericTableData + */ + public function testNumericTable($headers, $rows) + { + $table = new Table(); + + $expected = <<<'EXPECTED' +╔════╤═════╤══════╗ +║ 1 │ 2 │ 3 ║ +╟────┼─────┼──────╢ +║ 1 │ 1.2 │ -1.3 ║ +╟────┼─────┼──────╢ +║ -2 │ 2.2 │ 2.3 ║ +╚════╧═════╧══════╝ + EXPECTED; $tableContent = $table @@ -141,6 +256,35 @@ EXPECTED; ); } + public function testLongerListPrefix() + { + $table = new Table(); + + $expected = <<<'EXPECTED' +╔═════════════════════════════════╤═════════════════════════════════╤═════════════════════════════╗ +║ test1 │ test2 │ test3 ║ +╟─────────────────────────────────┼─────────────────────────────────┼─────────────────────────────╢ +║ testcontent1 │ testcontent2 │ testcontent3 ║ +╟─────────────────────────────────┼─────────────────────────────────┼─────────────────────────────╢ +║ testcontent21 with looooooooooo │ testcontent22 with looooooooooo │ -- col1 with looooooooooooo ║ +║ ooooooooooooong content │ ooooooooooooong content │ ooooooooooong content ║ +║ │ │ -- col2 with long content ║ +╚═════════════════════════════════╧═════════════════════════════════╧═════════════════════════════╝ + +EXPECTED; + + $this->assertEqualsWithoutLE($expected, $table->setHeaders(['test1', 'test2', 'test3']) + ->setRows([ + ['testcontent1', 'testcontent2', 'testcontent3'], + [ + 'testcontent21 with loooooooooooooooooooooooong content', + 'testcontent22 with loooooooooooooooooooooooong content', + ['col1 with loooooooooooooooooooooooong content', 'col2 with long content'] + ], + ])->setScreenWidth(100)->setListPrefix('-- ')->run() + ); + } + public function testCustomChars() { $table = new Table(); From 7d2e2b9e7020c7aa6923a2d1066c7799fb83ff19 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Mon, 24 Jul 2023 03:01:24 -0400 Subject: [PATCH 02/25] Fix #16208: Fix `yii\log\FileTarget` to not export empty messages --- framework/CHANGELOG.md | 1 + framework/log/FileTarget.php | 12 +++++-- tests/framework/log/FileTargetTest.php | 38 ++++++++++++++++++++++ tests/framework/log/mocks/CustomLogger.php | 22 +++++++++++++ 4 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 tests/framework/log/mocks/CustomLogger.php diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index dca3886227..ec66929b76 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -4,6 +4,7 @@ Yii Framework 2 Change Log 2.0.49 under development ------------------------ +- Bug #16208: Fix `yii\log\FileTarget` to not export empty messages (terabytesoftw) - Bug #19857: Fix AttributeTypecastBehavior::resetOldAttributes() causes "class has no attribute named" InvalidArgumentException (uaoleg) - Bug #18859: Fix `yii\web\Controller::bindInjectedParams()` to not throw error when argument of `ReflectionUnionType` type is passed (bizley) - Enh #19841: Allow jQuery 3.7 to be installed (wouter90) diff --git a/framework/log/FileTarget.php b/framework/log/FileTarget.php index 05ad09430a..e56909c32f 100644 --- a/framework/log/FileTarget.php +++ b/framework/log/FileTarget.php @@ -106,12 +106,18 @@ class FileTarget extends Target */ public function export() { + $text = implode("\n", array_map([$this, 'formatMessage'], $this->messages)) . "\n"; + $trimmedText = trim($text); + + if (empty($trimmedText)) { + return; // No messages to export, so we exit the function early + } + if (strpos($this->logFile, '://') === false || strncmp($this->logFile, 'file://', 7) === 0) { $logPath = dirname($this->logFile); FileHelper::createDirectory($logPath, $this->dirMode, true); } - $text = implode("\n", array_map([$this, 'formatMessage'], $this->messages)) . "\n"; if (($fp = @fopen($this->logFile, 'a')) === false) { throw new InvalidConfigException("Unable to append to log file: {$this->logFile}"); } @@ -124,12 +130,12 @@ class FileTarget extends Target if ($this->enableRotation && @filesize($this->logFile) > $this->maxFileSize * 1024) { $this->rotateFiles(); } - $writeResult = @fwrite($fp, $text); + $writeResult = @fwrite($fp, $trimmedText); if ($writeResult === false) { $error = error_get_last(); throw new LogRuntimeException("Unable to export log through file ({$this->logFile})!: {$error['message']}"); } - $textSize = strlen($text); + $textSize = strlen($trimmedText); if ($writeResult < $textSize) { throw new LogRuntimeException("Unable to export whole log through file ({$this->logFile})! Wrote $writeResult out of $textSize bytes."); } diff --git a/tests/framework/log/FileTargetTest.php b/tests/framework/log/FileTargetTest.php index 217a94af0f..fb71258057 100644 --- a/tests/framework/log/FileTargetTest.php +++ b/tests/framework/log/FileTargetTest.php @@ -12,6 +12,7 @@ use yii\helpers\FileHelper; use yii\log\Dispatcher; use yii\log\FileTarget; use yii\log\Logger; +use yiiunit\framework\log\mocks\CustomLogger; use yiiunit\TestCase; /** @@ -110,4 +111,41 @@ class FileTargetTest extends TestCase $this->assertFileNotExists($logFile . '.3'); $this->assertFileNotExists($logFile . '.4'); } + + public function testLogEmptyStrings() + { + $logFile = Yii::getAlias('@yiiunit/runtime/log/filetargettest.log'); + $this->clearLogFile($logFile); + + $logger = new CustomLogger(); + $logger->logFile = $logFile; + $logger->messages = array_fill(0, 1, 'xxx'); + $logger->export(); + + $test = file($logFile); + $this->assertEquals("xxx", $test[0]); + + $this->clearLogFile($logFile); + + $logger->messages = array_fill(0, 1, 'yyy'); + $logger->export(); + + $this->assertFileNotExists($logFile); + + $logger->messages = array_fill(0, 10, ''); + $logger->export(); + + $this->assertFileNotExists($logFile); + + $logger->messages = array_fill(0, 10, null); + $logger->export(); + + $this->assertFileNotExists($logFile); + } + + private function clearLogFile($logFile) + { + FileHelper::removeDirectory(dirname($logFile)); + mkdir(dirname($logFile), 0777, true); + } } diff --git a/tests/framework/log/mocks/CustomLogger.php b/tests/framework/log/mocks/CustomLogger.php new file mode 100644 index 0000000000..5dae134b7e --- /dev/null +++ b/tests/framework/log/mocks/CustomLogger.php @@ -0,0 +1,22 @@ + Date: Mon, 24 Jul 2023 03:03:18 -0400 Subject: [PATCH 03/25] Fix #9899: Fix caching a MSSQL query with BLOB data type --- framework/CHANGELOG.md | 1 + framework/caching/DbCache.php | 2 +- framework/db/mssql/QueryBuilder.php | 5 +- tests/framework/db/mssql/CommandTest.php | 19 +++---- tests/framework/db/mssql/QueryCacheTest.php | 55 +++++++++++++++++++ .../framework/db/mssql/type/VarbinaryTest.php | 44 +++++++++++++++ 6 files changed, 111 insertions(+), 15 deletions(-) create mode 100644 tests/framework/db/mssql/QueryCacheTest.php create mode 100644 tests/framework/db/mssql/type/VarbinaryTest.php diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index ec66929b76..ce580c49be 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -4,6 +4,7 @@ Yii Framework 2 Change Log 2.0.49 under development ------------------------ +- Bug #9899: Fix caching a MSSQL query with BLOB data type (terabytesoftw) - Bug #16208: Fix `yii\log\FileTarget` to not export empty messages (terabytesoftw) - Bug #19857: Fix AttributeTypecastBehavior::resetOldAttributes() causes "class has no attribute named" InvalidArgumentException (uaoleg) - Bug #18859: Fix `yii\web\Controller::bindInjectedParams()` to not throw error when argument of `ReflectionUnionType` type is passed (bizley) diff --git a/framework/caching/DbCache.php b/framework/caching/DbCache.php index 5bf3b02ded..d707ba41a2 100644 --- a/framework/caching/DbCache.php +++ b/framework/caching/DbCache.php @@ -317,7 +317,7 @@ class DbCache extends Cache */ protected function getDataFieldName() { - return $this->isVarbinaryDataField() ? 'convert(nvarchar(max),[data]) data' : 'data'; + return $this->isVarbinaryDataField() ? 'CONVERT(VARCHAR(MAX), [[data]]) data' : 'data'; } /** diff --git a/framework/db/mssql/QueryBuilder.php b/framework/db/mssql/QueryBuilder.php index cc3595519c..1225c466cc 100644 --- a/framework/db/mssql/QueryBuilder.php +++ b/framework/db/mssql/QueryBuilder.php @@ -460,10 +460,9 @@ class QueryBuilder extends \yii\db\QueryBuilder $columnSchemas = $tableSchema->columns; foreach ($columns as $name => $value) { // @see https://github.com/yiisoft/yii2/issues/12599 - if (isset($columnSchemas[$name]) && $columnSchemas[$name]->type === Schema::TYPE_BINARY && $columnSchemas[$name]->dbType === 'varbinary' && (is_string($value) || $value === null)) { - $phName = $this->bindParam($value, $params); + if (isset($columnSchemas[$name]) && $columnSchemas[$name]->type === Schema::TYPE_BINARY && $columnSchemas[$name]->dbType === 'varbinary' && (is_string($value))) { // @see https://github.com/yiisoft/yii2/issues/12599 - $columns[$name] = new Expression("CONVERT(VARBINARY(MAX), $phName)", $params); + $columns[$name] = new Expression('CONVERT(VARBINARY(MAX), ' . ('0x' . bin2hex($value)) . ')'); } } } diff --git a/tests/framework/db/mssql/CommandTest.php b/tests/framework/db/mssql/CommandTest.php index b09f87bb6b..25a58a3a9e 100644 --- a/tests/framework/db/mssql/CommandTest.php +++ b/tests/framework/db/mssql/CommandTest.php @@ -134,22 +134,19 @@ class CommandTest extends \yiiunit\framework\db\CommandTest { $db = $this->getConnection(); - $testData = json_encode(['test' => 'string', 'test2' => 'integer']); + $qb = $db->getQueryBuilder(); + $testData = json_encode(['test' => 'string', 'test2' => 'integer'], JSON_THROW_ON_ERROR); + $params = []; - $qb = $db->getQueryBuilder(); - $sql = $qb->upsert('T_upsert_varbinary', ['id' => 1, 'blob_col' => $testData] , ['blob_col' => $testData], $params); - + $sql = $qb->upsert('T_upsert_varbinary', ['id' => 1, 'blob_col' => $testData], ['blob_col' => $testData], $params); $result = $db->createCommand($sql, $params)->execute(); - $this->assertEquals(1, $result); - - $query = (new Query()) - ->select(['convert(nvarchar(max),blob_col) as blob_col']) - ->from('T_upsert_varbinary') - ->where(['id' => 1]); + $this->assertSame(1, $result); + $query = (new Query())->select(['blob_col'])->from('T_upsert_varbinary')->where(['id' => 1]); $resultData = $query->createCommand($db)->queryOne(); - $this->assertEquals($testData, $resultData['blob_col']); + + $this->assertSame($testData, $resultData['blob_col']); } } diff --git a/tests/framework/db/mssql/QueryCacheTest.php b/tests/framework/db/mssql/QueryCacheTest.php new file mode 100644 index 0000000000..b35c11fde1 --- /dev/null +++ b/tests/framework/db/mssql/QueryCacheTest.php @@ -0,0 +1,55 @@ +getConnection(); + $db->enableQueryCache = true; + $db->queryCache = new FileCache(['cachePath' => '@yiiunit/runtime/cache']); + + $db->createCommand()->delete('type')->execute(); + $db->createCommand()->insert('type', [ + 'int_col' => $key = 1, + 'char_col' => '', + 'char_col2' => '6a3ce1a0bffe8eeb6fa986caf443e24c', + 'float_col' => 0.0, + 'blob_col' => 'a:1:{s:13:"template";s:1:"1";}', + 'bool_col' => true, + ])->execute(); + + $function = function($db) use ($key){ + return (new Query()) + ->select(['blob_col']) + ->from('type') + ->where(['int_col' => $key]) + ->createCommand($db) + ->queryScalar(); + }; + + // First run return + $result = $db->cache($function); + $this->assertSame('a:1:{s:13:"template";s:1:"1";}', $result); + + // After the request has been cached return + $result = $db->cache($function); + $this->assertSame('a:1:{s:13:"template";s:1:"1";}', $result); + } +} diff --git a/tests/framework/db/mssql/type/VarbinaryTest.php b/tests/framework/db/mssql/type/VarbinaryTest.php new file mode 100644 index 0000000000..b72a2b4c46 --- /dev/null +++ b/tests/framework/db/mssql/type/VarbinaryTest.php @@ -0,0 +1,44 @@ +getConnection(); + + $db->createCommand()->delete('type')->execute(); + $db->createCommand()->insert('type', [ + 'int_col' => $key = 1, + 'char_col' => '', + 'char_col2' => '6a3ce1a0bffe8eeb6fa986caf443e24c', + 'float_col' => 0.0, + 'blob_col' => 'a:1:{s:13:"template";s:1:"1";}', + 'bool_col' => true, + ])->execute(); + + $result = (new Query()) + ->select(['blob_col']) + ->from('type') + ->where(['int_col' => $key]) + ->createCommand($db) + ->queryScalar(); + + $this->assertSame('a:1:{s:13:"template";s:1:"1";}', $result); + } +} From c8c0ea97c4ea387e526a4ad03d053546eb3824eb Mon Sep 17 00:00:00 2001 From: PowerGamer1 Date: Mon, 24 Jul 2023 11:52:38 +0300 Subject: [PATCH 04/25] Fix #19899: Fixed `GridView` in some cases calling `Model::generateAttributeLabel()` to generate label values that are never used --- framework/CHANGELOG.md | 1 + framework/data/ActiveDataProvider.php | 10 ++---- framework/data/Sort.php | 14 +++++++- tests/data/ar/NoAutoLabels.php | 27 ++++++++++++++ tests/framework/grid/GridViewTest.php | 51 +++++++++++++++++++++++++++ 5 files changed, 95 insertions(+), 8 deletions(-) create mode 100644 tests/data/ar/NoAutoLabels.php diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index ce580c49be..dc620a0748 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -4,6 +4,7 @@ Yii Framework 2 Change Log 2.0.49 under development ------------------------ +- Bug #19899: Fixed `GridView` in some cases calling `Model::generateAttributeLabel()` to generate label values that are never used (PowerGamer1) - Bug #9899: Fix caching a MSSQL query with BLOB data type (terabytesoftw) - Bug #16208: Fix `yii\log\FileTarget` to not export empty messages (terabytesoftw) - Bug #19857: Fix AttributeTypecastBehavior::resetOldAttributes() causes "class has no attribute named" InvalidArgumentException (uaoleg) diff --git a/framework/data/ActiveDataProvider.php b/framework/data/ActiveDataProvider.php index a8b6e158ec..3a129aa729 100644 --- a/framework/data/ActiveDataProvider.php +++ b/framework/data/ActiveDataProvider.php @@ -183,15 +183,11 @@ class ActiveDataProvider extends BaseDataProvider $sort->attributes[$attribute] = [ 'asc' => [$attribute => SORT_ASC], 'desc' => [$attribute => SORT_DESC], - 'label' => $model->getAttributeLabel($attribute), ]; } - } else { - foreach ($sort->attributes as $attribute => $config) { - if (!isset($config['label'])) { - $sort->attributes[$attribute]['label'] = $model->getAttributeLabel($attribute); - } - } + } + if ($sort->modelClass === null) { + $sort->modelClass = $modelClass; } } } diff --git a/framework/data/Sort.php b/framework/data/Sort.php index 1ed63f4ac8..0c0abc8b60 100644 --- a/framework/data/Sort.php +++ b/framework/data/Sort.php @@ -191,6 +191,12 @@ class Sort extends BaseObject * @since 2.0.33 */ public $sortFlags = SORT_REGULAR; + /** + * @var string|null the name of the [[\yii\base\Model]]-based class used by the [[link()]] method to retrieve + * attributes' labels. See [[link]] method for details. + * @since 2.0.49 + */ + public $modelClass; /** @@ -363,7 +369,8 @@ class Sort extends BaseObject * @param array $options additional HTML attributes for the hyperlink tag. * There is one special attribute `label` which will be used as the label of the hyperlink. * If this is not set, the label defined in [[attributes]] will be used. - * If no label is defined, [[\yii\helpers\Inflector::camel2words()]] will be called to get a label. + * If no label is defined, it will be retrieved from the instance of [[modelClass]] (if [[modelClass]] is not null) + * or generated from attribute name using [[\yii\helpers\Inflector::camel2words()]]. * Note that it will not be HTML-encoded. * @return string the generated hyperlink * @throws InvalidConfigException if the attribute is unknown @@ -388,6 +395,11 @@ class Sort extends BaseObject } else { if (isset($this->attributes[$attribute]['label'])) { $label = $this->attributes[$attribute]['label']; + } elseif ($this->modelClass !== null) { + $modelClass = $this->modelClass; + /** @var \yii\base\Model $model */ + $model = $modelClass::instance(); + $label = $model->getAttributeLabel($attribute); } else { $label = Inflector::camel2words($attribute); } diff --git a/tests/data/ar/NoAutoLabels.php b/tests/data/ar/NoAutoLabels.php new file mode 100644 index 0000000000..e33a3847d8 --- /dev/null +++ b/tests/data/ar/NoAutoLabels.php @@ -0,0 +1,27 @@ + 'Label for attr1', + ]; + } + + public function generateAttributeLabel($name) + { + throw new \yii\base\InvalidArgumentException('Label not defined!'); + } +} diff --git a/tests/framework/grid/GridViewTest.php b/tests/framework/grid/GridViewTest.php index 392aefbd0b..b698011493 100644 --- a/tests/framework/grid/GridViewTest.php +++ b/tests/framework/grid/GridViewTest.php @@ -7,10 +7,12 @@ namespace yiiunit\framework\grid; +use Yii; use yii\data\ArrayDataProvider; use yii\grid\DataColumn; use yii\grid\GridView; use yii\web\View; +use yiiunit\data\ar\NoAutoLabels; /** * @author Evgeniy Tkachenko @@ -150,4 +152,53 @@ class GridViewTest extends \yiiunit\TestCase $this->assertTrue(preg_match("/<\/tbody>/", $html) === 1); } + + public function testHeaderLabels() + { + // Ensure GridView does not call Model::generateAttributeLabel() to generate labels unless the labels are explicitly used. + + $this->mockApplication([ + 'components' => [ + 'db' => [ + 'class' => \yii\db\Connection::className(), + 'dsn' => 'sqlite::memory:', + ], + ], + ]); + + NoAutoLabels::$db = Yii::$app->getDb(); + Yii::$app->getDb()->createCommand()->createTable(NoAutoLabels::tableName(), ['attr1' => 'int', 'attr2' => 'int'])->execute(); + + $urlManager = new \yii\web\UrlManager([ + 'baseUrl' => '/', + 'scriptUrl' => '/index.php', + ]); + + $grid = new GridView([ + 'dataProvider' => new \yii\data\ActiveDataProvider([ + 'query' => NoAutoLabels::find(), + ]), + 'columns' => [ + 'attr1', + 'attr2:text:Label for attr2', + ], + ]); + + // NoAutoLabels::generateAttributeLabel() should not be called. + $grid->dataProvider->setSort([ + 'route' => '/', + 'urlManager' => $urlManager, + ]); + $grid->renderTableHeader(); + + // NoAutoLabels::generateAttributeLabel() should not be called. + $grid->dataProvider->setSort([ + 'route' => '/', + 'urlManager' => $urlManager, + 'attributes' => ['attr1', 'attr2'], + ]); + $grid->renderTableHeader(); + + // If NoAutoLabels::generateAttributeLabel() has not been called no exception will be thrown meaning this test passed successfully. + } } From 8a213315acb38c17a6f20d5d667b08d756a18341 Mon Sep 17 00:00:00 2001 From: August Miller Date: Fri, 28 Jul 2023 04:13:01 -0700 Subject: [PATCH 05/25] End fenced code block (#19919) --- framework/db/ActiveRecordInterface.php | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/db/ActiveRecordInterface.php b/framework/db/ActiveRecordInterface.php index d845e9d32c..441001a99f 100644 --- a/framework/db/ActiveRecordInterface.php +++ b/framework/db/ActiveRecordInterface.php @@ -144,6 +144,7 @@ interface ActiveRecordInterface extends StaticInstanceInterface * // Use where() to ignore the default condition * // SELECT FROM customer WHERE age>30 * $customers = Customer::find()->where('age>30')->all(); + * ``` * * @return ActiveQueryInterface the newly created [[ActiveQueryInterface]] instance. */ From 504a66dae50c43d7bcfd8cd506b0b4ec2f096b2a Mon Sep 17 00:00:00 2001 From: Clemens Date: Sun, 30 Jul 2023 11:51:25 +0200 Subject: [PATCH 06/25] Update documentation for setCookieParams (#19921) The link for more information about "sameSite" lead to a 404 Not Found. --- framework/web/Session.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/web/Session.php b/framework/web/Session.php index a470e7bfea..40768924cf 100644 --- a/framework/web/Session.php +++ b/framework/web/Session.php @@ -405,7 +405,7 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co * 'sameSite' => PHP_VERSION_ID >= 70300 ? yii\web\Cookie::SAME_SITE_LAX : null, * ] * ``` - * See https://www.owasp.org/index.php/SameSite for more information about `sameSite`. + * See https://owasp.org/www-community/SameSite for more information about `sameSite`. * * @throws InvalidArgumentException if the parameters are incomplete. * @see https://www.php.net/manual/en/function.session-set-cookie-params.php From 84c15dc5d1c9114dc0f57d208a557aa63087c576 Mon Sep 17 00:00:00 2001 From: rhertogh Date: Wed, 9 Aug 2023 14:05:46 +0200 Subject: [PATCH 07/25] Fix associative array cell content in Table widget (#19908) * Fixed rendering of assosative arrays in `\yii\console\widgets\Table` * Updated readme for #19908 (fix associative array cell content rendering in Table widget) --------- Co-authored-by: Alexander Makarov --- framework/CHANGELOG.md | 1 + framework/console/widgets/Table.php | 6 +++++- tests/framework/console/widgets/TableTest.php | 5 +++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index dc620a0748..9833be22ac 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -13,6 +13,7 @@ Yii Framework 2 Change Log - Enh #19853: Added support for default value for `\yii\helpers\Console::select()` (rhertogh) - Bug #19868: Added whitespace sanitation for tests, due to updates in ICU 72 (schmunk42) - Enh #19884: Added support Enums in Query Builder (sk1t0n) +- Bug #19908: Fix associative array cell content rendering in Table widget (rhertogh) - Bug #19906: Fixed multiline strings in the `\yii\console\widgets\Table` widget (rhertogh) diff --git a/framework/console/widgets/Table.php b/framework/console/widgets/Table.php index 658cf5fd55..c0ece4d4d8 100644 --- a/framework/console/widgets/Table.php +++ b/framework/console/widgets/Table.php @@ -136,7 +136,11 @@ class Table extends Widget { $this->rows = array_map(function($row) { return array_map(function($value) { - return empty($value) && !is_numeric($value) ? ' ' : $value; + return empty($value) && !is_numeric($value) + ? ' ' + : (is_array($value) + ? array_values($value) + : $value); }, array_values($row)); }, $rows); return $this; diff --git a/tests/framework/console/widgets/TableTest.php b/tests/framework/console/widgets/TableTest.php index b5bf6f2c6d..796c95ad1d 100644 --- a/tests/framework/console/widgets/TableTest.php +++ b/tests/framework/console/widgets/TableTest.php @@ -216,7 +216,8 @@ EXPECTED; ╔═══════════════╤═══════════════╤══════════════╗ ║ test1 │ test2 │ test3 ║ ╟───────────────┼───────────────┼──────────────╢ -║ testcontent1 │ testcontent2 │ testcontent3 ║ +║ • col1 │ testcontent2 │ testcontent3 ║ +║ • col2 │ │ ║ ╟───────────────┼───────────────┼──────────────╢ ║ testcontent21 │ testcontent22 │ • col1 ║ ║ │ │ • col2 ║ @@ -226,7 +227,7 @@ EXPECTED; $this->assertEqualsWithoutLE($expected, $table->setHeaders(['test1', 'test2', 'test3']) ->setRows([ - ['testcontent1', 'testcontent2', 'testcontent3'], + [['key1' => 'col1', 'key2' => 'col2'], 'testcontent2', 'testcontent3'], ['testcontent21', 'testcontent22', ['col1', 'col2']], ])->setScreenWidth(200)->run() ); From 73902f0730454f499d1a8bb49382e5021943656e Mon Sep 17 00:00:00 2001 From: rhertogh Date: Tue, 15 Aug 2023 18:38:10 +0200 Subject: [PATCH 08/25] Added support for string and DateTimeInterface as Cookie::$expire (#19920) * Added support for string as Cookie::$expire * Updated changelog for #19920 (Broadened the accepted type of `Cookie::$expire` from `int` to `int|string|null`) * Fixed `\yiiunit\framework\web\ResponseTest::parseHeaderCookies()` to overwrite existing cookie. * Added support for `\DateTimeInterface` in `\yii\web\Cookie::$expire` * Fixed `\yiiunit\framework\web\ResponseTest::cookiesTestProvider()` for PHP 5.4 and commited missing code for \DateTimeInterface processing in `\yii\web\Response::sendCookies()` --- framework/CHANGELOG.md | 1 + framework/web/Cookie.php | 4 +- framework/web/CookieCollection.php | 17 +++- framework/web/Response.php | 15 +++- tests/framework/web/ResponseTest.php | 111 +++++++++++++++++++++++++-- 5 files changed, 132 insertions(+), 16 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 9833be22ac..0b47c48c78 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -15,6 +15,7 @@ Yii Framework 2 Change Log - Enh #19884: Added support Enums in Query Builder (sk1t0n) - Bug #19908: Fix associative array cell content rendering in Table widget (rhertogh) - Bug #19906: Fixed multiline strings in the `\yii\console\widgets\Table` widget (rhertogh) +- Enh #19920: Broadened the accepted type of `Cookie::$expire` from `int` to `int|string|\DateTimeInterface|null` (rhertogh) 2.0.48.1 May 24, 2023 diff --git a/framework/web/Cookie.php b/framework/web/Cookie.php index ac9a723371..d249afa6cb 100644 --- a/framework/web/Cookie.php +++ b/framework/web/Cookie.php @@ -57,8 +57,8 @@ class Cookie extends \yii\base\BaseObject */ public $domain = ''; /** - * @var int the timestamp at which the cookie expires. This is the server timestamp. - * Defaults to 0, meaning "until the browser is closed". + * @var int|string|\DateTimeInterface|null the timestamp or date at which the cookie expires. This is the server timestamp. + * Defaults to 0, meaning "until the browser is closed" (the same applies to `null`). */ public $expire = 0; /** diff --git a/framework/web/CookieCollection.php b/framework/web/CookieCollection.php index 5c56e46f70..597fc2f5fd 100644 --- a/framework/web/CookieCollection.php +++ b/framework/web/CookieCollection.php @@ -51,7 +51,7 @@ class CookieCollection extends BaseObject implements \IteratorAggregate, \ArrayA * Returns an iterator for traversing the cookies in the collection. * This method is required by the SPL interface [[\IteratorAggregate]]. * It will be implicitly called when you use `foreach` to traverse the collection. - * @return ArrayIterator an iterator for traversing the cookies in the collection. + * @return ArrayIterator an iterator for traversing the cookies in the collection. */ #[\ReturnTypeWillChange] public function getIterator() @@ -113,7 +113,18 @@ class CookieCollection extends BaseObject implements \IteratorAggregate, \ArrayA public function has($name) { return isset($this->_cookies[$name]) && $this->_cookies[$name]->value !== '' - && ($this->_cookies[$name]->expire === null || $this->_cookies[$name]->expire === 0 || $this->_cookies[$name]->expire >= time()); + && ($this->_cookies[$name]->expire === null + || $this->_cookies[$name]->expire === 0 + || ( + (is_string($this->_cookies[$name]->expire) && strtotime($this->_cookies[$name]->expire) >= time()) + || ( + interface_exists('\\DateTimeInterface') + && $this->_cookies[$name]->expire instanceof \DateTimeInterface + && $this->_cookies[$name]->expire->getTimestamp() >= time() + ) + || $this->_cookies[$name]->expire >= time() + ) + ); } /** @@ -174,7 +185,7 @@ class CookieCollection extends BaseObject implements \IteratorAggregate, \ArrayA /** * Returns the collection as a PHP array. - * @return array the array representation of the collection. + * @return Cookie[] the array representation of the collection. * The array keys are cookie names, and the array values are the corresponding cookie objects. */ public function toArray() diff --git a/framework/web/Response.php b/framework/web/Response.php index 57349b599e..1724438803 100644 --- a/framework/web/Response.php +++ b/framework/web/Response.php @@ -401,12 +401,21 @@ class Response extends \yii\base\Response } foreach ($this->getCookies() as $cookie) { $value = $cookie->value; - if ($cookie->expire != 1 && isset($validationKey)) { + $expire = $cookie->expire; + if (is_string($expire)) { + $expire = strtotime($expire); + } elseif (interface_exists('\\DateTimeInterface') && $expire instanceof \DateTimeInterface) { + $expire = $expire->getTimestamp(); + } + if ($expire === null || $expire === false) { + $expire = 0; + } + if ($expire != 1 && isset($validationKey)) { $value = Yii::$app->getSecurity()->hashData(serialize([$cookie->name, $value]), $validationKey); } if (PHP_VERSION_ID >= 70300) { setcookie($cookie->name, $value, [ - 'expires' => $cookie->expire, + 'expires' => $expire, 'path' => $cookie->path, 'domain' => $cookie->domain, 'secure' => $cookie->secure, @@ -420,7 +429,7 @@ class Response extends \yii\base\Response if (!is_null($cookie->sameSite)) { $cookiePath .= '; samesite=' . $cookie->sameSite; } - setcookie($cookie->name, $value, $cookie->expire, $cookiePath, $cookie->domain, $cookie->secure, $cookie->httpOnly); + setcookie($cookie->name, $value, $expire, $cookiePath, $cookie->domain, $cookie->secure, $cookie->httpOnly); } } } diff --git a/tests/framework/web/ResponseTest.php b/tests/framework/web/ResponseTest.php index 07e55b7dfa..2c49964fbc 100644 --- a/tests/framework/web/ResponseTest.php +++ b/tests/framework/web/ResponseTest.php @@ -380,21 +380,116 @@ class ResponseTest extends \yiiunit\TestCase ); } - public function testSameSiteCookie() + /** + * @dataProvider cookiesTestProvider + */ + public function testCookies($cookieConfig, $expected) { $response = new Response(); - $response->cookies->add(new Cookie([ - 'name' => 'test', - 'value' => 'testValue', - 'sameSite' => Cookie::SAME_SITE_STRICT, - ])); + $response->cookies->add(new Cookie(array_merge( + [ + 'name' => 'test', + 'value' => 'testValue', + ], + $cookieConfig + ))); ob_start(); $response->send(); $content = ob_get_clean(); - // Only way to test is that it doesn't create any errors - $this->assertEquals('', $content); + $cookies = $this->parseHeaderCookies(); + if ($cookies === false) { + // Unable to resolve cookies, only way to test is that it doesn't create any errors + $this->assertEquals('', $content); + } else { + $testCookie = $cookies['test']; + $actual = array_intersect_key($testCookie, $expected); + ksort($actual); + ksort($expected); + $this->assertEquals($expected, $actual); + } + } + + public function cookiesTestProvider() + { + $expireInt = time() + 3600; + $expireString = date('D, d-M-Y H:i:s', $expireInt) . ' GMT'; + + $testCases = [ + 'same-site' => [ + ['sameSite' => Cookie::SAME_SITE_STRICT], + ['samesite' => Cookie::SAME_SITE_STRICT], + ], + 'expire-as-int' => [ + ['expire' => $expireInt], + ['expires' => $expireString], + ], + 'expire-as-string' => [ + ['expire' => $expireString], + ['expires' => $expireString], + ], + ]; + + if (version_compare(PHP_VERSION, '5.5.0', '>=')) { + $testCases = array_merge($testCases, [ + 'expire-as-date_time' => [ + ['expire' => new \DateTime('@' . $expireInt)], + ['expires' => $expireString], + ], + 'expire-as-date_time_immutable' => [ + ['expire' => new \DateTimeImmutable('@' . $expireInt)], + ['expires' => $expireString], + ], + ]); + } + + return $testCases; + } + + /** + * Tries to parse cookies set in the response headers. + * When running PHP on the CLI headers are not available (the `headers_list()` function always returns an + * empty array). If possible use xDebug: http://xdebug.org/docs/all_functions#xdebug_get_headers + * @param $name + * @return array|false + */ + protected function parseHeaderCookies() { + + if (!function_exists('xdebug_get_headers')) { + return false; + } + + $cookies = []; + foreach(xdebug_get_headers() as $header) { + if (strpos($header, 'Set-Cookie: ') !== 0) { + continue; + } + + $name = null; + $params = []; + $pairs = explode(';', substr($header, 12)); + foreach ($pairs as $index => $pair) { + $pair = trim($pair); + if (strpos($pair, '=') === false) { + $params[strtolower($pair)] = true; + } else { + list($paramName, $paramValue) = explode('=', $pair, 2); + if ($index === 0) { + $name = $paramName; + $params['value'] = urldecode($paramValue); + } else { + $params[strtolower($paramName)] = urldecode($paramValue); + } + } + } + if ($name === null) { + throw new \Exception('Could not determine cookie name for header "' . $header . '".'); + } + $cookies[$name] = $params; + } + + return $cookies; } /** From e40fb70fa85650c1c2a892f17edfb90d45d0459e Mon Sep 17 00:00:00 2001 From: Mark Huot Date: Fri, 18 Aug 2023 07:15:39 -0400 Subject: [PATCH 09/25] Remove unnecessary type (#19932) Because Web and Console application extend Base application there is no need to specify it. Actually, PHPStan narrows this to _just_ BaseApplication because it is the only consistent type of the three so you lose Web and Console Application type hints. See, https://phpstan.org/r/d21fb99f-c436-480b-99c2-32df35ec07fa --- framework/BaseYii.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/BaseYii.php b/framework/BaseYii.php index 8f76ea5123..dfa5419cb0 100644 --- a/framework/BaseYii.php +++ b/framework/BaseYii.php @@ -68,7 +68,7 @@ class BaseYii */ public static $classMap = []; /** - * @var \yii\console\Application|\yii\web\Application|\yii\base\Application the application instance + * @var \yii\console\Application|\yii\web\Application the application instance */ public static $app; /** From 73f57fdcb01b1651ef0f2c8a7588bd6c8508bdf6 Mon Sep 17 00:00:00 2001 From: Gusakov Egor <85644473+eegusakov@users.noreply.github.com> Date: Fri, 18 Aug 2023 14:19:24 +0300 Subject: [PATCH 10/25] Fix #19872: Fixed the definition of dirty attributes in AR properties for a non-associative array in case of changing the order of elements --- framework/CHANGELOG.md | 1 + framework/db/BaseActiveRecord.php | 2 +- tests/framework/db/BaseActiveRecordTest.php | 42 +++++++++++++++++ .../db/mysql/BaseActiveRecordTest.php | 37 +++++++++++++++ .../db/pgsql/BaseActiveRecordTest.php | 46 +++++++++++++++++++ 5 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 tests/framework/db/BaseActiveRecordTest.php create mode 100644 tests/framework/db/mysql/BaseActiveRecordTest.php create mode 100644 tests/framework/db/pgsql/BaseActiveRecordTest.php diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 0b47c48c78..eaa8bc6154 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -4,6 +4,7 @@ Yii Framework 2 Change Log 2.0.49 under development ------------------------ +- Bug #19872: Fixed the definition of dirty attributes in AR properties for a non-associative array in case of changing the order of elements (eegusakov) - Bug #19899: Fixed `GridView` in some cases calling `Model::generateAttributeLabel()` to generate label values that are never used (PowerGamer1) - Bug #9899: Fix caching a MSSQL query with BLOB data type (terabytesoftw) - Bug #16208: Fix `yii\log\FileTarget` to not export empty messages (terabytesoftw) diff --git a/framework/db/BaseActiveRecord.php b/framework/db/BaseActiveRecord.php index 88fb2f11d7..2648a48dae 100644 --- a/framework/db/BaseActiveRecord.php +++ b/framework/db/BaseActiveRecord.php @@ -1774,7 +1774,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface */ private function isValueDifferent($newValue, $oldValue) { - if (is_array($newValue) && is_array($oldValue) && !ArrayHelper::isAssociative($oldValue)) { + if (is_array($newValue) && is_array($oldValue) && ArrayHelper::isAssociative($oldValue)) { $newValue = ArrayHelper::recursiveSort($newValue); $oldValue = ArrayHelper::recursiveSort($oldValue); } diff --git a/tests/framework/db/BaseActiveRecordTest.php b/tests/framework/db/BaseActiveRecordTest.php new file mode 100644 index 0000000000..0427421cd8 --- /dev/null +++ b/tests/framework/db/BaseActiveRecordTest.php @@ -0,0 +1,42 @@ +getConnection(); + } + + public function provideArrayValueWithChange() + { + return [ + 'not an associative array with data change' => [ + [1, 2, 3], + [1, 3, 2], + ], + + 'associative array with data change case 1' => [ + ['pineapple' => 2, 'apple' => 5, 'banana' => 1], + ['apple' => 5, 'pineapple' => 1, 'banana' => 3], + ], + 'associative array with data change case 2' => [ + ['pineapple' => 2, 'apple' => 5, 'banana' => 1], + ['pineapple' => 2, 'apple' => 3, 'banana' => 1], + ], + + 'filling an empty array' => [ + [], + ['pineapple' => 3, 'apple' => 1, 'banana' => 1], + ], + 'zeroing the array' => [ + ['pineapple' => 3, 'apple' => 1, 'banana' => 17], + [], + ], + ]; + } +} diff --git a/tests/framework/db/mysql/BaseActiveRecordTest.php b/tests/framework/db/mysql/BaseActiveRecordTest.php new file mode 100644 index 0000000000..394922e87f --- /dev/null +++ b/tests/framework/db/mysql/BaseActiveRecordTest.php @@ -0,0 +1,37 @@ +getConnection()->getSchema()->getServerVersion(), '5.7', '<')) { + $this->markTestSkipped('JSON columns are not supported in MySQL < 5.7'); + } + if (version_compare(PHP_VERSION, '5.6', '<')) { + $this->markTestSkipped('JSON columns are not supported in PDO for PHP < 5.6'); + } + + $createdStorage = new Storage(['data' => $actual]); + + $createdStorage->save(); + + $foundStorage = Storage::find()->limit(1)->one(); + + $this->assertNotNull($foundStorage); + + $foundStorage->data = $modified; + + $this->assertSame(['data' => $modified], $foundStorage->getDirtyAttributes()); + } +} diff --git a/tests/framework/db/pgsql/BaseActiveRecordTest.php b/tests/framework/db/pgsql/BaseActiveRecordTest.php new file mode 100644 index 0000000000..a499368524 --- /dev/null +++ b/tests/framework/db/pgsql/BaseActiveRecordTest.php @@ -0,0 +1,46 @@ + new JsonExpression($actual), + ]); + + $createdStorage->save(); + + $foundStorage = ArrayAndJsonType::find()->limit(1)->one(); + + $this->assertNotNull($foundStorage); + + $foundStorage->json_col = $modified; + + $this->assertSame(['json_col' => $modified], $foundStorage->getDirtyAttributes()); + } +} + +/** + * {@inheritdoc} + * @property array id + * @property array json_col + */ +class ArrayAndJsonType extends ActiveRecord +{ + public static function tableName() + { + return '{{%array_and_json_types}}'; + } +} From 786a75ca639b1532eac98de9cbe269d52a69d1d6 Mon Sep 17 00:00:00 2001 From: Safuan Date: Fri, 18 Aug 2023 14:20:46 +0300 Subject: [PATCH 11/25] Fix incorrect translation in db-query-builder.md (#19916) --- docs/guide-ru/db-query-builder.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide-ru/db-query-builder.md b/docs/guide-ru/db-query-builder.md index 41b164124e..50bf94771e 100644 --- a/docs/guide-ru/db-query-builder.md +++ b/docs/guide-ru/db-query-builder.md @@ -373,7 +373,7 @@ $query->orderBy([ ``` В данном коде, ключи массива - это имена столбцов, а значения массива - это соответствующее направление сортировки. -PHP константа `SORT_ASC` определяет сортировку по возрастанию и `SORT_DESC` сортировка по умолчанию. +PHP константа `SORT_ASC` определяет сортировку по возрастанию и `SORT_DESC` сортировку по убыванию. Если `ORDER BY` содержит только простые имена столбцов, вы можете определить их с помощью столбцов, также как и при написании обычного SQL. Например, From e916e9d564ab0e24326f35f53eb62bb131a62edb Mon Sep 17 00:00:00 2001 From: rhertogh Date: Fri, 18 Aug 2023 13:31:09 +0200 Subject: [PATCH 12/25] Fix #19914: Fixed `ArrayHelper::keyExists()` and `::remove()` functions when the key is a float and the value is `null` --- framework/CHANGELOG.md | 1 + framework/db/BaseActiveRecord.php | 4 +- framework/helpers/BaseArrayHelper.php | 18 +++++-- tests/framework/helpers/ArrayHelperTest.php | 60 +++++++++++++++++++-- 4 files changed, 72 insertions(+), 11 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index eaa8bc6154..4ed527b0a7 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -16,6 +16,7 @@ Yii Framework 2 Change Log - Enh #19884: Added support Enums in Query Builder (sk1t0n) - Bug #19908: Fix associative array cell content rendering in Table widget (rhertogh) - Bug #19906: Fixed multiline strings in the `\yii\console\widgets\Table` widget (rhertogh) +- Bug #19914: Fixed `ArrayHelper::keyExists()` and `::remove()` functions when the key is a float and the value is `null` (rhertogh) - Enh #19920: Broadened the accepted type of `Cookie::$expire` from `int` to `int|string|\DateTimeInterface|null` (rhertogh) diff --git a/framework/db/BaseActiveRecord.php b/framework/db/BaseActiveRecord.php index 2648a48dae..60f621eb44 100644 --- a/framework/db/BaseActiveRecord.php +++ b/framework/db/BaseActiveRecord.php @@ -282,7 +282,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface */ public function __get($name) { - if (isset($this->_attributes[$name]) || array_key_exists($name, $this->_attributes)) { + if (array_key_exists($name, $this->_attributes)) { return $this->_attributes[$name]; } @@ -290,7 +290,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface return null; } - if (isset($this->_related[$name]) || array_key_exists($name, $this->_related)) { + if (array_key_exists($name, $this->_related)) { return $this->_related[$name]; } $value = parent::__get($name); diff --git a/framework/helpers/BaseArrayHelper.php b/framework/helpers/BaseArrayHelper.php index 0e615a579d..56411163e1 100644 --- a/framework/helpers/BaseArrayHelper.php +++ b/framework/helpers/BaseArrayHelper.php @@ -327,7 +327,12 @@ class BaseArrayHelper */ public static function remove(&$array, $key, $default = null) { - if (is_array($array) && (isset($array[$key]) || array_key_exists($key, $array))) { + // ToDo: This check can be removed when the minimum PHP version is >= 8.1 (Yii2.2) + if (is_float($key)) { + $key = (int)$key; + } + + if (is_array($array) && array_key_exists($key, $array)) { $value = $array[$key]; unset($array[$key]); @@ -608,17 +613,20 @@ class BaseArrayHelper * Checks if the given array contains the specified key. * This method enhances the `array_key_exists()` function by supporting case-insensitive * key comparison. - * @param string $key the key to check + * @param string|int $key the key to check * @param array|ArrayAccess $array the array with keys to check * @param bool $caseSensitive whether the key comparison should be case-sensitive * @return bool whether the array contains the specified key */ public static function keyExists($key, $array, $caseSensitive = true) { + // ToDo: This check can be removed when the minimum PHP version is >= 8.1 (Yii2.2) + if (is_float($key)) { + $key = (int)$key; + } + if ($caseSensitive) { - // Function `isset` checks key faster but skips `null`, `array_key_exists` handles this case - // https://www.php.net/manual/en/function.array-key-exists.php#107786 - if (is_array($array) && (isset($array[$key]) || array_key_exists($key, $array))) { + if (is_array($array) && array_key_exists($key, $array)) { return true; } // Cannot use `array_has_key` on Objects for PHP 7.4+, therefore we need to check using [[ArrayAccess::offsetExists()]] diff --git a/tests/framework/helpers/ArrayHelperTest.php b/tests/framework/helpers/ArrayHelperTest.php index 063eeafcaf..0d706bc552 100644 --- a/tests/framework/helpers/ArrayHelperTest.php +++ b/tests/framework/helpers/ArrayHelperTest.php @@ -135,6 +135,29 @@ class ArrayHelperTest extends TestCase $this->assertEquals('defaultValue', $default); } + /** + * @return void + */ + public function testRemoveWithFloat() + { + if (version_compare(PHP_VERSION, '8.1.0', '>=')) { + $this->markTestSkipped('Using floats as array key is deprecated.'); + } + + $array = ['name' => 'b', 'age' => 3, 1.1 => null]; + + $name = ArrayHelper::remove($array, 'name'); + $this->assertEquals($name, 'b'); + $this->assertEquals($array, ['age' => 3, 1.1 => null]); + + $floatVal = ArrayHelper::remove($array, 1.1); + $this->assertNull($floatVal); + $this->assertEquals($array, ['age' => 3]); + + $default = ArrayHelper::remove($array, 'nonExisting', 'defaultValue'); + $this->assertEquals('defaultValue', $default); + } + public function testRemoveValueMultiple() { $array = [ @@ -506,14 +529,21 @@ class ArrayHelperTest extends TestCase /** * @see https://github.com/yiisoft/yii2/pull/11549 */ - public function test() + public function testGetValueWithFloatKeys() { + if (version_compare(PHP_VERSION, '8.1.0', '>=')) { + $this->markTestSkipped('Using floats as array key is deprecated.'); + } + $array = []; - $array[1.0] = 'some value'; - - $result = ArrayHelper::getValue($array, 1.0); + $array[1.1] = 'some value'; + $array[2.1] = null; + $result = ArrayHelper::getValue($array, 1.2); $this->assertEquals('some value', $result); + + $result = ArrayHelper::getValue($array, 2.2); + $this->assertNull($result); } public function testIndex() @@ -712,6 +742,7 @@ class ArrayHelperTest extends TestCase 'a' => 1, 'B' => 2, ]; + $this->assertTrue(ArrayHelper::keyExists('a', $array)); $this->assertFalse(ArrayHelper::keyExists('b', $array)); $this->assertTrue(ArrayHelper::keyExists('B', $array)); @@ -723,6 +754,27 @@ class ArrayHelperTest extends TestCase $this->assertFalse(ArrayHelper::keyExists('c', $array, false)); } + public function testKeyExistsWithFloat() + { + if (version_compare(PHP_VERSION, '8.1.0', '>=')) { + $this->markTestSkipped('Using floats as array key is deprecated.'); + } + + $array = [ + 1 => 3, + 2.2 => 4, // Note: Floats are cast to ints, which means that the fractional part will be truncated. + 3.3 => null, + ]; + + $this->assertTrue(ArrayHelper::keyExists(1, $array)); + $this->assertTrue(ArrayHelper::keyExists(1.1, $array)); + $this->assertTrue(ArrayHelper::keyExists(2, $array)); + $this->assertTrue(ArrayHelper::keyExists('2', $array)); + $this->assertTrue(ArrayHelper::keyExists(2.2, $array)); + $this->assertTrue(ArrayHelper::keyExists(3, $array)); + $this->assertTrue(ArrayHelper::keyExists(3.3, $array)); + } + public function testKeyExistsArrayAccess() { $array = new TraversableArrayAccessibleObject([ From 4c0a00f2b9889c94abf5ac26cb90b491eb0ed902 Mon Sep 17 00:00:00 2001 From: Alain Rollmann Date: Mon, 21 Aug 2023 13:55:14 +0200 Subject: [PATCH 13/25] Fix #19924: Fix `yii\i18n\Formatter` to not throw error `Unknown named parameter` under PHP 8 --- framework/CHANGELOG.md | 1 + framework/i18n/Formatter.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 4ed527b0a7..84786927ce 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -16,6 +16,7 @@ Yii Framework 2 Change Log - Enh #19884: Added support Enums in Query Builder (sk1t0n) - Bug #19908: Fix associative array cell content rendering in Table widget (rhertogh) - Bug #19906: Fixed multiline strings in the `\yii\console\widgets\Table` widget (rhertogh) +- Bug #19924: Fix `yii\i18n\Formatter` to not throw error `Unknown named parameter` under PHP 8 (arollmann) - Bug #19914: Fixed `ArrayHelper::keyExists()` and `::remove()` functions when the key is a float and the value is `null` (rhertogh) - Enh #19920: Broadened the accepted type of `Cookie::$expire` from `int` to `int|string|\DateTimeInterface|null` (rhertogh) diff --git a/framework/i18n/Formatter.php b/framework/i18n/Formatter.php index 3236a433be..001b81bfa9 100644 --- a/framework/i18n/Formatter.php +++ b/framework/i18n/Formatter.php @@ -460,7 +460,7 @@ class Formatter extends Component } $method = 'as' . $format; if ($this->hasMethod($method)) { - return call_user_func_array([$this, $method], $params); + return call_user_func_array([$this, $method], array_values($params)); } throw new InvalidArgumentException("Unknown format type: $format"); From d5b3b6ca83061f1660f20f7a3441f4fa26e275ac Mon Sep 17 00:00:00 2001 From: Stefan Linke Date: Sat, 26 Aug 2023 03:08:16 +0200 Subject: [PATCH 14/25] Add note to UPGRADE guide for change in Validator behavior (#19938) The `unique` and `exists` validators behave slightly different since 2.0.46 (issue #19407) when used on multiple/combined attributes. See: https://github.com/yiisoft/yii2/issues/19407#issuecomment-1689625762 --- framework/UPGRADE.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/framework/UPGRADE.md b/framework/UPGRADE.md index 7d2ca03eb9..3a9569a982 100644 --- a/framework/UPGRADE.md +++ b/framework/UPGRADE.md @@ -100,6 +100,11 @@ Upgrade from Yii 2.0.45 2.0.45 behavior, [introduce your own method](https://github.com/yiisoft/yii2/pull/19495/files). * `yii\log\FileTarget::$rotateByCopy` is now deprecated and setting it to `false` has no effect since rotating of the files is done only by copy. +* `yii\validators\UniqueValidator` and `yii\validators\ExistValidator`, when used on multiple attributes, now only + generate an error on a single attribute. Previously, they would report a separate error on each attribute. + Old behavior can be achieved by setting `'skipOnError' => false`, but this might have undesired side effects with + additional validators on one of the target attributes. + See [issue #19407](https://github.com/yiisoft/yii2/issues/19407) Upgrade from Yii 2.0.44 ----------------------- From 8532622d7b119fdc37c96ebef727766a5dc84a39 Mon Sep 17 00:00:00 2001 From: PowerGamer1 Date: Sat, 26 Aug 2023 06:06:41 +0300 Subject: [PATCH 15/25] Fix #19911: Resolved inconsistency in `ActiveRecord::getAttributeLabel()` with regard of overriding in primary model labels for attributes of related model in favor of allowing such overriding for all levels of relation nesting --- framework/CHANGELOG.md | 1 + framework/db/BaseActiveRecord.php | 58 +++++++++-------- tests/framework/db/ActiveRecordTest.php | 83 +++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 26 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 84786927ce..362437e273 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -4,6 +4,7 @@ Yii Framework 2 Change Log 2.0.49 under development ------------------------ +- Bug #19911: Resolved inconsistency in `ActiveRecord::getAttributeLabel()` with regard of overriding in primary model labels for attributes of related model in favor of allowing such overriding for all levels of relation nesting (PowerGamer1) - Bug #19872: Fixed the definition of dirty attributes in AR properties for a non-associative array in case of changing the order of elements (eegusakov) - Bug #19899: Fixed `GridView` in some cases calling `Model::generateAttributeLabel()` to generate label values that are never used (PowerGamer1) - Bug #9899: Fix caching a MSSQL query with BLOB data type (terabytesoftw) diff --git a/framework/db/BaseActiveRecord.php b/framework/db/BaseActiveRecord.php index 60f621eb44..9b00cb430f 100644 --- a/framework/db/BaseActiveRecord.php +++ b/framework/db/BaseActiveRecord.php @@ -1610,40 +1610,46 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface /** * Returns the text label for the specified attribute. - * If the attribute looks like `relatedModel.attribute`, then the attribute will be received from the related model. + * The attribute may be specified in a dot format to retrieve the label from related model or allow this model to override the label defined in related model. + * For example, if the attribute is specified as 'relatedModel1.relatedModel2.attr' the function will return the first label definition it can find + * in the following order: + * - the label for 'relatedModel1.relatedModel2.attr' defined in [[attributeLabels()]] of this model; + * - the label for 'relatedModel2.attr' defined in related model represented by relation 'relatedModel1' of this model; + * - the label for 'attr' defined in related model represented by relation 'relatedModel2' of relation 'relatedModel1'. + * If no label definition was found then the value of $this->generateAttributeLabel('relatedModel1.relatedModel2.attr') will be returned. * @param string $attribute the attribute name * @return string the attribute label - * @see generateAttributeLabel() * @see attributeLabels() + * @see generateAttributeLabel() */ public function getAttributeLabel($attribute) { - $labels = $this->attributeLabels(); - if (isset($labels[$attribute])) { - return $labels[$attribute]; - } elseif (strpos($attribute, '.')) { - $attributeParts = explode('.', $attribute); - $neededAttribute = array_pop($attributeParts); - - $relatedModel = $this; - foreach ($attributeParts as $relationName) { - if ($relatedModel->isRelationPopulated($relationName) && $relatedModel->$relationName instanceof self) { - $relatedModel = $relatedModel->$relationName; - } else { - try { - $relation = $relatedModel->getRelation($relationName); - } catch (InvalidParamException $e) { - return $this->generateAttributeLabel($attribute); - } - /* @var $modelClass ActiveRecordInterface */ - $modelClass = $relation->modelClass; - $relatedModel = $modelClass::instance(); - } + $model = $this; + $modelAttribute = $attribute; + for (;;) { + $labels = $model->attributeLabels(); + if (isset($labels[$modelAttribute])) { + return $labels[$modelAttribute]; } - $labels = $relatedModel->attributeLabels(); - if (isset($labels[$neededAttribute])) { - return $labels[$neededAttribute]; + $parts = explode('.', $modelAttribute, 2); + if (count($parts) < 2) { + break; + } + + list ($relationName, $modelAttribute) = $parts; + + if ($model->isRelationPopulated($relationName) && $model->$relationName instanceof self) { + $model = $model->$relationName; + } else { + try { + $relation = $model->getRelation($relationName); + } catch (InvalidArgumentException $e) { + break; + } + /* @var $modelClass ActiveRecordInterface */ + $modelClass = $relation->modelClass; + $model = $modelClass::instance(); } } diff --git a/tests/framework/db/ActiveRecordTest.php b/tests/framework/db/ActiveRecordTest.php index f1370f4728..b74803b94d 100644 --- a/tests/framework/db/ActiveRecordTest.php +++ b/tests/framework/db/ActiveRecordTest.php @@ -2192,4 +2192,87 @@ abstract class ActiveRecordTest extends DatabaseTestCase $this->assertNotNull($order->virtualCustomer); } + public function labelTestModelProvider() + { + $data = []; + + // Model 2 and 3 are represented by objects. + $model1 = new LabelTestModel1(); + $model2 = new LabelTestModel2(); + $model3 = new LabelTestModel3(); + $model2->populateRelation('model3', $model3); + $model1->populateRelation('model2', $model2); + $data[] = [$model1]; + + // Model 2 and 3 are represented by arrays instead of objects. + $model1 = new LabelTestModel1(); + $model2 = ['model3' => []]; + $model1->populateRelation('model2', $model2); + $data[] = [$model1]; + + return $data; + } + + /** + * @dataProvider labelTestModelProvider + * @param \yii\db\ActiveRecord $model + */ + public function testGetAttributeLabel($model) + { + $this->assertEquals('model3.attr1 from model2', $model->getAttributeLabel('model2.model3.attr1')); + $this->assertEquals('attr2 from model3', $model->getAttributeLabel('model2.model3.attr2')); + $this->assertEquals('model3.attr3 from model2', $model->getAttributeLabel('model2.model3.attr3')); + $attr = 'model2.doesNotExist.attr1'; + $this->assertEquals($model->generateAttributeLabel($attr), $model->getAttributeLabel($attr)); + } +} + +class LabelTestModel1 extends \yii\db\ActiveRecord +{ + public function attributes() + { + return []; + } + + public function getModel2() + { + return $this->hasOne(LabelTestModel2::className(), []); + } +} + +class LabelTestModel2 extends \yii\db\ActiveRecord +{ + public function attributes() + { + return []; + } + + public function getModel3() + { + return $this->hasOne(LabelTestModel3::className(), []); + } + + public function attributeLabels() + { + return [ + 'model3.attr1' => 'model3.attr1 from model2', // Override label defined in model3. + 'model3.attr3' => 'model3.attr3 from model2', // Define label not defined in model3. + ]; + } +} + +class LabelTestModel3 extends \yii\db\ActiveRecord +{ + public function attributes() + { + return ['attr1', 'attr2', 'attr3']; + } + + public function attributeLabels() + { + return [ + 'attr1' => 'attr1 from model3', + 'attr2' => 'attr2 from model3', + ]; + } } From 4ffb58ed56357a0ddac9b371076db6972afef185 Mon Sep 17 00:00:00 2001 From: Yuriy Bachevskiy Date: Mon, 28 Aug 2023 14:30:51 +0700 Subject: [PATCH 16/25] Fix type (#19939) --- docs/guide-ru/runtime-bootstrapping.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide-ru/runtime-bootstrapping.md b/docs/guide-ru/runtime-bootstrapping.md index 0222473af5..4e74ac8c0c 100644 --- a/docs/guide-ru/runtime-bootstrapping.md +++ b/docs/guide-ru/runtime-bootstrapping.md @@ -10,7 +10,7 @@ В конструкторе приложения происходит следующий процесс предзагрузки: -1. Вызывается метод [[yii\base\Application::preInit()|preInit()]], которые конфигурирует свойства приложения, имеющие +1. Вызывается метод [[yii\base\Application::preInit()|preInit()]], который конфигурирует свойства приложения, имеющие наивысший приоритет, такие как [[yii\base\Application::basePath|basePath]]; 2. Регистрируется [[yii\base\Application::errorHandler|обработчик ошибок]]; 3. Происходит инициализация свойств приложения согласно заданной конфигурации; From 0f7248c7a2ffcf17d7f2f06d41d009a93be10930 Mon Sep 17 00:00:00 2001 From: Bizley Date: Tue, 29 Aug 2023 15:36:17 +0200 Subject: [PATCH 17/25] release version 2.0.49 --- framework/BaseYii.php | 2 +- framework/CHANGELOG.md | 22 +++++++++++----------- framework/db/BaseActiveRecord.php | 2 +- framework/db/Migration.php | 6 +++--- framework/helpers/mimeExtensions.php | 2 ++ framework/helpers/mimeTypes.php | 2 ++ 6 files changed, 20 insertions(+), 16 deletions(-) diff --git a/framework/BaseYii.php b/framework/BaseYii.php index dfa5419cb0..14fd3477f6 100644 --- a/framework/BaseYii.php +++ b/framework/BaseYii.php @@ -93,7 +93,7 @@ class BaseYii */ public static function getVersion() { - return '2.0.49-dev'; + return '2.0.49'; } /** diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 362437e273..c02e5cf5d8 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -1,24 +1,24 @@ Yii Framework 2 Change Log ========================== -2.0.49 under development ------------------------- +2.0.49 August 29, 2023 +---------------------- -- Bug #19911: Resolved inconsistency in `ActiveRecord::getAttributeLabel()` with regard of overriding in primary model labels for attributes of related model in favor of allowing such overriding for all levels of relation nesting (PowerGamer1) -- Bug #19872: Fixed the definition of dirty attributes in AR properties for a non-associative array in case of changing the order of elements (eegusakov) -- Bug #19899: Fixed `GridView` in some cases calling `Model::generateAttributeLabel()` to generate label values that are never used (PowerGamer1) - Bug #9899: Fix caching a MSSQL query with BLOB data type (terabytesoftw) - Bug #16208: Fix `yii\log\FileTarget` to not export empty messages (terabytesoftw) -- Bug #19857: Fix AttributeTypecastBehavior::resetOldAttributes() causes "class has no attribute named" InvalidArgumentException (uaoleg) - Bug #18859: Fix `yii\web\Controller::bindInjectedParams()` to not throw error when argument of `ReflectionUnionType` type is passed (bizley) +- Bug #19857: Fix AttributeTypecastBehavior::resetOldAttributes() causes "class has no attribute named" InvalidArgumentException (uaoleg) +- Bug #19868: Added whitespace sanitation for tests, due to updates in ICU 72 (schmunk42) +- Bug #19872: Fixed the definition of dirty attributes in AR properties for a non-associative array in case of changing the order of elements (eegusakov) +- Bug #19899: Fixed `GridView` in some cases calling `Model::generateAttributeLabel()` to generate label values that are never used (PowerGamer1) +- Bug #19906: Fixed multiline strings in the `\yii\console\widgets\Table` widget (rhertogh) +- Bug #19908: Fix associative array cell content rendering in Table widget (rhertogh) +- Bug #19911: Resolved inconsistency in `ActiveRecord::getAttributeLabel()` with regard of overriding in primary model labels for attributes of related model in favor of allowing such overriding for all levels of relation nesting (PowerGamer1) +- Bug #19914: Fixed `ArrayHelper::keyExists()` and `::remove()` functions when the key is a float and the value is `null` (rhertogh) +- Bug #19924: Fix `yii\i18n\Formatter` to not throw error `Unknown named parameter` under PHP 8 (arollmann) - Enh #19841: Allow jQuery 3.7 to be installed (wouter90) - Enh #19853: Added support for default value for `\yii\helpers\Console::select()` (rhertogh) -- Bug #19868: Added whitespace sanitation for tests, due to updates in ICU 72 (schmunk42) - Enh #19884: Added support Enums in Query Builder (sk1t0n) -- Bug #19908: Fix associative array cell content rendering in Table widget (rhertogh) -- Bug #19906: Fixed multiline strings in the `\yii\console\widgets\Table` widget (rhertogh) -- Bug #19924: Fix `yii\i18n\Formatter` to not throw error `Unknown named parameter` under PHP 8 (arollmann) -- Bug #19914: Fixed `ArrayHelper::keyExists()` and `::remove()` functions when the key is a float and the value is `null` (rhertogh) - Enh #19920: Broadened the accepted type of `Cookie::$expire` from `int` to `int|string|\DateTimeInterface|null` (rhertogh) diff --git a/framework/db/BaseActiveRecord.php b/framework/db/BaseActiveRecord.php index 9b00cb430f..61cf377409 100644 --- a/framework/db/BaseActiveRecord.php +++ b/framework/db/BaseActiveRecord.php @@ -1616,7 +1616,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface * - the label for 'relatedModel1.relatedModel2.attr' defined in [[attributeLabels()]] of this model; * - the label for 'relatedModel2.attr' defined in related model represented by relation 'relatedModel1' of this model; * - the label for 'attr' defined in related model represented by relation 'relatedModel2' of relation 'relatedModel1'. - * If no label definition was found then the value of $this->generateAttributeLabel('relatedModel1.relatedModel2.attr') will be returned. + * If no label definition was found then the value of $this->generateAttributeLabel('relatedModel1.relatedModel2.attr') will be returned. * @param string $attribute the attribute name * @return string the attribute label * @see attributeLabels() diff --git a/framework/db/Migration.php b/framework/db/Migration.php index 975898cd53..c4bf99981a 100644 --- a/framework/db/Migration.php +++ b/framework/db/Migration.php @@ -311,7 +311,7 @@ class Migration extends Component implements MigrationInterface * * If a column is specified with definition only (e.g. 'PRIMARY KEY (name, type)'), it will be directly * put into the generated SQL. - * + * * Example usage: * ```php * class m200000_000000_create_table_fruits extends \yii\db\Migration @@ -319,10 +319,10 @@ class Migration extends Component implements MigrationInterface * public function safeUp() * { * $this->createTable('{{%fruits}}', [ - * // ... + * // ... * 'column_name double precision null default null', * ``` - + * * * @param string $table the name of the table to be created. The name will be properly quoted by the method. * @param array $columns the columns (name => definition) in the new table. diff --git a/framework/helpers/mimeExtensions.php b/framework/helpers/mimeExtensions.php index dfe5ee5ae4..946d61cd0c 100644 --- a/framework/helpers/mimeExtensions.php +++ b/framework/helpers/mimeExtensions.php @@ -299,6 +299,7 @@ return [ 'application/vnd.fuzzysheet' => 'fzs', 'application/vnd.genomatix.tuxedo' => 'txd', 'application/vnd.geogebra.file' => 'ggb', + 'application/vnd.geogebra.slides' => 'ggs', 'application/vnd.geogebra.tool' => 'ggt', 'application/vnd.geometry-explorer' => [ 'gex', @@ -655,6 +656,7 @@ return [ ], 'application/vnd.zzazz.deck+xml' => 'zaz', 'application/voicexml+xml' => 'vxml', + 'application/wasm' => 'wasm', 'application/widget' => 'wgt', 'application/winhlp' => 'hlp', 'application/wsdl+xml' => 'wsdl', diff --git a/framework/helpers/mimeTypes.php b/framework/helpers/mimeTypes.php index f4430605a3..707bdc7717 100644 --- a/framework/helpers/mimeTypes.php +++ b/framework/helpers/mimeTypes.php @@ -282,6 +282,7 @@ $mimeTypes = [ 'geo' => 'application/vnd.dynageo', 'gex' => 'application/vnd.geometry-explorer', 'ggb' => 'application/vnd.geogebra.file', + 'ggs' => 'application/vnd.geogebra.slides', 'ggt' => 'application/vnd.geogebra.tool', 'ghf' => 'application/vnd.groove-help', 'gif' => 'image/gif', @@ -887,6 +888,7 @@ $mimeTypes = [ 'vxml' => 'application/voicexml+xml', 'w3d' => 'application/x-director', 'wad' => 'application/x-doom', + 'wasm' => 'application/wasm', 'wav' => 'audio/x-wav', 'wax' => 'audio/x-ms-wax', 'wbmp' => 'image/vnd.wap.wbmp', From a2ee22044c2df9d6b463c7c47563df762cc17fb6 Mon Sep 17 00:00:00 2001 From: Bizley Date: Tue, 29 Aug 2023 15:36:45 +0200 Subject: [PATCH 18/25] prepare for next release --- framework/BaseYii.php | 2 +- framework/CHANGELOG.md | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/framework/BaseYii.php b/framework/BaseYii.php index 14fd3477f6..496f6aa121 100644 --- a/framework/BaseYii.php +++ b/framework/BaseYii.php @@ -93,7 +93,7 @@ class BaseYii */ public static function getVersion() { - return '2.0.49'; + return '2.0.50-dev'; } /** diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index c02e5cf5d8..b1f82b066f 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -1,6 +1,12 @@ Yii Framework 2 Change Log ========================== +2.0.50 under development +------------------------ + +- no changes in this release. + + 2.0.49 August 29, 2023 ---------------------- From 671fbefe8457568ea1b83750f8a98a60bc62d9cd Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Wed, 30 Aug 2023 08:14:12 -0400 Subject: [PATCH 19/25] File Log writer without newline. (#19941) * File Log writer without newline. * Fix minor correction. * Fix tests. * Add more test. * Add line to CHANGELOG.md. --- framework/CHANGELOG.md | 2 +- framework/log/FileTarget.php | 4 ++-- tests/framework/log/FileTargetTest.php | 14 +++++++++++++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index b1f82b066f..a96d0eff96 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -4,7 +4,7 @@ Yii Framework 2 Change Log 2.0.50 under development ------------------------ -- no changes in this release. +- Bug #19940: File Log writer without newline (terabytesoftw) 2.0.49 August 29, 2023 diff --git a/framework/log/FileTarget.php b/framework/log/FileTarget.php index e56909c32f..d816f73a8d 100644 --- a/framework/log/FileTarget.php +++ b/framework/log/FileTarget.php @@ -130,12 +130,12 @@ class FileTarget extends Target if ($this->enableRotation && @filesize($this->logFile) > $this->maxFileSize * 1024) { $this->rotateFiles(); } - $writeResult = @fwrite($fp, $trimmedText); + $writeResult = @fwrite($fp, $text); if ($writeResult === false) { $error = error_get_last(); throw new LogRuntimeException("Unable to export log through file ({$this->logFile})!: {$error['message']}"); } - $textSize = strlen($trimmedText); + $textSize = strlen($text); if ($writeResult < $textSize) { throw new LogRuntimeException("Unable to export whole log through file ({$this->logFile})! Wrote $writeResult out of $textSize bytes."); } diff --git a/tests/framework/log/FileTargetTest.php b/tests/framework/log/FileTargetTest.php index fb71258057..4f6eaf4ae7 100644 --- a/tests/framework/log/FileTargetTest.php +++ b/tests/framework/log/FileTargetTest.php @@ -123,7 +123,19 @@ class FileTargetTest extends TestCase $logger->export(); $test = file($logFile); - $this->assertEquals("xxx", $test[0]); + $this->assertEquals("xxx\n", $test[0]); + + $this->clearLogFile($logFile); + + $logger = new CustomLogger(); + $logger->logFile = $logFile; + $logger->messages = array_fill(0, 3, 'xxx'); + $logger->export(); + + $test = file($logFile); + $this->assertEquals("xxx\n", $test[0]); + $this->assertEquals("xxx\n", $test[1]); + $this->assertEquals("xxx\n", $test[2]); $this->clearLogFile($logFile); From e8c4a7e56e6329860fc17c07a613af55e5f0bfcb Mon Sep 17 00:00:00 2001 From: Tobias Munk Date: Mon, 4 Sep 2023 10:09:49 +0200 Subject: [PATCH 20/25] added PHP version check, fixed #19925 (#19936) * added PHP version check, fixed #19925 * added CHANGELOG line * fixed typo * fixed typo --------- Co-authored-by: Alexander Makarov Co-authored-by: Bizley --- framework/CHANGELOG.md | 1 + framework/helpers/mimeTypes.php | 3 ++- tests/framework/helpers/MimeTest.php | 3 ++- tests/framework/validators/FileValidatorTest.php | 3 ++- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index a96d0eff96..95d436776d 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -4,6 +4,7 @@ Yii Framework 2 Change Log 2.0.50 under development ------------------------ +- Bug #19925: Improved PHP version check when handling MIME types (schmunk42) - Bug #19940: File Log writer without newline (terabytesoftw) diff --git a/framework/helpers/mimeTypes.php b/framework/helpers/mimeTypes.php index 707bdc7717..e91f80f95f 100644 --- a/framework/helpers/mimeTypes.php +++ b/framework/helpers/mimeTypes.php @@ -1003,7 +1003,8 @@ $mimeTypes = [ 'zmm' => 'application/vnd.handheld-entertainment+xml', ]; -if (PHP_VERSION_ID >= 80100) { +# fix for bundled libmagic bug, see also https://github.com/yiisoft/yii2/issues/19925 +if ((PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80122) || (PHP_VERSION_ID >= 80200 && PHP_VERSION_ID < 80209)) { $mimeTypes = array_replace($mimeTypes, array('xz' => 'application/octet-stream')); } diff --git a/tests/framework/helpers/MimeTest.php b/tests/framework/helpers/MimeTest.php index 2c0d8f09de..b3914d5a11 100644 --- a/tests/framework/helpers/MimeTest.php +++ b/tests/framework/helpers/MimeTest.php @@ -1031,7 +1031,8 @@ class MimeTest extends TestCase 'zmm' => 'application/vnd.handheld-entertainment+xml', ]; - if (PHP_VERSION_ID >= 80100) { + # fix for bundled libmagic bug, see also https://github.com/yiisoft/yii2/issues/19925 + if ((PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80122) || (PHP_VERSION_ID >= 80200 && PHP_VERSION_ID < 80209)) { $coreMimeTypes = array_replace($coreMimeTypes, array('xz' => 'application/octet-stream')); } diff --git a/tests/framework/validators/FileValidatorTest.php b/tests/framework/validators/FileValidatorTest.php index f6af4ec681..157269e5d4 100644 --- a/tests/framework/validators/FileValidatorTest.php +++ b/tests/framework/validators/FileValidatorTest.php @@ -546,7 +546,8 @@ class FileValidatorTest extends TestCase ['test.tar.xz', 'application/x-xz', 'tar.xz'], ]); - if (PHP_VERSION_ID >= 80100) { + # fix for bundled libmagic bug, see also https://github.com/yiisoft/yii2/issues/19925 + if ((PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80122) || (PHP_VERSION_ID >= 80200 && PHP_VERSION_ID < 80209)) { $v81_zx = ['test.tar.xz', 'application/octet-stream', 'tar.xz']; array_pop($validMimeTypes); $validMimeTypes[] = $v81_zx; From b05ad49a1943ca2f876ed23658d523cabf8b33a2 Mon Sep 17 00:00:00 2001 From: Oleg Poludnenko Date: Mon, 11 Sep 2023 19:38:41 +0300 Subject: [PATCH 21/25] trim(): Passing null to parameter #1 ($string) of type string is deprecated --- framework/db/Query.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/db/Query.php b/framework/db/Query.php index f0b215859d..1819c9c310 100644 --- a/framework/db/Query.php +++ b/framework/db/Query.php @@ -1049,7 +1049,7 @@ PATTERN; /** * Sets the GROUP BY part of the query. - * @param string|array|ExpressionInterface $columns the columns to be grouped by. + * @param string|array|ExpressionInterface|null $columns the columns to be grouped by. * Columns can be specified in either a string (e.g. "id, name") or an array (e.g. ['id', 'name']). * The method will automatically quote the column names unless a column contains some parenthesis * (which means the column contains a DB expression). @@ -1067,7 +1067,7 @@ PATTERN; { if ($columns instanceof ExpressionInterface) { $columns = [$columns]; - } elseif (!is_array($columns)) { + } elseif (!is_array($columns) && !is_null($columns)) { $columns = preg_split('/\s*,\s*/', trim($columns), -1, PREG_SPLIT_NO_EMPTY); } $this->groupBy = $columns; From 30b491dfdf2cf047ddcbec39c2533d1837699c4e Mon Sep 17 00:00:00 2001 From: Tobias Munk Date: Wed, 13 Sep 2023 13:23:21 +0200 Subject: [PATCH 22/25] removed MIME file tests (#19951) * removed MIME file tests see also https://github.com/yiisoft/yii2/commit/0f7248c7a2ffcf17d7f2f06d41d009a93be10930#commitcomment-127223170 * added CHANGELOG line --- framework/CHANGELOG.md | 1 + tests/framework/helpers/MimeTest.php | 2276 -------------------------- 2 files changed, 1 insertion(+), 2276 deletions(-) delete mode 100644 tests/framework/helpers/MimeTest.php diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 95d436776d..e468b61f78 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -6,6 +6,7 @@ Yii Framework 2 Change Log - Bug #19925: Improved PHP version check when handling MIME types (schmunk42) - Bug #19940: File Log writer without newline (terabytesoftw) +- Bug #19951: Removed unneeded MIME file tests (schmunk42) 2.0.49 August 29, 2023 diff --git a/tests/framework/helpers/MimeTest.php b/tests/framework/helpers/MimeTest.php deleted file mode 100644 index b3914d5a11..0000000000 --- a/tests/framework/helpers/MimeTest.php +++ /dev/null @@ -1,2276 +0,0 @@ -assertSame( - [ - 'text/rtf' => 'application/rtf', - 'text/xml' => 'application/xml', - 'image/svg' => 'image/svg+xml', - 'image/x-bmp' => 'image/bmp', - 'image/x-bitmap' => 'image/bmp', - 'image/x-xbitmap' => 'image/bmp', - 'image/x-win-bitmap' => 'image/bmp', - 'image/x-windows-bmp' => 'image/bmp', - 'image/ms-bmp' => 'image/bmp', - 'image/x-ms-bmp' => 'image/bmp', - 'application/bmp' => 'image/bmp', - 'application/x-bmp' => 'image/bmp', - 'application/x-win-bitmap' => 'image/bmp', - ], - require __DIR__ . '/../../../framework/helpers/mimeAliases.php' - ); - } - - public function testMimeTypes() - { - $coreMimeTypes = [ - 123 => 'application/vnd.lotus-1-2-3', - '3dml' => 'text/vnd.in3d.3dml', - '3ds' => 'image/x-3ds', - '3g2' => 'video/3gpp2', - '3gp' => 'video/3gpp', - '7z' => 'application/x-7z-compressed', - 'aab' => 'application/x-authorware-bin', - 'aac' => 'audio/x-aac', - 'aam' => 'application/x-authorware-map', - 'aas' => 'application/x-authorware-seg', - 'abw' => 'application/x-abiword', - 'ac' => 'application/pkix-attr-cert', - 'acc' => 'application/vnd.americandynamics.acc', - 'ace' => 'application/x-ace-compressed', - 'acu' => 'application/vnd.acucobol', - 'acutc' => 'application/vnd.acucorp', - 'adp' => 'audio/adpcm', - 'aep' => 'application/vnd.audiograph', - 'afm' => 'application/x-font-type1', - 'afp' => 'application/vnd.ibm.modcap', - 'ahead' => 'application/vnd.ahead.space', - 'ai' => 'application/postscript', - 'aif' => 'audio/x-aiff', - 'aifc' => 'audio/x-aiff', - 'aiff' => 'audio/x-aiff', - 'air' => 'application/vnd.adobe.air-application-installer-package+zip', - 'ait' => 'application/vnd.dvb.ait', - 'ami' => 'application/vnd.amiga.ami', - 'apk' => 'application/vnd.android.package-archive', - 'apng' => 'image/apng', - 'appcache' => 'text/cache-manifest', - 'application' => 'application/x-ms-application', - 'apr' => 'application/vnd.lotus-approach', - 'arc' => 'application/x-freearc', - 'asc' => 'application/pgp-signature', - 'asf' => 'video/x-ms-asf', - 'asm' => 'text/x-asm', - 'aso' => 'application/vnd.accpac.simply.aso', - 'asx' => 'video/x-ms-asf', - 'atc' => 'application/vnd.acucorp', - 'atom' => 'application/atom+xml', - 'atomcat' => 'application/atomcat+xml', - 'atomsvc' => 'application/atomsvc+xml', - 'atx' => 'application/vnd.antix.game-component', - 'au' => 'audio/basic', - 'avi' => 'video/x-msvideo', - 'avif' => 'image/avif', - 'aw' => 'application/applixware', - 'azf' => 'application/vnd.airzip.filesecure.azf', - 'azs' => 'application/vnd.airzip.filesecure.azs', - 'azw' => 'application/vnd.amazon.ebook', - 'bat' => 'application/x-msdownload', - 'bcpio' => 'application/x-bcpio', - 'bdf' => 'application/x-font-bdf', - 'bdm' => 'application/vnd.syncml.dm+wbxml', - 'bed' => 'application/vnd.realvnc.bed', - 'bh2' => 'application/vnd.fujitsu.oasysprs', - 'bin' => 'application/octet-stream', - 'blb' => 'application/x-blorb', - 'blorb' => 'application/x-blorb', - 'bmi' => 'application/vnd.bmi', - 'bmp' => 'image/bmp', - 'book' => 'application/vnd.framemaker', - 'box' => 'application/vnd.previewsystems.box', - 'boz' => 'application/x-bzip2', - 'bpk' => 'application/octet-stream', - 'btif' => 'image/prs.btif', - 'bz' => 'application/x-bzip', - 'bz2' => 'application/x-bzip2', - 'c' => 'text/x-c', - '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', - 'caf' => 'audio/x-caf', - 'cap' => 'application/vnd.tcpdump.pcap', - 'car' => 'application/vnd.curl.car', - 'cat' => 'application/vnd.ms-pki.seccat', - 'cb7' => 'application/x-cbr', - 'cba' => 'application/x-cbr', - 'cbr' => 'application/x-cbr', - 'cbt' => 'application/x-cbr', - 'cbz' => 'application/x-cbr', - 'cc' => 'text/x-c', - 'cct' => 'application/x-director', - 'ccxml' => 'application/ccxml+xml', - 'cdbcmsg' => 'application/vnd.contact.cmsg', - 'cdf' => 'application/x-netcdf', - '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', - 'cdx' => 'chemical/x-cdx', - 'cdxml' => 'application/vnd.chemdraw+xml', - 'cdy' => 'application/vnd.cinderella', - 'cer' => 'application/pkix-cert', - 'cfs' => 'application/x-cfs-compressed', - 'cgm' => 'image/cgm', - 'chat' => 'application/x-chat', - 'chm' => 'application/vnd.ms-htmlhelp', - 'chrt' => 'application/vnd.kde.kchart', - 'cif' => 'chemical/x-cif', - 'cii' => 'application/vnd.anser-web-certificate-issue-initiation', - 'cil' => 'application/vnd.ms-artgalry', - 'cla' => 'application/vnd.claymore', - 'class' => 'application/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', - 'cmc' => 'application/vnd.cosmocaller', - 'cmdf' => 'chemical/x-cmdf', - 'cml' => 'chemical/x-cml', - 'cmp' => 'application/vnd.yellowriver-custom-menu', - 'cmx' => 'image/x-cmx', - 'cod' => 'application/vnd.rim.cod', - 'com' => 'application/x-msdownload', - 'conf' => 'text/plain', - 'cpio' => 'application/x-cpio', - 'cpp' => 'text/x-c', - 'cpt' => 'application/mac-compactpro', - 'crd' => 'application/x-mscardfile', - 'crl' => 'application/pkix-crl', - 'crt' => 'application/x-x509-ca-cert', - 'cryptonote' => 'application/vnd.rig.cryptonote', - 'csh' => 'application/x-csh', - 'csml' => 'chemical/x-csml', - 'csp' => 'application/vnd.commonspace', - 'css' => 'text/css', - 'cst' => 'application/x-director', - 'csv' => 'text/csv', - 'cu' => 'application/cu-seeme', - 'curl' => 'text/vnd.curl', - 'cww' => 'application/prs.cww', - 'cxt' => 'application/x-director', - 'cxx' => 'text/x-c', - 'dae' => 'model/vnd.collada+xml', - 'daf' => 'application/vnd.mobius.daf', - 'dart' => 'application/vnd.dart', - 'dataless' => 'application/vnd.fdsn.seed', - 'davmount' => 'application/davmount+xml', - 'dbk' => 'application/docbook+xml', - 'dcr' => 'application/x-director', - 'dcurl' => 'text/vnd.curl.dcurl', - 'dd2' => 'application/vnd.oma.dd2+xml', - 'ddd' => 'application/vnd.fujixerox.ddd', - 'deb' => 'application/x-debian-package', - 'def' => 'text/plain', - 'deploy' => 'application/octet-stream', - 'der' => 'application/x-x509-ca-cert', - 'dfac' => 'application/vnd.dreamfactory', - 'dgc' => 'application/x-dgc-compressed', - 'dic' => 'text/x-c', - 'dir' => 'application/x-director', - 'dis' => 'application/vnd.mobius.dis', - 'dist' => 'application/octet-stream', - 'distz' => 'application/octet-stream', - 'djv' => 'image/vnd.djvu', - 'djvu' => 'image/vnd.djvu', - 'dll' => 'application/x-msdownload', - 'dmg' => 'application/x-apple-diskimage', - 'dmp' => 'application/vnd.tcpdump.pcap', - 'dms' => 'application/octet-stream', - 'dna' => 'application/vnd.dna', - 'doc' => 'application/msword', - 'docm' => 'application/vnd.ms-word.document.macroenabled.12', - 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'dot' => 'application/msword', - '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', - 'dsc' => 'text/prs.lines.tag', - 'dssc' => 'application/dssc+der', - 'dtb' => 'application/x-dtbook+xml', - 'dtd' => 'application/xml-dtd', - 'dts' => 'audio/vnd.dts', - 'dtshd' => 'audio/vnd.dts.hd', - 'dump' => 'application/octet-stream', - 'dvb' => 'video/vnd.dvb.file', - 'dvi' => 'application/x-dvi', - 'dwf' => 'model/vnd.dwf', - 'dwg' => 'image/vnd.dwg', - 'dxf' => 'image/vnd.dxf', - 'dxp' => 'application/vnd.spotfire.dxp', - 'dxr' => 'application/x-director', - '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', - 'ei6' => 'application/vnd.pg.osasli', - 'elc' => 'application/octet-stream', - 'emf' => 'application/x-msmetafile', - 'eml' => 'message/rfc822', - 'emma' => 'application/emma+xml', - 'emz' => 'application/x-msmetafile', - 'eol' => 'audio/vnd.digital-winds', - 'eot' => 'application/vnd.ms-fontobject', - 'eps' => 'application/postscript', - 'epub' => 'application/epub+zip', - 'es3' => 'application/vnd.eszigno3+xml', - 'esa' => 'application/vnd.osgi.subsystem', - 'esf' => 'application/vnd.epson.esf', - 'et3' => 'application/vnd.eszigno3+xml', - 'etx' => 'text/x-setext', - 'eva' => 'application/x-eva', - 'evy' => 'application/x-envoy', - 'exe' => 'application/x-msdownload', - 'exi' => 'application/exi', - 'ext' => 'application/vnd.novadigm.ext', - 'ez' => 'application/andrew-inset', - 'ez2' => 'application/vnd.ezpix-album', - 'ez3' => 'application/vnd.ezpix-package', - 'f' => 'text/x-fortran', - 'f4v' => 'video/x-f4v', - 'f77' => 'text/x-fortran', - 'f90' => 'text/x-fortran', - 'fbs' => 'image/vnd.fastbidsheet', - 'fcdt' => 'application/vnd.adobe.formscentral.fcdt', - 'fcs' => 'application/vnd.isac.fcs', - 'fdf' => 'application/vnd.fdf', - 'fe_launch' => 'application/vnd.denovo.fcselayout-link', - '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', - 'flac' => 'audio/x-flac', - 'fli' => 'video/x-fli', - 'flo' => 'application/vnd.micrografx.flo', - 'flv' => 'video/x-flv', - 'flw' => 'application/vnd.kde.kivio', - 'flx' => 'text/vnd.fmi.flexstor', - 'fly' => 'text/vnd.fly', - 'fm' => 'application/vnd.framemaker', - 'fnc' => 'application/vnd.frogans.fnc', - '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', - 'fxp' => 'application/vnd.adobe.fxp', - 'fxpl' => 'application/vnd.adobe.fxp', - 'fzs' => 'application/vnd.fuzzysheet', - 'g2w' => 'application/vnd.geoplan', - 'g3' => 'image/g3fax', - 'g3w' => 'application/vnd.geospace', - 'gac' => 'application/vnd.groove-account', - 'gam' => 'application/x-tads', - 'gbr' => 'application/rpki-ghostbusters', - 'gca' => 'application/x-gca-compressed', - 'gdl' => 'model/vnd.gdl', - 'geo' => 'application/vnd.dynageo', - 'gex' => 'application/vnd.geometry-explorer', - 'ggb' => 'application/vnd.geogebra.file', - 'ggt' => 'application/vnd.geogebra.tool', - 'ghf' => 'application/vnd.groove-help', - 'gif' => 'image/gif', - 'gim' => 'application/vnd.groove-identity-message', - 'gml' => 'application/gml+xml', - 'gmx' => 'application/vnd.gmx', - 'gnumeric' => 'application/x-gnumeric', - 'gph' => 'application/vnd.flographit', - 'gpx' => 'application/gpx+xml', - 'gqf' => 'application/vnd.grafeq', - 'gqs' => 'application/vnd.grafeq', - 'gram' => 'application/srgs', - 'gramps' => 'application/x-gramps-xml', - 'gre' => 'application/vnd.geometry-explorer', - 'grv' => 'application/vnd.groove-injector', - 'grxml' => 'application/srgs+xml', - 'gsf' => 'application/x-font-ghostscript', - 'gtar' => 'application/x-gtar', - 'gtm' => 'application/vnd.groove-tool-message', - 'gtw' => 'model/vnd.gtw', - 'gv' => 'text/vnd.graphviz', - 'gxf' => 'application/gxf', - 'gxt' => 'application/vnd.geonext', - 'h' => 'text/x-c', - 'h261' => 'video/h261', - 'h263' => 'video/h263', - 'h264' => 'video/h264', - 'hal' => 'application/vnd.hal+xml', - 'hbci' => 'application/vnd.hbci', - 'hdf' => 'application/x-hdf', - 'hh' => 'text/x-c', - 'hlp' => 'application/winhlp', - 'hpgl' => 'application/vnd.hp-hpgl', - 'hpid' => 'application/vnd.hp-hpid', - 'hps' => 'application/vnd.hp-hps', - 'hqx' => 'application/mac-binhex40', - 'htke' => 'application/vnd.kenameaapp', - 'htm' => 'text/html', - 'html' => 'text/html', - 'hvd' => 'application/vnd.yamaha.hv-dic', - 'hvp' => 'application/vnd.yamaha.hv-voice', - 'hvs' => 'application/vnd.yamaha.hv-script', - 'i2g' => 'application/vnd.intergeo', - 'icc' => 'application/vnd.iccprofile', - 'ice' => 'x-conference/x-cooltalk', - 'icm' => 'application/vnd.iccprofile', - 'ico' => 'image/x-icon', - 'ics' => 'text/calendar', - 'ief' => 'image/ief', - 'ifb' => 'text/calendar', - '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', - 'imp' => 'application/vnd.accpac.simply.imp', - 'ims' => 'application/vnd.ms-ims', - 'in' => 'text/plain', - 'ink' => 'application/inkml+xml', - 'inkml' => 'application/inkml+xml', - 'install' => 'application/x-install-instructions', - 'iota' => 'application/vnd.astraea-software.iota', - 'ipfix' => 'application/ipfix', - 'ipk' => 'application/vnd.shana.informed.package', - 'irm' => 'application/vnd.ibm.rights-management', - 'irp' => 'application/vnd.irepository.package+xml', - 'iso' => 'application/x-iso9660-image', - 'itp' => 'application/vnd.shana.informed.formtemplate', - 'ivp' => 'application/vnd.immervision-ivp', - 'ivu' => 'application/vnd.immervision-ivu', - 'jad' => 'text/vnd.sun.j2me.app-descriptor', - 'jam' => 'application/vnd.jam', - 'jar' => 'application/java-archive', - 'java' => 'text/x-java-source', - 'jfif' => 'image/jpeg', - 'jisp' => 'application/vnd.jisp', - 'jlt' => 'application/vnd.hp-jlyt', - 'jnlp' => 'application/x-java-jnlp-file', - 'joda' => 'application/vnd.joost.joda-archive', - 'jpe' => 'image/jpeg', - 'jpeg' => 'image/jpeg', - 'jpg' => 'image/jpeg', - 'jpgm' => 'video/jpm', - 'jpgv' => 'video/jpeg', - 'jpm' => 'video/jpm', - 'js' => 'text/javascript', - 'json' => 'application/json', - 'jsonml' => 'application/jsonml+json', - 'kar' => 'audio/midi', - 'karbon' => 'application/vnd.kde.karbon', - 'kfo' => 'application/vnd.kde.kformula', - 'kia' => 'application/vnd.kidspiration', - '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', - 'kpr' => 'application/vnd.kde.kpresenter', - 'kpt' => 'application/vnd.kde.kpresenter', - 'kpxx' => 'application/vnd.ds-keypoint', - 'ksp' => 'application/vnd.kde.kspread', - 'ktr' => 'application/vnd.kahootz', - 'ktx' => 'image/ktx', - 'ktz' => 'application/vnd.kahootz', - 'kwd' => 'application/vnd.kde.kword', - 'kwt' => 'application/vnd.kde.kword', - 'lasxml' => 'application/vnd.las.las+xml', - 'latex' => 'application/x-latex', - 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop', - 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml', - 'les' => 'application/vnd.hhe.lesson-player', - 'lha' => 'application/x-lzh-compressed', - 'link66' => 'application/vnd.route66.link66+xml', - 'list' => 'text/plain', - 'list3820' => 'application/vnd.ibm.modcap', - 'listafp' => 'application/vnd.ibm.modcap', - 'lnk' => 'application/x-ms-shortcut', - 'log' => 'text/plain', - 'lostxml' => 'application/lost+xml', - 'lrf' => 'application/octet-stream', - 'lrm' => 'application/vnd.ms-lrm', - 'ltf' => 'application/vnd.frogans.ltf', - 'lvp' => 'audio/vnd.lucent.voice', - 'lwp' => 'application/vnd.lotus-wordpro', - 'lzh' => 'application/x-lzh-compressed', - 'm13' => 'application/x-msmediaview', - 'm14' => 'application/x-msmediaview', - 'm1v' => 'video/mpeg', - 'm21' => 'application/mp21', - 'm2a' => 'audio/mpeg', - 'm2v' => 'video/mpeg', - 'm3a' => 'audio/mpeg', - 'm3u' => 'audio/x-mpegurl', - 'm3u8' => 'application/vnd.apple.mpegurl', - 'm4a' => 'audio/mp4', - 'm4u' => 'video/vnd.mpegurl', - 'm4v' => 'video/x-m4v', - 'ma' => 'application/mathematica', - 'mads' => 'application/mads+xml', - 'mag' => 'application/vnd.ecowin.chart', - 'maker' => 'application/vnd.framemaker', - 'man' => 'text/troff', - 'mar' => 'application/octet-stream', - 'mathml' => 'application/mathml+xml', - 'mb' => 'application/mathematica', - 'mbk' => 'application/vnd.mobius.mbk', - 'mbox' => 'application/mbox', - 'mc1' => 'application/vnd.medcalcdata', - 'mcd' => 'application/vnd.mcd', - 'mcurl' => 'text/vnd.curl.mcurl', - 'mdb' => 'application/x-msaccess', - 'mdi' => 'image/vnd.ms-modi', - 'me' => 'text/troff', - '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', - 'mgz' => 'application/vnd.proteus.magazine', - 'mid' => 'audio/midi', - 'midi' => 'audio/midi', - 'mie' => 'application/x-mie', - 'mif' => 'application/vnd.mif', - 'mime' => 'message/rfc822', - 'mj2' => 'video/mj2', - 'mjp2' => 'video/mj2', - 'mjs' => 'text/javascript', - 'mk3d' => 'video/x-matroska', - 'mka' => 'audio/x-matroska', - 'mks' => 'video/x-matroska', - 'mkv' => 'video/x-matroska', - 'mlp' => 'application/vnd.dolby.mlp', - 'mmd' => 'application/vnd.chipnuts.karaoke-mmd', - 'mmf' => 'application/vnd.smaf', - 'mmr' => 'image/vnd.fujixerox.edmics-mmr', - 'mng' => 'video/x-mng', - 'mny' => 'application/x-msmoney', - 'mobi' => 'application/x-mobipocket-ebook', - 'mods' => 'application/mods+xml', - 'mov' => 'video/quicktime', - 'movie' => 'video/x-sgi-movie', - 'mp2' => 'audio/mpeg', - 'mp21' => 'application/mp21', - 'mp2a' => 'audio/mpeg', - 'mp3' => 'audio/mpeg', - 'mp4' => 'video/mp4', - 'mp4a' => 'audio/mp4', - 'mp4s' => 'application/mp4', - 'mp4v' => 'video/mp4', - 'mpc' => 'application/vnd.mophun.certificate', - 'mpe' => 'video/mpeg', - 'mpeg' => 'video/mpeg', - 'mpg' => 'video/mpeg', - 'mpg4' => 'video/mp4', - 'mpga' => 'audio/mpeg', - 'mpkg' => 'application/vnd.apple.installer+xml', - 'mpm' => 'application/vnd.blueice.multipass', - 'mpn' => 'application/vnd.mophun.application', - 'mpp' => 'application/vnd.ms-project', - 'mpt' => 'application/vnd.ms-project', - 'mpy' => 'application/vnd.ibm.minipay', - 'mqy' => 'application/vnd.mobius.mqy', - 'mrc' => 'application/marc', - 'mrcx' => 'application/marcxml+xml', - 'ms' => 'text/troff', - 'mscml' => 'application/mediaservercontrol+xml', - 'mseed' => 'application/vnd.fdsn.mseed', - 'mseq' => 'application/vnd.mseq', - 'msf' => 'application/vnd.epson.msf', - 'msh' => 'model/mesh', - 'msi' => 'application/x-msdownload', - 'msl' => 'application/vnd.mobius.msl', - 'msty' => 'application/vnd.muvee.style', - 'mts' => 'model/vnd.mts', - 'mus' => 'application/vnd.musician', - 'musicxml' => 'application/vnd.recordare.musicxml+xml', - 'mvb' => 'application/x-msmediaview', - 'mwf' => 'application/vnd.mfer', - 'mxf' => 'application/mxf', - 'mxl' => 'application/vnd.recordare.musicxml', - 'mxml' => 'application/xv+xml', - 'mxs' => 'application/vnd.triscape.mxs', - 'mxu' => 'video/vnd.mpegurl', - 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install', - 'n3' => 'text/n3', - 'nb' => 'application/mathematica', - 'nbp' => 'application/vnd.wolfram.player', - 'nc' => 'application/x-netcdf', - 'ncx' => 'application/x-dtbncx+xml', - 'nfo' => 'text/x-nfo', - 'ngdat' => 'application/vnd.nokia.n-gage.data', - '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', - 'npx' => 'image/vnd.net-fpx', - 'nsc' => 'application/x-conference', - 'nsf' => 'application/vnd.lotus-notes', - 'ntf' => 'application/vnd.nitf', - 'nzb' => 'application/x-nzb', - 'oa2' => 'application/vnd.fujitsu.oasys2', - 'oa3' => 'application/vnd.fujitsu.oasys3', - 'oas' => 'application/vnd.fujitsu.oasys', - 'obd' => 'application/x-msbinder', - 'obj' => 'application/x-tgif', - 'oda' => 'application/oda', - 'odb' => 'application/vnd.oasis.opendocument.database', - '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', - 'ogg' => 'audio/ogg', - 'ogv' => 'video/ogg', - 'ogx' => 'application/ogg', - 'omdoc' => 'application/omdoc+xml', - 'onepkg' => 'application/onenote', - 'onetmp' => 'application/onenote', - 'onetoc' => 'application/onenote', - 'onetoc2' => 'application/onenote', - 'opf' => 'application/oebps-package+xml', - 'opml' => 'text/x-opml', - 'oprc' => 'application/vnd.palm', - 'opus' => 'audio/ogg', - 'org' => 'application/vnd.lotus-organizer', - 'osf' => 'application/vnd.yamaha.openscoreformat', - 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml', - 'otc' => 'application/vnd.oasis.opendocument.chart-template', - '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', - 'oxps' => 'application/oxps', - 'oxt' => 'application/vnd.openofficeorg.extension', - 'p' => 'text/x-pascal', - 'p10' => 'application/pkcs10', - 'p12' => 'application/x-pkcs12', - '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', - 'pas' => 'text/x-pascal', - 'paw' => 'application/vnd.pawaafile', - 'pbd' => 'application/vnd.powerbuilder6', - 'pbm' => 'image/x-portable-bitmap', - 'pcap' => 'application/vnd.tcpdump.pcap', - 'pcf' => '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/x-pcx', - 'pdb' => 'application/vnd.palm', - 'pdf' => 'application/pdf', - 'pfa' => 'application/x-font-type1', - 'pfb' => 'application/x-font-type1', - 'pfm' => 'application/x-font-type1', - 'pfr' => 'application/font-tdpfr', - 'pfx' => 'application/x-pkcs12', - 'pgm' => 'image/x-portable-graymap', - 'pgn' => 'application/x-chess-pgn', - 'pgp' => 'application/pgp-encrypted', - 'pic' => 'image/x-pict', - 'pjp' => 'image/jpeg', - 'pjpeg' => 'image/jpeg', - 'pkg' => 'application/octet-stream', - 'pki' => 'application/pkixcmp', - 'pkipath' => 'application/pkix-pkipath', - 'plb' => 'application/vnd.3gpp.pic-bw-large', - 'plc' => 'application/vnd.mobius.plc', - 'plf' => 'application/vnd.pocketlearn', - 'pls' => 'application/pls+xml', - 'pml' => 'application/vnd.ctc-posml', - 'png' => 'image/png', - 'pnm' => 'image/x-portable-anymap', - 'portpkg' => 'application/vnd.macports.portpkg', - 'pot' => 'application/vnd.ms-powerpoint', - '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/vnd.ms-powerpoint', - 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroenabled.12', - 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', - 'ppt' => 'application/vnd.ms-powerpoint', - 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroenabled.12', - 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', - 'pqa' => 'application/vnd.palm', - 'prc' => 'application/x-mobipocket-ebook', - 'pre' => 'application/vnd.lotus-freelance', - 'prf' => 'application/pics-rules', - 'ps' => 'application/postscript', - 'psb' => 'application/vnd.3gpp.pic-bw-small', - 'psd' => 'image/vnd.adobe.photoshop', - 'psf' => 'application/x-font-linux-psf', - 'pskcxml' => 'application/pskc+xml', - 'ptid' => 'application/vnd.pvi.ptid1', - 'pub' => 'application/x-mspublisher', - 'pvb' => 'application/vnd.3gpp.pic-bw-var', - 'pwn' => 'application/vnd.3m.post-it-notes', - 'pya' => 'audio/vnd.ms-playready.media.pya', - 'pyv' => 'video/vnd.ms-playready.media.pyv', - 'qam' => 'application/vnd.epson.quickanime', - 'qbo' => 'application/vnd.intu.qbo', - 'qfx' => 'application/vnd.intu.qfx', - 'qps' => 'application/vnd.publishare-delta-tree', - 'qt' => '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/x-pn-realaudio', - 'ram' => 'audio/x-pn-realaudio', - 'rar' => 'application/x-rar-compressed', - 'ras' => 'image/x-cmu-raster', - 'rcprofile' => 'application/vnd.ipunplugged.rcprofile', - 'rdf' => 'application/rdf+xml', - 'rdz' => 'application/vnd.data-vision.rdz', - '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', - 'rm' => 'application/vnd.rn-realmedia', - 'rmi' => 'audio/midi', - 'rmp' => 'audio/x-pn-realaudio-plugin', - 'rms' => 'application/vnd.jcp.javame.midlet-rms', - 'rmvb' => 'application/vnd.rn-realmedia-vbr', - 'rnc' => 'application/relax-ng-compact-syntax', - 'roa' => 'application/rpki-roa', - 'roff' => 'text/troff', - 'rp9' => 'application/vnd.cloanto.rp9', - 'rpss' => 'application/vnd.nokia.radio-presets', - 'rpst' => 'application/vnd.nokia.radio-preset', - 'rq' => 'application/sparql-query', - 'rs' => 'application/rls-services+xml', - 'rsd' => 'application/rsd+xml', - 'rss' => 'application/rss+xml', - 'rtf' => 'application/rtf', - 'rtx' => 'text/richtext', - 's' => 'text/x-asm', - 's3m' => 'audio/s3m', - 'saf' => 'application/vnd.yamaha.smaf-audio', - 'sbml' => 'application/sbml+xml', - 'sc' => 'application/vnd.ibm.secure-container', - 'scd' => 'application/x-msschedule', - 'scm' => 'application/vnd.lotus-screencam', - 'scq' => 'application/scvp-cv-request', - 'scs' => 'application/scvp-cv-response', - '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', - 'sdw' => 'application/vnd.stardivision.writer', - 'see' => 'application/vnd.seemail', - 'seed' => 'application/vnd.fdsn.seed', - 'sema' => 'application/vnd.sema', - 'semd' => 'application/vnd.semd', - 'semf' => 'application/vnd.semf', - 'ser' => 'application/java-serialized-object', - 'setpay' => 'application/set-payment-initiation', - 'setreg' => 'application/set-registration-initiation', - 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data', - 'sfs' => 'application/vnd.spotfire.sfs', - 'sfv' => 'text/x-sfv', - 'sgi' => 'image/sgi', - 'sgl' => 'application/vnd.stardivision.writer-global', - 'sgm' => 'text/sgml', - 'sgml' => 'text/sgml', - 'sh' => 'application/x-sh', - 'shar' => 'application/x-shar', - 'shf' => 'application/shf+xml', - 'sid' => 'image/x-mrsid-image', - 'sig' => 'application/pgp-signature', - 'sil' => 'audio/silk', - 'silo' => 'model/mesh', - 'sis' => 'application/vnd.symbian.install', - 'sisx' => 'application/vnd.symbian.install', - 'sit' => 'application/x-stuffit', - 'sitx' => 'application/x-stuffitx', - 'skd' => 'application/vnd.koan', - 'skm' => 'application/vnd.koan', - 'skp' => 'application/vnd.koan', - 'skt' => 'application/vnd.koan', - 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12', - 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', - 'slt' => 'application/vnd.epson.salt', - 'sm' => 'application/vnd.stepmania.stepchart', - 'smf' => 'application/vnd.stardivision.math', - 'smi' => 'application/smil+xml', - 'smil' => 'application/smil+xml', - 'smv' => 'video/x-smv', - 'smzip' => 'application/vnd.stepmania.package', - 'snd' => 'audio/basic', - 'snf' => 'application/x-font-snf', - 'so' => 'application/octet-stream', - 'spc' => 'application/x-pkcs7-certificates', - 'spf' => 'application/vnd.yamaha.smaf-phrase', - 'spl' => 'application/x-futuresplash', - 'spot' => 'text/vnd.in3d.spot', - 'spp' => 'application/scvp-vp-response', - 'spq' => 'application/scvp-vp-request', - 'spx' => 'audio/ogg', - 'sql' => 'application/x-sql', - 'src' => 'application/x-wais-source', - 'srt' => 'application/x-subrip', - 'sru' => 'application/sru+xml', - 'srx' => 'application/sparql-results+xml', - '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', - 'str' => 'application/vnd.pg.format', - 'stw' => 'application/vnd.sun.xml.writer.template', - 'sub' => 'text/vnd.dvb.subtitle', - 'sus' => 'application/vnd.sus-calendar', - 'susp' => 'application/vnd.sus-calendar', - 'sv4cpio' => 'application/x-sv4cpio', - 'sv4crc' => 'application/x-sv4crc', - 'svc' => 'application/vnd.dvb.service', - 'svd' => 'application/vnd.svd', - 'svg' => 'image/svg+xml', - 'svgz' => 'image/svg+xml', - 'swa' => 'application/x-director', - 'swf' => 'application/x-shockwave-flash', - 'swi' => 'application/vnd.aristanetworks.swi', - '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', - 't' => 'text/troff', - 't3' => 'application/x-t3vm-image', - 'taglet' => 'application/vnd.mynfc', - 'tao' => 'application/vnd.tao.intent-module-archive', - 'tar' => 'application/x-tar', - 'tcap' => 'application/vnd.3gpp2.tcap', - 'tcl' => 'application/x-tcl', - 'teacher' => 'application/vnd.smart.teacher', - 'tei' => 'application/tei+xml', - 'teicorpus' => 'application/tei+xml', - 'tex' => 'application/x-tex', - 'texi' => 'application/x-texinfo', - 'texinfo' => 'application/x-texinfo', - 'text' => 'text/plain', - 'tfi' => 'application/thraud+xml', - 'tfm' => 'application/x-tex-tfm', - 'tga' => 'image/x-tga', - 'thmx' => 'application/vnd.ms-officetheme', - 'tif' => 'image/tiff', - 'tiff' => 'image/tiff', - 'tmo' => 'application/vnd.tmobile-livetv', - 'torrent' => 'application/x-bittorrent', - 'tpl' => 'application/vnd.groove-tool-template', - 'tpt' => 'application/vnd.trid.tpt', - 'tr' => 'text/troff', - 'tra' => 'application/vnd.trueapp', - 'trm' => 'application/x-msterminal', - 'tsd' => 'application/timestamped-data', - 'tsv' => 'text/tab-separated-values', - 'ttc' => 'font/collection', - 'ttf' => 'font/ttf', - 'ttl' => 'text/turtle', - 'twd' => 'application/vnd.simtech-mindmapper', - 'twds' => 'application/vnd.simtech-mindmapper', - 'txd' => 'application/vnd.genomatix.tuxedo', - 'txf' => 'application/vnd.mobius.txf', - 'txt' => 'text/plain', - 'u32' => 'application/x-authorware-bin', - 'udeb' => 'application/x-debian-package', - 'ufd' => 'application/vnd.ufdl', - 'ufdl' => 'application/vnd.ufdl', - 'ulx' => 'application/x-glulx', - 'umj' => 'application/vnd.umajin', - 'unityweb' => 'application/vnd.unity', - 'uoml' => 'application/vnd.uoml+xml', - 'uri' => 'text/uri-list', - 'uris' => 'text/uri-list', - 'urls' => 'text/uri-list', - 'ustar' => 'application/x-ustar', - 'utz' => 'application/vnd.uiq.theme', - 'uu' => 'text/x-uuencode', - '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', - 'vcard' => 'text/vcard', - 'vcd' => 'application/x-cdlink', - 'vcf' => 'text/x-vcard', - 'vcg' => 'application/vnd.groove-vcard', - 'vcs' => 'text/x-vcalendar', - 'vcx' => 'application/vnd.vcx', - 'vis' => 'application/vnd.visionary', - 'viv' => 'video/vnd.vivo', - 'vob' => 'video/x-ms-vob', - 'vor' => 'application/vnd.stardivision.writer', - 'vox' => 'application/x-authorware-bin', - 'vrml' => 'model/vrml', - 'vsd' => 'application/vnd.visio', - 'vsf' => 'application/vnd.vsf', - 'vss' => 'application/vnd.visio', - 'vst' => 'application/vnd.visio', - 'vsw' => 'application/vnd.visio', - 'vtu' => 'model/vnd.vtu', - 'vxml' => 'application/voicexml+xml', - 'w3d' => 'application/x-director', - 'wad' => 'application/x-doom', - 'wav' => 'audio/x-wav', - 'wax' => 'audio/x-ms-wax', - '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', - 'webm' => 'video/webm', - 'webp' => 'image/webp', - 'wg' => 'application/vnd.pmi.widget', - 'wgt' => 'application/widget', - 'wks' => 'application/vnd.ms-works', - 'wm' => 'video/x-ms-wm', - 'wma' => 'audio/x-ms-wma', - 'wmd' => 'application/x-ms-wmd', - 'wmf' => 'application/x-msmetafile', - 'wml' => 'text/vnd.wap.wml', - 'wmlc' => 'application/vnd.wap.wmlc', - 'wmls' => 'text/vnd.wap.wmlscript', - 'wmlsc' => 'application/vnd.wap.wmlscriptc', - 'wmv' => 'video/x-ms-wmv', - 'wmx' => 'video/x-ms-wmx', - 'wmz' => 'application/x-msmetafile', - 'woff' => 'font/woff', - 'woff2' => 'font/woff2', - 'wpd' => 'application/vnd.wordperfect', - 'wpl' => 'application/vnd.ms-wpl', - 'wps' => 'application/vnd.ms-works', - 'wqd' => 'application/vnd.wqd', - 'wri' => 'application/x-mswrite', - 'wrl' => 'model/vrml', - 'wsdl' => 'application/wsdl+xml', - 'wspolicy' => 'application/wspolicy+xml', - 'wtb' => 'application/vnd.webturbo', - 'wvx' => 'video/x-ms-wvx', - 'x32' => 'application/x-authorware-bin', - 'x3d' => 'model/x3d+xml', - 'x3db' => 'model/x3d+binary', - 'x3dbz' => 'model/x3d+binary', - 'x3dv' => 'model/x3d+vrml', - 'x3dvz' => 'model/x3d+vrml', - 'x3dz' => 'model/x3d+xml', - 'xaml' => 'application/xaml+xml', - 'xap' => 'application/x-silverlight-app', - 'xar' => 'application/vnd.xara', - 'xbap' => 'application/x-ms-xbap', - 'xbd' => 'application/vnd.fujixerox.docuworks.binder', - 'xbm' => 'image/x-xbitmap', - 'xdf' => 'application/xcap-diff+xml', - 'xdm' => 'application/vnd.syncml.dm+xml', - 'xdp' => 'application/vnd.adobe.xdp+xml', - 'xdssc' => 'application/dssc+xml', - 'xdw' => 'application/vnd.fujixerox.docuworks', - 'xenc' => 'application/xenc+xml', - 'xer' => 'application/patch-ops-error+xml', - 'xfdf' => 'application/vnd.adobe.xfdf', - 'xfdl' => 'application/vnd.xfdl', - 'xht' => 'application/xhtml+xml', - 'xhtml' => 'application/xhtml+xml', - 'xhvml' => 'application/xv+xml', - 'xif' => 'image/vnd.xiff', - 'xla' => 'application/vnd.ms-excel', - 'xlam' => 'application/vnd.ms-excel.addin.macroenabled.12', - 'xlc' => 'application/vnd.ms-excel', - 'xlf' => 'application/x-xliff+xml', - 'xlm' => 'application/vnd.ms-excel', - 'xls' => 'application/vnd.ms-excel', - '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/vnd.ms-excel', - 'xltm' => 'application/vnd.ms-excel.template.macroenabled.12', - 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', - 'xlw' => 'application/vnd.ms-excel', - 'xm' => 'audio/xm', - 'xml' => 'application/xml', - 'xo' => 'application/vnd.olpc-sugar', - 'xop' => 'application/xop+xml', - 'xpi' => 'application/x-xpinstall', - 'xpl' => 'application/xproc+xml', - 'xpm' => 'image/x-xpixmap', - 'xpr' => 'application/vnd.is-xpr', - 'xps' => 'application/vnd.ms-xpsdocument', - 'xpw' => 'application/vnd.intercon.formnet', - 'xpx' => 'application/vnd.intercon.formnet', - 'xsl' => 'application/xml', - 'xslt' => 'application/xslt+xml', - 'xsm' => 'application/vnd.syncml+xml', - 'xspf' => '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', - 'yang' => 'application/yang', - 'yin' => 'application/yin+xml', - 'z1' => 'application/x-zmachine', - 'z2' => 'application/x-zmachine', - 'z3' => 'application/x-zmachine', - 'z4' => 'application/x-zmachine', - 'z5' => 'application/x-zmachine', - 'z6' => 'application/x-zmachine', - 'z7' => 'application/x-zmachine', - 'z8' => 'application/x-zmachine', - 'zaz' => 'application/vnd.zzazz.deck+xml', - 'zip' => 'application/zip', - 'zir' => 'application/vnd.zul', - 'zirz' => 'application/vnd.zul', - 'zmm' => 'application/vnd.handheld-entertainment+xml', - ]; - - # fix for bundled libmagic bug, see also https://github.com/yiisoft/yii2/issues/19925 - if ((PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80122) || (PHP_VERSION_ID >= 80200 && PHP_VERSION_ID < 80209)) { - $coreMimeTypes = array_replace($coreMimeTypes, array('xz' => 'application/octet-stream')); - } - - $this->assertSame($coreMimeTypes, - require __DIR__ . '/../../../framework/helpers/mimeTypes.php' - ); - } - - public function testMimeExtensions() - { - $coreMimeExtensions = [ - 'application/andrew-inset' => 'ez', - 'application/applixware' => 'aw', - 'application/atom+xml' => 'atom', - 'application/atomcat+xml' => 'atomcat', - 'application/atomsvc+xml' => 'atomsvc', - 'application/ccxml+xml' => 'ccxml', - 'application/cdmi-capability' => 'cdmia', - 'application/cdmi-container' => 'cdmic', - 'application/cdmi-domain' => 'cdmid', - 'application/cdmi-object' => 'cdmio', - 'application/cdmi-queue' => 'cdmiq', - 'application/cu-seeme' => 'cu', - 'application/davmount+xml' => 'davmount', - 'application/docbook+xml' => 'dbk', - 'application/dssc+der' => 'dssc', - 'application/dssc+xml' => 'xdssc', - 'application/ecmascript' => 'ecma', - 'application/emma+xml' => 'emma', - 'application/epub+zip' => 'epub', - 'application/exi' => 'exi', - 'application/font-tdpfr' => 'pfr', - 'application/gml+xml' => 'gml', - 'application/gpx+xml' => 'gpx', - 'application/gxf' => 'gxf', - 'application/hyperstudio' => 'stk', - 'application/inkml+xml' => [ - 'ink', - 'inkml', - ], - 'application/ipfix' => 'ipfix', - 'application/java-archive' => 'jar', - 'application/java-serialized-object' => 'ser', - 'application/java-vm' => 'class', - 'application/json' => 'json', - 'application/jsonml+json' => 'jsonml', - 'application/lost+xml' => 'lostxml', - 'application/mac-binhex40' => 'hqx', - 'application/mac-compactpro' => 'cpt', - 'application/mads+xml' => 'mads', - 'application/marc' => 'mrc', - 'application/marcxml+xml' => 'mrcx', - 'application/mathematica' => [ - 'ma', - 'nb', - 'mb', - ], - 'application/mathml+xml' => 'mathml', - 'application/mbox' => 'mbox', - 'application/mediaservercontrol+xml' => 'mscml', - 'application/metalink+xml' => 'metalink', - 'application/metalink4+xml' => 'meta4', - 'application/mets+xml' => 'mets', - 'application/mods+xml' => 'mods', - 'application/mp21' => [ - 'm21', - 'mp21', - ], - 'application/mp4' => 'mp4s', - 'application/msword' => [ - 'doc', - 'dot', - ], - 'application/mxf' => 'mxf', - 'application/octet-stream' => [ - 'bin', - 'dms', - 'lrf', - 'mar', - 'so', - 'dist', - 'distz', - 'pkg', - 'bpk', - 'dump', - 'elc', - 'deploy', - ], - 'application/oda' => 'oda', - 'application/oebps-package+xml' => 'opf', - 'application/ogg' => 'ogx', - 'application/omdoc+xml' => 'omdoc', - 'application/onenote' => [ - 'onetoc', - 'onetoc2', - 'onetmp', - 'onepkg', - ], - 'application/oxps' => 'oxps', - 'application/patch-ops-error+xml' => 'xer', - 'application/pdf' => 'pdf', - 'application/pgp-encrypted' => 'pgp', - 'application/pgp-signature' => [ - 'asc', - 'sig', - ], - 'application/pics-rules' => 'prf', - 'application/pkcs10' => 'p10', - 'application/pkcs7-mime' => [ - 'p7m', - 'p7c', - ], - 'application/pkcs7-signature' => 'p7s', - 'application/pkcs8' => 'p8', - 'application/pkix-attr-cert' => 'ac', - 'application/pkix-cert' => 'cer', - 'application/pkix-crl' => 'crl', - 'application/pkix-pkipath' => 'pkipath', - 'application/pkixcmp' => 'pki', - 'application/pls+xml' => 'pls', - 'application/postscript' => [ - 'ai', - 'eps', - 'ps', - ], - 'application/prs.cww' => 'cww', - 'application/pskc+xml' => 'pskcxml', - 'application/rdf+xml' => 'rdf', - '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/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/scvp-cv-request' => 'scq', - 'application/scvp-cv-response' => 'scs', - 'application/scvp-vp-request' => 'spq', - 'application/scvp-vp-response' => 'spp', - 'application/sdp' => 'sdp', - 'application/set-payment-initiation' => 'setpay', - 'application/set-registration-initiation' => 'setreg', - 'application/shf+xml' => 'shf', - 'application/smil+xml' => [ - 'smi', - 'smil', - ], - 'application/sparql-query' => 'rq', - 'application/sparql-results+xml' => 'srx', - 'application/srgs' => 'gram', - 'application/srgs+xml' => 'grxml', - 'application/sru+xml' => 'sru', - 'application/ssdl+xml' => 'ssdl', - 'application/ssml+xml' => 'ssml', - 'application/tei+xml' => [ - 'tei', - 'teicorpus', - ], - 'application/thraud+xml' => 'tfi', - 'application/timestamped-data' => 'tsd', - '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.formscentral.fcdt' => 'fcdt', - 'application/vnd.adobe.fxp' => [ - 'fxp', - 'fxpl', - ], - '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.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.apple.installer+xml' => 'mpkg', - 'application/vnd.apple.mpegurl' => 'm3u8', - 'application/vnd.aristanetworks.swi' => 'swi', - 'application/vnd.astraea-software.iota' => 'iota', - 'application/vnd.audiograph' => 'aep', - 'application/vnd.blueice.multipass' => 'mpm', - 'application/vnd.bmi' => 'bmi', - 'application/vnd.businessobjects' => 'rep', - 'application/vnd.chemdraw+xml' => 'cdxml', - 'application/vnd.chipnuts.karaoke-mmd' => 'mmd', - 'application/vnd.cinderella' => 'cdy', - '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.commonspace' => 'csp', - 'application/vnd.contact.cmsg' => 'cdbcmsg', - '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.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.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.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.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.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-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.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', - '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.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-artgalry' => 'cil', - 'application/vnd.ms-cab-compressed' => 'cab', - 'application/vnd.ms-excel' => [ - 'xls', - 'xlm', - 'xla', - 'xlc', - 'xlt', - 'xlw', - ], - '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-pki.seccat' => 'cat', - 'application/vnd.ms-pki.stl' => 'stl', - 'application/vnd.ms-powerpoint' => [ - 'ppt', - 'pps', - 'pot', - ], - '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-word.document.macroenabled.12' => 'docm', - 'application/vnd.ms-word.template.macroenabled.12' => 'dotm', - 'application/vnd.ms-works' => [ - 'wps', - 'wks', - 'wcm', - 'wdb', - ], - 'application/vnd.ms-wpl' => 'wpl', - 'application/vnd.ms-xpsdocument' => 'xps', - 'application/vnd.mseq' => 'mseq', - 'application/vnd.musician' => 'mus', - 'application/vnd.muvee.style' => 'msty', - 'application/vnd.mynfc' => 'taglet', - 'application/vnd.neurolanguage.nlu' => 'nlu', - '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.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.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', - 'application/vnd.oasis.opendocument.graphics' => 'odg', - '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-template' => 'otp', - 'application/vnd.oasis.opendocument.spreadsheet' => 'ods', - 'application/vnd.oasis.opendocument.spreadsheet-template' => 'ots', - 'application/vnd.oasis.opendocument.text' => 'odt', - '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.openofficeorg.extension' => 'oxt', - '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', - ], - '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.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', - 'application/vnd.rn-realmedia-vbr' => 'rmvb', - 'application/vnd.route66.link66+xml' => 'link66', - 'application/vnd.sailingtracker.track' => 'st', - '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', - 'application/vnd.smart.teacher' => 'teacher', - 'application/vnd.solent.sdkm+xml' => [ - 'sdkm', - 'sdkd', - ], - 'application/vnd.spotfire.dxp' => 'dxp', - 'application/vnd.spotfire.sfs' => 'sfs', - 'application/vnd.stardivision.calc' => 'sdc', - 'application/vnd.stardivision.draw' => 'sda', - 'application/vnd.stardivision.impress' => 'sdd', - 'application/vnd.stardivision.math' => 'smf', - 'application/vnd.stardivision.writer' => [ - 'sdw', - 'vor', - ], - 'application/vnd.stardivision.writer-global' => 'sgl', - 'application/vnd.stepmania.package' => 'smzip', - 'application/vnd.stepmania.stepchart' => 'sm', - '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.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', - 'application/vnd.wqd' => 'wqd', - 'application/vnd.wt.stf' => 'stf', - 'application/vnd.xara' => 'xar', - '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.zul' => [ - 'zir', - 'zirz', - ], - 'application/vnd.zzazz.deck+xml' => 'zaz', - 'application/voicexml+xml' => 'vxml', - 'application/widget' => 'wgt', - 'application/winhlp' => 'hlp', - 'application/wsdl+xml' => 'wsdl', - 'application/wspolicy+xml' => 'wspolicy', - 'application/x-7z-compressed' => '7z', - 'application/x-abiword' => 'abw', - 'application/x-ace-compressed' => 'ace', - 'application/x-apple-diskimage' => 'dmg', - 'application/x-authorware-bin' => [ - 'aab', - 'x32', - 'u32', - 'vox', - ], - 'application/x-authorware-map' => 'aam', - 'application/x-authorware-seg' => 'aas', - 'application/x-bcpio' => 'bcpio', - 'application/x-bittorrent' => 'torrent', - 'application/x-blorb' => [ - 'blb', - 'blorb', - ], - 'application/x-bzip' => 'bz', - 'application/x-bzip2' => [ - 'bz2', - 'boz', - ], - 'application/x-cbr' => [ - 'cbr', - 'cba', - 'cbt', - 'cbz', - 'cb7', - ], - 'application/x-cdlink' => 'vcd', - 'application/x-cfs-compressed' => 'cfs', - 'application/x-chat' => 'chat', - 'application/x-chess-pgn' => 'pgn', - 'application/x-conference' => 'nsc', - 'application/x-cpio' => 'cpio', - 'application/x-csh' => 'csh', - 'application/x-debian-package' => [ - 'deb', - 'udeb', - ], - 'application/x-dgc-compressed' => 'dgc', - 'application/x-director' => [ - 'dir', - 'dcr', - 'dxr', - 'cst', - 'cct', - 'cxt', - 'w3d', - 'fgd', - 'swa', - ], - 'application/x-doom' => 'wad', - 'application/x-dtbncx+xml' => 'ncx', - 'application/x-dtbook+xml' => 'dtb', - 'application/x-dtbresource+xml' => 'res', - 'application/x-dvi' => 'dvi', - 'application/x-envoy' => 'evy', - 'application/x-eva' => 'eva', - 'application/x-font-bdf' => 'bdf', - 'application/x-font-ghostscript' => 'gsf', - 'application/x-font-linux-psf' => 'psf', - 'application/x-font-pcf' => 'pcf', - 'application/x-font-snf' => 'snf', - 'application/x-font-type1' => [ - 'pfa', - 'pfb', - 'pfm', - 'afm', - ], - 'application/x-freearc' => 'arc', - 'application/x-futuresplash' => 'spl', - 'application/x-gca-compressed' => 'gca', - 'application/x-glulx' => 'ulx', - 'application/x-gnumeric' => 'gnumeric', - 'application/x-gramps-xml' => 'gramps', - 'application/x-gtar' => 'gtar', - 'application/x-hdf' => 'hdf', - 'application/x-install-instructions' => 'install', - 'application/x-iso9660-image' => 'iso', - 'application/x-java-jnlp-file' => 'jnlp', - 'application/x-latex' => 'latex', - 'application/x-lzh-compressed' => [ - 'lzh', - 'lha', - ], - 'application/x-mie' => 'mie', - 'application/x-mobipocket-ebook' => [ - 'prc', - 'mobi', - ], - 'application/x-ms-application' => 'application', - 'application/x-ms-shortcut' => 'lnk', - '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-msdownload' => [ - 'exe', - 'dll', - 'com', - 'bat', - 'msi', - ], - 'application/x-msmediaview' => [ - 'mvb', - 'm13', - 'm14', - ], - 'application/x-msmetafile' => [ - 'wmf', - 'wmz', - 'emf', - 'emz', - ], - 'application/x-msmoney' => 'mny', - 'application/x-mspublisher' => 'pub', - 'application/x-msschedule' => 'scd', - 'application/x-msterminal' => 'trm', - 'application/x-mswrite' => 'wri', - 'application/x-netcdf' => [ - 'nc', - 'cdf', - ], - 'application/x-nzb' => 'nzb', - 'application/x-pkcs12' => [ - 'p12', - 'pfx', - ], - 'application/x-pkcs7-certificates' => [ - 'p7b', - 'spc', - ], - 'application/x-pkcs7-certreqresp' => 'p7r', - 'application/x-rar-compressed' => 'rar', - 'application/x-research-info-systems' => 'ris', - 'application/x-sh' => 'sh', - 'application/x-shar' => 'shar', - 'application/x-shockwave-flash' => 'swf', - 'application/x-silverlight-app' => 'xap', - 'application/x-sql' => 'sql', - '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-tads' => 'gam', - 'application/x-tar' => 'tar', - 'application/x-tcl' => 'tcl', - 'application/x-tex' => 'tex', - 'application/x-tex-tfm' => 'tfm', - 'application/x-texinfo' => [ - 'texinfo', - 'texi', - ], - 'application/x-tgif' => 'obj', - 'application/x-ustar' => 'ustar', - 'application/x-wais-source' => 'src', - 'application/x-x509-ca-cert' => [ - 'der', - 'crt', - ], - 'application/x-xfig' => 'fig', - 'application/x-xliff+xml' => 'xlf', - 'application/x-xpinstall' => 'xpi', - 'application/x-xz' => 'xz', - 'application/x-zmachine' => [ - 'z1', - 'z2', - 'z3', - 'z4', - 'z5', - 'z6', - 'z7', - 'z8', - ], - 'application/xaml+xml' => 'xaml', - 'application/xcap-diff+xml' => 'xdf', - 'application/xenc+xml' => 'xenc', - 'application/xhtml+xml' => [ - 'xhtml', - 'xht', - ], - 'application/xml' => [ - 'xml', - 'xsl', - ], - 'application/xml-dtd' => 'dtd', - 'application/xop+xml' => 'xop', - 'application/xproc+xml' => 'xpl', - 'application/xslt+xml' => 'xslt', - 'application/xspf+xml' => 'xspf', - 'application/xv+xml' => [ - 'mxml', - 'xhvml', - 'xvml', - 'xvm', - ], - 'application/yang' => 'yang', - 'application/yin+xml' => 'yin', - 'application/zip' => 'zip', - 'audio/adpcm' => 'adp', - 'audio/basic' => [ - 'au', - 'snd', - ], - 'audio/midi' => [ - 'mid', - 'midi', - 'kar', - 'rmi', - ], - 'audio/mp4' => [ - 'm4a', - 'mp4a', - ], - 'audio/mpeg' => [ - 'mpga', - 'mp2', - 'mp2a', - 'mp3', - 'm2a', - 'm3a', - ], - 'audio/ogg' => [ - 'oga', - 'ogg', - 'spx', - 'opus', - ], - 'audio/s3m' => 's3m', - 'audio/silk' => 'sil', - '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.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/webm' => 'weba', - 'audio/x-aac' => 'aac', - 'audio/x-aiff' => [ - 'aif', - 'aiff', - 'aifc', - ], - 'audio/x-caf' => 'caf', - 'audio/x-flac' => 'flac', - 'audio/x-matroska' => 'mka', - 'audio/x-mpegurl' => 'm3u', - 'audio/x-ms-wax' => 'wax', - 'audio/x-ms-wma' => 'wma', - 'audio/x-pn-realaudio' => [ - 'ram', - 'ra', - ], - 'audio/x-pn-realaudio-plugin' => 'rmp', - 'audio/x-wav' => 'wav', - 'audio/xm' => 'xm', - 'chemical/x-cdx' => 'cdx', - 'chemical/x-cif' => 'cif', - 'chemical/x-cmdf' => 'cmdf', - 'chemical/x-cml' => 'cml', - 'chemical/x-csml' => 'csml', - 'chemical/x-xyz' => 'xyz', - 'font/collection' => 'ttc', - 'font/otf' => 'otf', - 'font/ttf' => 'ttf', - 'font/woff' => 'woff', - 'font/woff2' => 'woff2', - 'image/apng' => 'apng', - 'image/avif' => 'avif', - 'image/bmp' => 'bmp', - 'image/cgm' => 'cgm', - 'image/g3fax' => 'g3', - 'image/gif' => 'gif', - 'image/ief' => 'ief', - 'image/jpeg' => [ - 'jpeg', - 'jpg', - 'jpe', - 'jfif', - 'pjp', - 'pjpeg', - ], - 'image/ktx' => 'ktx', - 'image/png' => 'png', - 'image/prs.btif' => 'btif', - 'image/sgi' => 'sgi', - 'image/svg+xml' => [ - 'svg', - 'svgz', - ], - 'image/tiff' => [ - 'tiff', - 'tif', - ], - 'image/vnd.adobe.photoshop' => 'psd', - 'image/vnd.dece.graphic' => [ - 'uvi', - 'uvvi', - 'uvg', - 'uvvg', - ], - 'image/vnd.djvu' => [ - '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.ms-modi' => 'mdi', - 'image/vnd.ms-photo' => 'wdp', - 'image/vnd.net-fpx' => 'npx', - 'image/vnd.wap.wbmp' => 'wbmp', - 'image/vnd.xiff' => 'xif', - 'image/webp' => 'webp', - 'image/x-3ds' => '3ds', - 'image/x-cmu-raster' => 'ras', - 'image/x-cmx' => 'cmx', - 'image/x-freehand' => [ - 'fh', - 'fhc', - 'fh4', - 'fh5', - 'fh7', - ], - 'image/x-icon' => 'ico', - 'image/x-mrsid-image' => 'sid', - 'image/x-pcx' => 'pcx', - 'image/x-pict' => [ - 'pic', - 'pct', - ], - 'image/x-portable-anymap' => 'pnm', - 'image/x-portable-bitmap' => 'pbm', - 'image/x-portable-graymap' => 'pgm', - 'image/x-portable-pixmap' => 'ppm', - 'image/x-rgb' => 'rgb', - 'image/x-tga' => 'tga', - 'image/x-xbitmap' => 'xbm', - 'image/x-xpixmap' => 'xpm', - 'image/x-xwindowdump' => 'xwd', - 'message/rfc822' => [ - 'eml', - 'mime', - ], - 'model/iges' => [ - 'igs', - 'iges', - ], - 'model/mesh' => [ - 'msh', - 'mesh', - 'silo', - ], - 'model/vnd.collada+xml' => 'dae', - 'model/vnd.dwf' => 'dwf', - 'model/vnd.gdl' => 'gdl', - 'model/vnd.gtw' => 'gtw', - 'model/vnd.mts' => 'mts', - 'model/vnd.vtu' => 'vtu', - 'model/vrml' => [ - 'wrl', - 'vrml', - ], - 'model/x3d+binary' => [ - 'x3db', - 'x3dbz', - ], - 'model/x3d+vrml' => [ - 'x3dv', - 'x3dvz', - ], - 'model/x3d+xml' => [ - 'x3d', - 'x3dz', - ], - 'text/cache-manifest' => 'appcache', - 'text/calendar' => [ - 'ics', - 'ifb', - ], - 'text/css' => 'css', - 'text/csv' => 'csv', - 'text/html' => [ - 'html', - 'htm', - ], - 'text/javascript' => [ - 'js', - 'mjs', - 'mjs', - ], - 'text/n3' => 'n3', - 'text/plain' => [ - 'txt', - 'text', - 'conf', - 'def', - 'list', - 'log', - 'in', - ], - 'text/prs.lines.tag' => 'dsc', - 'text/richtext' => 'rtx', - 'text/sgml' => [ - 'sgml', - 'sgm', - ], - 'text/tab-separated-values' => 'tsv', - 'text/troff' => [ - 't', - 'tr', - 'roff', - 'man', - 'me', - 'ms', - ], - 'text/turtle' => 'ttl', - 'text/uri-list' => [ - 'uri', - 'uris', - 'urls', - ], - 'text/vcard' => 'vcard', - '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', - 'text/vnd.in3d.3dml' => '3dml', - 'text/vnd.in3d.spot' => 'spot', - 'text/vnd.sun.j2me.app-descriptor' => 'jad', - 'text/vnd.wap.wml' => 'wml', - 'text/vnd.wap.wmlscript' => 'wmls', - 'text/x-asm' => [ - 's', - 'asm', - ], - 'text/x-c' => [ - 'c', - 'cc', - 'cxx', - 'cpp', - 'h', - 'hh', - 'dic', - ], - 'text/x-fortran' => [ - 'f', - 'for', - 'f77', - 'f90', - ], - 'text/x-java-source' => 'java', - 'text/x-nfo' => 'nfo', - 'text/x-opml' => 'opml', - 'text/x-pascal' => [ - 'p', - 'pas', - ], - 'text/x-setext' => 'etx', - 'text/x-sfv' => 'sfv', - 'text/x-uuencode' => 'uu', - 'text/x-vcalendar' => 'vcs', - 'text/x-vcard' => 'vcf', - 'video/3gpp' => '3gp', - 'video/3gpp2' => '3g2', - 'video/h261' => 'h261', - 'video/h263' => 'h263', - 'video/h264' => 'h264', - 'video/jpeg' => 'jpgv', - 'video/jpm' => [ - 'jpm', - 'jpgm', - ], - 'video/mj2' => [ - 'mj2', - 'mjp2', - ], - 'video/mp4' => [ - 'mp4', - 'mp4v', - 'mpg4', - ], - 'video/mpeg' => [ - 'mpeg', - 'mpg', - 'mpe', - 'm1v', - 'm2v', - ], - 'video/ogg' => 'ogv', - 'video/quicktime' => [ - 'qt', - 'mov', - ], - '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.dvb.file' => 'dvb', - 'video/vnd.fvt' => 'fvt', - 'video/vnd.mpegurl' => [ - 'mxu', - 'm4u', - ], - 'video/vnd.ms-playready.media.pyv' => 'pyv', - 'video/vnd.uvvu.mp4' => [ - 'uvu', - 'uvvu', - ], - 'video/vnd.vivo' => 'viv', - 'video/webm' => 'webm', - 'video/x-f4v' => 'f4v', - 'video/x-fli' => 'fli', - 'video/x-flv' => 'flv', - 'video/x-m4v' => 'm4v', - 'video/x-matroska' => [ - 'mkv', - 'mk3d', - 'mks', - ], - 'video/x-mng' => 'mng', - 'video/x-ms-asf' => [ - 'asf', - 'asx', - ], - 'video/x-ms-vob' => 'vob', - 'video/x-ms-wm' => 'wm', - 'video/x-ms-wmv' => 'wmv', - 'video/x-ms-wmx' => 'wmx', - 'video/x-ms-wvx' => 'wvx', - 'video/x-msvideo' => 'avi', - 'video/x-sgi-movie' => 'movie', - 'video/x-smv' => 'smv', - 'x-conference/x-cooltalk' => 'ice', - ]; - - $this->assertSame($coreMimeExtensions, - require __DIR__ . '/../../../framework/helpers/mimeExtensions.php' - ); - } -} From 2995696db9268e0d947781904e5d57e19719c404 Mon Sep 17 00:00:00 2001 From: Sonia Zorba Date: Tue, 19 Sep 2023 10:24:11 +0200 Subject: [PATCH 23/25] Added section about Unsafe Reflection in Security best practices doc (#19948) Co-authored-by: Bizley --- docs/guide/security-best-practices.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/guide/security-best-practices.md b/docs/guide/security-best-practices.md index bafede12ae..291575c846 100644 --- a/docs/guide/security-best-practices.md +++ b/docs/guide/security-best-practices.md @@ -263,6 +263,12 @@ Further reading on the topic: - +Avoiding arbitrary object instantiations +---------------------------------------- + +Yii [configurations](concept-configurations.md) are associative arrays used by the framework to instantiate new objects through `Yii::createObject($config)`. These arrays specify the class name for instantiation, and it is important to ensure that this class name does not originate from untrusted sources. Otherwise, it can lead to Unsafe Reflection, a vulnerability that allows the execution of malicious code by exploiting the loading of specific classes. Additionally, when you need to dynamically add keys to an object derived from a framework class, such as the base `Component` class, it's essential to validate these dynamic properties using a whitelist approach. This precaution is necessary because the framework might employ `Yii::createObject($config)` within the `__set()` magic method. + + Avoiding file exposure ---------------------- From fd5c1bbf275702e88012bcedd22f0af86de2ba1f Mon Sep 17 00:00:00 2001 From: Oleg Poludnenko Date: Wed, 20 Sep 2023 12:27:33 +0300 Subject: [PATCH 24/25] Update CHANGELOG.md --- framework/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index e468b61f78..e2eefa083b 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -7,6 +7,7 @@ Yii Framework 2 Change Log - Bug #19925: Improved PHP version check when handling MIME types (schmunk42) - Bug #19940: File Log writer without newline (terabytesoftw) - Bug #19951: Removed unneeded MIME file tests (schmunk42) +- Bug #19950: Fix `Query::groupBy(null)` causes error for PHP 8.1: `trim(): Passing null to parameter #1 ($string) of type string is deprecated` 2.0.49 August 29, 2023 From 18421ab976472206b19324e30071ca5360e08cfe Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Wed, 20 Sep 2023 06:47:45 -0300 Subject: [PATCH 25/25] Fixed tests. --- framework/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index e2eefa083b..4459fe7741 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -7,7 +7,7 @@ Yii Framework 2 Change Log - Bug #19925: Improved PHP version check when handling MIME types (schmunk42) - Bug #19940: File Log writer without newline (terabytesoftw) - Bug #19951: Removed unneeded MIME file tests (schmunk42) -- Bug #19950: Fix `Query::groupBy(null)` causes error for PHP 8.1: `trim(): Passing null to parameter #1 ($string) of type string is deprecated` +- Bug #19950: Fix `Query::groupBy(null)` causes error for PHP 8.1: `trim(): Passing null to parameter #1 ($string) of type string is deprecated` (uaoleg) 2.0.49 August 29, 2023