Browse Source

Initial export from Lax

remotes/github/master
J. King 4 years ago
commit
76f5abedcd
  1. 7
      .gitattributes
  2. 5
      .gitignore
  3. 79
      .php_cs.dist
  4. 3
      AUTHORS
  5. 22
      LICENSE
  6. 146
      RoboFile.php
  7. 39
      composer.json
  8. 63
      composer.lock
  9. 158
      lib/MimeType.php
  10. 14
      robo
  11. 21
      robo.bat
  12. 20
      tests/bootstrap.php
  13. 42
      tests/cases/MimeTypeTest.php
  14. 20
      tests/cases/README
  15. 3526
      tests/cases/generated-mime-types.json
  16. 383
      tests/cases/mime-types.json
  17. 26
      tests/phpunit.dist.xml
  18. 5
      vendor-bin/csfixer/composer.json
  19. 1499
      vendor-bin/csfixer/composer.lock
  20. 6
      vendor-bin/phpunit/composer.json
  21. 1720
      vendor-bin/phpunit/composer.lock
  22. 5
      vendor-bin/robo/composer.json
  23. 1473
      vendor-bin/robo/composer.lock

7
.gitattributes

@ -0,0 +1,7 @@
* text=auto encoding=utf-8
*.html diff=html
*.php diff=php
*.bat eol=crlf
*.cmd eol=crlf
.gitignore -eol

5
.gitignore

