From e3821f9e58fadf16a89b3becb4a00e58d466f390 Mon Sep 17 00:00:00 2001 From: kenjis <action@github.com> Date: Sun, 26 Mar 2023 01:13:46 +0000 Subject: [PATCH] Release v4.3.3 --- app/Common.php | 2 +- app/Config/Encryption.php | 9 +++ composer.json | 2 +- system/API/ResponseTrait.php | 2 + system/Cache/Handlers/FileHandler.php | 2 +- system/Cache/Handlers/RedisHandler.php | 3 +- system/CodeIgniter.php | 2 +- system/Commands/Database/MigrateRollback.php | 2 +- .../Utilities/Routes/ControllerFinder.php | 1 + system/Database/BaseBuilder.php | 10 ++- system/Debug/Exceptions.php | 8 +- system/Email/Email.php | 5 +- system/Filters/FilterInterface.php | 4 +- system/HTTP/DownloadResponse.php | 5 +- system/HTTP/RequestInterface.php | 4 +- system/HTTP/RequestTrait.php | 8 +- system/HTTP/ResponseTrait.php | 6 +- system/Helpers/text_helper.php | 76 +++++++++++++++++-- system/Helpers/url_helper.php | 9 ++- .../SplFileInfoRepresentation.php | 2 +- .../resources/compiled/solarized-dark.css | 2 +- 21 files changed, 127 insertions(+), 37 deletions(-) diff --git a/app/Common.php b/app/Common.php index 23e3e614..95f55442 100644 --- a/app/Common.php +++ b/app/Common.php @@ -11,5 +11,5 @@ * loaded early on, and may also contain additional functions * that you'd like to use throughout your entire application * - * @see: https://codeigniter4.github.io/CodeIgniter4/ + * @see: https://codeigniter.com/user_guide/extending/common.html */ diff --git a/app/Config/Encryption.php b/app/Config/Encryption.php index e37b4e2a..28344134 100644 --- a/app/Config/Encryption.php +++ b/app/Config/Encryption.php @@ -80,4 +80,13 @@ class Encryption extends BaseConfig * Set to 'authentication' for CI3 Encryption compatibility. */ public string $authKeyInfo = ''; + + /** + * Cipher to use. + * This setting is only used by OpenSSLHandler. + * + * Set to 'AES-128-CBC' to decrypt encrypted data that encrypted + * by CI3 Encryption default configuration. + */ + public string $cipher = 'AES-256-CTR'; } diff --git a/composer.json b/composer.json index 2f3022a9..905e123c 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "psr/log": "^1.1" }, "require-dev": { - "kint-php/kint": "^5.0.3", + "kint-php/kint": "^5.0.4", "codeigniter/coding-standard": "^1.5", "fakerphp/faker": "^1.9", "friendsofphp/php-cs-fixer": "3.13.0", diff --git a/system/API/ResponseTrait.php b/system/API/ResponseTrait.php index 0b357f0a..9e8bad77 100644 --- a/system/API/ResponseTrait.php +++ b/system/API/ResponseTrait.php @@ -92,8 +92,10 @@ protected function respond($data = null, ?int $status = null, string $message = if ($data === null && $status === null) { $status = 404; $output = null; + $this->format($data); } elseif ($data === null && is_numeric($status)) { $output = null; + $this->format($data); } else { $status = empty($status) ? 200 : $status; $output = $this->format($data); diff --git a/system/Cache/Handlers/FileHandler.php b/system/Cache/Handlers/FileHandler.php index b95d7f9e..c217c7ed 100644 --- a/system/Cache/Handlers/FileHandler.php +++ b/system/Cache/Handlers/FileHandler.php @@ -346,7 +346,7 @@ protected function getDirFileInfo(string $sourceDir, bool $topLevelOnly = true, while (false !== ($file = readdir($fp))) { if (is_dir($sourceDir . $file) && $file[0] !== '.' && $topLevelOnly === false) { $this->getDirFileInfo($sourceDir . $file . DIRECTORY_SEPARATOR, $topLevelOnly, true); - } elseif ($file[0] !== '.') { + } elseif (! is_dir($sourceDir . $file) && $file[0] !== '.') { $_filedata[$file] = $this->getFileInfo($sourceDir . $file); $_filedata[$file]['relative_path'] = $relativePath; } diff --git a/system/Cache/Handlers/RedisHandler.php b/system/Cache/Handlers/RedisHandler.php index 8b3af585..6874a86c 100644 --- a/system/Cache/Handlers/RedisHandler.php +++ b/system/Cache/Handlers/RedisHandler.php @@ -233,12 +233,11 @@ public function getCacheInfo() */ public function getMetaData(string $key) { - $key = static::validateKey($key, $this->prefix); $value = $this->get($key); if ($value !== null) { $time = Time::now()->getTimestamp(); - $ttl = $this->redis->ttl($key); + $ttl = $this->redis->ttl(static::validateKey($key, $this->prefix)); return [ 'expire' => $ttl > 0 ? $time + $ttl : null, diff --git a/system/CodeIgniter.php b/system/CodeIgniter.php index d370e34c..42ddaa0c 100644 --- a/system/CodeIgniter.php +++ b/system/CodeIgniter.php @@ -47,7 +47,7 @@ class CodeIgniter /** * The current version of CodeIgniter Framework */ - public const CI_VERSION = '4.3.2'; + public const CI_VERSION = '4.3.3'; /** * App startup time. diff --git a/system/Commands/Database/MigrateRollback.php b/system/Commands/Database/MigrateRollback.php index 17434da4..c29ce84b 100644 --- a/system/Commands/Database/MigrateRollback.php +++ b/system/Commands/Database/MigrateRollback.php @@ -57,7 +57,7 @@ class MigrateRollback extends BaseCommand * @var array */ protected $options = [ - '-b' => 'Specify a batch to roll back to; e.g. "3" to return to batch #3 or "-2" to roll back twice', + '-b' => 'Specify a batch to roll back to; e.g. "3" to return to batch #3', '-g' => 'Set database group', '-f' => 'Force command - this option allows you to bypass the confirmation question when running this command in a production environment', ]; diff --git a/system/Commands/Utilities/Routes/ControllerFinder.php b/system/Commands/Utilities/Routes/ControllerFinder.php index 7e786587..e7d828c0 100644 --- a/system/Commands/Utilities/Routes/ControllerFinder.php +++ b/system/Commands/Utilities/Routes/ControllerFinder.php @@ -44,6 +44,7 @@ public function find(): array $nsArray = explode('\\', trim($this->namespace, '\\')); $count = count($nsArray); $ns = ''; + $files = []; for ($i = 0; $i < $count; $i++) { $ns .= '\\' . array_shift($nsArray); diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index 653f4301..fab6e30d 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -2021,9 +2021,9 @@ private function setAlias(string $alias): BaseBuilder /** * Sets update fields for upsert, update * - * @param string|string[] $set - * @param bool $addToDefault adds update fields to the default ones - * @param array|null $ignore ignores items in set + * @param RawSql[]|string|string[] $set + * @param bool $addToDefault adds update fields to the default ones + * @param array|null $ignore ignores items in set * * @return $this */ @@ -3082,6 +3082,10 @@ protected function compileWhereHaving(string $qbKey): string continue; } + if ($qbkey instanceof RawSql) { + continue; + } + if ($qbkey['condition'] instanceof RawSql) { $qbkey = $qbkey['condition']; diff --git a/system/Debug/Exceptions.php b/system/Debug/Exceptions.php index 6dc098d4..531e95fd 100644 --- a/system/Debug/Exceptions.php +++ b/system/Debug/Exceptions.php @@ -119,6 +119,11 @@ public function exceptionHandler(Throwable $exception) [$statusCode, $exitCode] = $this->determineCodes($exception); + // Get the first exception. + while ($prevException = $exception->getPrevious()) { + $exception = $prevException; + } + if ($this->config->log === true && ! in_array($statusCode, $this->config->ignoreCodes, true)) { log_message('critical', "{message}\nin {exFile} on line {exLine}.\n{trace}", [ 'message' => $exception->getMessage(), @@ -531,9 +536,6 @@ private static function renderBacktrace(array $backtrace): string case is_resource($value): return sprintf('resource (%s)', get_resource_type($value)); - case is_string($value): - return var_export(clean_path($value), true); - default: return var_export($value, true); } diff --git a/system/Email/Email.php b/system/Email/Email.php index 488a5ee7..fe68ff2d 100644 --- a/system/Email/Email.php +++ b/system/Email/Email.php @@ -1883,7 +1883,10 @@ protected function SMTPConnect() $crypto = stream_socket_enable_crypto( $this->SMTPConnect, true, - STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT + STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT + | STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT + | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT + | STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT ); if ($crypto !== true) { diff --git a/system/Filters/FilterInterface.php b/system/Filters/FilterInterface.php index 32a18de7..8055d11e 100644 --- a/system/Filters/FilterInterface.php +++ b/system/Filters/FilterInterface.php @@ -29,7 +29,7 @@ interface FilterInterface * sent back to the client, allowing for error pages, * redirects, etc. * - * @param null $arguments + * @param array|null $arguments * * @return mixed */ @@ -41,7 +41,7 @@ public function before(RequestInterface $request, $arguments = null); * to stop execution of other after filters, short of * throwing an Exception or Error. * - * @param null $arguments + * @param array|null $arguments * * @return mixed */ diff --git a/system/HTTP/DownloadResponse.php b/system/HTTP/DownloadResponse.php index 899bec85..d5824da1 100644 --- a/system/HTTP/DownloadResponse.php +++ b/system/HTTP/DownloadResponse.php @@ -227,9 +227,8 @@ public function setContentType(string $mime, string $charset = 'UTF-8') */ public function noCache(): self { - $this->removeHeader('Cache-control'); - - $this->setHeader('Cache-control', ['private', 'no-transform', 'no-store', 'must-revalidate']); + $this->removeHeader('Cache-Control'); + $this->setHeader('Cache-Control', ['private', 'no-transform', 'no-store', 'must-revalidate']); return $this; } diff --git a/system/HTTP/RequestInterface.php b/system/HTTP/RequestInterface.php index fd2cdfbb..367c4949 100644 --- a/system/HTTP/RequestInterface.php +++ b/system/HTTP/RequestInterface.php @@ -40,8 +40,8 @@ public function isValidIP(string $ip, ?string $which = null): bool; * Fetch an item from the $_SERVER array. * Supplied by RequestTrait. * - * @param string $index Index for item to be fetched from $_SERVER - * @param null $filter A filter name to be applied + * @param array|string|null $index Index for item to be fetched from $_SERVER + * @param int|null $filter A filter name to be applied * * @return mixed */ diff --git a/system/HTTP/RequestTrait.php b/system/HTTP/RequestTrait.php index 5dc0359b..2392ecbc 100644 --- a/system/HTTP/RequestTrait.php +++ b/system/HTTP/RequestTrait.php @@ -192,7 +192,7 @@ private function getClientIP(string $header): ?string * * @param array|string|null $index Index for item to be fetched from $_SERVER * @param int|null $filter A filter name to be applied - * @param null $flags + * @param array|int|null $flags * * @return mixed */ @@ -204,9 +204,9 @@ public function getServer($index = null, $filter = null, $flags = null) /** * Fetch an item from the $_ENV array. * - * @param null $index Index for item to be fetched from $_ENV - * @param null $filter A filter name to be applied - * @param null $flags + * @param array|string|null $index Index for item to be fetched from $_ENV + * @param int|null $filter A filter name to be applied + * @param array|int|null $flags * * @return mixed */ diff --git a/system/HTTP/ResponseTrait.php b/system/HTTP/ResponseTrait.php index 0ad3239e..dd490e90 100644 --- a/system/HTTP/ResponseTrait.php +++ b/system/HTTP/ResponseTrait.php @@ -345,8 +345,8 @@ protected function formatBody($body, string $format) */ public function noCache() { - $this->removeHeader('Cache-control'); - $this->setHeader('Cache-control', ['no-store', 'max-age=0', 'no-cache']); + $this->removeHeader('Cache-Control'); + $this->setHeader('Cache-Control', ['no-store', 'max-age=0', 'no-cache']); return $this; } @@ -399,7 +399,7 @@ public function setCache(array $options = []) unset($options['last-modified']); } - $this->setHeader('Cache-control', $options); + $this->setHeader('Cache-Control', $options); return $this; } diff --git a/system/Helpers/text_helper.php b/system/Helpers/text_helper.php index 51b2c7db..7b52fa34 100755 --- a/system/Helpers/text_helper.php +++ b/system/Helpers/text_helper.php @@ -543,7 +543,6 @@ function random_string(string $type = 'alnum', int $len = 8): string { switch ($type) { case 'alnum': - case 'numeric': case 'nozero': case 'alpha': switch ($type) { @@ -555,16 +554,18 @@ function random_string(string $type = 'alnum', int $len = 8): string $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; break; - case 'numeric': - $pool = '0123456789'; - break; - case 'nozero': $pool = '123456789'; break; } - return substr(str_shuffle(str_repeat($pool, (int) ceil($len / strlen($pool)))), 0, $len); + return _from_random($len, $pool); + + case 'numeric': + $max = 10 ** $len - 1; + $rand = random_int(0, $max); + + return sprintf('%0' . $len . 'd', $rand); case 'md5': return md5(uniqid((string) mt_rand(), true)); @@ -586,6 +587,69 @@ function random_string(string $type = 'alnum', int $len = 8): string } } +if (! function_exists('_from_random')) { + /** + * The following function was derived from code of Symfony (v6.2.7 - 2023-02-28) + * https://github.com/symfony/symfony/blob/80cac46a31d4561804c17d101591a4f59e6db3a2/src/Symfony/Component/String/ByteString.php#L45 + * Code subject to the MIT license (https://github.com/symfony/symfony/blob/v6.2.7/LICENSE). + * Copyright (c) 2004-present Fabien Potencier + * + * The following method was derived from code of the Hack Standard Library (v4.40 - 2020-05-03) + * https://github.com/hhvm/hsl/blob/80a42c02f036f72a42f0415e80d6b847f4bf62d5/src/random/private.php#L16 + * Code subject to the MIT license (https://github.com/hhvm/hsl/blob/master/LICENSE). + * Copyright (c) 2004-2020, Facebook, Inc. (https://www.facebook.com/) + * + * @internal Outside the framework this should not be used directly. + */ + function _from_random(int $length, string $pool): string + { + if ($length <= 0) { + throw new InvalidArgumentException( + sprintf('A strictly positive length is expected, "%d" given.', $length) + ); + } + + $poolSize = \strlen($pool); + $bits = (int) ceil(log($poolSize, 2.0)); + if ($bits <= 0 || $bits > 56) { + throw new InvalidArgumentException( + 'The length of the alphabet must in the [2^1, 2^56] range.' + ); + } + + $string = ''; + + while ($length > 0) { + $urandomLength = (int) ceil(2 * $length * $bits / 8.0); + $data = random_bytes($urandomLength); + $unpackedData = 0; + $unpackedBits = 0; + + for ($i = 0; $i < $urandomLength && $length > 0; $i++) { + // Unpack 8 bits + $unpackedData = ($unpackedData << 8) | \ord($data[$i]); + $unpackedBits += 8; + + // While we have enough bits to select a character from the alphabet, keep + // consuming the random data + for (; $unpackedBits >= $bits && $length > 0; $unpackedBits -= $bits) { + $index = ($unpackedData & ((1 << $bits) - 1)); + $unpackedData >>= $bits; + // Unfortunately, the alphabet size is not necessarily a power of two. + // Worst case, it is 2^k + 1, which means we need (k+1) bits and we + // have around a 50% chance of missing as k gets larger + if ($index < $poolSize) { + $string .= $pool[$index]; + $length--; + } + } + } + } + + return $string; + } +} + if (! function_exists('increment_string')) { /** * Add's _1 to a string or increment the ending number to allow _2, _3, etc diff --git a/system/Helpers/url_helper.php b/system/Helpers/url_helper.php index 1a064a76..8443c7a0 100644 --- a/system/Helpers/url_helper.php +++ b/system/Helpers/url_helper.php @@ -117,13 +117,20 @@ function site_url($relativePath = '', ?string $scheme = null, ?App $config = nul { $uri = _get_uri($relativePath, $config); - return URI::createURIString( + $uriString = URI::createURIString( $scheme ?? $uri->getScheme(), $uri->getAuthority(), $uri->getPath(), $uri->getQuery(), $uri->getFragment() ); + + // For protocol-relative links + if ($scheme === '') { + $uriString = '//' . $uriString; + } + + return $uriString; } } diff --git a/system/ThirdParty/Kint/Zval/Representation/SplFileInfoRepresentation.php b/system/ThirdParty/Kint/Zval/Representation/SplFileInfoRepresentation.php index 44980d7e..6424ee6a 100644 --- a/system/ThirdParty/Kint/Zval/Representation/SplFileInfoRepresentation.php +++ b/system/ThirdParty/Kint/Zval/Representation/SplFileInfoRepresentation.php @@ -57,7 +57,7 @@ public function __construct(SplFileInfo $fileInfo) $this->path = $fileInfo->getPathname(); try { - if ($fileInfo->getRealPath()) { + if (\strlen($this->path) && $fileInfo->getRealPath()) { $this->perms = $fileInfo->getPerms(); $this->size = $fileInfo->getSize(); $this->owner = $fileInfo->getOwner(); diff --git a/system/ThirdParty/Kint/resources/compiled/solarized-dark.css b/system/ThirdParty/Kint/resources/compiled/solarized-dark.css index 1d3c28b0..4ab5e287 100644 --- a/system/ThirdParty/Kint/resources/compiled/solarized-dark.css +++ b/system/ThirdParty/Kint/resources/compiled/solarized-dark.css @@ -1 +1 @@ -.kint-rich{font-size:13px;overflow-x:auto;white-space:nowrap;background:#073642}.kint-rich.kint-folder{position:fixed;bottom:0;left:0;right:0;z-index:999999;width:100%;margin:0;display:block}.kint-rich.kint-folder dd.kint-foldout{max-height:calc(100vh - 100px);padding-right:10px;overflow-y:scroll;display:none}.kint-rich.kint-folder dd.kint-foldout.kint-show{display:block}.kint-rich::selection,.kint-rich::-moz-selection,.kint-rich::-webkit-selection{background:#268bd2;color:#839496}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #2aa198}.kint-rich,.kint-rich::before,.kint-rich::after,.kint-rich *,.kint-rich *::before,.kint-rich *::after{box-sizing:border-box;border-radius:0;color:#839496;float:none !important;font-family:Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;line-height:15px;margin:0;padding:0;text-align:left}.kint-rich{margin:10px 0}.kint-rich dt,.kint-rich dl{width:auto}.kint-rich dt,.kint-rich div.access-path{background:#002b36;border:1px solid #586e75;color:#839496;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:5px}.kint-rich dt:hover,.kint-rich div.access-path:hover{border-color:#268bd2}.kint-rich>dl dl{padding:0 0 0 15px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMzAgMTUwIj48ZGVmcz48cGF0aCBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNNCAzYTI0IDMyIDAgMCAxIDAgMjQgNDAgMjAtMTAgMCAxIDIzLTEyQTQwIDIwIDEwIDAgMSA0IDN6IiBpZD0iYSIvPjwvZGVmcz48ZyBmaWxsPSIjOTNhMWExIiBzdHJva2U9IiM5M2ExYTEiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxnIGZpbGw9IiM1ODZlNzUiIHN0cm9rZT0iIzU4NmU3NSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAzMCkiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxwYXRoIGQ9Ik02IDEyNmwxOCAxOG0tMTggMGwxOC0xOCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2U9IiM1ODZlNzUiLz48L3N2Zz4=") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #586e75}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#268bd2;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:#2aa198}.kint-rich dfn{font-style:normal;font-family:monospace;color:#93a1a1}.kint-rich pre{color:#839496;margin:0 0 0 15px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #586e75;background:#002b36;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(131,148,150,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#002b36;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#839496;background:#002b36}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #586e75;border-top-width:0;border-bottom-width:0;padding:5px;float:right !important;margin:-5px 0;color:#93a1a1;background:#073642;height:26px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#252525;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#1b1b1b}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#073642;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#839496}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#839496;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#93a1a1;border-bottom:1px dotted #93a1a1}.kint-rich ul{list-style:none;padding-left:15px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #586e75}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 15px;padding-left:0;background:#002b36;border:1px solid #586e75;border-top:0}.kint-rich ul.kint-tabs>li{background:#073642;border:1px solid #586e75;cursor:pointer;display:inline-block;height:30px;margin:3px;padding:0 15px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#268bd2;color:#2aa198}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#002b36;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:25px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul.kint-tab-contents>li{display:none}.kint-rich ul.kint-tab-contents>li.kint-show{display:block}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#268bd2;color:#2aa198}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #586e75;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2"><path fill="%23FFF" d="M0 0h1v2h1V1H0z"/></svg>');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#268bd2}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2.5px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #586e75;padding:2.5px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#073642;color:#93a1a1}.kint-rich table td{background:#002b36;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #268bd2 inset}.kint-rich table tr:hover var{color:#2aa198}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:5px;padding-bottom:5px;border-bottom:1px solid #073642}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #268bd2;padding-right:10px;margin-right:10px}.kint-rich pre.kint-source>div.kint-highlight{background:#073642}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #268bd2,0 1px #268bd2,1px 0 #268bd2,0 -1px #268bd2;color:#002b36;font-weight:bold}input.kint-note-input{width:100%}body{background:#073642;color:#fff}.kint-rich{box-shadow:0 0 5px 3px #073642}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #859900 inset;border-radius:7px}.kint-rich>dl>dt,.kint-rich ul.kint-tabs{box-shadow:4px 0 2px -3px #268bd2 inset}.kint-rich ul.kint-tabs li.kint-active-tab{padding-top:7px;height:34px}.kint-rich footer li{color:#ddd} +.kint-rich{font-size:13px;overflow-x:auto;white-space:nowrap;background:#073642}.kint-rich.kint-folder{position:fixed;bottom:0;left:0;right:0;z-index:999999;width:100%;margin:0;display:block}.kint-rich.kint-folder dd.kint-foldout{max-height:calc(100vh - 100px);padding-right:10px;overflow-y:scroll;display:none}.kint-rich.kint-folder dd.kint-foldout.kint-show{display:block}.kint-rich::selection,.kint-rich::-moz-selection,.kint-rich::-webkit-selection{background:#268bd2;color:#839496}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #2aa198}.kint-rich,.kint-rich::before,.kint-rich::after,.kint-rich *,.kint-rich *::before,.kint-rich *::after{box-sizing:border-box;border-radius:0;color:#839496;float:none !important;font-family:Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;line-height:15px;margin:0;padding:0;text-align:left}.kint-rich{margin:10px 0}.kint-rich dt,.kint-rich dl{width:auto}.kint-rich dt,.kint-rich div.access-path{background:#002b36;border:1px solid #586e75;color:#839496;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:5px}.kint-rich dt:hover,.kint-rich div.access-path:hover{border-color:#268bd2}.kint-rich>dl dl{padding:0 0 0 15px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMzAgMTUwIj48ZGVmcz48cGF0aCBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNNCAzYTI0IDMyIDAgMCAxIDAgMjQgNDAgMjAtMTAgMCAxIDIzLTEyQTQwIDIwIDEwIDAgMSA0IDN6IiBpZD0iYSIvPjwvZGVmcz48ZyBmaWxsPSIjOTNhMWExIiBzdHJva2U9IiM5M2ExYTEiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxnIGZpbGw9IiM1ODZlNzUiIHN0cm9rZT0iIzU4NmU3NSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAzMCkiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxwYXRoIGQ9Ik02IDEyNmwxOCAxOG0tMTggMGwxOC0xOCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2U9IiM1ODZlNzUiLz48L3N2Zz4=") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #586e75}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#268bd2;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:#2aa198}.kint-rich dfn{font-style:normal;font-family:monospace;color:#93a1a1}.kint-rich pre{color:#839496;margin:0 0 0 15px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #586e75;background:#002b36;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(131,148,150,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#002b36;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#839496;background:#002b36}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #586e75;border-top-width:0;border-bottom-width:0;padding:5px;float:right !important;margin:-5px 0;color:#93a1a1;background:#073642;height:26px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#252525;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#1b1b1b}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#073642;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#839496}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#839496;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#93a1a1;border-bottom:1px dotted #93a1a1}.kint-rich ul{list-style:none;padding-left:15px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #586e75}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 15px;padding-left:0;background:#002b36;border:1px solid #586e75;border-top:0}.kint-rich ul.kint-tabs>li{background:#073642;border:1px solid #586e75;cursor:pointer;display:inline-block;height:30px;margin:3px;padding:0 15px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#268bd2;color:#2aa198}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#002b36;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:25px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul.kint-tab-contents>li{display:none}.kint-rich ul.kint-tab-contents>li.kint-show{display:block}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#268bd2;color:#2aa198}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #586e75;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2"><path fill="%23FFF" d="M0 0h1v2h1V1H0z"/></svg>');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#268bd2}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2.5px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #586e75;padding:2.5px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#073642;color:#93a1a1}.kint-rich table td{background:#002b36;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #268bd2 inset}.kint-rich table tr:hover var{color:#2aa198}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:5px;padding-bottom:5px;border-bottom:1px solid #073642}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #268bd2;padding-right:10px;margin-right:10px}.kint-rich pre.kint-source>div.kint-highlight{background:#073642}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #268bd2,0 1px #268bd2,1px 0 #268bd2,0 -1px #268bd2;color:#002b36;font-weight:bold}input.kint-note-input{width:100%}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #859900 inset;border-radius:7px}.kint-rich>dl>dt,.kint-rich ul.kint-tabs{box-shadow:4px 0 2px -3px #268bd2 inset}.kint-rich ul.kint-tabs li.kint-active-tab{padding-top:7px;height:34px}.kint-rich footer li{color:#ddd}