@ -0,0 +1,5 @@
/vendor
/vendor-bin/*/vendor
/tests/coverage
/tests/.phpunit.result.cache
/.php_cs.cache

79
.php_cs.dist

@ -0,0 +1,79 @@
<?php
declare(strict_types=1);
const BASE = __DIR__.DIRECTORY_SEPARATOR;
$paths = [
__FILE__,
BASE."RoboFile.php",
BASE."lib",
BASE."tests",
];
$rules = [
// house rules where PSR series is silent
'align_multiline_comment' => ['comment_type' => "phpdocs_only"],
'array_syntax' => ['syntax' => "short"],
'binary_operator_spaces' => [
'default' => "single_space",
'operators' => ['=>' => "align_single_space"],
],
'cast_spaces' => ['space' => "single"],
'concat_space' => ['spacing' => "none"],
'list_syntax' => ['syntax' => "short"],
'magic_constant_casing' => true,
'magic_method_casing' => true,
'modernize_types_casting' => true,
'native_function_casing' => true,
'native_function_type_declaration_casing' => true,
'no_binary_string' => true,
'no_blank_lines_after_phpdoc' => true,
'no_empty_comment' => true,
'no_empty_phpdoc' => true,
'no_extra_blank_lines' => true, // this could probably use more configuration
'no_mixed_echo_print' => ['use' => "echo"],
'no_short_bool_cast' => true,
'no_trailing_comma_in_singleline_array' => true,
'no_unneeded_control_parentheses' => true,
'no_unneeded_curly_braces' => true,
'no_unused_imports' => true,
'no_whitespace_before_comma_in_array' => true,
'normalize_index_brace' => true,
'object_operator_without_whitespace' => true,
'pow_to_exponentiation' => true,
'set_type_to_cast' => true,
'standardize_not_equals' => true,
'trailing_comma_in_multiline_array' => true,
'unary_operator_spaces' => true,
'yoda_style' => false,
// PSR standard to apply
'@PSR2' => true,
// PSR-12 rules; php-cs-fixer does not yet support PSR-12 natively
'compact_nullable_typehint' => true,
'declare_equal_normalize' => ['space' => "none"],
'function_typehint_space' => true,
'lowercase_cast' => true,
'lowercase_static_reference' => true,
'no_alternative_syntax' => true,
'no_empty_statement' => true,
'no_leading_import_slash' => true,
'no_leading_namespace_whitespace' => true,
'no_whitespace_in_blank_line' => true,
'return_type_declaration' => ['space_before' => "none"],
'single_trait_insert_per_statement' => true,
'short_scalar_cast' => true,
'visibility_required' => ['elements' => ["const", "property", "method"]],
// house exceptions to PSR rules
'braces' => ['position_after_functions_and_oop_constructs' => "same"],
'function_declaration' => ['closure_function_spacing' => "none"],
'new_with_braces' => false, // no option to specify absence of braces
];
$finder = \PhpCsFixer\Finder::create();
foreach ($paths as $path) {
if (is_file($path)) {
$finder = $finder->append([$path]);
} else {
$finder = $finder->in($path);
}
}
return \PhpCsFixer\Config::create()->setRiskyAllowed(true)->setRules($rules)->setFinder($finder);

3
AUTHORS

@ -0,0 +1,3 @@
Prohect lead
-------------
J. King https://jkingweb.ca/

22
LICENSE

@ -0,0 +1,22 @@
Copyright (c) 2018 J. King
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

146
RoboFile.php

@ -0,0 +1,146 @@
<?php
use Robo\Result;
const BASE = __DIR__.\DIRECTORY_SEPARATOR;
const BASE_TEST = BASE."tests".\DIRECTORY_SEPARATOR;
define("IS_WIN", defined("PHP_WINDOWS_VERSION_MAJOR"));
define("IS_MAC", php_uname("s") === "Darwin");
function norm(string $path): string {
$out = realpath($path);
if (!$out) {
$out = str_replace(["/", "\\"], \DIRECTORY_SEPARATOR, $path);
}
return $out;
}
class RoboFile extends \Robo\Tasks {
/** Runs the typical test suite
*
* Arguments passed to the task are passed on to PHPUnit. Thus one may, for
* example, run the following command and get the expected results:
*
* ./robo test --testsuite TTRSS --exclude-group slow --testdox
*
* Please see the PHPUnit documentation for available options.
*/
public function test(array $args): Result {
return $this->runTests(escapeshellarg(\PHP_BINARY), "typical", $args);
}
/** Runs the full test suite
*
* This includes pedantic tests which may help to identify problems.
* See help for the "test" task for more details.
*/
public function testFull(array $args): Result {
return $this->runTests(escapeshellarg(\PHP_BINARY), "full", $args);
}
/**
* Runs a quick subset of the test suite
*
* See help for the "test" task for more details.
*/
public function testQuick(array $args): Result {
return $this->runTests(escapeshellarg(\PHP_BINARY), "quick", $args);
}
/** Produces a code coverage report
*
* By default this task produces an HTML-format coverage report in
* tests/coverage/. Additional reports may be produced by passing
* arguments to this task as one would to PHPUnit.
*
* Robo first tries to use pcov and will fall back first to xdebug then
* phpdbg. Neither pcov nor xdebug need to be enabled to be used; they
* only need to be present in the extension load path to be used.
*/
public function coverage(array $args): Result {
// run tests with code coverage reporting enabled
$exec = $this->findCoverageEngine();
return $this->runTests($exec, "coverage", array_merge(["--coverage-html", BASE_TEST."coverage"], $args));
}
/** Produces a code coverage report, with redundant tests
*
* Depending on the environment, some tests that normally provide
* coverage may be skipped, while working alternatives are normally
* suppressed for reasons of time. This coverage report will try to
* run all tests which may cover code.
*
* See also help for the "coverage" task for more details.
*/
public function coverageFull(array $args): Result {
// run tests with code coverage reporting enabled
$exec = $this->findCoverageEngine();
return $this->runTests($exec, "typical", array_merge(["--coverage-html", BASE_TEST."coverage"], $args));
}
/** Runs the coding standards fixer */
public function clean($opts = ['demo|d' => false]): Result {
$t = $this->taskExec(norm(BASE."vendor/bin/php-cs-fixer"));
$t->arg("fix");
if ($opts['demo']) {
$t->args("--dry-run", "--diff")->option("--diff-format", "udiff");
}
return $t->run();
}
protected function findCoverageEngine(): string {
$dir = rtrim(ini_get("extension_dir"), "/").\DIRECTORY_SEPARATOR;
$ext = IS_WIN ? "dll" : (IS_MAC ? "dylib" : "so");
$php = escapeshellarg(\PHP_BINARY);
$code = escapeshellarg(BASE."lib");
if (extension_loaded("pcov")) {
return "$php -d pcov.enabled=1 -d pcov.directory=$code";
} elseif (extension_loaded("xdebug")) {
return $php;
} elseif (file_exists($dir."pcov.$ext")) {
return "$php -d extension=pcov.$ext -d pcov.enabled=1 -d pcov.directory=$code";
} elseif (file_exists($dir."pcov.$ext")) {
return "$php -d zend_extension=xdebug.$ext";
} else {
if (IS_WIN) {
$dbg = dirname(\PHP_BINARY)."\\phpdbg.exe";
$dbg = file_exists($dbg) ? $dbg : "";
} else {
$dbg = trim(`which phpdbg 2>/dev/null`);
}
if ($dbg) {
return escapeshellarg($dbg)." -qrr";
} else {
return $php;
}
}
}
protected function blackhole(bool $all = false): string {
$hole = IS_WIN ? "nul" : "/dev/null";
return $all ? ">$hole 2>&1" : "2>$hole";
}
protected function runTests(string $executor, string $set, array $args): Result {
switch ($set) {
case "typical":
$set = ["--exclude-group", "optional"];
break;
case "quick":
$set = ["--exclude-group", "optional,slow"];
break;
case "coverage":
$set = ["--exclude-group", "optional,coverageOptional"];
break;
case "full":
$set = [];
break;
default:
throw new \Exception;
}
$execpath = norm(BASE."vendor-bin/phpunit/vendor/phpunit/phpunit/phpunit");
$confpath = realpath(BASE_TEST."phpunit.dist.xml") ?: norm(BASE_TEST."phpunit.xml");
//$this->taskServer(8000)->host("localhost")->dir(BASE_TEST."docroot")->rawArg("-n")->arg(BASE_TEST."server.php")->rawArg($this->blackhole())->background()->run();
return $this->taskExec($executor)->option("-d", "zend.assertions=1")->arg($execpath)->option("-c", $confpath)->args(array_merge($set, $args))->run();
}
}

39
composer.json

@ -0,0 +1,39 @@
{
"name": "mensbeam/mimesniff",
"type": "library",
"description": "An implementation of the WHATWG Mimesniff specification",
"keywords": ["whatwg", "mime", "mimesniff"],
"license": "MIT",
"authors": [
{
"name": "J. King",
"email": "jking@jkingweb.ca",
"homepage": "https://jkingweb.ca/"
}
],
"require": {
"php": "^7.1"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.3"
},
"config": {
"platform": {
"php": "7.1.33"
}
},
"scripts": {
"post-install-cmd": ["@composer bin all install"],
"post-update-cmd": ["@composer bin all update"]
},
"autoload": {
"psr-4": {
"MensBeam\\Mime\\": "lib/"
}
},
"autoload-dev": {
"psr-4": {
"MensBeam\\Mime\\TestCase\\": "tests/cases/"
}
}
}

63
composer.lock

@ -0,0 +1,63 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "8ccabde36f4d647880e48bda8d68b1bc",
"packages": [],
"packages-dev": [
{
"name": "bamarni/composer-bin-plugin",
"version": "v1.3.0",
"source": {
"type": "git",
"url": "https://github.com/bamarni/composer-bin-plugin.git",
"reference": "67f9d314dc7ecf7245b8637906e151ccc62b8d24"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bamarni/composer-bin-plugin/zipball/67f9d314dc7ecf7245b8637906e151ccc62b8d24",
"reference": "67f9d314dc7ecf7245b8637906e151ccc62b8d24",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0"
},
"require-dev": {
"composer/composer": "dev-master",
"symfony/console": "^2.5 || ^3.0 || ^4.0"
},
"type": "composer-plugin",
"extra": {
"class": "Bamarni\\Composer\\Bin\\Plugin",
"branch-alias": {
"dev-master": "1.1-dev"
}
},
"autoload": {
"psr-4": {
"Bamarni\\Composer\\Bin\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"time": "2019-03-17T12:38:04+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": "^7.1"
},
"platform-dev": [],
"platform-overrides": {
"php": "7.1.33"
},
"plugin-api-version": "1.1.0"
}

158
lib/MimeType.php

@ -0,0 +1,158 @@
<?php
/** @license MIT
* Copyright 2020 J. King et al.
* See LICENSE and AUTHORS files for details */
declare(strict_types=1);
namespace MensBeam\Mime;
/** @property-read string $type
* @property-read string $subtype
* @property-read string $essence
* @property-read array $params
*/
class MimeType {
protected const TYPE_PATTERN = <<<'PATTERN'
<^
[\t\r\n ]* # optional leading whitespace
([^/]+) # type
/ # type/subtype delimiter
([^;]+) # subtype (possibly with trailing whitespace)
(;.*)? # optional parameters, to be parsed separately
[\t\r\n ]* # optional trailing whitespace
$>sx
PATTERN;
protected const PARAM_PATTERN = <<<'PATTERN'
<
[;\t\r\n ]* # parameter delimiter and leading whitespace, all optional
([^=;]*) # parameter name; may be empty
(?:= # parameter name/value delimiter
(
"(?:\\"|[^"])*(?:"|$)[^;]* # quoted parameter value and optional garbage
|[^;]* # unquoted parameter value (possibly with trailing whitespace)
)
)?
;? # optional trailing parameter delimiter
[\t\r\n ]* # optional trailing whitespace
>sx
PATTERN;
protected const TOKEN_PATTERN = '<^[A-Za-z0-9!#$%&\'*+\-\.\^_`|~]+$>s';
protected const BARE_VALUE_PATTERN = '<^[\t\x{20}-\x{7E}\x{80}-\x{FF}]+$>su';
protected const QUOTED_VALUE_PATTERN = '<^"((?:\\\"|[\t !\x{23}-\x{7E}\x{80}-\x{FF}])*)(?:"|$)>su';
protected const ESCAPE_PATTERN = '<\\\(.)>s';
protected const CHAR_MAP = [0x80 => "\u{80}","\u{81}","\u{82}","\u{83}","\u{84}","\u{85}","\u{86}","\u{87}","\u{88}","\u{89}","\u{8a}","\u{8b}","\u{8c}","\u{8d}","\u{8e}","\u{8f}","\u{90}","\u{91}","\u{92}","\u{93}","\u{94}","\u{95}","\u{96}","\u{97}","\u{98}","\u{99}","\u{9a}","\u{9b}","\u{9c}","\u{9d}","\u{9e}","\u{9f}","\u{a0}","\u{a1}","\u{a2}","\u{a3}","\u{a4}","\u{a5}","\u{a6}","\u{a7}","\u{a8}","\u{a9}","\u{aa}","\u{ab}","\u{ac}","\u{ad}","\u{ae}","\u{af}","\u{b0}","\u{b1}","\u{b2}","\u{b3}","\u{b4}","\u{b5}","\u{b6}","\u{b7}","\u{b8}","\u{b9}","\u{ba}","\u{bb}","\u{bc}","\u{bd}","\u{be}","\u{bf}","\u{c0}","\u{c1}","\u{c2}","\u{c3}","\u{c4}","\u{c5}","\u{c6}","\u{c7}","\u{c8}","\u{c9}","\u{ca}","\u{cb}","\u{cc}","\u{cd}","\u{ce}","\u{cf}","\u{d0}","\u{d1}","\u{d2}","\u{d3}","\u{d4}","\u{d5}","\u{d6}","\u{d7}","\u{d8}","\u{d9}","\u{da}","\u{db}","\u{dc}","\u{dd}","\u{de}","\u{df}","\u{e0}","\u{e1}","\u{e2}","\u{e3}","\u{e4}","\u{e5}","\u{e6}","\u{e7}","\u{e8}","\u{e9}","\u{ea}","\u{eb}","\u{ec}","\u{ed}","\u{ee}","\u{ef}","\u{f0}","\u{f1}","\u{f2}","\u{f3}","\u{f4}","\u{f5}","\u{f6}","\u{f7}","\u{f8}","\u{f9}","\u{fa}","\u{fb}","\u{fc}","\u{fd}","\u{fe}","\u{ff}"];
private $type = "";
private $subtype = "";
private $params = [];
private $essence;
private function __construct(string $type = "", string $subtype = "", array $params = []) {
$this->type = $type;
$this->subtype = $subtype;
$this->params = $params;
}
public function __get(string $name) {
if ($name === "essence") {
return $this->type."/".$this->subtype;
}
return $this->$name ?? null;
}
public function __toString(): string {
$out = $this->__get("essence");
if (is_array($this->params) && sizeof($this->params)) {
foreach ($this->params as $name => $value) {
$out .= ";$name=".(preg_match(self::TOKEN_PATTERN, $value) ? $value : '"'.str_replace(["\\", '"'], ["\\\\", "\\\""], $value).'"');
}
}
return $out;
}
public static function parse(string $mimeType): ?self {
if (preg_match(self::TYPE_PATTERN, $mimeType, $match)) {
[$mimeType, $type, $subtype, $params] = array_pad($match, 4, "");
if (strlen($type = static::parseHttpToken($type)) && strlen($subtype = static::parseHttpToken(rtrim($subtype, "\t\r\n ")))) {
return new static(strtolower($type), strtolower($subtype), static::parseParams($params));
}
}
return null;
}
public static function parseBytes(string $mimeType): ?self {
return static::parse(static::decode($mimeType));
}
public static function decode(string $bytes): string {
$out = "";
for ($a = 0; $a < strlen($bytes); $a++) {
$c = $bytes[$a];
$p = ord($c);
$out .= $p < 0x80 ? $c : self::CHAR_MAP[$a];
}
return $out;
}
public static function encode(string $chars): ?string {
$map = array_combine(array_values(self::CHAR_MAP), range(chr(0x80), chr(0xFF)));
$out = "";
foreach (preg_split("<>u", $chars) as $c) {
if (strlen($c) === 1) {
$out .= $c;
} elseif (isset($map[$c])) {
$out .= $map[$c];
} else {
return null;
}
}
return $out;
}
protected static function parseParams(string $params): array {
$out = [];
if (preg_match_all(self::PARAM_PATTERN, $params, $matches, \PREG_SET_ORDER)) {
foreach ($matches as $match) {
[$param, $name, $value] = array_pad($match, 3, "");
$name = strtolower(static::parseHttpToken($name));
if (!strlen($name) || isset($out[$name])) {
continue;
} elseif (strlen($value) && $value[0] === '"') {
$value = static::parseHttpQuotedValue($value);
if (is_null($value)) {
continue;
}
} else {
$value = static::parseHttpBareValue($value);
if (!strlen($value)) {
continue;
}
}
$out[$name] = $value;
}
}
return $out;
}
protected static function parseHttpToken(string $token): string {
if (preg_match(self::TOKEN_PATTERN, $token, $match)) {
return $token;
}
return "";
}
protected static function parseHttpBareValue(string $value): string {
$value = rtrim($value, "\t\r\n ");
if (preg_match(self::BARE_VALUE_PATTERN, $value, $match)) {
return $value;
}
return "";
}
protected static function parseHttpQuotedValue(string $value): ?string {
if (preg_match(self::QUOTED_VALUE_PATTERN, $value, $match)) {
return preg_replace(self::ESCAPE_PATTERN, '$1', $match[1]);
}
return null;
}
}

14
robo

@ -0,0 +1,14 @@
#! /bin/sh
base=`dirname "$0"`
roboCommand="$1"
if [ $# -eq 0 ]; then
"$base/vendor/bin/robo"
else
shift
ulimit -n 2048
if [ "$1" = "clean" ]; then
"$base/vendor/bin/robo" "$roboCommand" "$@"
else
"$base/vendor/bin/robo" "$roboCommand" -- "$@"
fi
fi

21
robo.bat

@ -0,0 +1,21 @@
@echo off
setlocal
set base=%~dp0
set roboCommand=%1
rem get all arguments except the first
shift
set "args="
:parse
if "%~1" neq "" (
set args=%args% %1
shift
goto :parse
)
if defined args set args=%args:~1%
if "%1"=="clean" (
call "%base%vendor\bin\robo" "%roboCommand%" %args%
) else (
call "%base%vendor\bin\robo" "%roboCommand%" -- %args%
)

20
tests/bootstrap.php

@ -0,0 +1,20 @@
<?php
/** @license MIT
* Copyright 2020 J. King
* See LICENSE and AUTHORS files for details */
declare(strict_types=1);
namespace MensBeam\Mime;
const NS_BASE = __NAMESPACE__."\\";
define(NS_BASE."BASE", dirname(__DIR__).DIRECTORY_SEPARATOR);
const DOCROOT = BASE."tests".DIRECTORY_SEPARATOR."docroot".DIRECTORY_SEPARATOR;
ini_set("memory_limit", "-1");
ini_set("zend.assertions", "1");
ini_set("assert.exception", "true");
error_reporting(\E_ALL);
require_once BASE."vendor".DIRECTORY_SEPARATOR."autoload.php";
if (function_exists("xdebug_set_filter")) {
xdebug_set_filter(\XDEBUG_FILTER_CODE_COVERAGE, \XDEBUG_PATH_WHITELIST, [BASE."lib/"]);
}

42
tests/cases/MimeTypeTest.php

@ -0,0 +1,42 @@
<?php
/** @license MIT
* Copyright 2020 J. King
* See LICENSE and AUTHORS files for details */
declare(strict_types=1);
namespace MensBeam\Mime\TestCase;
use MensBeam\Mime\MimeType as Mime;
/** @covers \MensBeam\Mime\MimeType */
class MimeTypeTest extends \PHPUnit\Framework\TestCase {
/** @dataProvider provideStandardTests */
public function testStandardTestSuite(string $input, ?string $exp): void {
if (is_null($exp)) {
$this->assertNull(Mime::parse($input));
} else {
$this->assertSame($exp, (string) Mime::parse($input));
}
}
public function provideStandardTests(): iterable {
foreach (new \GlobIterator(__DIR__."/*.json", \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::KEY_AS_FILENAME) as $file => $path) {
$indexOffset = 0;
$description = "";
foreach (json_decode(file_get_contents($path)) as $index => $test) {
if (is_string($test)) {
// the array member is a description of the next member
// the index offset should be decremented, the description stored, and this entry skipped
$indexOffset--;
$description = $test;
continue;
} else {
$index += $indexOffset;
$description = $description ? ": $description" : "";
yield "$file #$index$description" => [$test->input, $test->output];
$description = null;
}
}
}
}
}

20
tests/cases/README

@ -0,0 +1,20 @@
The MimeType class is an original work, but its test suite is derived
in part from an existing test corpus from the following source:
The Web Platform Test suite
<https://github.com/web-platform-tests/wpt/tree/62317fb983ca5687e4133d89f5523839fdab7f69/mimesniff/mime-types>
The license text is reproduced below, but please note that the license text
has changed since the last time the mimesniff portion of the test suite was
modified; the text included here is current as of 2019-04-25.
Copyright 2019 web-platform-tests contributors
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

3526
tests/cases/generated-mime-types.json

File diff suppressed because it is too large

383
tests/cases/mime-types.json

@ -0,0 +1,383 @@
[
"Basics",
{
"input": "text/html;charset=gbk",
"output": "text/html;charset=gbk",
"navigable": true,
"encoding": "GBK"
},
{
"input": "TEXT/HTML;CHARSET=GBK",
"output": "text/html;charset=GBK",
"navigable": true,
"encoding": "GBK"
},
"Legacy comment syntax",
{
"input": "text/html;charset=gbk(",
"output": "text/html;charset=\"gbk(\"",
"navigable": true,
"encoding": null
},
{
"input": "text/html;x=(;charset=gbk",
"output": "text/html;x=\"(\";charset=gbk",
"navigable": true,
"encoding": "GBK"
},
"Duplicate parameter",
{
"input": "text/html;charset=gbk;charset=windows-1255",
"output": "text/html;charset=gbk",
"navigable": true,
"encoding": "GBK"
},
{
"input": "text/html;charset=();charset=GBK",
"output": "text/html;charset=\"()\"",
"navigable": true,
"encoding": null
},
"Spaces",
{
"input": "text/html;charset =gbk",
"output": "text/html",
"navigable": true,
"encoding": null
},
{
"input": "text/html ;charset=gbk",
"output": "text/html;charset=gbk",
"navigable": true,
"encoding": "GBK"
},
{
"input": "text/html; charset=gbk",
"output": "text/html;charset=gbk",
"navigable": true,
"encoding": "GBK"
},
{
"input": "text/html;charset= gbk",
"output": "text/html;charset=\" gbk\"",
"navigable": true,
"encoding": "GBK"
},
{
"input": "text/html;charset= \"gbk\"",
"output": "text/html;charset=\" \\\"gbk\\\"\"",
"navigable": true,
"encoding": null
},
"0x0B and 0x0C",
{
"input": "text/html;charset=\u000Bgbk",
"output": "text/html",
"navigable": true,
"encoding": null
},
{
"input": "text/html;charset=\u000Cgbk",
"output": "text/html",
"navigable": true,
"encoding": null
},
{
"input": "text/html;\u000Bcharset=gbk",
"output": "text/html",
"navigable": true,
"encoding": null
},
{
"input": "text/html;\u000Ccharset=gbk",
"output": "text/html",
"navigable": true,
"encoding": null
},
"Single quotes are a token, not a delimiter",
{
"input": "text/html;charset='gbk'",
"output": "text/html;charset='gbk'",
"navigable": true,
"encoding": null
},
{
"input": "text/html;charset='gbk",
"output": "text/html;charset='gbk",
"navigable": true,
"encoding": null
},
{
"input": "text/html;charset=gbk'",
"output": "text/html;charset=gbk'",
"navigable": true,
"encoding": null
},
{
"input": "text/html;charset=';charset=GBK",
"output": "text/html;charset='",
"navigable": true,
"encoding": null
},
"Invalid parameters",
{
"input": "text/html;test;charset=gbk",
"output": "text/html;charset=gbk",
"navigable": true,
"encoding": "GBK"
},
{
"input": "text/html;test=;charset=gbk",
"output": "text/html;charset=gbk",
"navigable": true,
"encoding": "GBK"
},
{
"input": "text/html;';charset=gbk",
"output": "text/html;charset=gbk",
"navigable": true,
"encoding": "GBK"
},
{
"input": "text/html;\";charset=gbk",
"output": "text/html;charset=gbk",
"navigable": true,
"encoding": "GBK"
},
{
"input": "text/html ; ; charset=gbk",
"output": "text/html;charset=gbk",
"navigable": true,
"encoding": "GBK"
},
{
"input": "text/html;;;;charset=gbk",
"output": "text/html;charset=gbk",
"navigable": true,
"encoding": "GBK"
},
{
"input": "text/html;charset= \"\u007F;charset=GBK",
"output": "text/html;charset=GBK",
"navigable": true,
"encoding": "GBK"
},
{
"input": "text/html;charset=\"\u007F;charset=foo\";charset=GBK",
"output": "text/html;charset=GBK",
"navigable": true,
"encoding": "GBK"
},
"Double quotes",
{
"input": "text/html;charset=\"gbk\"",
"output": "text/html;charset=gbk",
"navigable": true,
"encoding": "GBK"
},
{
"input": "text/html;charset=\"gbk",
"output": "text/html;charset=gbk",
"navigable": true,
"encoding": "GBK"
},
{
"input": "text/html;charset=gbk\"",
"output": "text/html;charset=\"gbk\\\"\"",
"navigable": true,
"encoding": null
},
{
"input": "text/html;charset=\" gbk\"",
"output": "text/html;charset=\" gbk\"",
"navigable": true,
"encoding": "GBK"
},
{
"input": "text/html;charset=\"gbk \"",
"output": "text/html;charset=\"gbk \"",
"navigable": true,
"encoding": "GBK"
},
{
"input": "text/html;charset=\"\\ gbk\"",
"output": "text/html;charset=\" gbk\"",
"navigable": true,
"encoding": "GBK"
},
{
"input": "text/html;charset=\"\\g\\b\\k\"",
"output": "text/html;charset=gbk",
"navigable": true,
"encoding": "GBK"
},
{
"input": "text/html;charset=\"gbk\"x",
"output": "text/html;charset=gbk",
"navigable": true,
"encoding": "GBK"
},
{
"input": "text/html;charset=\"\";charset=GBK",
"output": "text/html;charset=\"\"",
"navigable": true,
"encoding": null
},
{
"input": "text/html;charset=\";charset=GBK",
"output": "text/html;charset=\";charset=GBK\"",
"navigable": true,
"encoding": null
},
"Unexpected code points",
{
"input": "text/html;charset={gbk}",
"output": "text/html;charset=\"{gbk}\"",
"navigable": true,
"encoding": null
},
"Parameter name longer than 127",
{
"input": "text/html;0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789=x;charset=gbk",
"output": "text/html;0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789=x;charset=gbk",
"navigable": true,
"encoding": "GBK"
},
"type/subtype longer than 127",
{
"input": "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789",
"output": "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
},
"Valid",
{
"input": "!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
"output": "!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
},
{
"input": "x/x;x=\"\t !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008A\u008B\u008C\u008D\u008E\u008F\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009A\u009B\u009C\u009D\u009E\u009F\u00A0\u00A1\u00A2\u00A3\u00A4\u00A5\u00A6\u00A7\u00A8\u00A9\u00AA\u00AB\u00AC\u00AD\u00AE\u00AF\u00B0\u00B1\u00B2\u00B3\u00B4\u00B5\u00B6\u00B7\u00B8\u00B9\u00BA\u00BB\u00BC\u00BD\u00BE\u00BF\u00C0\u00C1\u00C2\u00C3\u00C4\u00C5\u00C6\u00C7\u00C8\u00C9\u00CA\u00CB\u00CC\u00CD\u00CE\u00CF\u00D0\u00D1\u00D2\u00D3\u00D4\u00D5\u00D6\u00D7\u00D8\u00D9\u00DA\u00DB\u00DC\u00DD\u00DE\u00DF\u00E0\u00E1\u00E2\u00E3\u00E4\u00E5\u00E6\u00E7\u00E8\u00E9\u00EA\u00EB\u00EC\u00ED\u00EE\u00EF\u00F0\u00F1\u00F2\u00F3\u00F4\u00F5\u00F6\u00F7\u00F8\u00F9\u00FA\u00FB\u00FC\u00FD\u00FE\u00FF\"",
"output": "x/x;x=\"\t !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008A\u008B\u008C\u008D\u008E\u008F\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009A\u009B\u009C\u009D\u009E\u009F\u00A0\u00A1\u00A2\u00A3\u00A4\u00A5\u00A6\u00A7\u00A8\u00A9\u00AA\u00AB\u00AC\u00AD\u00AE\u00AF\u00B0\u00B1\u00B2\u00B3\u00B4\u00B5\u00B6\u00B7\u00B8\u00B9\u00BA\u00BB\u00BC\u00BD\u00BE\u00BF\u00C0\u00C1\u00C2\u00C3\u00C4\u00C5\u00C6\u00C7\u00C8\u00C9\u00CA\u00CB\u00CC\u00CD\u00CE\u00CF\u00D0\u00D1\u00D2\u00D3\u00D4\u00D5\u00D6\u00D7\u00D8\u00D9\u00DA\u00DB\u00DC\u00DD\u00DE\u00DF\u00E0\u00E1\u00E2\u00E3\u00E4\u00E5\u00E6\u00E7\u00E8\u00E9\u00EA\u00EB\u00EC\u00ED\u00EE\u00EF\u00F0\u00F1\u00F2\u00F3\u00F4\u00F5\u00F6\u00F7\u00F8\u00F9\u00FA\u00FB\u00FC\u00FD\u00FE\u00FF\""
},
"End-of-file handling",
{
"input": "x/x;test",
"output": "x/x"
},
{
"input": "x/x;test=\"\\",
"output": "x/x;test=\"\\\\\""
},
"Whitespace (not handled by generated-mime-types.json or above)",
{
"input": "x/x;x= ",
"output": "x/x"
},
{
"input": "x/x;x=\t",
"output": "x/x"
},
{
"input": "x/x\n\r\t ;x=x",
"output": "x/x;x=x"
},
{
"input": "\n\r\t x/x;x=x\n\r\t ",
"output": "x/x;x=x"
},
{
"input": "x/x;\n\r\t x=x\n\r\t ;x=y",
"output": "x/x;x=x"
},
"Latin1",
{
"input": "text/html;test=\u00FF;charset=gbk",
"output": "text/html;test=\"\u00FF\";charset=gbk",
"navigable": true,
"encoding": "GBK"
},
">Latin1",
{
"input": "x/x;test=\uFFFD;x=x",
"output": "x/x;x=x"
},
"Failure",
{
"input": "\u000Bx/x",
"output": null
},
{
"input": "\u000Cx/x",
"output": null
},
{
"input": "x/x\u000B",
"output": null
},
{
"input": "x/x\u000C",
"output": null
},
{
"input": "",
"output": null
},
{
"input": "\t",
"output": null
},
{
"input": "/",
"output": null
},
{
"input": "bogus",
"output": null
},
{
"input": "bogus/",
"output": null
},
{
"input": "bogus/ ",
"output": null
},
{
"input": "bogus/bogus/;",
"output": null
},
{
"input": "</>",
"output": null
},
{
"input": "(/)",
"output": null
},
{
"input": "ÿ/ÿ",
"output": null
},
{
"input": "text/html(;doesnot=matter",
"output": null
},
{
"input": "{/}",
"output": null
},
{
"input": "\u0100/\u0100",
"output": null
},
{
"input": "text /html",
"output": null
},
{
"input": "text/ html",
"output": null
},
{
"input": "\"text/html\"",
"output": null
}
]

26
tests/phpunit.dist.xml

@ -0,0 +1,26 @@
<?xml version="1.0"?>
<phpunit
colors="true"
bootstrap="bootstrap.php"
cacheTokens="true"
convertErrorsToExceptions="false"
convertNoticesToExceptions="false"
convertWarningsToExceptions="false"
beStrictAboutTestsThatDoNotTestAnything="true"
beStrictAboutOutputDuringTests="true"
forceCoversAnnotation="true"
executionOrder="default"
>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">../lib</directory>
</whitelist>
</filter>
<testsuites>
<testsuite name="MIME">
<directory>cases</directory>
</testsuite>
</testsuites>
</phpunit>

5
vendor-bin/csfixer/composer.json

@ -0,0 +1,5 @@
{
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.16"
}
}

1499
vendor-bin/csfixer/composer.lock

File diff suppressed because it is too large

6
vendor-bin/phpunit/composer.json

@ -0,0 +1,6 @@
{
"require-dev": {
"phpunit/phpunit": "^9.0",
"symfony/yaml": "^5.0"
}
}

1720
vendor-bin/phpunit/composer.lock

File diff suppressed because it is too large

5
vendor-bin/robo/composer.json

@ -0,0 +1,5 @@
{
"require-dev": {
"consolidation/robo": "^2.0"
}
}

1473
vendor-bin/robo/composer.lock

File diff suppressed because it is too large
Loading…
Cancel
Save