diff --git a/composer.json b/composer.json
index 87e47f8..79148ec 100644
--- a/composer.json
+++ b/composer.json
@@ -3,7 +3,7 @@
"vendor-dir": "system/vendor/",
"optimize-autoloader": true,
"platform": {
- "php": "5.3"
+ "php": "8.1"
}
},
"require": {
@@ -11,7 +11,9 @@
"michelf/php-markdown": "1.*",
"suin/php-rss-writer": "1.*",
"kanti/hub-updater": "0.*",
- "jbroadway/urlify": "^1.0"
+ "jbroadway/urlify": "^1.0",
+ "pragmarx/google2fa": "^8.0",
+ "bacon/bacon-qr-code": "^3.0"
},
"autoload": {
"files": [
diff --git a/composer.lock b/composer.lock
index b55d54d..20e88e9 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,188 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "250bd035a1d26dd3e3e01e504833c798",
+ "content-hash": "efadd4c9da9b1a72ba66914255b2b943",
"packages": [
+ {
+ "name": "bacon/bacon-qr-code",
+ "version": "v3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Bacon/BaconQrCode.git",
+ "reference": "510de6eca6248d77d31b339d62437cc995e2fb41"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/510de6eca6248d77d31b339d62437cc995e2fb41",
+ "reference": "510de6eca6248d77d31b339d62437cc995e2fb41",
+ "shasum": ""
+ },
+ "require": {
+ "dasprid/enum": "^1.0.3",
+ "ext-iconv": "*",
+ "php": "^8.1"
+ },
+ "require-dev": {
+ "phly/keep-a-changelog": "^2.12",
+ "phpunit/phpunit": "^10.5.11 || 11.0.4",
+ "spatie/phpunit-snapshot-assertions": "^5.1.5",
+ "squizlabs/php_codesniffer": "^3.9"
+ },
+ "suggest": {
+ "ext-imagick": "to generate QR code images"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "BaconQrCode\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-2-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Ben Scholzen 'DASPRiD'",
+ "email": "mail@dasprids.de",
+ "homepage": "https://dasprids.de/",
+ "role": "Developer"
+ }
+ ],
+ "description": "BaconQrCode is a QR code generator for PHP.",
+ "homepage": "https://github.com/Bacon/BaconQrCode",
+ "support": {
+ "issues": "https://github.com/Bacon/BaconQrCode/issues",
+ "source": "https://github.com/Bacon/BaconQrCode/tree/v3.0.0"
+ },
+ "time": "2024-04-18T11:16:25+00:00"
+ },
+ {
+ "name": "composer/ca-bundle",
+ "version": "1.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/ca-bundle.git",
+ "reference": "0c5ccfcfea312b5c5a190a21ac5cef93f74baf99"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/ca-bundle/zipball/0c5ccfcfea312b5c5a190a21ac5cef93f74baf99",
+ "reference": "0c5ccfcfea312b5c5a190a21ac5cef93f74baf99",
+ "shasum": ""
+ },
+ "require": {
+ "ext-openssl": "*",
+ "ext-pcre": "*",
+ "php": "^7.2 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.10",
+ "psr/log": "^1.0",
+ "symfony/phpunit-bridge": "^4.2 || ^5",
+ "symfony/process": "^4.0 || ^5.0 || ^6.0 || ^7.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\CaBundle\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
+ "keywords": [
+ "cabundle",
+ "cacert",
+ "certificate",
+ "ssl",
+ "tls"
+ ],
+ "support": {
+ "irc": "irc://irc.freenode.org/composer",
+ "issues": "https://github.com/composer/ca-bundle/issues",
+ "source": "https://github.com/composer/ca-bundle/tree/1.5.0"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-03-15T14:00:32+00:00"
+ },
+ {
+ "name": "dasprid/enum",
+ "version": "1.0.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/DASPRiD/Enum.git",
+ "reference": "6faf451159fb8ba4126b925ed2d78acfce0dc016"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/6faf451159fb8ba4126b925ed2d78acfce0dc016",
+ "reference": "6faf451159fb8ba4126b925ed2d78acfce0dc016",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1 <9.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7 | ^8 | ^9",
+ "squizlabs/php_codesniffer": "*"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "DASPRiD\\Enum\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-2-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Ben Scholzen 'DASPRiD'",
+ "email": "mail@dasprids.de",
+ "homepage": "https://dasprids.de/",
+ "role": "Developer"
+ }
+ ],
+ "description": "PHP 7.1 enum implementation",
+ "keywords": [
+ "enum",
+ "map"
+ ],
+ "support": {
+ "issues": "https://github.com/DASPRiD/Enum/issues",
+ "source": "https://github.com/DASPRiD/Enum/tree/1.0.5"
+ },
+ "time": "2023-08-25T16:18:39+00:00"
+ },
{
"name": "ircmaxell/password-compat",
"version": "v1.0.4",
@@ -46,27 +226,33 @@
"hashing",
"password"
],
+ "support": {
+ "issues": "https://github.com/ircmaxell/password_compat/issues",
+ "source": "https://github.com/ircmaxell/password_compat/tree/v1.0"
+ },
"time": "2014-11-20T16:49:30+00:00"
},
{
"name": "jbroadway/urlify",
- "version": "1.1.3-stable",
+ "version": "1.2.4-stable",
"source": {
"type": "git",
"url": "https://github.com/jbroadway/urlify.git",
- "reference": "37fe4e7680a1c8cd68ac43a27dac7ef4be476300"
+ "reference": "d0fafbaa1dc14e8039cdf5c72a932a8d1de1750e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/jbroadway/urlify/zipball/37fe4e7680a1c8cd68ac43a27dac7ef4be476300",
- "reference": "37fe4e7680a1c8cd68ac43a27dac7ef4be476300",
+ "url": "https://api.github.com/repos/jbroadway/urlify/zipball/d0fafbaa1dc14e8039cdf5c72a932a8d1de1750e",
+ "reference": "d0fafbaa1dc14e8039cdf5c72a932a8d1de1750e",
"shasum": ""
},
"require": {
- "php": ">=5.3.0"
+ "php": ">=7.2",
+ "voku/portable-ascii": "^2.0",
+ "voku/stop-words": "^2.0"
},
"require-dev": {
- "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5"
+ "phpunit/phpunit": "^8.5"
},
"type": "library",
"extra": {
@@ -90,43 +276,58 @@
"homepage": "http://www.johnnybroadway.com/"
}
],
- "description": "PHP port of URLify.js from the Django project. Transliterates non-ascii characters for use in URLs.",
+ "description": "A fast PHP slug generator and transliteration library that converts non-ascii characters for use in URLs.",
"homepage": "https://github.com/jbroadway/urlify",
"keywords": [
+ "ascii",
+ "blogging",
+ "blogs",
+ "downcode",
"encode",
"iconv",
"link",
+ "seo",
"slug",
+ "slugify",
+ "slugs",
"translit",
"transliterate",
"transliteration",
+ "unicode",
"url",
"urlify"
],
- "time": "2019-06-13T18:30:56+00:00"
+ "support": {
+ "issues": "https://github.com/jbroadway/urlify/issues",
+ "source": "https://github.com/jbroadway/urlify/tree/1.2.4-stable"
+ },
+ "time": "2022-06-15T16:46:46+00:00"
},
{
"name": "kanti/hub-updater",
- "version": "v0.4.1",
+ "version": "v0.5.1",
"source": {
"type": "git",
"url": "https://github.com/Kanti/hub-updater.git",
- "reference": "c9cdc7ce407c2a3596961e2193673303789e084d"
+ "reference": "014b33c1e3880bd8e037a960a89e7116eb08a26e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Kanti/hub-updater/zipball/c9cdc7ce407c2a3596961e2193673303789e084d",
- "reference": "c9cdc7ce407c2a3596961e2193673303789e084d",
+ "url": "https://api.github.com/repos/Kanti/hub-updater/zipball/014b33c1e3880bd8e037a960a89e7116eb08a26e",
+ "reference": "014b33c1e3880bd8e037a960a89e7116eb08a26e",
"shasum": ""
},
"require": {
- "php": ">=5.3.0"
+ "composer/ca-bundle": "^1.0",
+ "php": ">=5.3.6"
},
"require-dev": {
- "codeclimate/php-test-reporter": "dev-master",
+ "codeclimate/php-test-reporter": "0.*",
+ "friendsofphp/php-cs-fixer": "1.*",
+ "phpro/grumphp": "0.*",
"phpunit/phpunit": "4.*",
- "sebastian/phpcpd": "*",
- "squizlabs/php_codesniffer": "*"
+ "sebastian/phpcpd": "2.*",
+ "squizlabs/php_codesniffer": "2.*"
},
"type": "library",
"autoload": {
@@ -147,21 +348,26 @@
}
],
"description": "Simple Github Updater for Web Projects",
+ "support": {
+ "forum": "https://github.com/Kanti/hub-updater/issues",
+ "issues": "https://github.com/Kanti/hub-updater/issues",
+ "source": "https://github.com/Kanti/hub-updater"
+ },
"abandoned": true,
- "time": "2015-11-28T18:52:10+00:00"
+ "time": "2016-08-02T19:12:55+00:00"
},
{
"name": "michelf/php-markdown",
- "version": "1.9.0",
+ "version": "1.9.1",
"source": {
"type": "git",
"url": "https://github.com/michelf/php-markdown.git",
- "reference": "c83178d49e372ca967d1a8c77ae4e051b3a3c75c"
+ "reference": "5024d623c1a057dcd2d076d25b7d270a1d0d55f3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/michelf/php-markdown/zipball/c83178d49e372ca967d1a8c77ae4e051b3a3c75c",
- "reference": "c83178d49e372ca967d1a8c77ae4e051b3a3c75c",
+ "url": "https://api.github.com/repos/michelf/php-markdown/zipball/5024d623c1a057dcd2d076d25b7d270a1d0d55f3",
+ "reference": "5024d623c1a057dcd2d076d25b7d270a1d0d55f3",
"shasum": ""
},
"require": {
@@ -197,24 +403,152 @@
"keywords": [
"markdown"
],
- "time": "2019-12-02T02:32:27+00:00"
+ "support": {
+ "issues": "https://github.com/michelf/php-markdown/issues",
+ "source": "https://github.com/michelf/php-markdown/tree/1.9.1"
+ },
+ "time": "2021-11-24T02:52:38+00:00"
},
{
- "name": "suin/php-rss-writer",
- "version": "1.3.2",
+ "name": "paragonie/constant_time_encoding",
+ "version": "v2.7.0",
"source": {
"type": "git",
- "url": "https://github.com/suin/php-rss-writer.git",
- "reference": "51840d2fad4087a4bdd93fb6937aa4b324b5c94f"
+ "url": "https://github.com/paragonie/constant_time_encoding.git",
+ "reference": "52a0d99e69f56b9ec27ace92ba56897fe6993105"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/suin/php-rss-writer/zipball/51840d2fad4087a4bdd93fb6937aa4b324b5c94f",
- "reference": "51840d2fad4087a4bdd93fb6937aa4b324b5c94f",
+ "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/52a0d99e69f56b9ec27ace92ba56897fe6993105",
+ "reference": "52a0d99e69f56b9ec27ace92ba56897fe6993105",
"shasum": ""
},
"require": {
- "php": ">=5.3.0"
+ "php": "^7|^8"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^6|^7|^8|^9",
+ "vimeo/psalm": "^1|^2|^3|^4"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "ParagonIE\\ConstantTime\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Paragon Initiative Enterprises",
+ "email": "security@paragonie.com",
+ "homepage": "https://paragonie.com",
+ "role": "Maintainer"
+ },
+ {
+ "name": "Steve 'Sc00bz' Thomas",
+ "email": "steve@tobtu.com",
+ "homepage": "https://www.tobtu.com",
+ "role": "Original Developer"
+ }
+ ],
+ "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
+ "keywords": [
+ "base16",
+ "base32",
+ "base32_decode",
+ "base32_encode",
+ "base64",
+ "base64_decode",
+ "base64_encode",
+ "bin2hex",
+ "encoding",
+ "hex",
+ "hex2bin",
+ "rfc4648"
+ ],
+ "support": {
+ "email": "info@paragonie.com",
+ "issues": "https://github.com/paragonie/constant_time_encoding/issues",
+ "source": "https://github.com/paragonie/constant_time_encoding"
+ },
+ "time": "2024-05-08T12:18:48+00:00"
+ },
+ {
+ "name": "pragmarx/google2fa",
+ "version": "v8.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/antonioribeiro/google2fa.git",
+ "reference": "80c3d801b31fe165f8fe99ea085e0a37834e1be3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/antonioribeiro/google2fa/zipball/80c3d801b31fe165f8fe99ea085e0a37834e1be3",
+ "reference": "80c3d801b31fe165f8fe99ea085e0a37834e1be3",
+ "shasum": ""
+ },
+ "require": {
+ "paragonie/constant_time_encoding": "^1.0|^2.0",
+ "php": "^7.1|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^0.12.18",
+ "phpunit/phpunit": "^7.5.15|^8.5|^9.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "PragmaRX\\Google2FA\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Antonio Carlos Ribeiro",
+ "email": "acr@antoniocarlosribeiro.com",
+ "role": "Creator & Designer"
+ }
+ ],
+ "description": "A One Time Password Authentication package, compatible with Google Authenticator.",
+ "keywords": [
+ "2fa",
+ "Authentication",
+ "Two Factor Authentication",
+ "google2fa"
+ ],
+ "support": {
+ "issues": "https://github.com/antonioribeiro/google2fa/issues",
+ "source": "https://github.com/antonioribeiro/google2fa/tree/v8.0.1"
+ },
+ "time": "2022-06-13T21:57:56+00:00"
+ },
+ {
+ "name": "suin/php-rss-writer",
+ "version": "1.6.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/suin/php-rss-writer.git",
+ "reference": "78f45e44a2a7cb0d82e4b9efb6f7b7a075b9051c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/suin/php-rss-writer/zipball/78f45e44a2a7cb0d82e4b9efb6f7b7a075b9051c",
+ "reference": "78f45e44a2a7cb0d82e4b9efb6f7b7a075b9051c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "eher/phpunit": ">=1.6",
+ "mockery/mockery": ">=0.7.2",
+ "suin/xoopsunit": ">=1.2"
},
"type": "library",
"autoload": {
@@ -228,11 +562,11 @@
],
"authors": [
{
- "name": "Hidehito Nozawa aka Suin",
+ "name": "suin",
"email": "suinyeze@gmail.com"
}
],
- "description": "Yet another simple RSS writer library for PHP 5.3 or later.",
+ "description": "Yet another simple RSS writer library for PHP 5.4 or later.",
"homepage": "https://github.com/suin/php-rss-writer",
"keywords": [
"feed",
@@ -241,7 +575,132 @@
"rss",
"writer"
],
- "time": "2016-03-01T12:09:17+00:00"
+ "support": {
+ "issues": "https://github.com/suin/php-rss-writer/issues",
+ "source": "https://github.com/suin/php-rss-writer/tree/master"
+ },
+ "time": "2017-07-13T10:47:50+00:00"
+ },
+ {
+ "name": "voku/portable-ascii",
+ "version": "2.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/voku/portable-ascii.git",
+ "reference": "b56450eed252f6801410d810c8e1727224ae0743"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b56450eed252f6801410d810c8e1727224ae0743",
+ "reference": "b56450eed252f6801410d810c8e1727224ae0743",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.0.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0"
+ },
+ "suggest": {
+ "ext-intl": "Use Intl for transliterator_transliterate() support"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "voku\\": "src/voku/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Lars Moelleken",
+ "homepage": "http://www.moelleken.org/"
+ }
+ ],
+ "description": "Portable ASCII library - performance optimized (ascii) string functions for php.",
+ "homepage": "https://github.com/voku/portable-ascii",
+ "keywords": [
+ "ascii",
+ "clean",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/voku/portable-ascii/issues",
+ "source": "https://github.com/voku/portable-ascii/tree/2.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://www.paypal.me/moelleken",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/voku",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/portable-ascii",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://www.patreon.com/voku",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-03-08T17:03:00+00:00"
+ },
+ {
+ "name": "voku/stop-words",
+ "version": "2.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/voku/stop-words.git",
+ "reference": "8e63c0af20f800b1600783764e0ce19e53969f71"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/voku/stop-words/zipball/8e63c0af20f800b1600783764e0ce19e53969f71",
+ "reference": "8e63c0af20f800b1600783764e0ce19e53969f71",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.0.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~6.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "voku\\": "src/voku/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Lars Moelleken",
+ "homepage": "http://www.moelleken.org/"
+ }
+ ],
+ "description": "Stop-Words via PHP",
+ "keywords": [
+ "stop words",
+ "stop-words"
+ ],
+ "support": {
+ "issues": "https://github.com/voku/stop-words/issues",
+ "source": "https://github.com/voku/stop-words/tree/master"
+ },
+ "time": "2018-11-23T01:37:27+00:00"
}
],
"packages-dev": [],
@@ -253,7 +712,7 @@
"platform": [],
"platform-dev": [],
"platform-overrides": {
- "php": "5.3"
+ "php": "8.1"
},
- "plugin-api-version": "1.1.0"
+ "plugin-api-version": "2.6.0"
}
diff --git a/system/vendor/autoload.php b/system/vendor/autoload.php
index 637e8f6..b81c1a6 100644
--- a/system/vendor/autoload.php
+++ b/system/vendor/autoload.php
@@ -2,6 +2,24 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ if (!headers_sent()) {
+ header('HTTP/1.1 500 Internal Server Error');
+ }
+ $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ if (!ini_get('display_errors')) {
+ if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
+ fwrite(STDERR, $err);
+ } elseif (!headers_sent()) {
+ echo $err;
+ }
+ }
+ trigger_error(
+ $err,
+ E_USER_ERROR
+ );
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitd88c6c25320034df85dd42f1462fbda7::getLoader();
diff --git a/system/vendor/bacon/bacon-qr-code/LICENSE b/system/vendor/bacon/bacon-qr-code/LICENSE
new file mode 100644
index 0000000..d45a356
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2017, Ben Scholzen 'DASPRiD'
+All rights reserved.
+
+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.
+
+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 OWNER 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.
diff --git a/system/vendor/bacon/bacon-qr-code/README.md b/system/vendor/bacon/bacon-qr-code/README.md
new file mode 100644
index 0000000..e429889
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/README.md
@@ -0,0 +1,57 @@
+# QR Code generator
+
+[](https://github.com/Bacon/BaconQrCode/actions/workflows/ci.yml)
+[](https://codecov.io/gh/Bacon/BaconQrCode)
+[](https://packagist.org/packages/bacon/bacon-qr-code)
+[](https://packagist.org/packages/bacon/bacon-qr-code)
+[](https://packagist.org/packages/bacon/bacon-qr-code)
+
+
+## Introduction
+BaconQrCode is a port of QR code portion of the ZXing library. It currently
+only features the encoder part, but could later receive the decoder part as
+well.
+
+As the Reed Solomon codec implementation of the ZXing library performs quite
+slow in PHP, it was exchanged with the implementation by Phil Karn.
+
+
+## Example usage
+```php
+use BaconQrCode\Renderer\ImageRenderer;
+use BaconQrCode\Renderer\Image\ImagickImageBackEnd;
+use BaconQrCode\Renderer\RendererStyle\RendererStyle;
+use BaconQrCode\Writer;
+
+$renderer = new ImageRenderer(
+ new RendererStyle(400),
+ new ImagickImageBackEnd()
+);
+$writer = new Writer($renderer);
+$writer->writeFile('Hello World!', 'qrcode.png');
+```
+
+## Available image renderer back ends
+BaconQrCode comes with multiple back ends for rendering images. Currently included are the following:
+
+- `ImagickImageBackEnd`: renders raster images using the Imagick library
+- `SvgImageBackEnd`: renders SVG files using XMLWriter
+- `EpsImageBackEnd`: renders EPS files
+
+### GDLib Renderer
+GD library has so many limitations, that GD support is not added as backend, but as separated renderer.
+Use `GDLibRenderer` instead of `ImageRenderer`. These are the limitations:
+
+- Does not support gradient.
+- Does not support any curves, so you QR code is always squared.
+
+Example usage:
+
+```php
+use BaconQrCode\Renderer\GDLibRenderer;
+use BaconQrCode\Writer;
+
+$renderer = new GDLibRenderer(400);
+$writer = new Writer($renderer);
+$writer->writeFile('Hello World!', 'qrcode.png');
+```
diff --git a/system/vendor/bacon/bacon-qr-code/composer.json b/system/vendor/bacon/bacon-qr-code/composer.json
new file mode 100644
index 0000000..41f4166
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/composer.json
@@ -0,0 +1,50 @@
+{
+ "name": "bacon/bacon-qr-code",
+ "description": "BaconQrCode is a QR code generator for PHP.",
+ "license": "BSD-2-Clause",
+ "homepage": "https://github.com/Bacon/BaconQrCode",
+ "require": {
+ "php": "^8.1",
+ "ext-iconv": "*",
+ "dasprid/enum": "^1.0.3"
+ },
+ "suggest": {
+ "ext-imagick": "to generate QR code images"
+ },
+ "authors": [
+ {
+ "name": "Ben Scholzen 'DASPRiD'",
+ "email": "mail@dasprids.de",
+ "homepage": "https://dasprids.de/",
+ "role": "Developer"
+ }
+ ],
+ "autoload": {
+ "psr-4": {
+ "BaconQrCode\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "BaconQrCodeTest\\": "test/"
+ }
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.5.11 || 11.0.4",
+ "spatie/phpunit-snapshot-assertions": "^5.1.5",
+ "squizlabs/php_codesniffer": "^3.9",
+ "phly/keep-a-changelog": "^2.12"
+ },
+ "config": {
+ "allow-plugins": {
+ "ocramius/package-versions": true,
+ "php-http/discovery": true
+ }
+ },
+ "archive": {
+ "exclude": [
+ "/test",
+ "/phpunit.xml.dist"
+ ]
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Common/BitArray.php b/system/vendor/bacon/bacon-qr-code/src/Common/BitArray.php
new file mode 100644
index 0000000..9ec8629
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Common/BitArray.php
@@ -0,0 +1,364 @@
+
+ */
+ private SplFixedArray $bits;
+
+ /**
+ * Creates a new bit array with a given size.
+ */
+ public function __construct(private int $size = 0)
+ {
+ $this->bits = SplFixedArray::fromArray(array_fill(0, ($this->size + 31) >> 3, 0));
+ }
+
+ /**
+ * Gets the size in bits.
+ */
+ public function getSize() : int
+ {
+ return $this->size;
+ }
+
+ /**
+ * Gets the size in bytes.
+ */
+ public function getSizeInBytes() : int
+ {
+ return ($this->size + 7) >> 3;
+ }
+
+ /**
+ * Ensures that the array has a minimum capacity.
+ */
+ public function ensureCapacity(int $size) : void
+ {
+ if ($size > count($this->bits) << 5) {
+ $this->bits->setSize(($size + 31) >> 5);
+ }
+ }
+
+ /**
+ * Gets a specific bit.
+ */
+ public function get(int $i) : bool
+ {
+ return 0 !== ($this->bits[$i >> 5] & (1 << ($i & 0x1f)));
+ }
+
+ /**
+ * Sets a specific bit.
+ */
+ public function set(int $i) : void
+ {
+ $this->bits[$i >> 5] = $this->bits[$i >> 5] | 1 << ($i & 0x1f);
+ }
+
+ /**
+ * Flips a specific bit.
+ */
+ public function flip(int $i) : void
+ {
+ $this->bits[$i >> 5] ^= 1 << ($i & 0x1f);
+ }
+
+ /**
+ * Gets the next set bit position from a given position.
+ */
+ public function getNextSet(int $from) : int
+ {
+ if ($from >= $this->size) {
+ return $this->size;
+ }
+
+ $bitsOffset = $from >> 5;
+ $currentBits = $this->bits[$bitsOffset];
+ $bitsLength = count($this->bits);
+ $currentBits &= ~((1 << ($from & 0x1f)) - 1);
+
+ while (0 === $currentBits) {
+ if (++$bitsOffset === $bitsLength) {
+ return $this->size;
+ }
+
+ $currentBits = $this->bits[$bitsOffset];
+ }
+
+ $result = ($bitsOffset << 5) + BitUtils::numberOfTrailingZeros($currentBits);
+ return min($result, $this->size);
+ }
+
+ /**
+ * Gets the next unset bit position from a given position.
+ */
+ public function getNextUnset(int $from) : int
+ {
+ if ($from >= $this->size) {
+ return $this->size;
+ }
+
+ $bitsOffset = $from >> 5;
+ $currentBits = ~$this->bits[$bitsOffset];
+ $bitsLength = count($this->bits);
+ $currentBits &= ~((1 << ($from & 0x1f)) - 1);
+
+ while (0 === $currentBits) {
+ if (++$bitsOffset === $bitsLength) {
+ return $this->size;
+ }
+
+ $currentBits = ~$this->bits[$bitsOffset];
+ }
+
+ $result = ($bitsOffset << 5) + BitUtils::numberOfTrailingZeros($currentBits);
+ return min($result, $this->size);
+ }
+
+ /**
+ * Sets a bulk of bits.
+ */
+ public function setBulk(int $i, int $newBits) : void
+ {
+ $this->bits[$i >> 5] = $newBits;
+ }
+
+ /**
+ * Sets a range of bits.
+ *
+ * @throws InvalidArgumentException if end is smaller than start
+ */
+ public function setRange(int $start, int $end) : void
+ {
+ if ($end < $start) {
+ throw new InvalidArgumentException('End must be greater or equal to start');
+ }
+
+ if ($end === $start) {
+ return;
+ }
+
+ --$end;
+
+ $firstInt = $start >> 5;
+ $lastInt = $end >> 5;
+
+ for ($i = $firstInt; $i <= $lastInt; ++$i) {
+ $firstBit = $i > $firstInt ? 0 : $start & 0x1f;
+ $lastBit = $i < $lastInt ? 31 : $end & 0x1f;
+
+ if (0 === $firstBit && 31 === $lastBit) {
+ $mask = 0x7fffffff;
+ } else {
+ $mask = 0;
+
+ for ($j = $firstBit; $j < $lastBit; ++$j) {
+ $mask |= 1 << $j;
+ }
+ }
+
+ $this->bits[$i] = $this->bits[$i] | $mask;
+ }
+ }
+
+ /**
+ * Clears the bit array, unsetting every bit.
+ */
+ public function clear() : void
+ {
+ $bitsLength = count($this->bits);
+
+ for ($i = 0; $i < $bitsLength; ++$i) {
+ $this->bits[$i] = 0;
+ }
+ }
+
+ /**
+ * Checks if a range of bits is set or not set.
+
+ * @throws InvalidArgumentException if end is smaller than start
+ */
+ public function isRange(int $start, int $end, bool $value) : bool
+ {
+ if ($end < $start) {
+ throw new InvalidArgumentException('End must be greater or equal to start');
+ }
+
+ if ($end === $start) {
+ return true;
+ }
+
+ --$end;
+
+ $firstInt = $start >> 5;
+ $lastInt = $end >> 5;
+
+ for ($i = $firstInt; $i <= $lastInt; ++$i) {
+ $firstBit = $i > $firstInt ? 0 : $start & 0x1f;
+ $lastBit = $i < $lastInt ? 31 : $end & 0x1f;
+
+ if (0 === $firstBit && 31 === $lastBit) {
+ $mask = 0x7fffffff;
+ } else {
+ $mask = 0;
+
+ for ($j = $firstBit; $j <= $lastBit; ++$j) {
+ $mask |= 1 << $j;
+ }
+ }
+
+ if (($this->bits[$i] & $mask) !== ($value ? $mask : 0)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Appends a bit to the array.
+ */
+ public function appendBit(bool $bit) : void
+ {
+ $this->ensureCapacity($this->size + 1);
+
+ if ($bit) {
+ $this->bits[$this->size >> 5] = $this->bits[$this->size >> 5] | (1 << ($this->size & 0x1f));
+ }
+
+ ++$this->size;
+ }
+
+ /**
+ * Appends a number of bits (up to 32) to the array.
+
+ * @throws InvalidArgumentException if num bits is not between 0 and 32
+ */
+ public function appendBits(int $value, int $numBits) : void
+ {
+ if ($numBits < 0 || $numBits > 32) {
+ throw new InvalidArgumentException('Num bits must be between 0 and 32');
+ }
+
+ $this->ensureCapacity($this->size + $numBits);
+
+ for ($numBitsLeft = $numBits; $numBitsLeft > 0; $numBitsLeft--) {
+ $this->appendBit((($value >> ($numBitsLeft - 1)) & 0x01) === 1);
+ }
+ }
+
+ /**
+ * Appends another bit array to this array.
+ */
+ public function appendBitArray(self $other) : void
+ {
+ $otherSize = $other->getSize();
+ $this->ensureCapacity($this->size + $other->getSize());
+
+ for ($i = 0; $i < $otherSize; ++$i) {
+ $this->appendBit($other->get($i));
+ }
+ }
+
+ /**
+ * Makes an exclusive-or comparision on the current bit array.
+ *
+ * @throws InvalidArgumentException if sizes don't match
+ */
+ public function xorBits(self $other) : void
+ {
+ $bitsLength = count($this->bits);
+ $otherBits = $other->getBitArray();
+
+ if ($bitsLength !== count($otherBits)) {
+ throw new InvalidArgumentException('Sizes don\'t match');
+ }
+
+ for ($i = 0; $i < $bitsLength; ++$i) {
+ $this->bits[$i] = $this->bits[$i] ^ $otherBits[$i];
+ }
+ }
+
+ /**
+ * Converts the bit array to a byte array.
+ *
+ * @return SplFixedArray
+ */
+ public function toBytes(int $bitOffset, int $numBytes) : SplFixedArray
+ {
+ $bytes = new SplFixedArray($numBytes);
+
+ for ($i = 0; $i < $numBytes; ++$i) {
+ $byte = 0;
+
+ for ($j = 0; $j < 8; ++$j) {
+ if ($this->get($bitOffset)) {
+ $byte |= 1 << (7 - $j);
+ }
+
+ ++$bitOffset;
+ }
+
+ $bytes[$i] = $byte;
+ }
+
+ return $bytes;
+ }
+
+ /**
+ * Gets the internal bit array.
+ *
+ * @return SplFixedArray
+ */
+ public function getBitArray() : SplFixedArray
+ {
+ return $this->bits;
+ }
+
+ /**
+ * Reverses the array.
+ */
+ public function reverse() : void
+ {
+ $newBits = new SplFixedArray(count($this->bits));
+
+ for ($i = 0; $i < $this->size; ++$i) {
+ if ($this->get($this->size - $i - 1)) {
+ $newBits[$i >> 5] = $newBits[$i >> 5] | (1 << ($i & 0x1f));
+ }
+ }
+
+ $this->bits = $newBits;
+ }
+
+ /**
+ * Returns a string representation of the bit array.
+ */
+ public function __toString() : string
+ {
+ $result = '';
+
+ for ($i = 0; $i < $this->size; ++$i) {
+ if (0 === ($i & 0x07)) {
+ $result .= ' ';
+ }
+
+ $result .= $this->get($i) ? 'X' : '.';
+ }
+
+ return $result;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Common/BitMatrix.php b/system/vendor/bacon/bacon-qr-code/src/Common/BitMatrix.php
new file mode 100644
index 0000000..294afb4
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Common/BitMatrix.php
@@ -0,0 +1,307 @@
+
+ */
+ private SplFixedArray $bits;
+
+ /**
+ * @throws InvalidArgumentException if a dimension is smaller than zero
+ */
+ public function __construct(int $width, ?int $height = null)
+ {
+ if (null === $height) {
+ $height = $width;
+ }
+
+ if ($width < 1 || $height < 1) {
+ throw new InvalidArgumentException('Both dimensions must be greater than zero');
+ }
+
+ $this->width = $width;
+ $this->height = $height;
+ $this->rowSize = ($width + 31) >> 5;
+ $this->bits = SplFixedArray::fromArray(array_fill(0, $this->rowSize * $height, 0));
+ }
+
+ /**
+ * Gets the requested bit, where true means black.
+ */
+ public function get(int $x, int $y) : bool
+ {
+ $offset = $y * $this->rowSize + ($x >> 5);
+ return 0 !== (BitUtils::unsignedRightShift($this->bits[$offset], ($x & 0x1f)) & 1);
+ }
+
+ /**
+ * Sets the given bit to true.
+ */
+ public function set(int $x, int $y) : void
+ {
+ $offset = $y * $this->rowSize + ($x >> 5);
+ $this->bits[$offset] = $this->bits[$offset] | (1 << ($x & 0x1f));
+ }
+
+ /**
+ * Flips the given bit.
+ */
+ public function flip(int $x, int $y) : void
+ {
+ $offset = $y * $this->rowSize + ($x >> 5);
+ $this->bits[$offset] = $this->bits[$offset] ^ (1 << ($x & 0x1f));
+ }
+
+ /**
+ * Clears all bits (set to false).
+ */
+ public function clear() : void
+ {
+ $max = count($this->bits);
+
+ for ($i = 0; $i < $max; ++$i) {
+ $this->bits[$i] = 0;
+ }
+ }
+
+ /**
+ * Sets a square region of the bit matrix to true.
+ *
+ * @throws InvalidArgumentException if left or top are negative
+ * @throws InvalidArgumentException if width or height are smaller than 1
+ * @throws InvalidArgumentException if region does not fit into the matix
+ */
+ public function setRegion(int $left, int $top, int $width, int $height) : void
+ {
+ if ($top < 0 || $left < 0) {
+ throw new InvalidArgumentException('Left and top must be non-negative');
+ }
+
+ if ($height < 1 || $width < 1) {
+ throw new InvalidArgumentException('Width and height must be at least 1');
+ }
+
+ $right = $left + $width;
+ $bottom = $top + $height;
+
+ if ($bottom > $this->height || $right > $this->width) {
+ throw new InvalidArgumentException('The region must fit inside the matrix');
+ }
+
+ for ($y = $top; $y < $bottom; ++$y) {
+ $offset = $y * $this->rowSize;
+
+ for ($x = $left; $x < $right; ++$x) {
+ $index = $offset + ($x >> 5);
+ $this->bits[$index] = $this->bits[$index] | (1 << ($x & 0x1f));
+ }
+ }
+ }
+
+ /**
+ * A fast method to retrieve one row of data from the matrix as a BitArray.
+ */
+ public function getRow(int $y, ?BitArray $row = null) : BitArray
+ {
+ if (null === $row || $row->getSize() < $this->width) {
+ $row = new BitArray($this->width);
+ }
+
+ $offset = $y * $this->rowSize;
+
+ for ($x = 0; $x < $this->rowSize; ++$x) {
+ $row->setBulk($x << 5, $this->bits[$offset + $x]);
+ }
+
+ return $row;
+ }
+
+ /**
+ * Sets a row of data from a BitArray.
+ */
+ public function setRow(int $y, BitArray $row) : void
+ {
+ $bits = $row->getBitArray();
+
+ for ($i = 0; $i < $this->rowSize; ++$i) {
+ $this->bits[$y * $this->rowSize + $i] = $bits[$i];
+ }
+ }
+
+ /**
+ * This is useful in detecting the enclosing rectangle of a 'pure' barcode.
+ *
+ * @return int[]|null
+ */
+ public function getEnclosingRectangle() : ?array
+ {
+ $left = $this->width;
+ $top = $this->height;
+ $right = -1;
+ $bottom = -1;
+
+ for ($y = 0; $y < $this->height; ++$y) {
+ for ($x32 = 0; $x32 < $this->rowSize; ++$x32) {
+ $bits = $this->bits[$y * $this->rowSize + $x32];
+
+ if (0 !== $bits) {
+ if ($y < $top) {
+ $top = $y;
+ }
+
+ if ($y > $bottom) {
+ $bottom = $y;
+ }
+
+ if ($x32 * 32 < $left) {
+ $bit = 0;
+
+ while (($bits << (31 - $bit)) === 0) {
+ $bit++;
+ }
+
+ if (($x32 * 32 + $bit) < $left) {
+ $left = $x32 * 32 + $bit;
+ }
+ }
+ }
+
+ if ($x32 * 32 + 31 > $right) {
+ $bit = 31;
+
+ while (0 === BitUtils::unsignedRightShift($bits, $bit)) {
+ --$bit;
+ }
+
+ if (($x32 * 32 + $bit) > $right) {
+ $right = $x32 * 32 + $bit;
+ }
+ }
+ }
+ }
+
+ $width = $right - $left;
+ $height = $bottom - $top;
+
+ if ($width < 0 || $height < 0) {
+ return null;
+ }
+
+ return [$left, $top, $width, $height];
+ }
+
+ /**
+ * Gets the most top left set bit.
+ *
+ * This is useful in detecting a corner of a 'pure' barcode.
+ *
+ * @return int[]|null
+ */
+ public function getTopLeftOnBit() : ?array
+ {
+ $bitsOffset = 0;
+
+ while ($bitsOffset < count($this->bits) && 0 === $this->bits[$bitsOffset]) {
+ ++$bitsOffset;
+ }
+
+ if (count($this->bits) === $bitsOffset) {
+ return null;
+ }
+
+ $x = intdiv($bitsOffset, $this->rowSize);
+ $y = ($bitsOffset % $this->rowSize) << 5;
+
+ $bits = $this->bits[$bitsOffset];
+ $bit = 0;
+
+ while (0 === ($bits << (31 - $bit))) {
+ ++$bit;
+ }
+
+ $x += $bit;
+
+ return [$x, $y];
+ }
+
+ /**
+ * Gets the most bottom right set bit.
+ *
+ * This is useful in detecting a corner of a 'pure' barcode.
+ *
+ * @return int[]|null
+ */
+ public function getBottomRightOnBit() : ?array
+ {
+ $bitsOffset = count($this->bits) - 1;
+
+ while ($bitsOffset >= 0 && 0 === $this->bits[$bitsOffset]) {
+ --$bitsOffset;
+ }
+
+ if ($bitsOffset < 0) {
+ return null;
+ }
+
+ $x = intdiv($bitsOffset, $this->rowSize);
+ $y = ($bitsOffset % $this->rowSize) << 5;
+
+ $bits = $this->bits[$bitsOffset];
+ $bit = 0;
+
+ while (0 === BitUtils::unsignedRightShift($bits, $bit)) {
+ --$bit;
+ }
+
+ $x += $bit;
+
+ return [$x, $y];
+ }
+
+ /**
+ * Gets the width of the matrix,
+ */
+ public function getWidth() : int
+ {
+ return $this->width;
+ }
+
+ /**
+ * Gets the height of the matrix.
+ */
+ public function getHeight() : int
+ {
+ return $this->height;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Common/BitUtils.php b/system/vendor/bacon/bacon-qr-code/src/Common/BitUtils.php
new file mode 100644
index 0000000..0c575b4
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Common/BitUtils.php
@@ -0,0 +1,41 @@
+>>" in other
+ * languages.
+ */
+ public static function unsignedRightShift(int $a, int $b) : int
+ {
+ return (
+ $a >= 0
+ ? $a >> $b
+ : (($a & 0x7fffffff) >> $b) | (0x40000000 >> ($b - 1))
+ );
+ }
+
+ /**
+ * Gets the number of trailing zeros.
+ */
+ public static function numberOfTrailingZeros(int $i) : int
+ {
+ $lastPos = strrpos(str_pad(decbin($i), 32, '0', STR_PAD_LEFT), '1');
+ return $lastPos === false ? 32 : 31 - $lastPos;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Common/CharacterSetEci.php b/system/vendor/bacon/bacon-qr-code/src/Common/CharacterSetEci.php
new file mode 100644
index 0000000..8b62b8c
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Common/CharacterSetEci.php
@@ -0,0 +1,177 @@
+|null
+ */
+ private static ?array $valueToEci;
+
+ /**
+ * @var array|null
+ */
+ private static ?array $nameToEci = null;
+
+ /**
+ * @param int[] $values
+ */
+ public function __construct(private readonly array $values, string ...$otherEncodingNames)
+ {
+ $this->otherEncodingNames = $otherEncodingNames;
+ }
+
+ /**
+ * Returns the primary value.
+ */
+ public function getValue() : int
+ {
+ return $this->values[0];
+ }
+
+ /**
+ * Gets character set ECI by value.
+ *
+ * Returns the representing ECI of a given value, or null if it is legal but unsupported.
+ *
+ * @throws InvalidArgumentException if value is not between 0 and 900
+ */
+ public static function getCharacterSetEciByValue(int $value) : ?self
+ {
+ if ($value < 0 || $value >= 900) {
+ throw new InvalidArgumentException('Value must be between 0 and 900');
+ }
+
+ $valueToEci = self::valueToEci();
+
+ if (! array_key_exists($value, $valueToEci)) {
+ return null;
+ }
+
+ return $valueToEci[$value];
+ }
+
+ /**
+ * Returns character set ECI by name.
+ *
+ * Returns the representing ECI of a given name, or null if it is legal but unsupported
+ */
+ public static function getCharacterSetEciByName(string $name) : ?self
+ {
+ $nameToEci = self::nameToEci();
+ $name = strtolower($name);
+
+ if (! array_key_exists($name, $nameToEci)) {
+ return null;
+ }
+
+ return $nameToEci[$name];
+ }
+
+ private static function valueToEci() : array
+ {
+ if (null !== self::$valueToEci) {
+ return self::$valueToEci;
+ }
+
+ self::$valueToEci = [];
+
+ foreach (self::values() as $eci) {
+ foreach ($eci->values as $value) {
+ self::$valueToEci[$value] = $eci;
+ }
+ }
+
+ return self::$valueToEci;
+ }
+
+ private static function nameToEci() : array
+ {
+ if (null !== self::$nameToEci) {
+ return self::$nameToEci;
+ }
+
+ self::$nameToEci = [];
+
+ foreach (self::values() as $eci) {
+ self::$nameToEci[strtolower($eci->name())] = $eci;
+
+ foreach ($eci->otherEncodingNames as $name) {
+ self::$nameToEci[strtolower($name)] = $eci;
+ }
+ }
+
+ return self::$nameToEci;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Common/EcBlock.php b/system/vendor/bacon/bacon-qr-code/src/Common/EcBlock.php
new file mode 100644
index 0000000..bc9e865
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Common/EcBlock.php
@@ -0,0 +1,33 @@
+count;
+ }
+
+ /**
+ * Returns the number of data codewords.
+ */
+ public function getDataCodewords() : int
+ {
+ return $this->dataCodewords;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Common/EcBlocks.php b/system/vendor/bacon/bacon-qr-code/src/Common/EcBlocks.php
new file mode 100644
index 0000000..63c52a9
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Common/EcBlocks.php
@@ -0,0 +1,66 @@
+ecBlocks = $ecBlocks;
+ }
+
+ /**
+ * Returns the number of EC codewords per block.
+ */
+ public function getEcCodewordsPerBlock() : int
+ {
+ return $this->ecCodewordsPerBlock;
+ }
+
+ /**
+ * Returns the total number of EC block appearances.
+ */
+ public function getNumBlocks() : int
+ {
+ $total = 0;
+
+ foreach ($this->ecBlocks as $ecBlock) {
+ $total += $ecBlock->getCount();
+ }
+
+ return $total;
+ }
+
+ /**
+ * Returns the total count of EC codewords.
+ */
+ public function getTotalEcCodewords() : int
+ {
+ return $this->ecCodewordsPerBlock * $this->getNumBlocks();
+ }
+
+ /**
+ * Returns the EC blocks included in this collection.
+ *
+ * @return EcBlock[]
+ */
+ public function getEcBlocks() : array
+ {
+ return $this->ecBlocks;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Common/ErrorCorrectionLevel.php b/system/vendor/bacon/bacon-qr-code/src/Common/ErrorCorrectionLevel.php
new file mode 100644
index 0000000..ac84d66
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Common/ErrorCorrectionLevel.php
@@ -0,0 +1,57 @@
+bits;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Common/FormatInformation.php b/system/vendor/bacon/bacon-qr-code/src/Common/FormatInformation.php
new file mode 100644
index 0000000..6a5da0b
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Common/FormatInformation.php
@@ -0,0 +1,196 @@
+ecLevel = ErrorCorrectionLevel::forBits(($formatInfo >> 3) & 0x3);
+ $this->dataMask = $formatInfo & 0x7;
+ }
+
+ /**
+ * Checks how many bits are different between two integers.
+ */
+ public static function numBitsDiffering(int $a, int $b) : int
+ {
+ $a ^= $b;
+
+ return (
+ self::BITS_SET_IN_HALF_BYTE[$a & 0xf]
+ + self::BITS_SET_IN_HALF_BYTE[(BitUtils::unsignedRightShift($a, 4) & 0xf)]
+ + self::BITS_SET_IN_HALF_BYTE[(BitUtils::unsignedRightShift($a, 8) & 0xf)]
+ + self::BITS_SET_IN_HALF_BYTE[(BitUtils::unsignedRightShift($a, 12) & 0xf)]
+ + self::BITS_SET_IN_HALF_BYTE[(BitUtils::unsignedRightShift($a, 16) & 0xf)]
+ + self::BITS_SET_IN_HALF_BYTE[(BitUtils::unsignedRightShift($a, 20) & 0xf)]
+ + self::BITS_SET_IN_HALF_BYTE[(BitUtils::unsignedRightShift($a, 24) & 0xf)]
+ + self::BITS_SET_IN_HALF_BYTE[(BitUtils::unsignedRightShift($a, 28) & 0xf)]
+ );
+ }
+
+ /**
+ * Decodes format information.
+ */
+ public static function decodeFormatInformation(int $maskedFormatInfo1, int $maskedFormatInfo2) : ?self
+ {
+ $formatInfo = self::doDecodeFormatInformation($maskedFormatInfo1, $maskedFormatInfo2);
+
+ if (null !== $formatInfo) {
+ return $formatInfo;
+ }
+
+ // Should return null, but, some QR codes apparently do not mask this info. Try again by actually masking the
+ // pattern first.
+ return self::doDecodeFormatInformation(
+ $maskedFormatInfo1 ^ self::FORMAT_INFO_MASK_QR,
+ $maskedFormatInfo2 ^ self::FORMAT_INFO_MASK_QR
+ );
+ }
+
+ /**
+ * Internal method for decoding format information.
+ */
+ private static function doDecodeFormatInformation(int $maskedFormatInfo1, int $maskedFormatInfo2) : ?self
+ {
+ $bestDifference = PHP_INT_MAX;
+ $bestFormatInfo = 0;
+
+ foreach (self::FORMAT_INFO_DECODE_LOOKUP as $decodeInfo) {
+ $targetInfo = $decodeInfo[0];
+
+ if ($targetInfo === $maskedFormatInfo1 || $targetInfo === $maskedFormatInfo2) {
+ // Found an exact match
+ return new self($decodeInfo[1]);
+ }
+
+ $bitsDifference = self::numBitsDiffering($maskedFormatInfo1, $targetInfo);
+
+ if ($bitsDifference < $bestDifference) {
+ $bestFormatInfo = $decodeInfo[1];
+ $bestDifference = $bitsDifference;
+ }
+
+ if ($maskedFormatInfo1 !== $maskedFormatInfo2) {
+ // Also try the other option
+ $bitsDifference = self::numBitsDiffering($maskedFormatInfo2, $targetInfo);
+
+ if ($bitsDifference < $bestDifference) {
+ $bestFormatInfo = $decodeInfo[1];
+ $bestDifference = $bitsDifference;
+ }
+ }
+ }
+
+ // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits differing means we found a match.
+ if ($bestDifference <= 3) {
+ return new self($bestFormatInfo);
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the error correction level.
+ */
+ public function getErrorCorrectionLevel() : ErrorCorrectionLevel
+ {
+ return $this->ecLevel;
+ }
+
+ /**
+ * Returns the data mask.
+ */
+ public function getDataMask() : int
+ {
+ return $this->dataMask;
+ }
+
+ /**
+ * Hashes the code of the EC level.
+ */
+ public function hashCode() : int
+ {
+ return ($this->ecLevel->getBits() << 3) | $this->dataMask;
+ }
+
+ /**
+ * Verifies if this instance equals another one.
+ */
+ public function equals(self $other) : bool
+ {
+ return (
+ $this->ecLevel === $other->ecLevel
+ && $this->dataMask === $other->dataMask
+ );
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Common/Mode.php b/system/vendor/bacon/bacon-qr-code/src/Common/Mode.php
new file mode 100644
index 0000000..f5fb153
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Common/Mode.php
@@ -0,0 +1,69 @@
+getVersionNumber();
+
+ if ($number <= 9) {
+ $offset = 0;
+ } elseif ($number <= 26) {
+ $offset = 1;
+ } else {
+ $offset = 2;
+ }
+
+ return $this->characterCountBitsForVersions[$offset];
+ }
+
+ /**
+ * Returns the four bits used to encode this mode.
+ */
+ public function getBits() : int
+ {
+ return $this->bits;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Common/ReedSolomonCodec.php b/system/vendor/bacon/bacon-qr-code/src/Common/ReedSolomonCodec.php
new file mode 100644
index 0000000..d16a75e
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Common/ReedSolomonCodec.php
@@ -0,0 +1,454 @@
+ 8) {
+ throw new InvalidArgumentException('Symbol size must be between 0 and 8');
+ }
+
+ if ($firstRoot < 0 || $firstRoot >= (1 << $symbolSize)) {
+ throw new InvalidArgumentException('First root must be between 0 and ' . (1 << $symbolSize));
+ }
+
+ if ($numRoots < 0 || $numRoots >= (1 << $symbolSize)) {
+ throw new InvalidArgumentException('Num roots must be between 0 and ' . (1 << $symbolSize));
+ }
+
+ if ($padding < 0 || $padding >= ((1 << $symbolSize) - 1 - $numRoots)) {
+ throw new InvalidArgumentException(
+ 'Padding must be between 0 and ' . ((1 << $symbolSize) - 1 - $numRoots)
+ );
+ }
+
+ $this->symbolSize = $symbolSize;
+ $this->blockSize = (1 << $symbolSize) - 1;
+ $this->padding = $padding;
+ $this->alphaTo = SplFixedArray::fromArray(array_fill(0, $this->blockSize + 1, 0), false);
+ $this->indexOf = SplFixedArray::fromArray(array_fill(0, $this->blockSize + 1, 0), false);
+
+ // Generate galous field lookup table
+ $this->indexOf[0] = $this->blockSize;
+ $this->alphaTo[$this->blockSize] = 0;
+
+ $sr = 1;
+
+ for ($i = 0; $i < $this->blockSize; ++$i) {
+ $this->indexOf[$sr] = $i;
+ $this->alphaTo[$i] = $sr;
+
+ $sr <<= 1;
+
+ if ($sr & (1 << $symbolSize)) {
+ $sr ^= $gfPoly;
+ }
+
+ $sr &= $this->blockSize;
+ }
+
+ if (1 !== $sr) {
+ throw new RuntimeException('Field generator polynomial is not primitive');
+ }
+
+ // Form RS code generator polynomial from its roots
+ $this->generatorPoly = SplFixedArray::fromArray(array_fill(0, $numRoots + 1, 0), false);
+ $this->firstRoot = $firstRoot;
+ $this->primitive = $primitive;
+ $this->numRoots = $numRoots;
+
+ // Find prim-th root of 1, used in decoding
+ for ($iPrimitive = 1; ($iPrimitive % $primitive) !== 0; $iPrimitive += $this->blockSize) {
+ }
+
+ $this->iPrimitive = intdiv($iPrimitive, $primitive);
+
+ $this->generatorPoly[0] = 1;
+
+ for ($i = 0, $root = $firstRoot * $primitive; $i < $numRoots; ++$i, $root += $primitive) {
+ $this->generatorPoly[$i + 1] = 1;
+
+ for ($j = $i; $j > 0; $j--) {
+ if ($this->generatorPoly[$j] !== 0) {
+ $this->generatorPoly[$j] = $this->generatorPoly[$j - 1] ^ $this->alphaTo[
+ $this->modNn($this->indexOf[$this->generatorPoly[$j]] + $root)
+ ];
+ } else {
+ $this->generatorPoly[$j] = $this->generatorPoly[$j - 1];
+ }
+ }
+
+ $this->generatorPoly[$j] = $this->alphaTo[$this->modNn($this->indexOf[$this->generatorPoly[0]] + $root)];
+ }
+
+ // Convert generator poly to index form for quicker encoding
+ for ($i = 0; $i <= $numRoots; ++$i) {
+ $this->generatorPoly[$i] = $this->indexOf[$this->generatorPoly[$i]];
+ }
+ }
+
+ /**
+ * Encodes data and writes result back into parity array.
+ */
+ public function encode(SplFixedArray $data, SplFixedArray $parity) : void
+ {
+ for ($i = 0; $i < $this->numRoots; ++$i) {
+ $parity[$i] = 0;
+ }
+
+ $iterations = $this->blockSize - $this->numRoots - $this->padding;
+
+ for ($i = 0; $i < $iterations; ++$i) {
+ $feedback = $this->indexOf[$data[$i] ^ $parity[0]];
+
+ if ($feedback !== $this->blockSize) {
+ // Feedback term is non-zero
+ $feedback = $this->modNn($this->blockSize - $this->generatorPoly[$this->numRoots] + $feedback);
+
+ for ($j = 1; $j < $this->numRoots; ++$j) {
+ $parity[$j] = $parity[$j] ^ $this->alphaTo[
+ $this->modNn($feedback + $this->generatorPoly[$this->numRoots - $j])
+ ];
+ }
+ }
+
+ for ($j = 0; $j < $this->numRoots - 1; ++$j) {
+ $parity[$j] = $parity[$j + 1];
+ }
+
+ if ($feedback !== $this->blockSize) {
+ $parity[$this->numRoots - 1] = $this->alphaTo[$this->modNn($feedback + $this->generatorPoly[0])];
+ } else {
+ $parity[$this->numRoots - 1] = 0;
+ }
+ }
+ }
+
+ /**
+ * Decodes received data.
+ */
+ public function decode(SplFixedArray $data, ?SplFixedArray $erasures = null) : ?int
+ {
+ // This speeds up the initialization a bit.
+ $numRootsPlusOne = SplFixedArray::fromArray(array_fill(0, $this->numRoots + 1, 0), false);
+ $numRoots = SplFixedArray::fromArray(array_fill(0, $this->numRoots, 0), false);
+
+ $lambda = clone $numRootsPlusOne;
+ $b = clone $numRootsPlusOne;
+ $t = clone $numRootsPlusOne;
+ $omega = clone $numRootsPlusOne;
+ $root = clone $numRoots;
+ $loc = clone $numRoots;
+
+ $numErasures = (null !== $erasures ? count($erasures) : 0);
+
+ // Form the Syndromes; i.e., evaluate data(x) at roots of g(x)
+ $syndromes = SplFixedArray::fromArray(array_fill(0, $this->numRoots, $data[0]), false);
+
+ for ($i = 1; $i < $this->blockSize - $this->padding; ++$i) {
+ for ($j = 0; $j < $this->numRoots; ++$j) {
+ if ($syndromes[$j] === 0) {
+ $syndromes[$j] = $data[$i];
+ } else {
+ $syndromes[$j] = $data[$i] ^ $this->alphaTo[
+ $this->modNn($this->indexOf[$syndromes[$j]] + ($this->firstRoot + $j) * $this->primitive)
+ ];
+ }
+ }
+ }
+
+ // Convert syndromes to index form, checking for nonzero conditions
+ $syndromeError = 0;
+
+ for ($i = 0; $i < $this->numRoots; ++$i) {
+ $syndromeError |= $syndromes[$i];
+ $syndromes[$i] = $this->indexOf[$syndromes[$i]];
+ }
+
+ if (! $syndromeError) {
+ // If syndrome is zero, data[] is a codeword and there are no errors to correct, so return data[]
+ // unmodified.
+ return 0;
+ }
+
+ $lambda[0] = 1;
+
+ if ($numErasures > 0) {
+ // Init lambda to be the erasure locator polynomial
+ $lambda[1] = $this->alphaTo[$this->modNn($this->primitive * ($this->blockSize - 1 - $erasures[0]))];
+
+ for ($i = 1; $i < $numErasures; ++$i) {
+ $u = $this->modNn($this->primitive * ($this->blockSize - 1 - $erasures[$i]));
+
+ for ($j = $i + 1; $j > 0; --$j) {
+ $tmp = $this->indexOf[$lambda[$j - 1]];
+
+ if ($tmp !== $this->blockSize) {
+ $lambda[$j] = $lambda[$j] ^ $this->alphaTo[$this->modNn($u + $tmp)];
+ }
+ }
+ }
+ }
+
+ for ($i = 0; $i <= $this->numRoots; ++$i) {
+ $b[$i] = $this->indexOf[$lambda[$i]];
+ }
+
+ // Begin Berlekamp-Massey algorithm to determine error+erasure locator polynomial
+ $r = $numErasures;
+ $el = $numErasures;
+
+ while (++$r <= $this->numRoots) {
+ // Compute discrepancy at the r-th step in poly form
+ $discrepancyR = 0;
+
+ for ($i = 0; $i < $r; ++$i) {
+ if ($lambda[$i] !== 0 && $syndromes[$r - $i - 1] !== $this->blockSize) {
+ $discrepancyR ^= $this->alphaTo[
+ $this->modNn($this->indexOf[$lambda[$i]] + $syndromes[$r - $i - 1])
+ ];
+ }
+ }
+
+ $discrepancyR = $this->indexOf[$discrepancyR];
+
+ if ($discrepancyR === $this->blockSize) {
+ $tmp = $b->toArray();
+ array_unshift($tmp, $this->blockSize);
+ array_pop($tmp);
+ $b = SplFixedArray::fromArray($tmp, false);
+ continue;
+ }
+
+ $t[0] = $lambda[0];
+
+ for ($i = 0; $i < $this->numRoots; ++$i) {
+ if ($b[$i] !== $this->blockSize) {
+ $t[$i + 1] = $lambda[$i + 1] ^ $this->alphaTo[$this->modNn($discrepancyR + $b[$i])];
+ } else {
+ $t[$i + 1] = $lambda[$i + 1];
+ }
+ }
+
+ if (2 * $el <= $r + $numErasures - 1) {
+ $el = $r + $numErasures - $el;
+
+ for ($i = 0; $i <= $this->numRoots; ++$i) {
+ $b[$i] = (
+ $lambda[$i] === 0
+ ? $this->blockSize
+ : $this->modNn($this->indexOf[$lambda[$i]] - $discrepancyR + $this->blockSize)
+ );
+ }
+ } else {
+ $tmp = $b->toArray();
+ array_unshift($tmp, $this->blockSize);
+ array_pop($tmp);
+ $b = SplFixedArray::fromArray($tmp, false);
+ }
+
+ $lambda = clone $t;
+ }
+
+ // Convert lambda to index form and compute deg(lambda(x))
+ $degLambda = 0;
+
+ for ($i = 0; $i <= $this->numRoots; ++$i) {
+ $lambda[$i] = $this->indexOf[$lambda[$i]];
+
+ if ($lambda[$i] !== $this->blockSize) {
+ $degLambda = $i;
+ }
+ }
+
+ // Find roots of the error+erasure locator polynomial by Chien search.
+ $reg = clone $lambda;
+ $reg[0] = 0;
+ $count = 0;
+ $i = 1;
+
+ for ($k = $this->iPrimitive - 1; $i <= $this->blockSize; ++$i, $k = $this->modNn($k + $this->iPrimitive)) {
+ $q = 1;
+
+ for ($j = $degLambda; $j > 0; $j--) {
+ if ($reg[$j] !== $this->blockSize) {
+ $reg[$j] = $this->modNn($reg[$j] + $j);
+ $q ^= $this->alphaTo[$reg[$j]];
+ }
+ }
+
+ if ($q !== 0) {
+ // Not a root
+ continue;
+ }
+
+ // Store root (index-form) and error location number
+ $root[$count] = $i;
+ $loc[$count] = $k;
+
+ if (++$count === $degLambda) {
+ break;
+ }
+ }
+
+ if ($degLambda !== $count) {
+ // deg(lambda) unequal to number of roots: uncorrectable error detected
+ return null;
+ }
+
+ // Compute err+eras evaluate poly omega(x) = s(x)*lambda(x) (modulo x**numRoots). In index form. Also find
+ // deg(omega).
+ $degOmega = $degLambda - 1;
+
+ for ($i = 0; $i <= $degOmega; ++$i) {
+ $tmp = 0;
+
+ for ($j = $i; $j >= 0; --$j) {
+ if ($syndromes[$i - $j] !== $this->blockSize && $lambda[$j] !== $this->blockSize) {
+ $tmp ^= $this->alphaTo[$this->modNn($syndromes[$i - $j] + $lambda[$j])];
+ }
+ }
+
+ $omega[$i] = $this->indexOf[$tmp];
+ }
+
+ // Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = inv(X(l))**(firstRoot-1) and
+ // den = lambda_pr(inv(X(l))) all in poly form.
+ for ($j = $count - 1; $j >= 0; --$j) {
+ $num1 = 0;
+
+ for ($i = $degOmega; $i >= 0; $i--) {
+ if ($omega[$i] !== $this->blockSize) {
+ $num1 ^= $this->alphaTo[$this->modNn($omega[$i] + $i * $root[$j])];
+ }
+ }
+
+ $num2 = $this->alphaTo[$this->modNn($root[$j] * ($this->firstRoot - 1) + $this->blockSize)];
+ $den = 0;
+
+ // lambda[i+1] for i even is the formal derivativelambda_pr of lambda[i]
+ for ($i = min($degLambda, $this->numRoots - 1) & ~1; $i >= 0; $i -= 2) {
+ if ($lambda[$i + 1] !== $this->blockSize) {
+ $den ^= $this->alphaTo[$this->modNn($lambda[$i + 1] + $i * $root[$j])];
+ }
+ }
+
+ // Apply error to data
+ if ($num1 !== 0 && $loc[$j] >= $this->padding) {
+ $data[$loc[$j] - $this->padding] = $data[$loc[$j] - $this->padding] ^ (
+ $this->alphaTo[
+ $this->modNn(
+ $this->indexOf[$num1] + $this->indexOf[$num2] + $this->blockSize - $this->indexOf[$den]
+ )
+ ]
+ );
+ }
+ }
+
+ if (null !== $erasures) {
+ if (count($erasures) < $count) {
+ $erasures->setSize($count);
+ }
+
+ for ($i = 0; $i < $count; $i++) {
+ $erasures[$i] = $loc[$i];
+ }
+ }
+
+ return $count;
+ }
+
+ /**
+ * Computes $x % GF_SIZE, where GF_SIZE is 2**GF_BITS - 1, without a slow divide.
+ */
+ private function modNn(int $x) : int
+ {
+ while ($x >= $this->blockSize) {
+ $x -= $this->blockSize;
+ $x = ($x >> $this->symbolSize) + ($x & $this->blockSize);
+ }
+
+ return $x;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Common/Version.php b/system/vendor/bacon/bacon-qr-code/src/Common/Version.php
new file mode 100644
index 0000000..68d3d16
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Common/Version.php
@@ -0,0 +1,592 @@
+|null
+ */
+ private static ?array $versions = null;
+
+ /**
+ * @param int[] $alignmentPatternCenters
+ */
+ private function __construct(
+ int $versionNumber,
+ array $alignmentPatternCenters,
+ EcBlocks ...$ecBlocks
+ ) {
+ $this->versionNumber = $versionNumber;
+ $this->alignmentPatternCenters = $alignmentPatternCenters;
+ $this->ecBlocks = $ecBlocks;
+
+ $totalCodewords = 0;
+ $ecCodewords = $ecBlocks[0]->getEcCodewordsPerBlock();
+
+ foreach ($ecBlocks[0]->getEcBlocks() as $ecBlock) {
+ $totalCodewords += $ecBlock->getCount() * ($ecBlock->getDataCodewords() + $ecCodewords);
+ }
+
+ $this->totalCodewords = $totalCodewords;
+ }
+
+ /**
+ * Returns the version number.
+ */
+ public function getVersionNumber() : int
+ {
+ return $this->versionNumber;
+ }
+
+ /**
+ * Returns the alignment pattern centers.
+ *
+ * @return int[]
+ */
+ public function getAlignmentPatternCenters() : array
+ {
+ return $this->alignmentPatternCenters;
+ }
+
+ /**
+ * Returns the total number of codewords.
+ */
+ public function getTotalCodewords() : int
+ {
+ return $this->totalCodewords;
+ }
+
+ /**
+ * Calculates the dimension for the current version.
+ */
+ public function getDimensionForVersion() : int
+ {
+ return 17 + 4 * $this->versionNumber;
+ }
+
+ /**
+ * Returns the number of EC blocks for a specific EC level.
+ */
+ public function getEcBlocksForLevel(ErrorCorrectionLevel $ecLevel) : EcBlocks
+ {
+ return $this->ecBlocks[$ecLevel->ordinal()];
+ }
+
+ /**
+ * Gets a provisional version number for a specific dimension.
+ *
+ * @throws InvalidArgumentException if dimension is not 1 mod 4
+ */
+ public static function getProvisionalVersionForDimension(int $dimension) : self
+ {
+ if (1 !== $dimension % 4) {
+ throw new InvalidArgumentException('Dimension is not 1 mod 4');
+ }
+
+ return self::getVersionForNumber(intdiv($dimension - 17, 4));
+ }
+
+ /**
+ * Gets a version instance for a specific version number.
+ *
+ * @throws InvalidArgumentException if version number is out of range
+ */
+ public static function getVersionForNumber(int $versionNumber) : self
+ {
+ if ($versionNumber < 1 || $versionNumber > 40) {
+ throw new InvalidArgumentException('Version number must be between 1 and 40');
+ }
+
+ return self::versions()[$versionNumber - 1];
+ }
+
+ /**
+ * Decodes version information from an integer and returns the version.
+ */
+ public static function decodeVersionInformation(int $versionBits) : ?self
+ {
+ $bestDifference = PHP_INT_MAX;
+ $bestVersion = 0;
+
+ foreach (self::VERSION_DECODE_INFO as $i => $targetVersion) {
+ if ($targetVersion === $versionBits) {
+ return self::getVersionForNumber($i + 7);
+ }
+
+ $bitsDifference = FormatInformation::numBitsDiffering($versionBits, $targetVersion);
+
+ if ($bitsDifference < $bestDifference) {
+ $bestVersion = $i + 7;
+ $bestDifference = $bitsDifference;
+ }
+ }
+
+ if ($bestDifference <= 3) {
+ return self::getVersionForNumber($bestVersion);
+ }
+
+ return null;
+ }
+
+ /**
+ * Builds the function pattern for the current version.
+ */
+ public function buildFunctionPattern() : BitMatrix
+ {
+ $dimension = $this->getDimensionForVersion();
+ $bitMatrix = new BitMatrix($dimension);
+
+ // Top left finder pattern + separator + format
+ $bitMatrix->setRegion(0, 0, 9, 9);
+ // Top right finder pattern + separator + format
+ $bitMatrix->setRegion($dimension - 8, 0, 8, 9);
+ // Bottom left finder pattern + separator + format
+ $bitMatrix->setRegion(0, $dimension - 8, 9, 8);
+
+ // Alignment patterns
+ $max = count($this->alignmentPatternCenters);
+
+ for ($x = 0; $x < $max; ++$x) {
+ $i = $this->alignmentPatternCenters[$x] - 2;
+
+ for ($y = 0; $y < $max; ++$y) {
+ if (($x === 0 && ($y === 0 || $y === $max - 1)) || ($x === $max - 1 && $y === 0)) {
+ // No alignment patterns near the three finder paterns
+ continue;
+ }
+
+ $bitMatrix->setRegion($this->alignmentPatternCenters[$y] - 2, $i, 5, 5);
+ }
+ }
+
+ // Vertical timing pattern
+ $bitMatrix->setRegion(6, 9, 1, $dimension - 17);
+ // Horizontal timing pattern
+ $bitMatrix->setRegion(9, 6, $dimension - 17, 1);
+
+ if ($this->versionNumber > 6) {
+ // Version info, top right
+ $bitMatrix->setRegion($dimension - 11, 0, 3, 6);
+ // Version info, bottom left
+ $bitMatrix->setRegion(0, $dimension - 11, 6, 3);
+ }
+
+ return $bitMatrix;
+ }
+
+ /**
+ * Returns a string representation for the version.
+ */
+ public function __toString() : string
+ {
+ return (string) $this->versionNumber;
+ }
+
+ /**
+ * Build and cache a specific version.
+ *
+ * See ISO 18004:2006 6.5.1 Table 9.
+ *
+ * @return array
+ */
+ private static function versions() : array
+ {
+ if (null !== self::$versions) {
+ return self::$versions;
+ }
+
+ return self::$versions = [
+ new self(
+ 1,
+ [],
+ new EcBlocks(7, new EcBlock(1, 19)),
+ new EcBlocks(10, new EcBlock(1, 16)),
+ new EcBlocks(13, new EcBlock(1, 13)),
+ new EcBlocks(17, new EcBlock(1, 9))
+ ),
+ new self(
+ 2,
+ [6, 18],
+ new EcBlocks(10, new EcBlock(1, 34)),
+ new EcBlocks(16, new EcBlock(1, 28)),
+ new EcBlocks(22, new EcBlock(1, 22)),
+ new EcBlocks(28, new EcBlock(1, 16))
+ ),
+ new self(
+ 3,
+ [6, 22],
+ new EcBlocks(15, new EcBlock(1, 55)),
+ new EcBlocks(26, new EcBlock(1, 44)),
+ new EcBlocks(18, new EcBlock(2, 17)),
+ new EcBlocks(22, new EcBlock(2, 13))
+ ),
+ new self(
+ 4,
+ [6, 26],
+ new EcBlocks(20, new EcBlock(1, 80)),
+ new EcBlocks(18, new EcBlock(2, 32)),
+ new EcBlocks(26, new EcBlock(2, 24)),
+ new EcBlocks(16, new EcBlock(4, 9))
+ ),
+ new self(
+ 5,
+ [6, 30],
+ new EcBlocks(26, new EcBlock(1, 108)),
+ new EcBlocks(24, new EcBlock(2, 43)),
+ new EcBlocks(18, new EcBlock(2, 15), new EcBlock(2, 16)),
+ new EcBlocks(22, new EcBlock(2, 11), new EcBlock(2, 12))
+ ),
+ new self(
+ 6,
+ [6, 34],
+ new EcBlocks(18, new EcBlock(2, 68)),
+ new EcBlocks(16, new EcBlock(4, 27)),
+ new EcBlocks(24, new EcBlock(4, 19)),
+ new EcBlocks(28, new EcBlock(4, 15))
+ ),
+ new self(
+ 7,
+ [6, 22, 38],
+ new EcBlocks(20, new EcBlock(2, 78)),
+ new EcBlocks(18, new EcBlock(4, 31)),
+ new EcBlocks(18, new EcBlock(2, 14), new EcBlock(4, 15)),
+ new EcBlocks(26, new EcBlock(4, 13), new EcBlock(1, 14))
+ ),
+ new self(
+ 8,
+ [6, 24, 42],
+ new EcBlocks(24, new EcBlock(2, 97)),
+ new EcBlocks(22, new EcBlock(2, 38), new EcBlock(2, 39)),
+ new EcBlocks(22, new EcBlock(4, 18), new EcBlock(2, 19)),
+ new EcBlocks(26, new EcBlock(4, 14), new EcBlock(2, 15))
+ ),
+ new self(
+ 9,
+ [6, 26, 46],
+ new EcBlocks(30, new EcBlock(2, 116)),
+ new EcBlocks(22, new EcBlock(3, 36), new EcBlock(2, 37)),
+ new EcBlocks(20, new EcBlock(4, 16), new EcBlock(4, 17)),
+ new EcBlocks(24, new EcBlock(4, 12), new EcBlock(4, 13))
+ ),
+ new self(
+ 10,
+ [6, 28, 50],
+ new EcBlocks(18, new EcBlock(2, 68), new EcBlock(2, 69)),
+ new EcBlocks(26, new EcBlock(4, 43), new EcBlock(1, 44)),
+ new EcBlocks(24, new EcBlock(6, 19), new EcBlock(2, 20)),
+ new EcBlocks(28, new EcBlock(6, 15), new EcBlock(2, 16))
+ ),
+ new self(
+ 11,
+ [6, 30, 54],
+ new EcBlocks(20, new EcBlock(4, 81)),
+ new EcBlocks(30, new EcBlock(1, 50), new EcBlock(4, 51)),
+ new EcBlocks(28, new EcBlock(4, 22), new EcBlock(4, 23)),
+ new EcBlocks(24, new EcBlock(3, 12), new EcBlock(8, 13))
+ ),
+ new self(
+ 12,
+ [6, 32, 58],
+ new EcBlocks(24, new EcBlock(2, 92), new EcBlock(2, 93)),
+ new EcBlocks(22, new EcBlock(6, 36), new EcBlock(2, 37)),
+ new EcBlocks(26, new EcBlock(4, 20), new EcBlock(6, 21)),
+ new EcBlocks(28, new EcBlock(7, 14), new EcBlock(4, 15))
+ ),
+ new self(
+ 13,
+ [6, 34, 62],
+ new EcBlocks(26, new EcBlock(4, 107)),
+ new EcBlocks(22, new EcBlock(8, 37), new EcBlock(1, 38)),
+ new EcBlocks(24, new EcBlock(8, 20), new EcBlock(4, 21)),
+ new EcBlocks(22, new EcBlock(12, 11), new EcBlock(4, 12))
+ ),
+ new self(
+ 14,
+ [6, 26, 46, 66],
+ new EcBlocks(30, new EcBlock(3, 115), new EcBlock(1, 116)),
+ new EcBlocks(24, new EcBlock(4, 40), new EcBlock(5, 41)),
+ new EcBlocks(20, new EcBlock(11, 16), new EcBlock(5, 17)),
+ new EcBlocks(24, new EcBlock(11, 12), new EcBlock(5, 13))
+ ),
+ new self(
+ 15,
+ [6, 26, 48, 70],
+ new EcBlocks(22, new EcBlock(5, 87), new EcBlock(1, 88)),
+ new EcBlocks(24, new EcBlock(5, 41), new EcBlock(5, 42)),
+ new EcBlocks(30, new EcBlock(5, 24), new EcBlock(7, 25)),
+ new EcBlocks(24, new EcBlock(11, 12), new EcBlock(7, 13))
+ ),
+ new self(
+ 16,
+ [6, 26, 50, 74],
+ new EcBlocks(24, new EcBlock(5, 98), new EcBlock(1, 99)),
+ new EcBlocks(28, new EcBlock(7, 45), new EcBlock(3, 46)),
+ new EcBlocks(24, new EcBlock(15, 19), new EcBlock(2, 20)),
+ new EcBlocks(30, new EcBlock(3, 15), new EcBlock(13, 16))
+ ),
+ new self(
+ 17,
+ [6, 30, 54, 78],
+ new EcBlocks(28, new EcBlock(1, 107), new EcBlock(5, 108)),
+ new EcBlocks(28, new EcBlock(10, 46), new EcBlock(1, 47)),
+ new EcBlocks(28, new EcBlock(1, 22), new EcBlock(15, 23)),
+ new EcBlocks(28, new EcBlock(2, 14), new EcBlock(17, 15))
+ ),
+ new self(
+ 18,
+ [6, 30, 56, 82],
+ new EcBlocks(30, new EcBlock(5, 120), new EcBlock(1, 121)),
+ new EcBlocks(26, new EcBlock(9, 43), new EcBlock(4, 44)),
+ new EcBlocks(28, new EcBlock(17, 22), new EcBlock(1, 23)),
+ new EcBlocks(28, new EcBlock(2, 14), new EcBlock(19, 15))
+ ),
+ new self(
+ 19,
+ [6, 30, 58, 86],
+ new EcBlocks(28, new EcBlock(3, 113), new EcBlock(4, 114)),
+ new EcBlocks(26, new EcBlock(3, 44), new EcBlock(11, 45)),
+ new EcBlocks(26, new EcBlock(17, 21), new EcBlock(4, 22)),
+ new EcBlocks(26, new EcBlock(9, 13), new EcBlock(16, 14))
+ ),
+ new self(
+ 20,
+ [6, 34, 62, 90],
+ new EcBlocks(28, new EcBlock(3, 107), new EcBlock(5, 108)),
+ new EcBlocks(26, new EcBlock(3, 41), new EcBlock(13, 42)),
+ new EcBlocks(30, new EcBlock(15, 24), new EcBlock(5, 25)),
+ new EcBlocks(28, new EcBlock(15, 15), new EcBlock(10, 16))
+ ),
+ new self(
+ 21,
+ [6, 28, 50, 72, 94],
+ new EcBlocks(28, new EcBlock(4, 116), new EcBlock(4, 117)),
+ new EcBlocks(26, new EcBlock(17, 42)),
+ new EcBlocks(28, new EcBlock(17, 22), new EcBlock(6, 23)),
+ new EcBlocks(30, new EcBlock(19, 16), new EcBlock(6, 17))
+ ),
+ new self(
+ 22,
+ [6, 26, 50, 74, 98],
+ new EcBlocks(28, new EcBlock(2, 111), new EcBlock(7, 112)),
+ new EcBlocks(28, new EcBlock(17, 46)),
+ new EcBlocks(30, new EcBlock(7, 24), new EcBlock(16, 25)),
+ new EcBlocks(24, new EcBlock(34, 13))
+ ),
+ new self(
+ 23,
+ [6, 30, 54, 78, 102],
+ new EcBlocks(30, new EcBlock(4, 121), new EcBlock(5, 122)),
+ new EcBlocks(28, new EcBlock(4, 47), new EcBlock(14, 48)),
+ new EcBlocks(30, new EcBlock(11, 24), new EcBlock(14, 25)),
+ new EcBlocks(30, new EcBlock(16, 15), new EcBlock(14, 16))
+ ),
+ new self(
+ 24,
+ [6, 28, 54, 80, 106],
+ new EcBlocks(30, new EcBlock(6, 117), new EcBlock(4, 118)),
+ new EcBlocks(28, new EcBlock(6, 45), new EcBlock(14, 46)),
+ new EcBlocks(30, new EcBlock(11, 24), new EcBlock(16, 25)),
+ new EcBlocks(30, new EcBlock(30, 16), new EcBlock(2, 17))
+ ),
+ new self(
+ 25,
+ [6, 32, 58, 84, 110],
+ new EcBlocks(26, new EcBlock(8, 106), new EcBlock(4, 107)),
+ new EcBlocks(28, new EcBlock(8, 47), new EcBlock(13, 48)),
+ new EcBlocks(30, new EcBlock(7, 24), new EcBlock(22, 25)),
+ new EcBlocks(30, new EcBlock(22, 15), new EcBlock(13, 16))
+ ),
+ new self(
+ 26,
+ [6, 30, 58, 86, 114],
+ new EcBlocks(28, new EcBlock(10, 114), new EcBlock(2, 115)),
+ new EcBlocks(28, new EcBlock(19, 46), new EcBlock(4, 47)),
+ new EcBlocks(28, new EcBlock(28, 22), new EcBlock(6, 23)),
+ new EcBlocks(30, new EcBlock(33, 16), new EcBlock(4, 17))
+ ),
+ new self(
+ 27,
+ [6, 34, 62, 90, 118],
+ new EcBlocks(30, new EcBlock(8, 122), new EcBlock(4, 123)),
+ new EcBlocks(28, new EcBlock(22, 45), new EcBlock(3, 46)),
+ new EcBlocks(30, new EcBlock(8, 23), new EcBlock(26, 24)),
+ new EcBlocks(30, new EcBlock(12, 15), new EcBlock(28, 16))
+ ),
+ new self(
+ 28,
+ [6, 26, 50, 74, 98, 122],
+ new EcBlocks(30, new EcBlock(3, 117), new EcBlock(10, 118)),
+ new EcBlocks(28, new EcBlock(3, 45), new EcBlock(23, 46)),
+ new EcBlocks(30, new EcBlock(4, 24), new EcBlock(31, 25)),
+ new EcBlocks(30, new EcBlock(11, 15), new EcBlock(31, 16))
+ ),
+ new self(
+ 29,
+ [6, 30, 54, 78, 102, 126],
+ new EcBlocks(30, new EcBlock(7, 116), new EcBlock(7, 117)),
+ new EcBlocks(28, new EcBlock(21, 45), new EcBlock(7, 46)),
+ new EcBlocks(30, new EcBlock(1, 23), new EcBlock(37, 24)),
+ new EcBlocks(30, new EcBlock(19, 15), new EcBlock(26, 16))
+ ),
+ new self(
+ 30,
+ [6, 26, 52, 78, 104, 130],
+ new EcBlocks(30, new EcBlock(5, 115), new EcBlock(10, 116)),
+ new EcBlocks(28, new EcBlock(19, 47), new EcBlock(10, 48)),
+ new EcBlocks(30, new EcBlock(15, 24), new EcBlock(25, 25)),
+ new EcBlocks(30, new EcBlock(23, 15), new EcBlock(25, 16))
+ ),
+ new self(
+ 31,
+ [6, 30, 56, 82, 108, 134],
+ new EcBlocks(30, new EcBlock(13, 115), new EcBlock(3, 116)),
+ new EcBlocks(28, new EcBlock(2, 46), new EcBlock(29, 47)),
+ new EcBlocks(30, new EcBlock(42, 24), new EcBlock(1, 25)),
+ new EcBlocks(30, new EcBlock(23, 15), new EcBlock(28, 16))
+ ),
+ new self(
+ 32,
+ [6, 34, 60, 86, 112, 138],
+ new EcBlocks(30, new EcBlock(17, 115)),
+ new EcBlocks(28, new EcBlock(10, 46), new EcBlock(23, 47)),
+ new EcBlocks(30, new EcBlock(10, 24), new EcBlock(35, 25)),
+ new EcBlocks(30, new EcBlock(19, 15), new EcBlock(35, 16))
+ ),
+ new self(
+ 33,
+ [6, 30, 58, 86, 114, 142],
+ new EcBlocks(30, new EcBlock(17, 115), new EcBlock(1, 116)),
+ new EcBlocks(28, new EcBlock(14, 46), new EcBlock(21, 47)),
+ new EcBlocks(30, new EcBlock(29, 24), new EcBlock(19, 25)),
+ new EcBlocks(30, new EcBlock(11, 15), new EcBlock(46, 16))
+ ),
+ new self(
+ 34,
+ [6, 34, 62, 90, 118, 146],
+ new EcBlocks(30, new EcBlock(13, 115), new EcBlock(6, 116)),
+ new EcBlocks(28, new EcBlock(14, 46), new EcBlock(23, 47)),
+ new EcBlocks(30, new EcBlock(44, 24), new EcBlock(7, 25)),
+ new EcBlocks(30, new EcBlock(59, 16), new EcBlock(1, 17))
+ ),
+ new self(
+ 35,
+ [6, 30, 54, 78, 102, 126, 150],
+ new EcBlocks(30, new EcBlock(12, 121), new EcBlock(7, 122)),
+ new EcBlocks(28, new EcBlock(12, 47), new EcBlock(26, 48)),
+ new EcBlocks(30, new EcBlock(39, 24), new EcBlock(14, 25)),
+ new EcBlocks(30, new EcBlock(22, 15), new EcBlock(41, 16))
+ ),
+ new self(
+ 36,
+ [6, 24, 50, 76, 102, 128, 154],
+ new EcBlocks(30, new EcBlock(6, 121), new EcBlock(14, 122)),
+ new EcBlocks(28, new EcBlock(6, 47), new EcBlock(34, 48)),
+ new EcBlocks(30, new EcBlock(46, 24), new EcBlock(10, 25)),
+ new EcBlocks(30, new EcBlock(2, 15), new EcBlock(64, 16))
+ ),
+ new self(
+ 37,
+ [6, 28, 54, 80, 106, 132, 158],
+ new EcBlocks(30, new EcBlock(17, 122), new EcBlock(4, 123)),
+ new EcBlocks(28, new EcBlock(29, 46), new EcBlock(14, 47)),
+ new EcBlocks(30, new EcBlock(49, 24), new EcBlock(10, 25)),
+ new EcBlocks(30, new EcBlock(24, 15), new EcBlock(46, 16))
+ ),
+ new self(
+ 38,
+ [6, 32, 58, 84, 110, 136, 162],
+ new EcBlocks(30, new EcBlock(4, 122), new EcBlock(18, 123)),
+ new EcBlocks(28, new EcBlock(13, 46), new EcBlock(32, 47)),
+ new EcBlocks(30, new EcBlock(48, 24), new EcBlock(14, 25)),
+ new EcBlocks(30, new EcBlock(42, 15), new EcBlock(32, 16))
+ ),
+ new self(
+ 39,
+ [6, 26, 54, 82, 110, 138, 166],
+ new EcBlocks(30, new EcBlock(20, 117), new EcBlock(4, 118)),
+ new EcBlocks(28, new EcBlock(40, 47), new EcBlock(7, 48)),
+ new EcBlocks(30, new EcBlock(43, 24), new EcBlock(22, 25)),
+ new EcBlocks(30, new EcBlock(10, 15), new EcBlock(67, 16))
+ ),
+ new self(
+ 40,
+ [6, 30, 58, 86, 114, 142, 170],
+ new EcBlocks(30, new EcBlock(19, 118), new EcBlock(6, 119)),
+ new EcBlocks(28, new EcBlock(18, 47), new EcBlock(31, 48)),
+ new EcBlocks(30, new EcBlock(34, 24), new EcBlock(34, 25)),
+ new EcBlocks(30, new EcBlock(20, 15), new EcBlock(61, 16))
+ ),
+ ];
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Encoder/BlockPair.php b/system/vendor/bacon/bacon-qr-code/src/Encoder/BlockPair.php
new file mode 100644
index 0000000..b1dc5c4
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Encoder/BlockPair.php
@@ -0,0 +1,44 @@
+ $dataBytes Data bytes in the block.
+ * @param SplFixedArray $errorCorrectionBytes Error correction bytes in the block.
+ */
+ public function __construct(
+ private readonly SplFixedArray $dataBytes,
+ private readonly SplFixedArray $errorCorrectionBytes
+ ) {
+ }
+
+ /**
+ * Gets the data bytes.
+ *
+ * @return SplFixedArray
+ */
+ public function getDataBytes() : SplFixedArray
+ {
+ return $this->dataBytes;
+ }
+
+ /**
+ * Gets the error correction bytes.
+ *
+ * @return SplFixedArray
+ */
+ public function getErrorCorrectionBytes() : SplFixedArray
+ {
+ return $this->errorCorrectionBytes;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Encoder/ByteMatrix.php b/system/vendor/bacon/bacon-qr-code/src/Encoder/ByteMatrix.php
new file mode 100644
index 0000000..eefcf1c
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Encoder/ByteMatrix.php
@@ -0,0 +1,134 @@
+>
+ */
+ private SplFixedArray $bytes;
+
+ public function __construct(private readonly int $width, private readonly int $height)
+ {
+ $this->bytes = new SplFixedArray($height);
+
+ for ($y = 0; $y < $height; ++$y) {
+ $this->bytes[$y] = SplFixedArray::fromArray(array_fill(0, $width, 0));
+ }
+ }
+
+ /**
+ * Gets the width of the matrix.
+ */
+ public function getWidth() : int
+ {
+ return $this->width;
+ }
+
+ /**
+ * Gets the height of the matrix.
+ */
+ public function getHeight() : int
+ {
+ return $this->height;
+ }
+
+ /**
+ * Gets the internal representation of the matrix.
+ *
+ * @return SplFixedArray>
+ */
+ public function getArray() : SplFixedArray
+ {
+ return $this->bytes;
+ }
+
+ /**
+ * @return Traversable
+ */
+ public function getBytes() : Traversable
+ {
+ foreach ($this->bytes as $row) {
+ foreach ($row as $byte) {
+ yield $byte;
+ }
+ }
+ }
+
+ /**
+ * Gets the byte for a specific position.
+ */
+ public function get(int $x, int $y) : int
+ {
+ return $this->bytes[$y][$x];
+ }
+
+ /**
+ * Sets the byte for a specific position.
+ */
+ public function set(int $x, int $y, int $value) : void
+ {
+ $this->bytes[$y][$x] = $value;
+ }
+
+ /**
+ * Clears the matrix with a specific value.
+ */
+ public function clear(int $value) : void
+ {
+ for ($y = 0; $y < $this->height; ++$y) {
+ for ($x = 0; $x < $this->width; ++$x) {
+ $this->bytes[$y][$x] = $value;
+ }
+ }
+ }
+
+ public function __clone()
+ {
+ $this->bytes = clone $this->bytes;
+
+ foreach ($this->bytes as $index => $row) {
+ $this->bytes[$index] = clone $row;
+ }
+ }
+
+ /**
+ * Returns a string representation of the matrix.
+ */
+ public function __toString() : string
+ {
+ $result = '';
+
+ for ($y = 0; $y < $this->height; $y++) {
+ for ($x = 0; $x < $this->width; $x++) {
+ switch ($this->bytes[$y][$x]) {
+ case 0:
+ $result .= ' 0';
+ break;
+
+ case 1:
+ $result .= ' 1';
+ break;
+
+ default:
+ $result .= ' ';
+ break;
+ }
+ }
+
+ $result .= "\n";
+ }
+
+ return $result;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Encoder/Encoder.php b/system/vendor/bacon/bacon-qr-code/src/Encoder/Encoder.php
new file mode 100644
index 0000000..c363953
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Encoder/Encoder.php
@@ -0,0 +1,679 @@
+
+ */
+ private static array $codecs = [];
+
+ /**
+ * Encodes "content" with the error correction level "ecLevel".
+ */
+ public static function encode(
+ string $content,
+ ErrorCorrectionLevel $ecLevel,
+ string $encoding = self::DEFAULT_BYTE_MODE_ENCODING,
+ ?Version $forcedVersion = null,
+ // Barcode scanner might not be able to read the encoded message of the QR code with the prefix ECI of UTF-8
+ bool $prefixEci = true
+ ) : QrCode {
+ // Pick an encoding mode appropriate for the content. Note that this
+ // will not attempt to use multiple modes / segments even if that were
+ // more efficient. Would be nice.
+ $mode = self::chooseMode($content, $encoding);
+
+ // This will store the header information, like mode and length, as well
+ // as "header" segments like an ECI segment.
+ $headerBits = new BitArray();
+
+ // Append ECI segment if applicable
+ if ($prefixEci && Mode::BYTE() === $mode && self::DEFAULT_BYTE_MODE_ENCODING !== $encoding) {
+ $eci = CharacterSetEci::getCharacterSetEciByName($encoding);
+
+ if (null !== $eci) {
+ self::appendEci($eci, $headerBits);
+ }
+ }
+
+ // (With ECI in place,) Write the mode marker
+ self::appendModeInfo($mode, $headerBits);
+
+ // Collect data within the main segment, separately, to count its size
+ // if needed. Don't add it to main payload yet.
+ $dataBits = new BitArray();
+ self::appendBytes($content, $mode, $dataBits, $encoding);
+
+ // Hard part: need to know version to know how many bits length takes.
+ // But need to know how many bits it takes to know version. First we
+ // take a guess at version by assuming version will be the minimum, 1:
+ $provisionalBitsNeeded = $headerBits->getSize()
+ + $mode->getCharacterCountBits(Version::getVersionForNumber(1))
+ + $dataBits->getSize();
+ $provisionalVersion = self::chooseVersion($provisionalBitsNeeded, $ecLevel);
+
+ // Use that guess to calculate the right version. I am still not sure
+ // this works in 100% of cases.
+ $bitsNeeded = $headerBits->getSize()
+ + $mode->getCharacterCountBits($provisionalVersion)
+ + $dataBits->getSize();
+ $version = self::chooseVersion($bitsNeeded, $ecLevel);
+
+ if (null !== $forcedVersion) {
+ // Forced version check
+ if ($version->getVersionNumber() <= $forcedVersion->getVersionNumber()) {
+ // Calculated minimum version is same or equal as forced version
+ $version = $forcedVersion;
+ } else {
+ throw new WriterException(
+ 'Invalid version! Calculated version: '
+ . $version->getVersionNumber()
+ . ', requested version: '
+ . $forcedVersion->getVersionNumber()
+ );
+ }
+ }
+
+ $headerAndDataBits = new BitArray();
+ $headerAndDataBits->appendBitArray($headerBits);
+
+ // Find "length" of main segment and write it.
+ $numLetters = (Mode::BYTE() === $mode ? $dataBits->getSizeInBytes() : strlen($content));
+ self::appendLengthInfo($numLetters, $version, $mode, $headerAndDataBits);
+
+ // Put data together into the overall payload.
+ $headerAndDataBits->appendBitArray($dataBits);
+ $ecBlocks = $version->getEcBlocksForLevel($ecLevel);
+ $numDataBytes = $version->getTotalCodewords() - $ecBlocks->getTotalEcCodewords();
+
+ // Terminate the bits properly.
+ self::terminateBits($numDataBytes, $headerAndDataBits);
+
+ // Interleave data bits with error correction code.
+ $finalBits = self::interleaveWithEcBytes(
+ $headerAndDataBits,
+ $version->getTotalCodewords(),
+ $numDataBytes,
+ $ecBlocks->getNumBlocks()
+ );
+
+ // Choose the mask pattern.
+ $dimension = $version->getDimensionForVersion();
+ $matrix = new ByteMatrix($dimension, $dimension);
+ $maskPattern = self::chooseMaskPattern($finalBits, $ecLevel, $version, $matrix);
+
+ // Build the matrix.
+ MatrixUtil::buildMatrix($finalBits, $ecLevel, $version, $maskPattern, $matrix);
+
+ return new QrCode($mode, $ecLevel, $version, $maskPattern, $matrix);
+ }
+
+ /**
+ * Gets the alphanumeric code for a byte.
+ */
+ private static function getAlphanumericCode(int $code) : int
+ {
+ if (isset(self::ALPHANUMERIC_TABLE[$code])) {
+ return self::ALPHANUMERIC_TABLE[$code];
+ }
+
+ return -1;
+ }
+
+ /**
+ * Chooses the best mode for a given content.
+ */
+ private static function chooseMode(string $content, ?string $encoding = null) : Mode
+ {
+ if (null !== $encoding && 0 === strcasecmp($encoding, 'SHIFT-JIS')) {
+ return self::isOnlyDoubleByteKanji($content) ? Mode::KANJI() : Mode::BYTE();
+ }
+
+ $hasNumeric = false;
+ $hasAlphanumeric = false;
+ $contentLength = strlen($content);
+
+ for ($i = 0; $i < $contentLength; ++$i) {
+ $char = $content[$i];
+
+ if (ctype_digit($char)) {
+ $hasNumeric = true;
+ } elseif (-1 !== self::getAlphanumericCode(ord($char))) {
+ $hasAlphanumeric = true;
+ } else {
+ return Mode::BYTE();
+ }
+ }
+
+ if ($hasAlphanumeric) {
+ return Mode::ALPHANUMERIC();
+ } elseif ($hasNumeric) {
+ return Mode::NUMERIC();
+ }
+
+ return Mode::BYTE();
+ }
+
+ /**
+ * Calculates the mask penalty for a matrix.
+ */
+ private static function calculateMaskPenalty(ByteMatrix $matrix) : int
+ {
+ return (
+ MaskUtil::applyMaskPenaltyRule1($matrix)
+ + MaskUtil::applyMaskPenaltyRule2($matrix)
+ + MaskUtil::applyMaskPenaltyRule3($matrix)
+ + MaskUtil::applyMaskPenaltyRule4($matrix)
+ );
+ }
+
+ /**
+ * Checks if content only consists of double-byte kanji characters.
+ */
+ private static function isOnlyDoubleByteKanji(string $content) : bool
+ {
+ $bytes = @iconv('utf-8', 'SHIFT-JIS', $content);
+
+ if (false === $bytes) {
+ return false;
+ }
+
+ $length = strlen($bytes);
+
+ if (0 !== $length % 2) {
+ return false;
+ }
+
+ for ($i = 0; $i < $length; $i += 2) {
+ $byte = ord($bytes[$i]) & 0xff;
+
+ if (($byte < 0x81 || $byte > 0x9f) && $byte < 0xe0 || $byte > 0xeb) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Chooses the best mask pattern for a matrix.
+ */
+ private static function chooseMaskPattern(
+ BitArray $bits,
+ ErrorCorrectionLevel $ecLevel,
+ Version $version,
+ ByteMatrix $matrix
+ ) : int {
+ $minPenalty = PHP_INT_MAX;
+ $bestMaskPattern = -1;
+
+ for ($maskPattern = 0; $maskPattern < QrCode::NUM_MASK_PATTERNS; ++$maskPattern) {
+ MatrixUtil::buildMatrix($bits, $ecLevel, $version, $maskPattern, $matrix);
+ $penalty = self::calculateMaskPenalty($matrix);
+
+ if ($penalty < $minPenalty) {
+ $minPenalty = $penalty;
+ $bestMaskPattern = $maskPattern;
+ }
+ }
+
+ return $bestMaskPattern;
+ }
+
+ /**
+ * Chooses the best version for the input.
+ *
+ * @throws WriterException if data is too big
+ */
+ private static function chooseVersion(int $numInputBits, ErrorCorrectionLevel $ecLevel) : Version
+ {
+ for ($versionNum = 1; $versionNum <= 40; ++$versionNum) {
+ $version = Version::getVersionForNumber($versionNum);
+ $numBytes = $version->getTotalCodewords();
+
+ $ecBlocks = $version->getEcBlocksForLevel($ecLevel);
+ $numEcBytes = $ecBlocks->getTotalEcCodewords();
+
+ $numDataBytes = $numBytes - $numEcBytes;
+ $totalInputBytes = intdiv($numInputBits + 8, 8);
+
+ if ($numDataBytes >= $totalInputBytes) {
+ return $version;
+ }
+ }
+
+ throw new WriterException('Data too big');
+ }
+
+ /**
+ * Terminates the bits in a bit array.
+ *
+ * @throws WriterException if data bits cannot fit in the QR code
+ * @throws WriterException if bits size does not equal the capacity
+ */
+ private static function terminateBits(int $numDataBytes, BitArray $bits) : void
+ {
+ $capacity = $numDataBytes << 3;
+
+ if ($bits->getSize() > $capacity) {
+ throw new WriterException('Data bits cannot fit in the QR code');
+ }
+
+ for ($i = 0; $i < 4 && $bits->getSize() < $capacity; ++$i) {
+ $bits->appendBit(false);
+ }
+
+ $numBitsInLastByte = $bits->getSize() & 0x7;
+
+ if ($numBitsInLastByte > 0) {
+ for ($i = $numBitsInLastByte; $i < 8; ++$i) {
+ $bits->appendBit(false);
+ }
+ }
+
+ $numPaddingBytes = $numDataBytes - $bits->getSizeInBytes();
+
+ for ($i = 0; $i < $numPaddingBytes; ++$i) {
+ $bits->appendBits(0 === ($i & 0x1) ? 0xec : 0x11, 8);
+ }
+
+ if ($bits->getSize() !== $capacity) {
+ throw new WriterException('Bits size does not equal capacity');
+ }
+ }
+
+ /**
+ * Gets number of data- and EC bytes for a block ID.
+ *
+ * @return int[]
+ * @throws WriterException if block ID is too large
+ * @throws WriterException if EC bytes mismatch
+ * @throws WriterException if RS blocks mismatch
+ * @throws WriterException if total bytes mismatch
+ */
+ private static function getNumDataBytesAndNumEcBytesForBlockId(
+ int $numTotalBytes,
+ int $numDataBytes,
+ int $numRsBlocks,
+ int $blockId
+ ) : array {
+ if ($blockId >= $numRsBlocks) {
+ throw new WriterException('Block ID too large');
+ }
+
+ $numRsBlocksInGroup2 = $numTotalBytes % $numRsBlocks;
+ $numRsBlocksInGroup1 = $numRsBlocks - $numRsBlocksInGroup2;
+ $numTotalBytesInGroup1 = intdiv($numTotalBytes, $numRsBlocks);
+ $numTotalBytesInGroup2 = $numTotalBytesInGroup1 + 1;
+ $numDataBytesInGroup1 = intdiv($numDataBytes, $numRsBlocks);
+ $numDataBytesInGroup2 = $numDataBytesInGroup1 + 1;
+ $numEcBytesInGroup1 = $numTotalBytesInGroup1 - $numDataBytesInGroup1;
+ $numEcBytesInGroup2 = $numTotalBytesInGroup2 - $numDataBytesInGroup2;
+
+ if ($numEcBytesInGroup1 !== $numEcBytesInGroup2) {
+ throw new WriterException('EC bytes mismatch');
+ }
+
+ if ($numRsBlocks !== $numRsBlocksInGroup1 + $numRsBlocksInGroup2) {
+ throw new WriterException('RS blocks mismatch');
+ }
+
+ if ($numTotalBytes !==
+ (($numDataBytesInGroup1 + $numEcBytesInGroup1) * $numRsBlocksInGroup1)
+ + (($numDataBytesInGroup2 + $numEcBytesInGroup2) * $numRsBlocksInGroup2)
+ ) {
+ throw new WriterException('Total bytes mismatch');
+ }
+
+ if ($blockId < $numRsBlocksInGroup1) {
+ return [$numDataBytesInGroup1, $numEcBytesInGroup1];
+ } else {
+ return [$numDataBytesInGroup2, $numEcBytesInGroup2];
+ }
+ }
+
+ /**
+ * Interleaves data with EC bytes.
+ *
+ * @throws WriterException if number of bits and data bytes does not match
+ * @throws WriterException if data bytes does not match offset
+ * @throws WriterException if an interleaving error occurs
+ */
+ private static function interleaveWithEcBytes(
+ BitArray $bits,
+ int $numTotalBytes,
+ int $numDataBytes,
+ int $numRsBlocks
+ ) : BitArray {
+ if ($bits->getSizeInBytes() !== $numDataBytes) {
+ throw new WriterException('Number of bits and data bytes does not match');
+ }
+
+ $dataBytesOffset = 0;
+ $maxNumDataBytes = 0;
+ $maxNumEcBytes = 0;
+
+ $blocks = new SplFixedArray($numRsBlocks);
+
+ for ($i = 0; $i < $numRsBlocks; ++$i) {
+ list($numDataBytesInBlock, $numEcBytesInBlock) = self::getNumDataBytesAndNumEcBytesForBlockId(
+ $numTotalBytes,
+ $numDataBytes,
+ $numRsBlocks,
+ $i
+ );
+
+ $size = $numDataBytesInBlock;
+ $dataBytes = $bits->toBytes(8 * $dataBytesOffset, $size);
+ $ecBytes = self::generateEcBytes($dataBytes, $numEcBytesInBlock);
+ $blocks[$i] = new BlockPair($dataBytes, $ecBytes);
+
+ $maxNumDataBytes = max($maxNumDataBytes, $size);
+ $maxNumEcBytes = max($maxNumEcBytes, count($ecBytes));
+ $dataBytesOffset += $numDataBytesInBlock;
+ }
+
+ if ($numDataBytes !== $dataBytesOffset) {
+ throw new WriterException('Data bytes does not match offset');
+ }
+
+ $result = new BitArray();
+
+ for ($i = 0; $i < $maxNumDataBytes; ++$i) {
+ foreach ($blocks as $block) {
+ $dataBytes = $block->getDataBytes();
+
+ if ($i < count($dataBytes)) {
+ $result->appendBits($dataBytes[$i], 8);
+ }
+ }
+ }
+
+ for ($i = 0; $i < $maxNumEcBytes; ++$i) {
+ foreach ($blocks as $block) {
+ $ecBytes = $block->getErrorCorrectionBytes();
+
+ if ($i < count($ecBytes)) {
+ $result->appendBits($ecBytes[$i], 8);
+ }
+ }
+ }
+
+ if ($numTotalBytes !== $result->getSizeInBytes()) {
+ throw new WriterException(
+ 'Interleaving error: ' . $numTotalBytes . ' and ' . $result->getSizeInBytes() . ' differ'
+ );
+ }
+
+ return $result;
+ }
+
+ /**
+ * Generates EC bytes for given data.
+ *
+ * @param SplFixedArray $dataBytes
+ * @return SplFixedArray
+ */
+ private static function generateEcBytes(SplFixedArray $dataBytes, int $numEcBytesInBlock) : SplFixedArray
+ {
+ $numDataBytes = count($dataBytes);
+ $toEncode = new SplFixedArray($numDataBytes + $numEcBytesInBlock);
+
+ for ($i = 0; $i < $numDataBytes; $i++) {
+ $toEncode[$i] = $dataBytes[$i] & 0xff;
+ }
+
+ $ecBytes = new SplFixedArray($numEcBytesInBlock);
+ $codec = self::getCodec($numDataBytes, $numEcBytesInBlock);
+ $codec->encode($toEncode, $ecBytes);
+
+ return $ecBytes;
+ }
+
+ /**
+ * Gets an RS codec and caches it.
+ */
+ private static function getCodec(int $numDataBytes, int $numEcBytesInBlock) : ReedSolomonCodec
+ {
+ $cacheId = $numDataBytes . '-' . $numEcBytesInBlock;
+
+ if (isset(self::$codecs[$cacheId])) {
+ return self::$codecs[$cacheId];
+ }
+
+ return self::$codecs[$cacheId] = new ReedSolomonCodec(
+ 8,
+ 0x11d,
+ 0,
+ 1,
+ $numEcBytesInBlock,
+ 255 - $numDataBytes - $numEcBytesInBlock
+ );
+ }
+
+ /**
+ * Appends mode information to a bit array.
+ */
+ private static function appendModeInfo(Mode $mode, BitArray $bits) : void
+ {
+ $bits->appendBits($mode->getBits(), 4);
+ }
+
+ /**
+ * Appends length information to a bit array.
+ *
+ * @throws WriterException if num letters is bigger than expected
+ */
+ private static function appendLengthInfo(int $numLetters, Version $version, Mode $mode, BitArray $bits) : void
+ {
+ $numBits = $mode->getCharacterCountBits($version);
+
+ if ($numLetters >= (1 << $numBits)) {
+ throw new WriterException($numLetters . ' is bigger than ' . ((1 << $numBits) - 1));
+ }
+
+ $bits->appendBits($numLetters, $numBits);
+ }
+
+ /**
+ * Appends bytes to a bit array in a specific mode.
+ *
+ * @throws WriterException if an invalid mode was supplied
+ */
+ private static function appendBytes(string $content, Mode $mode, BitArray $bits, string $encoding) : void
+ {
+ switch ($mode) {
+ case Mode::NUMERIC():
+ self::appendNumericBytes($content, $bits);
+ break;
+
+ case Mode::ALPHANUMERIC():
+ self::appendAlphanumericBytes($content, $bits);
+ break;
+
+ case Mode::BYTE():
+ self::append8BitBytes($content, $bits, $encoding);
+ break;
+
+ case Mode::KANJI():
+ self::appendKanjiBytes($content, $bits);
+ break;
+
+ default:
+ throw new WriterException('Invalid mode: ' . $mode);
+ }
+ }
+
+ /**
+ * Appends numeric bytes to a bit array.
+ */
+ private static function appendNumericBytes(string $content, BitArray $bits) : void
+ {
+ $length = strlen($content);
+ $i = 0;
+
+ while ($i < $length) {
+ $num1 = (int) $content[$i];
+
+ if ($i + 2 < $length) {
+ // Encode three numeric letters in ten bits.
+ $num2 = (int) $content[$i + 1];
+ $num3 = (int) $content[$i + 2];
+ $bits->appendBits($num1 * 100 + $num2 * 10 + $num3, 10);
+ $i += 3;
+ } elseif ($i + 1 < $length) {
+ // Encode two numeric letters in seven bits.
+ $num2 = (int) $content[$i + 1];
+ $bits->appendBits($num1 * 10 + $num2, 7);
+ $i += 2;
+ } else {
+ // Encode one numeric letter in four bits.
+ $bits->appendBits($num1, 4);
+ ++$i;
+ }
+ }
+ }
+
+ /**
+ * Appends alpha-numeric bytes to a bit array.
+ *
+ * @throws WriterException if an invalid alphanumeric code was found
+ */
+ private static function appendAlphanumericBytes(string $content, BitArray $bits) : void
+ {
+ $length = strlen($content);
+ $i = 0;
+
+ while ($i < $length) {
+ $code1 = self::getAlphanumericCode(ord($content[$i]));
+
+ if (-1 === $code1) {
+ throw new WriterException('Invalid alphanumeric code');
+ }
+
+ if ($i + 1 < $length) {
+ $code2 = self::getAlphanumericCode(ord($content[$i + 1]));
+
+ if (-1 === $code2) {
+ throw new WriterException('Invalid alphanumeric code');
+ }
+
+ // Encode two alphanumeric letters in 11 bits.
+ $bits->appendBits($code1 * 45 + $code2, 11);
+ $i += 2;
+ } else {
+ // Encode one alphanumeric letter in six bits.
+ $bits->appendBits($code1, 6);
+ ++$i;
+ }
+ }
+ }
+
+ /**
+ * Appends regular 8-bit bytes to a bit array.
+ *
+ * @throws WriterException if content cannot be encoded to target encoding
+ */
+ private static function append8BitBytes(string $content, BitArray $bits, string $encoding) : void
+ {
+ $bytes = @iconv('utf-8', $encoding, $content);
+
+ if (false === $bytes) {
+ throw new WriterException('Could not encode content to ' . $encoding);
+ }
+
+ $length = strlen($bytes);
+
+ for ($i = 0; $i < $length; $i++) {
+ $bits->appendBits(ord($bytes[$i]), 8);
+ }
+ }
+
+ /**
+ * Appends KANJI bytes to a bit array.
+ *
+ * @throws WriterException if content does not seem to be encoded in SHIFT-JIS
+ * @throws WriterException if an invalid byte sequence occurs
+ */
+ private static function appendKanjiBytes(string $content, BitArray $bits) : void
+ {
+ $bytes = @iconv('utf-8', 'SHIFT-JIS', $content);
+
+ if (false === $bytes) {
+ throw new WriterException('Content could not be converted to SHIFT-JIS');
+ }
+
+ if (strlen($bytes) % 2 > 0) {
+ // We just do a simple length check here. The for loop will check
+ // individual characters.
+ throw new WriterException('Content does not seem to be encoded in SHIFT-JIS');
+ }
+
+ $length = strlen($bytes);
+
+ for ($i = 0; $i < $length; $i += 2) {
+ $byte1 = ord($bytes[$i]) & 0xff;
+ $byte2 = ord($bytes[$i + 1]) & 0xff;
+ $code = ($byte1 << 8) | $byte2;
+
+ if ($code >= 0x8140 && $code <= 0x9ffc) {
+ $subtracted = $code - 0x8140;
+ } elseif ($code >= 0xe040 && $code <= 0xebbf) {
+ $subtracted = $code - 0xc140;
+ } else {
+ throw new WriterException('Invalid byte sequence');
+ }
+
+ $encoded = (($subtracted >> 8) * 0xc0) + ($subtracted & 0xff);
+
+ $bits->appendBits($encoded, 13);
+ }
+ }
+
+ /**
+ * Appends ECI information to a bit array.
+ */
+ private static function appendEci(CharacterSetEci $eci, BitArray $bits) : void
+ {
+ $mode = Mode::ECI();
+ $bits->appendBits($mode->getBits(), 4);
+ $bits->appendBits($eci->getValue(), 8);
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Encoder/MaskUtil.php b/system/vendor/bacon/bacon-qr-code/src/Encoder/MaskUtil.php
new file mode 100644
index 0000000..54a07ba
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Encoder/MaskUtil.php
@@ -0,0 +1,271 @@
+getArray();
+ $width = $matrix->getWidth();
+ $height = $matrix->getHeight();
+
+ for ($y = 0; $y < $height - 1; ++$y) {
+ for ($x = 0; $x < $width - 1; ++$x) {
+ $value = $array[$y][$x];
+
+ if ($value === $array[$y][$x + 1]
+ && $value === $array[$y + 1][$x]
+ && $value === $array[$y + 1][$x + 1]
+ ) {
+ ++$penalty;
+ }
+ }
+ }
+
+ return self::N2 * $penalty;
+ }
+
+ /**
+ * Applies mask penalty rule 3 and returns the penalty.
+ *
+ * Finds consecutive cells of 00001011101 or 10111010000, and gives penalty
+ * to them. If we find patterns like 000010111010000, we give penalties
+ * twice (i.e. 40 * 2).
+ */
+ public static function applyMaskPenaltyRule3(ByteMatrix $matrix) : int
+ {
+ $penalty = 0;
+ $array = $matrix->getArray();
+ $width = $matrix->getWidth();
+ $height = $matrix->getHeight();
+
+ for ($y = 0; $y < $height; ++$y) {
+ for ($x = 0; $x < $width; ++$x) {
+ if ($x + 6 < $width
+ && 1 === $array[$y][$x]
+ && 0 === $array[$y][$x + 1]
+ && 1 === $array[$y][$x + 2]
+ && 1 === $array[$y][$x + 3]
+ && 1 === $array[$y][$x + 4]
+ && 0 === $array[$y][$x + 5]
+ && 1 === $array[$y][$x + 6]
+ && (
+ (
+ $x + 10 < $width
+ && 0 === $array[$y][$x + 7]
+ && 0 === $array[$y][$x + 8]
+ && 0 === $array[$y][$x + 9]
+ && 0 === $array[$y][$x + 10]
+ )
+ || (
+ $x - 4 >= 0
+ && 0 === $array[$y][$x - 1]
+ && 0 === $array[$y][$x - 2]
+ && 0 === $array[$y][$x - 3]
+ && 0 === $array[$y][$x - 4]
+ )
+ )
+ ) {
+ $penalty += self::N3;
+ }
+
+ if ($y + 6 < $height
+ && 1 === $array[$y][$x]
+ && 0 === $array[$y + 1][$x]
+ && 1 === $array[$y + 2][$x]
+ && 1 === $array[$y + 3][$x]
+ && 1 === $array[$y + 4][$x]
+ && 0 === $array[$y + 5][$x]
+ && 1 === $array[$y + 6][$x]
+ && (
+ (
+ $y + 10 < $height
+ && 0 === $array[$y + 7][$x]
+ && 0 === $array[$y + 8][$x]
+ && 0 === $array[$y + 9][$x]
+ && 0 === $array[$y + 10][$x]
+ )
+ || (
+ $y - 4 >= 0
+ && 0 === $array[$y - 1][$x]
+ && 0 === $array[$y - 2][$x]
+ && 0 === $array[$y - 3][$x]
+ && 0 === $array[$y - 4][$x]
+ )
+ )
+ ) {
+ $penalty += self::N3;
+ }
+ }
+ }
+
+ return $penalty;
+ }
+
+ /**
+ * Applies mask penalty rule 4 and returns the penalty.
+ *
+ * Calculates the ratio of dark cells and gives penalty if the ratio is far
+ * from 50%. It gives 10 penalty for 5% distance.
+ */
+ public static function applyMaskPenaltyRule4(ByteMatrix $matrix) : int
+ {
+ $numDarkCells = 0;
+
+ $array = $matrix->getArray();
+ $width = $matrix->getWidth();
+ $height = $matrix->getHeight();
+
+ for ($y = 0; $y < $height; ++$y) {
+ $arrayY = $array[$y];
+
+ for ($x = 0; $x < $width; ++$x) {
+ if (1 === $arrayY[$x]) {
+ ++$numDarkCells;
+ }
+ }
+ }
+
+ $numTotalCells = $height * $width;
+ $darkRatio = $numDarkCells / $numTotalCells;
+ $fixedPercentVariances = (int) (abs($darkRatio - 0.5) * 20);
+
+ return $fixedPercentVariances * self::N4;
+ }
+
+ /**
+ * Returns the mask bit for "getMaskPattern" at "x" and "y".
+ *
+ * See 8.8 of JISX0510:2004 for mask pattern conditions.
+ *
+ * @throws InvalidArgumentException if an invalid mask pattern was supplied
+ */
+ public static function getDataMaskBit(int $maskPattern, int $x, int $y) : bool
+ {
+ switch ($maskPattern) {
+ case 0:
+ $intermediate = ($y + $x) & 0x1;
+ break;
+
+ case 1:
+ $intermediate = $y & 0x1;
+ break;
+
+ case 2:
+ $intermediate = $x % 3;
+ break;
+
+ case 3:
+ $intermediate = ($y + $x) % 3;
+ break;
+
+ case 4:
+ $intermediate = (BitUtils::unsignedRightShift($y, 1) + (int) ($x / 3)) & 0x1;
+ break;
+
+ case 5:
+ $temp = $y * $x;
+ $intermediate = ($temp & 0x1) + ($temp % 3);
+ break;
+
+ case 6:
+ $temp = $y * $x;
+ $intermediate = (($temp & 0x1) + ($temp % 3)) & 0x1;
+ break;
+
+ case 7:
+ $temp = $y * $x;
+ $intermediate = (($temp % 3) + (($y + $x) & 0x1)) & 0x1;
+ break;
+
+ default:
+ throw new InvalidArgumentException('Invalid mask pattern: ' . $maskPattern);
+ }
+
+ return 0 == $intermediate;
+ }
+
+ /**
+ * Helper function for applyMaskPenaltyRule1.
+ *
+ * We need this for doing this calculation in both vertical and horizontal
+ * orders respectively.
+ */
+ private static function applyMaskPenaltyRule1Internal(ByteMatrix $matrix, bool $isHorizontal) : int
+ {
+ $penalty = 0;
+ $iLimit = $isHorizontal ? $matrix->getHeight() : $matrix->getWidth();
+ $jLimit = $isHorizontal ? $matrix->getWidth() : $matrix->getHeight();
+ $array = $matrix->getArray();
+
+ for ($i = 0; $i < $iLimit; ++$i) {
+ $numSameBitCells = 0;
+ $prevBit = -1;
+
+ for ($j = 0; $j < $jLimit; $j++) {
+ $bit = $isHorizontal ? $array[$i][$j] : $array[$j][$i];
+
+ if ($bit === $prevBit) {
+ ++$numSameBitCells;
+ } else {
+ if ($numSameBitCells >= 5) {
+ $penalty += self::N1 + ($numSameBitCells - 5);
+ }
+
+ $numSameBitCells = 1;
+ $prevBit = $bit;
+ }
+ }
+
+ if ($numSameBitCells >= 5) {
+ $penalty += self::N1 + ($numSameBitCells - 5);
+ }
+ }
+
+ return $penalty;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Encoder/MatrixUtil.php b/system/vendor/bacon/bacon-qr-code/src/Encoder/MatrixUtil.php
new file mode 100644
index 0000000..0967e29
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Encoder/MatrixUtil.php
@@ -0,0 +1,513 @@
+clear(-1);
+ }
+
+ /**
+ * Builds a complete matrix.
+ */
+ public static function buildMatrix(
+ BitArray $dataBits,
+ ErrorCorrectionLevel $level,
+ Version $version,
+ int $maskPattern,
+ ByteMatrix $matrix
+ ) : void {
+ self::clearMatrix($matrix);
+ self::embedBasicPatterns($version, $matrix);
+ self::embedTypeInfo($level, $maskPattern, $matrix);
+ self::maybeEmbedVersionInfo($version, $matrix);
+ self::embedDataBits($dataBits, $maskPattern, $matrix);
+ }
+
+ /**
+ * Removes the position detection patterns from a matrix.
+ *
+ * This can be useful if you need to render those patterns separately.
+ */
+ public static function removePositionDetectionPatterns(ByteMatrix $matrix) : void
+ {
+ $pdpWidth = count(self::POSITION_DETECTION_PATTERN[0]);
+
+ self::removePositionDetectionPattern(0, 0, $matrix);
+ self::removePositionDetectionPattern($matrix->getWidth() - $pdpWidth, 0, $matrix);
+ self::removePositionDetectionPattern(0, $matrix->getWidth() - $pdpWidth, $matrix);
+ }
+
+ /**
+ * Embeds type information into a matrix.
+ */
+ private static function embedTypeInfo(ErrorCorrectionLevel $level, int $maskPattern, ByteMatrix $matrix) : void
+ {
+ $typeInfoBits = new BitArray();
+ self::makeTypeInfoBits($level, $maskPattern, $typeInfoBits);
+
+ $typeInfoBitsSize = $typeInfoBits->getSize();
+
+ for ($i = 0; $i < $typeInfoBitsSize; ++$i) {
+ $bit = $typeInfoBits->get($typeInfoBitsSize - 1 - $i);
+
+ $x1 = self::TYPE_INFO_COORDINATES[$i][0];
+ $y1 = self::TYPE_INFO_COORDINATES[$i][1];
+
+ $matrix->set($x1, $y1, (int) $bit);
+
+ if ($i < 8) {
+ $x2 = $matrix->getWidth() - $i - 1;
+ $y2 = 8;
+ } else {
+ $x2 = 8;
+ $y2 = $matrix->getHeight() - 7 + ($i - 8);
+ }
+
+ $matrix->set($x2, $y2, (int) $bit);
+ }
+ }
+
+ /**
+ * Generates type information bits and appends them to a bit array.
+ *
+ * @throws RuntimeException if bit array resulted in invalid size
+ */
+ private static function makeTypeInfoBits(ErrorCorrectionLevel $level, int $maskPattern, BitArray $bits) : void
+ {
+ $typeInfo = ($level->getBits() << 3) | $maskPattern;
+ $bits->appendBits($typeInfo, 5);
+
+ $bchCode = self::calculateBchCode($typeInfo, self::TYPE_INFO_POLY);
+ $bits->appendBits($bchCode, 10);
+
+ $maskBits = new BitArray();
+ $maskBits->appendBits(self::TYPE_INFO_MASK_PATTERN, 15);
+ $bits->xorBits($maskBits);
+
+ if (15 !== $bits->getSize()) {
+ throw new RuntimeException('Bit array resulted in invalid size: ' . $bits->getSize());
+ }
+ }
+
+ /**
+ * Embeds version information if required.
+ */
+ private static function maybeEmbedVersionInfo(Version $version, ByteMatrix $matrix) : void
+ {
+ if ($version->getVersionNumber() < 7) {
+ return;
+ }
+
+ $versionInfoBits = new BitArray();
+ self::makeVersionInfoBits($version, $versionInfoBits);
+
+ $bitIndex = 6 * 3 - 1;
+
+ for ($i = 0; $i < 6; ++$i) {
+ for ($j = 0; $j < 3; ++$j) {
+ $bit = $versionInfoBits->get($bitIndex);
+ --$bitIndex;
+
+ $matrix->set($i, $matrix->getHeight() - 11 + $j, (int) $bit);
+ $matrix->set($matrix->getHeight() - 11 + $j, $i, (int) $bit);
+ }
+ }
+ }
+
+ /**
+ * Generates version information bits and appends them to a bit array.
+ *
+ * @throws RuntimeException if bit array resulted in invalid size
+ */
+ private static function makeVersionInfoBits(Version $version, BitArray $bits) : void
+ {
+ $bits->appendBits($version->getVersionNumber(), 6);
+
+ $bchCode = self::calculateBchCode($version->getVersionNumber(), self::VERSION_INFO_POLY);
+ $bits->appendBits($bchCode, 12);
+
+ if (18 !== $bits->getSize()) {
+ throw new RuntimeException('Bit array resulted in invalid size: ' . $bits->getSize());
+ }
+ }
+
+ /**
+ * Calculates the BCH code for a value and a polynomial.
+ */
+ private static function calculateBchCode(int $value, int $poly) : int
+ {
+ $msbSetInPoly = self::findMsbSet($poly);
+ $value <<= $msbSetInPoly - 1;
+
+ while (self::findMsbSet($value) >= $msbSetInPoly) {
+ $value ^= $poly << (self::findMsbSet($value) - $msbSetInPoly);
+ }
+
+ return $value;
+ }
+
+ /**
+ * Finds and MSB set.
+ */
+ private static function findMsbSet(int $value) : int
+ {
+ $numDigits = 0;
+
+ while (0 !== $value) {
+ $value >>= 1;
+ ++$numDigits;
+ }
+
+ return $numDigits;
+ }
+
+ /**
+ * Embeds basic patterns into a matrix.
+ */
+ private static function embedBasicPatterns(Version $version, ByteMatrix $matrix) : void
+ {
+ self::embedPositionDetectionPatternsAndSeparators($matrix);
+ self::embedDarkDotAtLeftBottomCorner($matrix);
+ self::maybeEmbedPositionAdjustmentPatterns($version, $matrix);
+ self::embedTimingPatterns($matrix);
+ }
+
+ /**
+ * Embeds position detection patterns and separators into a byte matrix.
+ */
+ private static function embedPositionDetectionPatternsAndSeparators(ByteMatrix $matrix) : void
+ {
+ $pdpWidth = count(self::POSITION_DETECTION_PATTERN[0]);
+
+ self::embedPositionDetectionPattern(0, 0, $matrix);
+ self::embedPositionDetectionPattern($matrix->getWidth() - $pdpWidth, 0, $matrix);
+ self::embedPositionDetectionPattern(0, $matrix->getWidth() - $pdpWidth, $matrix);
+
+ $hspWidth = 8;
+
+ self::embedHorizontalSeparationPattern(0, $hspWidth - 1, $matrix);
+ self::embedHorizontalSeparationPattern($matrix->getWidth() - $hspWidth, $hspWidth - 1, $matrix);
+ self::embedHorizontalSeparationPattern(0, $matrix->getWidth() - $hspWidth, $matrix);
+
+ $vspSize = 7;
+
+ self::embedVerticalSeparationPattern($vspSize, 0, $matrix);
+ self::embedVerticalSeparationPattern($matrix->getHeight() - $vspSize - 1, 0, $matrix);
+ self::embedVerticalSeparationPattern($vspSize, $matrix->getHeight() - $vspSize, $matrix);
+ }
+
+ /**
+ * Embeds a single position detection pattern into a byte matrix.
+ */
+ private static function embedPositionDetectionPattern(int $xStart, int $yStart, ByteMatrix $matrix) : void
+ {
+ for ($y = 0; $y < 7; ++$y) {
+ for ($x = 0; $x < 7; ++$x) {
+ $matrix->set($xStart + $x, $yStart + $y, self::POSITION_DETECTION_PATTERN[$y][$x]);
+ }
+ }
+ }
+
+ private static function removePositionDetectionPattern(int $xStart, int $yStart, ByteMatrix $matrix) : void
+ {
+ for ($y = 0; $y < 7; ++$y) {
+ for ($x = 0; $x < 7; ++$x) {
+ $matrix->set($xStart + $x, $yStart + $y, 0);
+ }
+ }
+ }
+
+ /**
+ * Embeds a single horizontal separation pattern.
+ *
+ * @throws RuntimeException if a byte was already set
+ */
+ private static function embedHorizontalSeparationPattern(int $xStart, int $yStart, ByteMatrix $matrix) : void
+ {
+ for ($x = 0; $x < 8; $x++) {
+ if (-1 !== $matrix->get($xStart + $x, $yStart)) {
+ throw new RuntimeException('Byte already set');
+ }
+
+ $matrix->set($xStart + $x, $yStart, 0);
+ }
+ }
+
+ /**
+ * Embeds a single vertical separation pattern.
+ *
+ * @throws RuntimeException if a byte was already set
+ */
+ private static function embedVerticalSeparationPattern(int $xStart, int $yStart, ByteMatrix $matrix) : void
+ {
+ for ($y = 0; $y < 7; $y++) {
+ if (-1 !== $matrix->get($xStart, $yStart + $y)) {
+ throw new RuntimeException('Byte already set');
+ }
+
+ $matrix->set($xStart, $yStart + $y, 0);
+ }
+ }
+
+ /**
+ * Embeds a dot at the left bottom corner.
+ *
+ * @throws RuntimeException if a byte was already set to 0
+ */
+ private static function embedDarkDotAtLeftBottomCorner(ByteMatrix $matrix) : void
+ {
+ if (0 === $matrix->get(8, $matrix->getHeight() - 8)) {
+ throw new RuntimeException('Byte already set to 0');
+ }
+
+ $matrix->set(8, $matrix->getHeight() - 8, 1);
+ }
+
+ /**
+ * Embeds position adjustment patterns if required.
+ */
+ private static function maybeEmbedPositionAdjustmentPatterns(Version $version, ByteMatrix $matrix) : void
+ {
+ if ($version->getVersionNumber() < 2) {
+ return;
+ }
+
+ $index = $version->getVersionNumber() - 1;
+
+ $coordinates = self::POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[$index];
+ $numCoordinates = count($coordinates);
+
+ for ($i = 0; $i < $numCoordinates; ++$i) {
+ for ($j = 0; $j < $numCoordinates; ++$j) {
+ $y = $coordinates[$i];
+ $x = $coordinates[$j];
+
+ if (null === $x || null === $y) {
+ continue;
+ }
+
+ if (-1 === $matrix->get($x, $y)) {
+ self::embedPositionAdjustmentPattern($x - 2, $y - 2, $matrix);
+ }
+ }
+ }
+ }
+
+ /**
+ * Embeds a single position adjustment pattern.
+ */
+ private static function embedPositionAdjustmentPattern(int $xStart, int $yStart, ByteMatrix $matrix) : void
+ {
+ for ($y = 0; $y < 5; $y++) {
+ for ($x = 0; $x < 5; $x++) {
+ $matrix->set($xStart + $x, $yStart + $y, self::POSITION_ADJUSTMENT_PATTERN[$y][$x]);
+ }
+ }
+ }
+
+ /**
+ * Embeds timing patterns into a matrix.
+ */
+ private static function embedTimingPatterns(ByteMatrix $matrix) : void
+ {
+ $matrixWidth = $matrix->getWidth();
+
+ for ($i = 8; $i < $matrixWidth - 8; ++$i) {
+ $bit = ($i + 1) % 2;
+
+ if (-1 === $matrix->get($i, 6)) {
+ $matrix->set($i, 6, $bit);
+ }
+
+ if (-1 === $matrix->get(6, $i)) {
+ $matrix->set(6, $i, $bit);
+ }
+ }
+ }
+
+ /**
+ * Embeds "dataBits" using "getMaskPattern".
+ *
+ * For debugging purposes, it skips masking process if "getMaskPattern" is -1. See 8.7 of JISX0510:2004 (p.38) for
+ * how to embed data bits.
+ *
+ * @throws WriterException if not all bits could be consumed
+ */
+ private static function embedDataBits(BitArray $dataBits, int $maskPattern, ByteMatrix $matrix) : void
+ {
+ $bitIndex = 0;
+ $direction = -1;
+
+ // Start from the right bottom cell.
+ $x = $matrix->getWidth() - 1;
+ $y = $matrix->getHeight() - 1;
+
+ while ($x > 0) {
+ // Skip vertical timing pattern.
+ if (6 === $x) {
+ --$x;
+ }
+
+ while ($y >= 0 && $y < $matrix->getHeight()) {
+ for ($i = 0; $i < 2; $i++) {
+ $xx = $x - $i;
+
+ // Skip the cell if it's not empty.
+ if (-1 !== $matrix->get($xx, $y)) {
+ continue;
+ }
+
+ if ($bitIndex < $dataBits->getSize()) {
+ $bit = $dataBits->get($bitIndex);
+ ++$bitIndex;
+ } else {
+ // Padding bit. If there is no bit left, we'll fill the
+ // left cells with 0, as described in 8.4.9 of
+ // JISX0510:2004 (p. 24).
+ $bit = false;
+ }
+
+ // Skip masking if maskPattern is -1.
+ if (-1 !== $maskPattern && MaskUtil::getDataMaskBit($maskPattern, $xx, $y)) {
+ $bit = ! $bit;
+ }
+
+ $matrix->set($xx, $y, (int) $bit);
+ }
+
+ $y += $direction;
+ }
+
+ $direction = -$direction;
+ $y += $direction;
+ $x -= 2;
+ }
+
+ // All bits should be consumed
+ if ($dataBits->getSize() !== $bitIndex) {
+ throw new WriterException('Not all bits consumed (' . $bitIndex . ' out of ' . $dataBits->getSize() .')');
+ }
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Encoder/QrCode.php b/system/vendor/bacon/bacon-qr-code/src/Encoder/QrCode.php
new file mode 100644
index 0000000..c3398f4
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Encoder/QrCode.php
@@ -0,0 +1,108 @@
+maskPattern = $maskPattern;
+ $this->matrix = $matrix;
+ }
+
+ /**
+ * Gets the mode.
+ */
+ public function getMode() : Mode
+ {
+ return $this->mode;
+ }
+
+ /**
+ * Gets the EC level.
+ */
+ public function getErrorCorrectionLevel() : ErrorCorrectionLevel
+ {
+ return $this->errorCorrectionLevel;
+ }
+
+ /**
+ * Gets the version.
+ */
+ public function getVersion() : Version
+ {
+ return $this->version;
+ }
+
+ /**
+ * Gets the mask pattern.
+ */
+ public function getMaskPattern() : int
+ {
+ return $this->maskPattern;
+ }
+
+ public function getMatrix(): ByteMatrix
+ {
+ return $this->matrix;
+ }
+
+ /**
+ * Validates whether a mask pattern is valid.
+ */
+ public static function isValidMaskPattern(int $maskPattern) : bool
+ {
+ return $maskPattern > 0 && $maskPattern < self::NUM_MASK_PATTERNS;
+ }
+
+ /**
+ * Returns a string representation of the QR code.
+ */
+ public function __toString() : string
+ {
+ $result = "<<\n"
+ . ' mode: ' . $this->mode . "\n"
+ . ' ecLevel: ' . $this->errorCorrectionLevel . "\n"
+ . ' version: ' . $this->version . "\n"
+ . ' maskPattern: ' . $this->maskPattern . "\n";
+
+ if ($this->matrix === null) {
+ $result .= " matrix: null\n";
+ } else {
+ $result .= " matrix:\n";
+ $result .= $this->matrix;
+ }
+
+ $result .= ">>\n";
+
+ return $result;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Exception/ExceptionInterface.php b/system/vendor/bacon/bacon-qr-code/src/Exception/ExceptionInterface.php
new file mode 100644
index 0000000..6f70c20
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Exception/ExceptionInterface.php
@@ -0,0 +1,10 @@
+ 100) {
+ throw new Exception\InvalidArgumentException('Alpha must be between 0 and 100');
+ }
+ }
+
+ public function getAlpha() : int
+ {
+ return $this->alpha;
+ }
+
+ public function getBaseColor() : ColorInterface
+ {
+ return $this->baseColor;
+ }
+
+ public function toRgb() : Rgb
+ {
+ return $this->baseColor->toRgb();
+ }
+
+ public function toCmyk() : Cmyk
+ {
+ return $this->baseColor->toCmyk();
+ }
+
+ public function toGray() : Gray
+ {
+ return $this->baseColor->toGray();
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Color/Cmyk.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Color/Cmyk.php
new file mode 100644
index 0000000..d028210
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Color/Cmyk.php
@@ -0,0 +1,82 @@
+ 100) {
+ throw new Exception\InvalidArgumentException('Cyan must be between 0 and 100');
+ }
+
+ if ($magenta < 0 || $magenta > 100) {
+ throw new Exception\InvalidArgumentException('Magenta must be between 0 and 100');
+ }
+
+ if ($yellow < 0 || $yellow > 100) {
+ throw new Exception\InvalidArgumentException('Yellow must be between 0 and 100');
+ }
+
+ if ($black < 0 || $black > 100) {
+ throw new Exception\InvalidArgumentException('Black must be between 0 and 100');
+ }
+ }
+
+ public function getCyan() : int
+ {
+ return $this->cyan;
+ }
+
+ public function getMagenta() : int
+ {
+ return $this->magenta;
+ }
+
+ public function getYellow() : int
+ {
+ return $this->yellow;
+ }
+
+ public function getBlack() : int
+ {
+ return $this->black;
+ }
+
+ public function toRgb() : Rgb
+ {
+ $k = $this->black / 100;
+ $c = (-$k * $this->cyan + $k * 100 + $this->cyan) / 100;
+ $m = (-$k * $this->magenta + $k * 100 + $this->magenta) / 100;
+ $y = (-$k * $this->yellow + $k * 100 + $this->yellow) / 100;
+
+ return new Rgb(
+ (int) (-$c * 255 + 255),
+ (int) (-$m * 255 + 255),
+ (int) (-$y * 255 + 255)
+ );
+ }
+
+ public function toCmyk() : Cmyk
+ {
+ return $this;
+ }
+
+ public function toGray() : Gray
+ {
+ return $this->toRgb()->toGray();
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Color/ColorInterface.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Color/ColorInterface.php
new file mode 100644
index 0000000..b50d1ca
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Color/ColorInterface.php
@@ -0,0 +1,22 @@
+ 100) {
+ throw new Exception\InvalidArgumentException('Gray must be between 0 and 100');
+ }
+ }
+
+ public function getGray() : int
+ {
+ return $this->gray;
+ }
+
+ public function toRgb() : Rgb
+ {
+ return new Rgb((int) ($this->gray * 2.55), (int) ($this->gray * 2.55), (int) ($this->gray * 2.55));
+ }
+
+ public function toCmyk() : Cmyk
+ {
+ return new Cmyk(0, 0, 0, 100 - $this->gray);
+ }
+
+ public function toGray() : Gray
+ {
+ return $this;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Color/Rgb.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Color/Rgb.php
new file mode 100644
index 0000000..9e388da
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Color/Rgb.php
@@ -0,0 +1,73 @@
+ 255) {
+ throw new Exception\InvalidArgumentException('Red must be between 0 and 255');
+ }
+
+ if ($green < 0 || $green > 255) {
+ throw new Exception\InvalidArgumentException('Green must be between 0 and 255');
+ }
+
+ if ($blue < 0 || $blue > 255) {
+ throw new Exception\InvalidArgumentException('Blue must be between 0 and 255');
+ }
+ }
+
+ public function getRed() : int
+ {
+ return $this->red;
+ }
+
+ public function getGreen() : int
+ {
+ return $this->green;
+ }
+
+ public function getBlue() : int
+ {
+ return $this->blue;
+ }
+
+ public function toRgb() : Rgb
+ {
+ return $this;
+ }
+
+ public function toCmyk() : Cmyk
+ {
+ $c = 1 - ($this->red / 255);
+ $m = 1 - ($this->green / 255);
+ $y = 1 - ($this->blue / 255);
+ $k = min($c, $m, $y);
+
+ if ($k === 0) {
+ return new Cmyk(0, 0, 0, 0);
+ }
+
+ return new Cmyk(
+ (int) (100 * ($c - $k) / (1 - $k)),
+ (int) (100 * ($m - $k) / (1 - $k)),
+ (int) (100 * ($y - $k) / (1 - $k)),
+ (int) (100 * $k)
+ );
+ }
+
+ public function toGray() : Gray
+ {
+ return new Gray((int) (($this->red * 0.21 + $this->green * 0.71 + $this->blue * 0.07) / 2.55));
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Eye/CompositeEye.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Eye/CompositeEye.php
new file mode 100644
index 0000000..379e5c7
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Eye/CompositeEye.php
@@ -0,0 +1,26 @@
+externalEye->getExternalPath();
+ }
+
+ public function getInternalPath() : Path
+ {
+ return $this->internalEye->getInternalPath();
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Eye/EyeInterface.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Eye/EyeInterface.php
new file mode 100644
index 0000000..ab68f3c
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Eye/EyeInterface.php
@@ -0,0 +1,26 @@
+set($x, 0, 1);
+ $matrix->set($x, 6, 1);
+ }
+
+ for ($y = 1; $y < 6; ++$y) {
+ $matrix->set(0, $y, 1);
+ $matrix->set(6, $y, 1);
+ }
+
+ return $this->module->createPath($matrix)->translate(-3.5, -3.5);
+ }
+
+ public function getInternalPath() : Path
+ {
+ $matrix = new ByteMatrix(3, 3);
+
+ for ($x = 0; $x < 3; ++$x) {
+ for ($y = 0; $y < 3; ++$y) {
+ $matrix->set($x, $y, 1);
+ }
+ }
+
+ return $this->module->createPath($matrix)->translate(-1.5, -1.5);
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Eye/PointyEye.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Eye/PointyEye.php
new file mode 100644
index 0000000..39c7d23
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Eye/PointyEye.php
@@ -0,0 +1,56 @@
+move(-3.5, 3.5)
+ ->line(-3.5, 0)
+ ->ellipticArc(3.5, 3.5, 0, false, true, 0, -3.5)
+ ->line(3.5, -3.5)
+ ->line(3.5, 3.5)
+ ->close()
+ ->move(2.5, 0)
+ ->ellipticArc(2.5, 2.5, 0, false, true, 0, 2.5)
+ ->ellipticArc(2.5, 2.5, 0, false, true, -2.5, 0)
+ ->ellipticArc(2.5, 2.5, 0, false, true, 0, -2.5)
+ ->ellipticArc(2.5, 2.5, 0, false, true, 2.5, 0)
+ ->close()
+ ;
+ }
+
+ public function getInternalPath() : Path
+ {
+ return (new Path())
+ ->move(1.5, 0)
+ ->ellipticArc(1.5, 1.5, 0., false, true, 0., 1.5)
+ ->ellipticArc(1.5, 1.5, 0., false, true, -1.5, 0.)
+ ->ellipticArc(1.5, 1.5, 0., false, true, 0., -1.5)
+ ->ellipticArc(1.5, 1.5, 0., false, true, 1.5, 0.)
+ ->close()
+ ;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Eye/SimpleCircleEye.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Eye/SimpleCircleEye.php
new file mode 100644
index 0000000..735d326
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Eye/SimpleCircleEye.php
@@ -0,0 +1,51 @@
+move(-3.5, -3.5)
+ ->line(3.5, -3.5)
+ ->line(3.5, 3.5)
+ ->line(-3.5, 3.5)
+ ->close()
+ ->move(-2.5, -2.5)
+ ->line(-2.5, 2.5)
+ ->line(2.5, 2.5)
+ ->line(2.5, -2.5)
+ ->close()
+ ;
+ }
+
+ public function getInternalPath() : Path
+ {
+ return (new Path())
+ ->move(1.5, 0)
+ ->ellipticArc(1.5, 1.5, 0., false, true, 0., 1.5)
+ ->ellipticArc(1.5, 1.5, 0., false, true, -1.5, 0.)
+ ->ellipticArc(1.5, 1.5, 0., false, true, 0., -1.5)
+ ->ellipticArc(1.5, 1.5, 0., false, true, 1.5, 0.)
+ ->close()
+ ;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Eye/SquareEye.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Eye/SquareEye.php
new file mode 100644
index 0000000..09bedfe
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Eye/SquareEye.php
@@ -0,0 +1,50 @@
+move(-3.5, -3.5)
+ ->line(3.5, -3.5)
+ ->line(3.5, 3.5)
+ ->line(-3.5, 3.5)
+ ->close()
+ ->move(-2.5, -2.5)
+ ->line(-2.5, 2.5)
+ ->line(2.5, 2.5)
+ ->line(2.5, -2.5)
+ ->close()
+ ;
+ }
+
+ public function getInternalPath() : Path
+ {
+ return (new Path())
+ ->move(-1.5, -1.5)
+ ->line(1.5, -1.5)
+ ->line(1.5, 1.5)
+ ->line(-1.5, 1.5)
+ ->close()
+ ;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/GDLibRenderer.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/GDLibRenderer.php
new file mode 100644
index 0000000..51164b9
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/GDLibRenderer.php
@@ -0,0 +1,238 @@
+
+ */
+ private array $colors;
+
+ public function __construct(
+ private int $size,
+ private int $margin = 4,
+ private string $imageFormat = 'png',
+ private int $compressionQuality = 9,
+ private ?Fill $fill = null
+ ) {
+ if (! extension_loaded('gd') || ! function_exists('gd_info')) {
+ throw new RuntimeException('You need to install the GD extension to use this back end');
+ }
+
+ if ($this->fill === null) {
+ $this->fill = Fill::default();
+ }
+ if ($this->fill->hasGradientFill()) {
+ throw new InvalidArgumentException('GDLibRenderer does not support gradients');
+ }
+ }
+
+ /**
+ * @throws InvalidArgumentException if matrix width doesn't match height
+ */
+ public function render(QrCode $qrCode): string
+ {
+ $matrix = $qrCode->getMatrix();
+ $matrixSize = $matrix->getWidth();
+
+ if ($matrixSize !== $matrix->getHeight()) {
+ throw new InvalidArgumentException('Matrix must have the same width and height');
+ }
+
+ MatrixUtil::removePositionDetectionPatterns($matrix);
+ $this->newImage();
+ $this->draw($matrix);
+
+ return $this->renderImage();
+ }
+
+ private function newImage(): void
+ {
+ $img = imagecreatetruecolor($this->size, $this->size);
+ if ($img === false) {
+ throw new RuntimeException('Failed to create image of that size');
+ }
+
+ $this->image = $img;
+ imagealphablending($this->image, false);
+ imagesavealpha($this->image, true);
+
+
+ $bg = $this->getColor($this->fill->getBackgroundColor());
+ imagefilledrectangle($this->image, 0, 0, $this->size, $this->size, $bg);
+ imagealphablending($this->image, true);
+ }
+
+ private function draw(ByteMatrix $matrix): void
+ {
+ $matrixSize = $matrix->getWidth();
+
+ $pointsOnSide = $matrix->getWidth() + $this->margin * 2;
+ $pointInPx = $this->size / $pointsOnSide;
+
+ $this->drawEye(0, 0, $pointInPx, $this->fill->getTopLeftEyeFill());
+ $this->drawEye($matrixSize - 7, 0, $pointInPx, $this->fill->getTopRightEyeFill());
+ $this->drawEye(0, $matrixSize - 7, $pointInPx, $this->fill->getBottomLeftEyeFill());
+
+ $rows = $matrix->getArray()->toArray();
+ $color = $this->getColor($this->fill->getForegroundColor());
+ for ($y = 0; $y < $matrixSize; $y += 1) {
+ for ($x = 0; $x < $matrixSize; $x += 1) {
+ if (! $rows[$y][$x]) {
+ continue;
+ }
+
+ $points = $this->normalizePoints([
+ ($this->margin + $x) * $pointInPx, ($this->margin + $y) * $pointInPx,
+ ($this->margin + $x + 1) * $pointInPx, ($this->margin + $y) * $pointInPx,
+ ($this->margin + $x + 1) * $pointInPx, ($this->margin + $y + 1) * $pointInPx,
+ ($this->margin + $x) * $pointInPx, ($this->margin + $y + 1) * $pointInPx,
+ ]);
+ imagefilledpolygon($this->image, $points, $color);
+ }
+ }
+ }
+
+ private function drawEye(int $xOffset, int $yOffset, float $pointInPx, EyeFill $eyeFill): void
+ {
+ $internalColor = $this->getColor($eyeFill->inheritsInternalColor()
+ ? $this->fill->getForegroundColor()
+ : $eyeFill->getInternalColor());
+
+ $externalColor = $this->getColor($eyeFill->inheritsExternalColor()
+ ? $this->fill->getForegroundColor()
+ : $eyeFill->getExternalColor());
+
+ for ($y = 0; $y < 7; $y += 1) {
+ for ($x = 0; $x < 7; $x += 1) {
+ if ((($y === 1 || $y === 5) && $x > 0 && $x < 6) || (($x === 1 || $x === 5) && $y > 0 && $y < 6)) {
+ continue;
+ }
+
+ $points = $this->normalizePoints([
+ ($this->margin + $x + $xOffset) * $pointInPx, ($this->margin + $y + $yOffset) * $pointInPx,
+ ($this->margin + $x + $xOffset + 1) * $pointInPx, ($this->margin + $y + $yOffset) * $pointInPx,
+ ($this->margin + $x + $xOffset + 1) * $pointInPx, ($this->margin + $y + $yOffset + 1) * $pointInPx,
+ ($this->margin + $x + $xOffset) * $pointInPx, ($this->margin + $y + $yOffset + 1) * $pointInPx,
+ ]);
+
+ if ($y > 1 && $y < 5 && $x > 1 && $x < 5) {
+ imagefilledpolygon($this->image, $points, $internalColor);
+ } else {
+ imagefilledpolygon($this->image, $points, $externalColor);
+ }
+ }
+ }
+ }
+
+ /**
+ * Normalize points will trim right and bottom line by 1 pixel.
+ * Otherwise pixels of neighbors are overlapping which leads to issue with transparency and small QR codes.
+ */
+ private function normalizePoints(array $points): array
+ {
+ $maxX = $maxY = 0;
+ for ($i = 0; $i < count($points); $i += 2) {
+ // Do manual round as GD just removes decimal part
+ $points[$i] = $newX = round($points[$i]);
+ $points[$i + 1] = $newY = round($points[$i + 1]);
+
+ $maxX = max($maxX, $newX);
+ $maxY = max($maxY, $newY);
+ }
+
+ // Do trimming only if there are 4 points (8 coordinates), assumes this is square.
+
+ for ($i = 0; $i < count($points); $i += 2) {
+ $points[$i] = min($points[$i], $maxX - 1);
+ $points[$i + 1] = min($points[$i + 1], $maxY - 1);
+ }
+
+ return $points;
+ }
+
+ private function renderImage(): string
+ {
+ ob_start();
+ $quality = $this->compressionQuality;
+ switch ($this->imageFormat) {
+ case 'png':
+ if ($quality > 9 || $quality < 0) {
+ $quality = 9;
+ }
+ imagepng($this->image, null, $quality);
+ break;
+
+ case 'gif':
+ imagegif($this->image, null);
+ break;
+
+ case 'jpeg':
+ case 'jpg':
+ if ($quality > 100 || $quality < 0) {
+ $quality = 85;
+ }
+ imagejpeg($this->image, null, $quality);
+ break;
+ default:
+ ob_end_clean();
+ throw new InvalidArgumentException(
+ 'Supported image formats are jpeg, png and gif, got: ' . $this->imageFormat
+ );
+ }
+
+ imagedestroy($this->image);
+ $this->colors = [];
+ $this->image = null;
+
+ return ob_get_clean();
+ }
+
+ private function getColor(ColorInterface $color): int
+ {
+ $alpha = 100;
+
+ if ($color instanceof Alpha) {
+ $alpha = $color->getAlpha();
+ $color = $color->getBaseColor();
+ }
+
+ $rgb = $color->toRgb();
+
+ $colorKey = sprintf('%02X%02X%02X%02X', $rgb->getRed(), $rgb->getGreen(), $rgb->getBlue(), $alpha);
+
+ if (! isset($this->colors[$colorKey])) {
+ $colorId = imagecolorallocatealpha(
+ $this->image,
+ $rgb->getRed(),
+ $rgb->getGreen(),
+ $rgb->getBlue(),
+ (int)((100 - $alpha) / 100 * 127) // Alpha for GD is in range 0 (opaque) - 127 (transparent)
+ );
+
+ if ($colorId === false) {
+ throw new RuntimeException('Failed to create color: #' . $colorKey);
+ }
+
+ $this->colors[$colorKey] = $colorId;
+ }
+
+ return $this->colors[$colorKey];
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Image/EpsImageBackEnd.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Image/EpsImageBackEnd.php
new file mode 100644
index 0000000..4269456
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Image/EpsImageBackEnd.php
@@ -0,0 +1,373 @@
+eps = "%!PS-Adobe-3.0 EPSF-3.0\n"
+ . "%%Creator: BaconQrCode\n"
+ . sprintf("%%%%BoundingBox: 0 0 %d %d \n", $size, $size)
+ . "%%BeginProlog\n"
+ . "save\n"
+ . "50 dict begin\n"
+ . "/q { gsave } bind def\n"
+ . "/Q { grestore } bind def\n"
+ . "/s { scale } bind def\n"
+ . "/t { translate } bind def\n"
+ . "/r { rotate } bind def\n"
+ . "/n { newpath } bind def\n"
+ . "/m { moveto } bind def\n"
+ . "/l { lineto } bind def\n"
+ . "/c { curveto } bind def\n"
+ . "/z { closepath } bind def\n"
+ . "/f { eofill } bind def\n"
+ . "/rgb { setrgbcolor } bind def\n"
+ . "/cmyk { setcmykcolor } bind def\n"
+ . "/gray { setgray } bind def\n"
+ . "%%EndProlog\n"
+ . "1 -1 s\n"
+ . sprintf("0 -%d t\n", $size);
+
+ if ($backgroundColor instanceof Alpha && 0 === $backgroundColor->getAlpha()) {
+ return;
+ }
+
+ $this->eps .= wordwrap(
+ '0 0 m'
+ . sprintf(' %s 0 l', (string) $size)
+ . sprintf(' %s %s l', (string) $size, (string) $size)
+ . sprintf(' 0 %s l', (string) $size)
+ . ' z'
+ . ' ' .$this->getColorSetString($backgroundColor) . " f\n",
+ 75,
+ "\n "
+ );
+ }
+
+ public function scale(float $size) : void
+ {
+ if (null === $this->eps) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $this->eps .= sprintf("%1\$s %1\$s s\n", round($size, self::PRECISION));
+ }
+
+ public function translate(float $x, float $y) : void
+ {
+ if (null === $this->eps) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $this->eps .= sprintf("%s %s t\n", round($x, self::PRECISION), round($y, self::PRECISION));
+ }
+
+ public function rotate(int $degrees) : void
+ {
+ if (null === $this->eps) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $this->eps .= sprintf("%d r\n", $degrees);
+ }
+
+ public function push() : void
+ {
+ if (null === $this->eps) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $this->eps .= "q\n";
+ }
+
+ public function pop() : void
+ {
+ if (null === $this->eps) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $this->eps .= "Q\n";
+ }
+
+ public function drawPathWithColor(Path $path, ColorInterface $color) : void
+ {
+ if (null === $this->eps) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $fromX = 0;
+ $fromY = 0;
+ $this->eps .= wordwrap(
+ 'n '
+ . $this->drawPathOperations($path, $fromX, $fromY)
+ . ' ' . $this->getColorSetString($color) . " f\n",
+ 75,
+ "\n "
+ );
+ }
+
+ public function drawPathWithGradient(
+ Path $path,
+ Gradient $gradient,
+ float $x,
+ float $y,
+ float $width,
+ float $height
+ ) : void {
+ if (null === $this->eps) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $fromX = 0;
+ $fromY = 0;
+ $this->eps .= wordwrap(
+ 'q n ' . $this->drawPathOperations($path, $fromX, $fromY) . "\n",
+ 75,
+ "\n "
+ );
+
+ $this->createGradientFill($gradient, $x, $y, $width, $height);
+ }
+
+ public function done() : string
+ {
+ if (null === $this->eps) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $this->eps .= "%%TRAILER\nend restore\n%%EOF";
+ $blob = $this->eps;
+ $this->eps = null;
+
+ return $blob;
+ }
+
+ private function drawPathOperations(Iterable $ops, &$fromX, &$fromY) : string
+ {
+ $pathData = [];
+
+ foreach ($ops as $op) {
+ switch (true) {
+ case $op instanceof Move:
+ $fromX = $toX = round($op->getX(), self::PRECISION);
+ $fromY = $toY = round($op->getY(), self::PRECISION);
+ $pathData[] = sprintf('%s %s m', $toX, $toY);
+ break;
+
+ case $op instanceof Line:
+ $fromX = $toX = round($op->getX(), self::PRECISION);
+ $fromY = $toY = round($op->getY(), self::PRECISION);
+ $pathData[] = sprintf('%s %s l', $toX, $toY);
+ break;
+
+ case $op instanceof EllipticArc:
+ $pathData[] = $this->drawPathOperations($op->toCurves($fromX, $fromY), $fromX, $fromY);
+ break;
+
+ case $op instanceof Curve:
+ $x1 = round($op->getX1(), self::PRECISION);
+ $y1 = round($op->getY1(), self::PRECISION);
+ $x2 = round($op->getX2(), self::PRECISION);
+ $y2 = round($op->getY2(), self::PRECISION);
+ $fromX = $x3 = round($op->getX3(), self::PRECISION);
+ $fromY = $y3 = round($op->getY3(), self::PRECISION);
+ $pathData[] = sprintf('%s %s %s %s %s %s c', $x1, $y1, $x2, $y2, $x3, $y3);
+ break;
+
+ case $op instanceof Close:
+ $pathData[] = 'z';
+ break;
+
+ default:
+ throw new RuntimeException('Unexpected draw operation: ' . get_class($op));
+ }
+ }
+
+ return implode(' ', $pathData);
+ }
+
+ private function createGradientFill(Gradient $gradient, float $x, float $y, float $width, float $height) : void
+ {
+ $startColor = $gradient->getStartColor();
+ $endColor = $gradient->getEndColor();
+
+ if ($startColor instanceof Alpha) {
+ $startColor = $startColor->getBaseColor();
+ }
+
+ $startColorType = get_class($startColor);
+
+ if (! in_array($startColorType, [Rgb::class, Cmyk::class, Gray::class])) {
+ $startColorType = Cmyk::class;
+ $startColor = $startColor->toCmyk();
+ }
+
+ if (get_class($endColor) !== $startColorType) {
+ switch ($startColorType) {
+ case Cmyk::class:
+ $endColor = $endColor->toCmyk();
+ break;
+
+ case Rgb::class:
+ $endColor = $endColor->toRgb();
+ break;
+
+ case Gray::class:
+ $endColor = $endColor->toGray();
+ break;
+ }
+ }
+
+ $this->eps .= "eoclip\n<<\n";
+
+ if ($gradient->getType() === GradientType::RADIAL()) {
+ $this->eps .= " /ShadingType 3\n";
+ } else {
+ $this->eps .= " /ShadingType 2\n";
+ }
+
+ $this->eps .= " /Extend [ true true ]\n"
+ . " /AntiAlias true\n";
+
+ switch ($startColorType) {
+ case Cmyk::class:
+ $this->eps .= " /ColorSpace /DeviceCMYK\n";
+ break;
+
+ case Rgb::class:
+ $this->eps .= " /ColorSpace /DeviceRGB\n";
+ break;
+
+ case Gray::class:
+ $this->eps .= " /ColorSpace /DeviceGray\n";
+ break;
+ }
+
+ switch ($gradient->getType()) {
+ case GradientType::HORIZONTAL():
+ $this->eps .= sprintf(
+ " /Coords [ %s %s %s %s ]\n",
+ round($x, self::PRECISION),
+ round($y, self::PRECISION),
+ round($x + $width, self::PRECISION),
+ round($y, self::PRECISION)
+ );
+ break;
+
+ case GradientType::VERTICAL():
+ $this->eps .= sprintf(
+ " /Coords [ %s %s %s %s ]\n",
+ round($x, self::PRECISION),
+ round($y, self::PRECISION),
+ round($x, self::PRECISION),
+ round($y + $height, self::PRECISION)
+ );
+ break;
+
+ case GradientType::DIAGONAL():
+ $this->eps .= sprintf(
+ " /Coords [ %s %s %s %s ]\n",
+ round($x, self::PRECISION),
+ round($y, self::PRECISION),
+ round($x + $width, self::PRECISION),
+ round($y + $height, self::PRECISION)
+ );
+ break;
+
+ case GradientType::INVERSE_DIAGONAL():
+ $this->eps .= sprintf(
+ " /Coords [ %s %s %s %s ]\n",
+ round($x, self::PRECISION),
+ round($y + $height, self::PRECISION),
+ round($x + $width, self::PRECISION),
+ round($y, self::PRECISION)
+ );
+ break;
+
+ case GradientType::RADIAL():
+ $centerX = ($x + $width) / 2;
+ $centerY = ($y + $height) / 2;
+
+ $this->eps .= sprintf(
+ " /Coords [ %s %s 0 %s %s %s ]\n",
+ round($centerX, self::PRECISION),
+ round($centerY, self::PRECISION),
+ round($centerX, self::PRECISION),
+ round($centerY, self::PRECISION),
+ round(max($width, $height) / 2, self::PRECISION)
+ );
+ break;
+ }
+
+ $this->eps .= " /Function\n"
+ . " <<\n"
+ . " /FunctionType 2\n"
+ . " /Domain [ 0 1 ]\n"
+ . sprintf(" /C0 [ %s ]\n", $this->getColorString($startColor))
+ . sprintf(" /C1 [ %s ]\n", $this->getColorString($endColor))
+ . " /N 1\n"
+ . " >>\n>>\nshfill\nQ\n";
+ }
+
+ private function getColorSetString(ColorInterface $color) : string
+ {
+ if ($color instanceof Rgb) {
+ return $this->getColorString($color) . ' rgb';
+ }
+
+ if ($color instanceof Cmyk) {
+ return $this->getColorString($color) . ' cmyk';
+ }
+
+ if ($color instanceof Gray) {
+ return $this->getColorString($color) . ' gray';
+ }
+
+ return $this->getColorSetString($color->toCmyk());
+ }
+
+ private function getColorString(ColorInterface $color) : string
+ {
+ if ($color instanceof Rgb) {
+ return sprintf('%s %s %s', $color->getRed() / 255, $color->getGreen() / 255, $color->getBlue() / 255);
+ }
+
+ if ($color instanceof Cmyk) {
+ return sprintf(
+ '%s %s %s %s',
+ $color->getCyan() / 100,
+ $color->getMagenta() / 100,
+ $color->getYellow() / 100,
+ $color->getBlack() / 100
+ );
+ }
+
+ if ($color instanceof Gray) {
+ return sprintf('%s', $color->getGray() / 100);
+ }
+
+ return $this->getColorString($color->toCmyk());
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Image/ImageBackEndInterface.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Image/ImageBackEndInterface.php
new file mode 100644
index 0000000..0935819
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Image/ImageBackEndInterface.php
@@ -0,0 +1,87 @@
+imageFormat = $imageFormat;
+ $this->compressionQuality = $compressionQuality;
+ }
+
+ public function new(int $size, ColorInterface $backgroundColor) : void
+ {
+ $this->image = new Imagick();
+ $this->image->newImage($size, $size, $this->getColorPixel($backgroundColor));
+ $this->image->setImageFormat($this->imageFormat);
+ $this->image->setCompressionQuality($this->compressionQuality);
+ $this->draw = new ImagickDraw();
+ $this->gradientCount = 0;
+ $this->matrices = [new TransformationMatrix()];
+ $this->matrixIndex = 0;
+ }
+
+ public function scale(float $size) : void
+ {
+ if (null === $this->draw) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $this->draw->scale($size, $size);
+ $this->matrices[$this->matrixIndex] = $this->matrices[$this->matrixIndex]
+ ->multiply(TransformationMatrix::scale($size));
+ }
+
+ public function translate(float $x, float $y) : void
+ {
+ if (null === $this->draw) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $this->draw->translate($x, $y);
+ $this->matrices[$this->matrixIndex] = $this->matrices[$this->matrixIndex]
+ ->multiply(TransformationMatrix::translate($x, $y));
+ }
+
+ public function rotate(int $degrees) : void
+ {
+ if (null === $this->draw) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $this->draw->rotate($degrees);
+ $this->matrices[$this->matrixIndex] = $this->matrices[$this->matrixIndex]
+ ->multiply(TransformationMatrix::rotate($degrees));
+ }
+
+ public function push() : void
+ {
+ if (null === $this->draw) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $this->draw->push();
+ $this->matrices[++$this->matrixIndex] = $this->matrices[$this->matrixIndex - 1];
+ }
+
+ public function pop() : void
+ {
+ if (null === $this->draw) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $this->draw->pop();
+ unset($this->matrices[$this->matrixIndex--]);
+ }
+
+ public function drawPathWithColor(Path $path, ColorInterface $color) : void
+ {
+ if (null === $this->draw) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $this->draw->setFillColor($this->getColorPixel($color));
+ $this->drawPath($path);
+ }
+
+ public function drawPathWithGradient(
+ Path $path,
+ Gradient $gradient,
+ float $x,
+ float $y,
+ float $width,
+ float $height
+ ) : void {
+ if (null === $this->draw) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $this->draw->setFillPatternURL('#' . $this->createGradientFill($gradient, $x, $y, $width, $height));
+ $this->drawPath($path);
+ }
+
+ public function done() : string
+ {
+ if (null === $this->draw) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $this->image->drawImage($this->draw);
+ $blob = $this->image->getImageBlob();
+ $this->draw->clear();
+ $this->image->clear();
+ $this->draw = null;
+ $this->image = null;
+ $this->gradientCount = null;
+
+ return $blob;
+ }
+
+ private function drawPath(Path $path) : void
+ {
+ $this->draw->pathStart();
+
+ foreach ($path as $op) {
+ switch (true) {
+ case $op instanceof Move:
+ $this->draw->pathMoveToAbsolute($op->getX(), $op->getY());
+ break;
+
+ case $op instanceof Line:
+ $this->draw->pathLineToAbsolute($op->getX(), $op->getY());
+ break;
+
+ case $op instanceof EllipticArc:
+ $this->draw->pathEllipticArcAbsolute(
+ $op->getXRadius(),
+ $op->getYRadius(),
+ $op->getXAxisAngle(),
+ $op->isLargeArc(),
+ $op->isSweep(),
+ $op->getX(),
+ $op->getY()
+ );
+ break;
+
+ case $op instanceof Curve:
+ $this->draw->pathCurveToAbsolute(
+ $op->getX1(),
+ $op->getY1(),
+ $op->getX2(),
+ $op->getY2(),
+ $op->getX3(),
+ $op->getY3()
+ );
+ break;
+
+ case $op instanceof Close:
+ $this->draw->pathClose();
+ break;
+
+ default:
+ throw new RuntimeException('Unexpected draw operation: ' . get_class($op));
+ }
+ }
+
+ $this->draw->pathFinish();
+ }
+
+ private function createGradientFill(Gradient $gradient, float $x, float $y, float $width, float $height) : string
+ {
+ list($width, $height) = $this->matrices[$this->matrixIndex]->apply($width, $height);
+
+ $startColor = $this->getColorPixel($gradient->getStartColor())->getColorAsString();
+ $endColor = $this->getColorPixel($gradient->getEndColor())->getColorAsString();
+ $gradientImage = new Imagick();
+
+ switch ($gradient->getType()) {
+ case GradientType::HORIZONTAL():
+ $gradientImage->newPseudoImage((int) $height, (int) $width, sprintf(
+ 'gradient:%s-%s',
+ $startColor,
+ $endColor
+ ));
+ $gradientImage->rotateImage('transparent', -90);
+ break;
+
+ case GradientType::VERTICAL():
+ $gradientImage->newPseudoImage((int) $width, (int) $height, sprintf(
+ 'gradient:%s-%s',
+ $startColor,
+ $endColor
+ ));
+ break;
+
+ case GradientType::DIAGONAL():
+ case GradientType::INVERSE_DIAGONAL():
+ $gradientImage->newPseudoImage((int) ($width * sqrt(2)), (int) ($height * sqrt(2)), sprintf(
+ 'gradient:%s-%s',
+ $startColor,
+ $endColor
+ ));
+
+ if (GradientType::DIAGONAL() === $gradient->getType()) {
+ $gradientImage->rotateImage('transparent', -45);
+ } else {
+ $gradientImage->rotateImage('transparent', -135);
+ }
+
+ $rotatedWidth = $gradientImage->getImageWidth();
+ $rotatedHeight = $gradientImage->getImageHeight();
+
+ $gradientImage->setImagePage($rotatedWidth, $rotatedHeight, 0, 0);
+ $gradientImage->cropImage(
+ intdiv($rotatedWidth, 2) - 2,
+ intdiv($rotatedHeight, 2) - 2,
+ intdiv($rotatedWidth, 4) + 1,
+ intdiv($rotatedWidth, 4) + 1
+ );
+ break;
+
+ case GradientType::RADIAL():
+ $gradientImage->newPseudoImage((int) $width, (int) $height, sprintf(
+ 'radial-gradient:%s-%s',
+ $startColor,
+ $endColor
+ ));
+ break;
+ }
+
+ $id = sprintf('g%d', ++$this->gradientCount);
+ $this->draw->pushPattern($id, 0, 0, $width, $height);
+ $this->draw->composite(Imagick::COMPOSITE_COPY, 0, 0, $width, $height, $gradientImage);
+ $this->draw->popPattern();
+ return $id;
+ }
+
+ private function getColorPixel(ColorInterface $color) : ImagickPixel
+ {
+ $alpha = 100;
+
+ if ($color instanceof Alpha) {
+ $alpha = $color->getAlpha();
+ $color = $color->getBaseColor();
+ }
+
+ if ($color instanceof Rgb) {
+ return new ImagickPixel(sprintf(
+ 'rgba(%d, %d, %d, %F)',
+ $color->getRed(),
+ $color->getGreen(),
+ $color->getBlue(),
+ $alpha / 100
+ ));
+ }
+
+ if ($color instanceof Cmyk) {
+ return new ImagickPixel(sprintf(
+ 'cmyka(%d, %d, %d, %d, %F)',
+ $color->getCyan(),
+ $color->getMagenta(),
+ $color->getYellow(),
+ $color->getBlack(),
+ $alpha / 100
+ ));
+ }
+
+ if ($color instanceof Gray) {
+ return new ImagickPixel(sprintf(
+ 'graya(%d%%, %F)',
+ $color->getGray(),
+ $alpha / 100
+ ));
+ }
+
+ return $this->getColorPixel(new Alpha($alpha, $color->toRgb()));
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Image/SvgImageBackEnd.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Image/SvgImageBackEnd.php
new file mode 100644
index 0000000..227afa7
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Image/SvgImageBackEnd.php
@@ -0,0 +1,359 @@
+xmlWriter = new XMLWriter();
+ $this->xmlWriter->openMemory();
+
+ $this->xmlWriter->startDocument('1.0', 'UTF-8');
+ $this->xmlWriter->startElement('svg');
+ $this->xmlWriter->writeAttribute('xmlns', 'http://www.w3.org/2000/svg');
+ $this->xmlWriter->writeAttribute('version', '1.1');
+ $this->xmlWriter->writeAttribute('width', (string) $size);
+ $this->xmlWriter->writeAttribute('height', (string) $size);
+ $this->xmlWriter->writeAttribute('viewBox', '0 0 '. $size . ' ' . $size);
+
+ $this->gradientCount = 0;
+ $this->currentStack = 0;
+ $this->stack[0] = 0;
+
+ $alpha = 1;
+
+ if ($backgroundColor instanceof Alpha) {
+ $alpha = $backgroundColor->getAlpha() / 100;
+ }
+
+ if (0 === $alpha) {
+ return;
+ }
+
+ $this->xmlWriter->startElement('rect');
+ $this->xmlWriter->writeAttribute('x', '0');
+ $this->xmlWriter->writeAttribute('y', '0');
+ $this->xmlWriter->writeAttribute('width', (string) $size);
+ $this->xmlWriter->writeAttribute('height', (string) $size);
+ $this->xmlWriter->writeAttribute('fill', $this->getColorString($backgroundColor));
+
+ if ($alpha < 1) {
+ $this->xmlWriter->writeAttribute('fill-opacity', (string) $alpha);
+ }
+
+ $this->xmlWriter->endElement();
+ }
+
+ public function scale(float $size) : void
+ {
+ if (null === $this->xmlWriter) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $this->xmlWriter->startElement('g');
+ $this->xmlWriter->writeAttribute(
+ 'transform',
+ sprintf(self::SCALE_FORMAT, round($size, self::PRECISION))
+ );
+ ++$this->stack[$this->currentStack];
+ }
+
+ public function translate(float $x, float $y) : void
+ {
+ if (null === $this->xmlWriter) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $this->xmlWriter->startElement('g');
+ $this->xmlWriter->writeAttribute(
+ 'transform',
+ sprintf(self::TRANSLATE_FORMAT, round($x, self::PRECISION), round($y, self::PRECISION))
+ );
+ ++$this->stack[$this->currentStack];
+ }
+
+ public function rotate(int $degrees) : void
+ {
+ if (null === $this->xmlWriter) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $this->xmlWriter->startElement('g');
+ $this->xmlWriter->writeAttribute('transform', sprintf('rotate(%d)', $degrees));
+ ++$this->stack[$this->currentStack];
+ }
+
+ public function push() : void
+ {
+ if (null === $this->xmlWriter) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $this->xmlWriter->startElement('g');
+ $this->stack[] = 1;
+ ++$this->currentStack;
+ }
+
+ public function pop() : void
+ {
+ if (null === $this->xmlWriter) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ for ($i = 0; $i < $this->stack[$this->currentStack]; ++$i) {
+ $this->xmlWriter->endElement();
+ }
+
+ array_pop($this->stack);
+ --$this->currentStack;
+ }
+
+ public function drawPathWithColor(Path $path, ColorInterface $color) : void
+ {
+ if (null === $this->xmlWriter) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $alpha = 1;
+
+ if ($color instanceof Alpha) {
+ $alpha = $color->getAlpha() / 100;
+ }
+
+ $this->startPathElement($path);
+ $this->xmlWriter->writeAttribute('fill', $this->getColorString($color));
+
+ if ($alpha < 1) {
+ $this->xmlWriter->writeAttribute('fill-opacity', (string) $alpha);
+ }
+
+ $this->xmlWriter->endElement();
+ }
+
+ public function drawPathWithGradient(
+ Path $path,
+ Gradient $gradient,
+ float $x,
+ float $y,
+ float $width,
+ float $height
+ ) : void {
+ if (null === $this->xmlWriter) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ $gradientId = $this->createGradientFill($gradient, $x, $y, $width, $height);
+ $this->startPathElement($path);
+ $this->xmlWriter->writeAttribute('fill', 'url(#' . $gradientId . ')');
+ $this->xmlWriter->endElement();
+ }
+
+ public function done() : string
+ {
+ if (null === $this->xmlWriter) {
+ throw new RuntimeException('No image has been started');
+ }
+
+ foreach ($this->stack as $openElements) {
+ for ($i = $openElements; $i > 0; --$i) {
+ $this->xmlWriter->endElement();
+ }
+ }
+
+ $this->xmlWriter->endDocument();
+ $blob = $this->xmlWriter->outputMemory(true);
+ $this->xmlWriter = null;
+ $this->stack = null;
+ $this->currentStack = null;
+ $this->gradientCount = null;
+
+ return $blob;
+ }
+
+ private function startPathElement(Path $path) : void
+ {
+ $pathData = [];
+
+ foreach ($path as $op) {
+ switch (true) {
+ case $op instanceof Move:
+ $pathData[] = sprintf(
+ 'M%s %s',
+ round($op->getX(), self::PRECISION),
+ round($op->getY(), self::PRECISION)
+ );
+ break;
+
+ case $op instanceof Line:
+ $pathData[] = sprintf(
+ 'L%s %s',
+ round($op->getX(), self::PRECISION),
+ round($op->getY(), self::PRECISION)
+ );
+ break;
+
+ case $op instanceof EllipticArc:
+ $pathData[] = sprintf(
+ 'A%s %s %s %u %u %s %s',
+ round($op->getXRadius(), self::PRECISION),
+ round($op->getYRadius(), self::PRECISION),
+ round($op->getXAxisAngle(), self::PRECISION),
+ $op->isLargeArc(),
+ $op->isSweep(),
+ round($op->getX(), self::PRECISION),
+ round($op->getY(), self::PRECISION)
+ );
+ break;
+
+ case $op instanceof Curve:
+ $pathData[] = sprintf(
+ 'C%s %s %s %s %s %s',
+ round($op->getX1(), self::PRECISION),
+ round($op->getY1(), self::PRECISION),
+ round($op->getX2(), self::PRECISION),
+ round($op->getY2(), self::PRECISION),
+ round($op->getX3(), self::PRECISION),
+ round($op->getY3(), self::PRECISION)
+ );
+ break;
+
+ case $op instanceof Close:
+ $pathData[] = 'Z';
+ break;
+
+ default:
+ throw new RuntimeException('Unexpected draw operation: ' . get_class($op));
+ }
+ }
+
+ $this->xmlWriter->startElement('path');
+ $this->xmlWriter->writeAttribute('fill-rule', 'evenodd');
+ $this->xmlWriter->writeAttribute('d', implode('', $pathData));
+ }
+
+ private function createGradientFill(Gradient $gradient, float $x, float $y, float $width, float $height) : string
+ {
+ $this->xmlWriter->startElement('defs');
+
+ $startColor = $gradient->getStartColor();
+ $endColor = $gradient->getEndColor();
+
+ if ($gradient->getType() === GradientType::RADIAL()) {
+ $this->xmlWriter->startElement('radialGradient');
+ } else {
+ $this->xmlWriter->startElement('linearGradient');
+ }
+
+ $this->xmlWriter->writeAttribute('gradientUnits', 'userSpaceOnUse');
+
+ switch ($gradient->getType()) {
+ case GradientType::HORIZONTAL():
+ $this->xmlWriter->writeAttribute('x1', (string) round($x, self::PRECISION));
+ $this->xmlWriter->writeAttribute('y1', (string) round($y, self::PRECISION));
+ $this->xmlWriter->writeAttribute('x2', (string) round($x + $width, self::PRECISION));
+ $this->xmlWriter->writeAttribute('y2', (string) round($y, self::PRECISION));
+ break;
+
+ case GradientType::VERTICAL():
+ $this->xmlWriter->writeAttribute('x1', (string) round($x, self::PRECISION));
+ $this->xmlWriter->writeAttribute('y1', (string) round($y, self::PRECISION));
+ $this->xmlWriter->writeAttribute('x2', (string) round($x, self::PRECISION));
+ $this->xmlWriter->writeAttribute('y2', (string) round($y + $height, self::PRECISION));
+ break;
+
+ case GradientType::DIAGONAL():
+ $this->xmlWriter->writeAttribute('x1', (string) round($x, self::PRECISION));
+ $this->xmlWriter->writeAttribute('y1', (string) round($y, self::PRECISION));
+ $this->xmlWriter->writeAttribute('x2', (string) round($x + $width, self::PRECISION));
+ $this->xmlWriter->writeAttribute('y2', (string) round($y + $height, self::PRECISION));
+ break;
+
+ case GradientType::INVERSE_DIAGONAL():
+ $this->xmlWriter->writeAttribute('x1', (string) round($x, self::PRECISION));
+ $this->xmlWriter->writeAttribute('y1', (string) round($y + $height, self::PRECISION));
+ $this->xmlWriter->writeAttribute('x2', (string) round($x + $width, self::PRECISION));
+ $this->xmlWriter->writeAttribute('y2', (string) round($y, self::PRECISION));
+ break;
+
+ case GradientType::RADIAL():
+ $this->xmlWriter->writeAttribute('cx', (string) round(($x + $width) / 2, self::PRECISION));
+ $this->xmlWriter->writeAttribute('cy', (string) round(($y + $height) / 2, self::PRECISION));
+ $this->xmlWriter->writeAttribute('r', (string) round(max($width, $height) / 2, self::PRECISION));
+ break;
+ }
+
+ $id = sprintf('g%d', ++$this->gradientCount);
+ $this->xmlWriter->writeAttribute('id', $id);
+
+ $this->xmlWriter->startElement('stop');
+ $this->xmlWriter->writeAttribute('offset', '0%');
+ $this->xmlWriter->writeAttribute('stop-color', $this->getColorString($startColor));
+
+ if ($startColor instanceof Alpha) {
+ $this->xmlWriter->writeAttribute('stop-opacity', (string) $startColor->getAlpha());
+ }
+
+ $this->xmlWriter->endElement();
+
+ $this->xmlWriter->startElement('stop');
+ $this->xmlWriter->writeAttribute('offset', '100%');
+ $this->xmlWriter->writeAttribute('stop-color', $this->getColorString($endColor));
+
+ if ($endColor instanceof Alpha) {
+ $this->xmlWriter->writeAttribute('stop-opacity', (string) $endColor->getAlpha());
+ }
+
+ $this->xmlWriter->endElement();
+
+ $this->xmlWriter->endElement();
+ $this->xmlWriter->endElement();
+
+ return $id;
+ }
+
+ private function getColorString(ColorInterface $color) : string
+ {
+ $color = $color->toRgb();
+
+ return sprintf(
+ '#%02x%02x%02x',
+ $color->getRed(),
+ $color->getGreen(),
+ $color->getBlue()
+ );
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Image/TransformationMatrix.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Image/TransformationMatrix.php
new file mode 100644
index 0000000..9b435a0
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Image/TransformationMatrix.php
@@ -0,0 +1,68 @@
+values = [1, 0, 0, 1, 0, 0];
+ }
+
+ public function multiply(self $other) : self
+ {
+ $matrix = new self();
+ $matrix->values[0] = $this->values[0] * $other->values[0] + $this->values[2] * $other->values[1];
+ $matrix->values[1] = $this->values[1] * $other->values[0] + $this->values[3] * $other->values[1];
+ $matrix->values[2] = $this->values[0] * $other->values[2] + $this->values[2] * $other->values[3];
+ $matrix->values[3] = $this->values[1] * $other->values[2] + $this->values[3] * $other->values[3];
+ $matrix->values[4] = $this->values[0] * $other->values[4] + $this->values[2] * $other->values[5]
+ + $this->values[4];
+ $matrix->values[5] = $this->values[1] * $other->values[4] + $this->values[3] * $other->values[5]
+ + $this->values[5];
+
+ return $matrix;
+ }
+
+ public static function scale(float $size) : self
+ {
+ $matrix = new self();
+ $matrix->values = [$size, 0, 0, $size, 0, 0];
+ return $matrix;
+ }
+
+ public static function translate(float $x, float $y) : self
+ {
+ $matrix = new self();
+ $matrix->values = [1, 0, 0, 1, $x, $y];
+ return $matrix;
+ }
+
+ public static function rotate(int $degrees) : self
+ {
+ $matrix = new self();
+ $rad = deg2rad($degrees);
+ $matrix->values = [cos($rad), sin($rad), -sin($rad), cos($rad), 0, 0];
+ return $matrix;
+ }
+
+
+ /**
+ * Applies this matrix onto a point and returns the resulting viewport point.
+ *
+ * @return float[]
+ */
+ public function apply(float $x, float $y) : array
+ {
+ return [
+ $x * $this->values[0] + $y * $this->values[2] + $this->values[4],
+ $x * $this->values[1] + $y * $this->values[3] + $this->values[5],
+ ];
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/ImageRenderer.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/ImageRenderer.php
new file mode 100644
index 0000000..0d33303
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/ImageRenderer.php
@@ -0,0 +1,150 @@
+rendererStyle->getSize();
+ $margin = $this->rendererStyle->getMargin();
+ $matrix = $qrCode->getMatrix();
+ $matrixSize = $matrix->getWidth();
+
+ if ($matrixSize !== $matrix->getHeight()) {
+ throw new InvalidArgumentException('Matrix must have the same width and height');
+ }
+
+ $totalSize = $matrixSize + ($margin * 2);
+ $moduleSize = $size / $totalSize;
+ $fill = $this->rendererStyle->getFill();
+
+ $this->imageBackEnd->new($size, $fill->getBackgroundColor());
+ $this->imageBackEnd->scale((float) $moduleSize);
+ $this->imageBackEnd->translate((float) $margin, (float) $margin);
+
+ $module = $this->rendererStyle->getModule();
+ $moduleMatrix = clone $matrix;
+ MatrixUtil::removePositionDetectionPatterns($moduleMatrix);
+ $modulePath = $this->drawEyes($matrixSize, $module->createPath($moduleMatrix));
+
+ if ($fill->hasGradientFill()) {
+ $this->imageBackEnd->drawPathWithGradient(
+ $modulePath,
+ $fill->getForegroundGradient(),
+ 0,
+ 0,
+ $matrixSize,
+ $matrixSize
+ );
+ } else {
+ $this->imageBackEnd->drawPathWithColor($modulePath, $fill->getForegroundColor());
+ }
+
+ return $this->imageBackEnd->done();
+ }
+
+ private function drawEyes(int $matrixSize, Path $modulePath) : Path
+ {
+ $fill = $this->rendererStyle->getFill();
+
+ $eye = $this->rendererStyle->getEye();
+ $externalPath = $eye->getExternalPath();
+ $internalPath = $eye->getInternalPath();
+
+ $modulePath = $this->drawEye(
+ $externalPath,
+ $internalPath,
+ $fill->getTopLeftEyeFill(),
+ 3.5,
+ 3.5,
+ 0,
+ $modulePath
+ );
+ $modulePath = $this->drawEye(
+ $externalPath,
+ $internalPath,
+ $fill->getTopRightEyeFill(),
+ $matrixSize - 3.5,
+ 3.5,
+ 90,
+ $modulePath
+ );
+ $modulePath = $this->drawEye(
+ $externalPath,
+ $internalPath,
+ $fill->getBottomLeftEyeFill(),
+ 3.5,
+ $matrixSize - 3.5,
+ -90,
+ $modulePath
+ );
+
+ return $modulePath;
+ }
+
+ private function drawEye(
+ Path $externalPath,
+ Path $internalPath,
+ EyeFill $fill,
+ float $xTranslation,
+ float $yTranslation,
+ int $rotation,
+ Path $modulePath
+ ) : Path {
+ if ($fill->inheritsBothColors()) {
+ return $modulePath
+ ->append(
+ $externalPath->rotate($rotation)->translate($xTranslation, $yTranslation)
+ )
+ ->append(
+ $internalPath->rotate($rotation)->translate($xTranslation, $yTranslation)
+ );
+ }
+
+ $this->imageBackEnd->push();
+ $this->imageBackEnd->translate($xTranslation, $yTranslation);
+
+ if (0 !== $rotation) {
+ $this->imageBackEnd->rotate($rotation);
+ }
+
+ if ($fill->inheritsExternalColor()) {
+ $modulePath = $modulePath->append(
+ $externalPath->rotate($rotation)->translate($xTranslation, $yTranslation)
+ );
+ } else {
+ $this->imageBackEnd->drawPathWithColor($externalPath, $fill->getExternalColor());
+ }
+
+ if ($fill->inheritsInternalColor()) {
+ $modulePath = $modulePath->append(
+ $internalPath->rotate($rotation)->translate($xTranslation, $yTranslation)
+ );
+ } else {
+ $this->imageBackEnd->drawPathWithColor($internalPath, $fill->getInternalColor());
+ }
+
+ $this->imageBackEnd->pop();
+
+ return $modulePath;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Module/DotsModule.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Module/DotsModule.php
new file mode 100644
index 0000000..c5d5c6f
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Module/DotsModule.php
@@ -0,0 +1,56 @@
+ 1) {
+ throw new InvalidArgumentException('Size must between 0 (exclusive) and 1 (inclusive)');
+ }
+ }
+
+ public function createPath(ByteMatrix $matrix) : Path
+ {
+ $width = $matrix->getWidth();
+ $height = $matrix->getHeight();
+ $path = new Path();
+ $halfSize = $this->size / 2;
+ $margin = (1 - $this->size) / 2;
+
+ for ($y = 0; $y < $height; ++$y) {
+ for ($x = 0; $x < $width; ++$x) {
+ if (! $matrix->get($x, $y)) {
+ continue;
+ }
+
+ $pathX = $x + $margin;
+ $pathY = $y + $margin;
+
+ $path = $path
+ ->move($pathX + $this->size, $pathY + $halfSize)
+ ->ellipticArc($halfSize, $halfSize, 0, false, true, $pathX + $halfSize, $pathY + $this->size)
+ ->ellipticArc($halfSize, $halfSize, 0, false, true, $pathX, $pathY + $halfSize)
+ ->ellipticArc($halfSize, $halfSize, 0, false, true, $pathX + $halfSize, $pathY)
+ ->ellipticArc($halfSize, $halfSize, 0, false, true, $pathX + $this->size, $pathY + $halfSize)
+ ->close()
+ ;
+ }
+ }
+
+ return $path;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/Edge.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/Edge.php
new file mode 100644
index 0000000..141d66c
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/Edge.php
@@ -0,0 +1,82 @@
+
+ */
+ private array $points = [];
+
+ /**
+ * @var array|null
+ */
+ private ?array $simplifiedPoints = null;
+
+ private int $minX = PHP_INT_MAX;
+
+ private int $minY = PHP_INT_MAX;
+
+ private int $maxX = -1;
+
+ private int $maxY = -1;
+
+ public function __construct(private readonly bool $positive)
+ {
+ }
+
+ public function addPoint(int $x, int $y) : void
+ {
+ $this->points[] = [$x, $y];
+ $this->minX = min($this->minX, $x);
+ $this->minY = min($this->minY, $y);
+ $this->maxX = max($this->maxX, $x);
+ $this->maxY = max($this->maxY, $y);
+ }
+
+ public function isPositive() : bool
+ {
+ return $this->positive;
+ }
+
+ /**
+ * @return array
+ */
+ public function getPoints() : array
+ {
+ return $this->points;
+ }
+
+ public function getMaxX() : int
+ {
+ return $this->maxX;
+ }
+
+ public function getSimplifiedPoints() : array
+ {
+ if (null !== $this->simplifiedPoints) {
+ return $this->simplifiedPoints;
+ }
+
+ $points = [];
+ $length = count($this->points);
+
+ for ($i = 0; $i < $length; ++$i) {
+ $previousPoint = $this->points[(0 === $i ? $length : $i) - 1];
+ $nextPoint = $this->points[($length - 1 === $i ? -1 : $i) + 1];
+ $currentPoint = $this->points[$i];
+
+ if (($previousPoint[0] === $currentPoint[0] && $currentPoint[0] === $nextPoint[0])
+ || ($previousPoint[1] === $currentPoint[1] && $currentPoint[1] === $nextPoint[1])
+ ) {
+ continue;
+ }
+
+ $points[] = $currentPoint;
+ }
+
+ return $this->simplifiedPoints = $points;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/EdgeIterator.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/EdgeIterator.php
new file mode 100644
index 0000000..01f692c
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/EdgeIterator.php
@@ -0,0 +1,160 @@
+bytes = iterator_to_array($matrix->getBytes());
+ $this->size = count($this->bytes);
+ $this->width = $matrix->getWidth();
+ $this->height = $matrix->getHeight();
+ }
+
+ /**
+ * @return Traversable
+ */
+ public function getIterator() : Traversable
+ {
+ $originalBytes = $this->bytes;
+ $point = $this->findNext(0, 0);
+
+ while (null !== $point) {
+ $edge = $this->findEdge($point[0], $point[1]);
+ $this->xorEdge($edge);
+
+ yield $edge;
+
+ $point = $this->findNext($point[0], $point[1]);
+ }
+
+ $this->bytes = $originalBytes;
+ }
+
+ /**
+ * @return int[]|null
+ */
+ private function findNext(int $x, int $y) : ?array
+ {
+ $i = $this->width * $y + $x;
+
+ while ($i < $this->size && 1 !== $this->bytes[$i]) {
+ ++$i;
+ }
+
+ if ($i < $this->size) {
+ return $this->pointOf($i);
+ }
+
+ return null;
+ }
+
+ private function findEdge(int $x, int $y) : Edge
+ {
+ $edge = new Edge($this->isSet($x, $y));
+ $startX = $x;
+ $startY = $y;
+ $dirX = 0;
+ $dirY = 1;
+
+ while (true) {
+ $edge->addPoint($x, $y);
+ $x += $dirX;
+ $y += $dirY;
+
+ if ($x === $startX && $y === $startY) {
+ break;
+ }
+
+ $left = $this->isSet($x + ($dirX + $dirY - 1 ) / 2, $y + ($dirY - $dirX - 1) / 2);
+ $right = $this->isSet($x + ($dirX - $dirY - 1) / 2, $y + ($dirY + $dirX - 1) / 2);
+
+ if ($right && ! $left) {
+ $tmp = $dirX;
+ $dirX = -$dirY;
+ $dirY = $tmp;
+ } elseif ($right) {
+ $tmp = $dirX;
+ $dirX = -$dirY;
+ $dirY = $tmp;
+ } elseif (! $left) {
+ $tmp = $dirX;
+ $dirX = $dirY;
+ $dirY = -$tmp;
+ }
+ }
+
+ return $edge;
+ }
+
+ private function xorEdge(Edge $path) : void
+ {
+ $points = $path->getPoints();
+ $y1 = $points[0][1];
+ $length = count($points);
+ $maxX = $path->getMaxX();
+
+ for ($i = 1; $i < $length; ++$i) {
+ $y = $points[$i][1];
+
+ if ($y === $y1) {
+ continue;
+ }
+
+ $x = $points[$i][0];
+ $minY = min($y1, $y);
+
+ for ($j = $x; $j < $maxX; ++$j) {
+ $this->flip($j, $minY);
+ }
+
+ $y1 = $y;
+ }
+ }
+
+ private function isSet(int $x, int $y) : bool
+ {
+ return (
+ $x >= 0
+ && $x < $this->width
+ && $y >= 0
+ && $y < $this->height
+ ) && 1 === $this->bytes[$this->width * $y + $x];
+ }
+
+ /**
+ * @return int[]
+ */
+ private function pointOf(int $i) : array
+ {
+ $y = intdiv($i, $this->width);
+ return [$i - $y * $this->width, $y];
+ }
+
+ private function flip(int $x, int $y) : void
+ {
+ $this->bytes[$this->width * $y + $x] = (
+ $this->isSet($x, $y) ? 0 : 1
+ );
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Module/ModuleInterface.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Module/ModuleInterface.php
new file mode 100644
index 0000000..0ccb0e0
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Module/ModuleInterface.php
@@ -0,0 +1,18 @@
+ 1) {
+ throw new InvalidArgumentException('Intensity must between 0 (exclusive) and 1 (inclusive)');
+ }
+
+ $this->intensity = $intensity / 2;
+ }
+
+ public function createPath(ByteMatrix $matrix) : Path
+ {
+ $path = new Path();
+
+ foreach (new EdgeIterator($matrix) as $edge) {
+ $points = $edge->getSimplifiedPoints();
+ $length = count($points);
+
+ $currentPoint = $points[0];
+ $nextPoint = $points[1];
+ $horizontal = ($currentPoint[1] === $nextPoint[1]);
+
+ if ($horizontal) {
+ $right = $nextPoint[0] > $currentPoint[0];
+ $path = $path->move(
+ $currentPoint[0] + ($right ? $this->intensity : -$this->intensity),
+ $currentPoint[1]
+ );
+ } else {
+ $up = $nextPoint[0] < $currentPoint[0];
+ $path = $path->move(
+ $currentPoint[0],
+ $currentPoint[1] + ($up ? -$this->intensity : $this->intensity)
+ );
+ }
+
+ for ($i = 1; $i <= $length; ++$i) {
+ if ($i === $length) {
+ $previousPoint = $points[$length - 1];
+ $currentPoint = $points[0];
+ $nextPoint = $points[1];
+ } else {
+ $previousPoint = $points[(0 === $i ? $length : $i) - 1];
+ $currentPoint = $points[$i];
+ $nextPoint = $points[($length - 1 === $i ? -1 : $i) + 1];
+ }
+
+ $horizontal = ($previousPoint[1] === $currentPoint[1]);
+
+ if ($horizontal) {
+ $right = $previousPoint[0] < $currentPoint[0];
+ $up = $nextPoint[1] < $currentPoint[1];
+ $sweep = ($up xor $right);
+
+ if ($this->intensity < 0.5
+ || ($right && $previousPoint[0] !== $currentPoint[0] - 1)
+ || (! $right && $previousPoint[0] - 1 !== $currentPoint[0])
+ ) {
+ $path = $path->line(
+ $currentPoint[0] + ($right ? -$this->intensity : $this->intensity),
+ $currentPoint[1]
+ );
+ }
+
+ $path = $path->ellipticArc(
+ $this->intensity,
+ $this->intensity,
+ 0,
+ false,
+ $sweep,
+ $currentPoint[0],
+ $currentPoint[1] + ($up ? -$this->intensity : $this->intensity)
+ );
+ } else {
+ $up = $previousPoint[1] > $currentPoint[1];
+ $right = $nextPoint[0] > $currentPoint[0];
+ $sweep = ! ($up xor $right);
+
+ if ($this->intensity < 0.5
+ || ($up && $previousPoint[1] !== $currentPoint[1] + 1)
+ || (! $up && $previousPoint[0] + 1 !== $currentPoint[0])
+ ) {
+ $path = $path->line(
+ $currentPoint[0],
+ $currentPoint[1] + ($up ? $this->intensity : -$this->intensity)
+ );
+ }
+
+ $path = $path->ellipticArc(
+ $this->intensity,
+ $this->intensity,
+ 0,
+ false,
+ $sweep,
+ $currentPoint[0] + ($right ? $this->intensity : -$this->intensity),
+ $currentPoint[1]
+ );
+ }
+ }
+
+ $path = $path->close();
+ }
+
+ return $path;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Module/SquareModule.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Module/SquareModule.php
new file mode 100644
index 0000000..8cf1d0b
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Module/SquareModule.php
@@ -0,0 +1,44 @@
+getSimplifiedPoints();
+ $length = count($points);
+ $path = $path->move($points[0][0], $points[0][1]);
+
+ for ($i = 1; $i < $length; ++$i) {
+ $path = $path->line($points[$i][0], $points[$i][1]);
+ }
+
+ $path = $path->close();
+ }
+
+ return $path;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Path/Close.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Path/Close.php
new file mode 100644
index 0000000..bddf2d0
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Path/Close.php
@@ -0,0 +1,34 @@
+x1;
+ }
+
+ public function getY1() : float
+ {
+ return $this->y1;
+ }
+
+ public function getX2() : float
+ {
+ return $this->x2;
+ }
+
+ public function getY2() : float
+ {
+ return $this->y2;
+ }
+
+ public function getX3() : float
+ {
+ return $this->x3;
+ }
+
+ public function getY3() : float
+ {
+ return $this->y3;
+ }
+
+ /**
+ * @return self
+ */
+ public function translate(float $x, float $y) : OperationInterface
+ {
+ return new self(
+ $this->x1 + $x,
+ $this->y1 + $y,
+ $this->x2 + $x,
+ $this->y2 + $y,
+ $this->x3 + $x,
+ $this->y3 + $y
+ );
+ }
+
+ /**
+ * @return self
+ */
+ public function rotate(int $degrees) : OperationInterface
+ {
+ $radians = deg2rad($degrees);
+ $sin = sin($radians);
+ $cos = cos($radians);
+ $x1r = $this->x1 * $cos - $this->y1 * $sin;
+ $y1r = $this->x1 * $sin + $this->y1 * $cos;
+ $x2r = $this->x2 * $cos - $this->y2 * $sin;
+ $y2r = $this->x2 * $sin + $this->y2 * $cos;
+ $x3r = $this->x3 * $cos - $this->y3 * $sin;
+ $y3r = $this->x3 * $sin + $this->y3 * $cos;
+ return new self(
+ $x1r,
+ $y1r,
+ $x2r,
+ $y2r,
+ $x3r,
+ $y3r
+ );
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Path/EllipticArc.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Path/EllipticArc.php
new file mode 100644
index 0000000..ee957d4
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Path/EllipticArc.php
@@ -0,0 +1,264 @@
+xRadius = abs($xRadius);
+ $this->yRadius = abs($yRadius);
+ $this->xAxisAngle = $xAxisAngle % 360;
+ }
+
+ public function getXRadius() : float
+ {
+ return $this->xRadius;
+ }
+
+ public function getYRadius() : float
+ {
+ return $this->yRadius;
+ }
+
+ public function getXAxisAngle() : float
+ {
+ return $this->xAxisAngle;
+ }
+
+ public function isLargeArc() : bool
+ {
+ return $this->largeArc;
+ }
+
+ public function isSweep() : bool
+ {
+ return $this->sweep;
+ }
+
+ public function getX() : float
+ {
+ return $this->x;
+ }
+
+ public function getY() : float
+ {
+ return $this->y;
+ }
+
+ /**
+ * @return self
+ */
+ public function translate(float $x, float $y) : OperationInterface
+ {
+ return new self(
+ $this->xRadius,
+ $this->yRadius,
+ $this->xAxisAngle,
+ $this->largeArc,
+ $this->sweep,
+ $this->x + $x,
+ $this->y + $y
+ );
+ }
+
+ /**
+ * @return self
+ */
+ public function rotate(int $degrees) : OperationInterface
+ {
+ $radians = deg2rad($degrees);
+ $sin = sin($radians);
+ $cos = cos($radians);
+ $xr = $this->x * $cos - $this->y * $sin;
+ $yr = $this->x * $sin + $this->y * $cos;
+ return new self(
+ $this->xRadius,
+ $this->yRadius,
+ $this->xAxisAngle,
+ $this->largeArc,
+ $this->sweep,
+ $xr,
+ $yr
+ );
+ }
+
+ /**
+ * Converts the elliptic arc to multiple curves.
+ *
+ * Since not all image back ends support elliptic arcs, this method allows to convert the arc into multiple curves
+ * resembling the same result.
+ *
+ * @see https://mortoray.com/2017/02/16/rendering-an-svg-elliptical-arc-as-bezier-curves/
+ * @return array
+ */
+ public function toCurves(float $fromX, float $fromY) : array
+ {
+ if (sqrt(($fromX - $this->x) ** 2 + ($fromY - $this->y) ** 2) < self::ZERO_TOLERANCE) {
+ return [];
+ }
+
+ if ($this->xRadius < self::ZERO_TOLERANCE || $this->yRadius < self::ZERO_TOLERANCE) {
+ return [new Line($this->x, $this->y)];
+ }
+
+ return $this->createCurves($fromX, $fromY);
+ }
+
+ /**
+ * @return Curve[]
+ */
+ private function createCurves(float $fromX, float $fromY) : array
+ {
+ $xAngle = deg2rad($this->xAxisAngle);
+ list($centerX, $centerY, $radiusX, $radiusY, $startAngle, $deltaAngle) =
+ $this->calculateCenterPointParameters($fromX, $fromY, $xAngle);
+
+ $s = $startAngle;
+ $e = $s + $deltaAngle;
+ $sign = ($e < $s) ? -1 : 1;
+ $remain = abs($e - $s);
+ $p1 = self::point($centerX, $centerY, $radiusX, $radiusY, $xAngle, $s);
+ $curves = [];
+
+ while ($remain > self::ZERO_TOLERANCE) {
+ $step = min($remain, pi() / 2);
+ $signStep = $step * $sign;
+ $p2 = self::point($centerX, $centerY, $radiusX, $radiusY, $xAngle, $s + $signStep);
+
+ $alphaT = tan($signStep / 2);
+ $alpha = sin($signStep) * (sqrt(4 + 3 * $alphaT ** 2) - 1) / 3;
+ $d1 = self::derivative($radiusX, $radiusY, $xAngle, $s);
+ $d2 = self::derivative($radiusX, $radiusY, $xAngle, $s + $signStep);
+
+ $curves[] = new Curve(
+ $p1[0] + $alpha * $d1[0],
+ $p1[1] + $alpha * $d1[1],
+ $p2[0] - $alpha * $d2[0],
+ $p2[1] - $alpha * $d2[1],
+ $p2[0],
+ $p2[1]
+ );
+
+ $s += $signStep;
+ $remain -= $step;
+ $p1 = $p2;
+ }
+
+ return $curves;
+ }
+
+ /**
+ * @return float[]
+ */
+ private function calculateCenterPointParameters(float $fromX, float $fromY, float $xAngle): array
+ {
+ $rX = $this->xRadius;
+ $rY = $this->yRadius;
+
+ // F.6.5.1
+ $dx2 = ($fromX - $this->x) / 2;
+ $dy2 = ($fromY - $this->y) / 2;
+ $x1p = cos($xAngle) * $dx2 + sin($xAngle) * $dy2;
+ $y1p = -sin($xAngle) * $dx2 + cos($xAngle) * $dy2;
+
+ // F.6.5.2
+ $rxs = $rX ** 2;
+ $rys = $rY ** 2;
+ $x1ps = $x1p ** 2;
+ $y1ps = $y1p ** 2;
+ $cr = $x1ps / $rxs + $y1ps / $rys;
+
+ if ($cr > 1) {
+ $s = sqrt($cr);
+ $rX *= $s;
+ $rY *= $s;
+ $rxs = $rX ** 2;
+ $rys = $rY ** 2;
+ }
+
+ $dq = ($rxs * $y1ps + $rys * $x1ps);
+ $pq = ($rxs * $rys - $dq) / $dq;
+ $q = sqrt(max(0, $pq));
+
+ if ($this->largeArc === $this->sweep) {
+ $q = -$q;
+ }
+
+ $cxp = $q * $rX * $y1p / $rY;
+ $cyp = -$q * $rY * $x1p / $rX;
+
+ // F.6.5.3
+ $cx = cos($xAngle) * $cxp - sin($xAngle) * $cyp + ($fromX + $this->x) / 2;
+ $cy = sin($xAngle) * $cxp + cos($xAngle) * $cyp + ($fromY + $this->y) / 2;
+
+ // F.6.5.5
+ $theta = self::angle(1, 0, ($x1p - $cxp) / $rX, ($y1p - $cyp) / $rY);
+
+ // F.6.5.6
+ $delta = self::angle(($x1p - $cxp) / $rX, ($y1p - $cyp) / $rY, (-$x1p - $cxp) / $rX, (-$y1p - $cyp) / $rY);
+ $delta = fmod($delta, pi() * 2);
+
+ if (! $this->sweep) {
+ $delta -= 2 * pi();
+ }
+
+ return [$cx, $cy, $rX, $rY, $theta, $delta];
+ }
+
+ private static function angle(float $ux, float $uy, float $vx, float $vy) : float
+ {
+ // F.6.5.4
+ $dot = $ux * $vx + $uy * $vy;
+ $length = sqrt($ux ** 2 + $uy ** 2) * sqrt($vx ** 2 + $vy ** 2);
+ $angle = acos(min(1, max(-1, $dot / $length)));
+
+ if (($ux * $vy - $uy * $vx) < 0) {
+ return -$angle;
+ }
+
+ return $angle;
+ }
+
+ /**
+ * @return float[]
+ */
+ private static function point(
+ float $centerX,
+ float $centerY,
+ float $radiusX,
+ float $radiusY,
+ float $xAngle,
+ float $angle
+ ) : array {
+ return [
+ $centerX + $radiusX * cos($xAngle) * cos($angle) - $radiusY * sin($xAngle) * sin($angle),
+ $centerY + $radiusX * sin($xAngle) * cos($angle) + $radiusY * cos($xAngle) * sin($angle),
+ ];
+ }
+
+ /**
+ * @return float[]
+ */
+ private static function derivative(float $radiusX, float $radiusY, float $xAngle, float $angle) : array
+ {
+ return [
+ -$radiusX * cos($xAngle) * sin($angle) - $radiusY * sin($xAngle) * cos($angle),
+ -$radiusX * sin($xAngle) * sin($angle) + $radiusY * cos($xAngle) * cos($angle),
+ ];
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Path/Line.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Path/Line.php
new file mode 100644
index 0000000..dec46fd
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Path/Line.php
@@ -0,0 +1,42 @@
+x;
+ }
+
+ public function getY() : float
+ {
+ return $this->y;
+ }
+
+ /**
+ * @return self
+ */
+ public function translate(float $x, float $y) : OperationInterface
+ {
+ return new self($this->x + $x, $this->y + $y);
+ }
+
+ /**
+ * @return self
+ */
+ public function rotate(int $degrees) : OperationInterface
+ {
+ $radians = deg2rad($degrees);
+ $sin = sin($radians);
+ $cos = cos($radians);
+ $xr = $this->x * $cos - $this->y * $sin;
+ $yr = $this->x * $sin + $this->y * $cos;
+ return new self($xr, $yr);
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Path/Move.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Path/Move.php
new file mode 100644
index 0000000..c3c9a56
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Path/Move.php
@@ -0,0 +1,42 @@
+x;
+ }
+
+ public function getY() : float
+ {
+ return $this->y;
+ }
+
+ /**
+ * @return self
+ */
+ public function translate(float $x, float $y) : OperationInterface
+ {
+ return new self($this->x + $x, $this->y + $y);
+ }
+
+ /**
+ * @return self
+ */
+ public function rotate(int $degrees) : OperationInterface
+ {
+ $radians = deg2rad($degrees);
+ $sin = sin($radians);
+ $cos = cos($radians);
+ $xr = $this->x * $cos - $this->y * $sin;
+ $yr = $this->x * $sin + $this->y * $cos;
+ return new self($xr, $yr);
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/Path/OperationInterface.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/Path/OperationInterface.php
new file mode 100644
index 0000000..9271555
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/Path/OperationInterface.php
@@ -0,0 +1,17 @@
+operations[] = new Move($x, $y);
+ return $path;
+ }
+
+ /**
+ * Draws a line from the current position to another position.
+ */
+ public function line(float $x, float $y) : self
+ {
+ $path = clone $this;
+ $path->operations[] = new Line($x, $y);
+ return $path;
+ }
+
+ /**
+ * Draws an elliptic arc from the current position to another position.
+ */
+ public function ellipticArc(
+ float $xRadius,
+ float $yRadius,
+ float $xAxisRotation,
+ bool $largeArc,
+ bool $sweep,
+ float $x,
+ float $y
+ ) : self {
+ $path = clone $this;
+ $path->operations[] = new EllipticArc($xRadius, $yRadius, $xAxisRotation, $largeArc, $sweep, $x, $y);
+ return $path;
+ }
+
+ /**
+ * Draws a curve from the current position to another position.
+ */
+ public function curve(float $x1, float $y1, float $x2, float $y2, float $x3, float $y3) : self
+ {
+ $path = clone $this;
+ $path->operations[] = new Curve($x1, $y1, $x2, $y2, $x3, $y3);
+ return $path;
+ }
+
+ /**
+ * Closes a sub-path.
+ */
+ public function close() : self
+ {
+ $path = clone $this;
+ $path->operations[] = Close::instance();
+ return $path;
+ }
+
+ /**
+ * Appends another path to this one.
+ */
+ public function append(self $other) : self
+ {
+ $path = clone $this;
+ $path->operations = array_merge($this->operations, $other->operations);
+ return $path;
+ }
+
+ public function translate(float $x, float $y) : self
+ {
+ $path = new self();
+
+ foreach ($this->operations as $operation) {
+ $path->operations[] = $operation->translate($x, $y);
+ }
+
+ return $path;
+ }
+
+ public function rotate(int $degrees) : self
+ {
+ $path = new self();
+
+ foreach ($this->operations as $operation) {
+ $path->operations[] = $operation->rotate($degrees);
+ }
+
+ return $path;
+ }
+
+ /**
+ * @return Traversable
+ */
+ public function getIterator() : Traversable
+ {
+ foreach ($this->operations as $operation) {
+ yield $operation;
+ }
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/PlainTextRenderer.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/PlainTextRenderer.php
new file mode 100644
index 0000000..219bbf3
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/PlainTextRenderer.php
@@ -0,0 +1,80 @@
+getMatrix();
+ $matrixSize = $matrix->getWidth();
+
+ if ($matrixSize !== $matrix->getHeight()) {
+ throw new InvalidArgumentException('Matrix must have the same width and height');
+ }
+
+ $rows = $matrix->getArray()->toArray();
+
+ if (0 !== $matrixSize % 2) {
+ $rows[] = array_fill(0, $matrixSize, 0);
+ }
+
+ $horizontalMargin = str_repeat(self::EMPTY_BLOCK, $this->margin);
+ $result = str_repeat("\n", (int) ceil($this->margin / 2));
+
+ for ($i = 0; $i < $matrixSize; $i += 2) {
+ $result .= $horizontalMargin;
+
+ $upperRow = $rows[$i];
+ $lowerRow = $rows[$i + 1];
+
+ for ($j = 0; $j < $matrixSize; ++$j) {
+ $upperBit = $upperRow[$j];
+ $lowerBit = $lowerRow[$j];
+
+ if ($upperBit) {
+ $result .= $lowerBit ? self::FULL_BLOCK : self::UPPER_HALF_BLOCK;
+ } else {
+ $result .= $lowerBit ? self::LOWER_HALF_BLOCK : self::EMPTY_BLOCK;
+ }
+ }
+
+ $result .= $horizontalMargin . "\n";
+ }
+
+ $result .= str_repeat("\n", (int) ceil($this->margin / 2));
+
+ return $result;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/RendererInterface.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/RendererInterface.php
new file mode 100644
index 0000000..b0aae39
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/RendererInterface.php
@@ -0,0 +1,11 @@
+externalColor && null === $this->internalColor;
+ }
+
+ public function inheritsExternalColor() : bool
+ {
+ return null === $this->externalColor;
+ }
+
+ public function inheritsInternalColor() : bool
+ {
+ return null === $this->internalColor;
+ }
+
+ public function getExternalColor() : ColorInterface
+ {
+ if (null === $this->externalColor) {
+ throw new RuntimeException('External eye color inherits foreground color');
+ }
+
+ return $this->externalColor;
+ }
+
+ public function getInternalColor() : ColorInterface
+ {
+ if (null === $this->internalColor) {
+ throw new RuntimeException('Internal eye color inherits foreground color');
+ }
+
+ return $this->internalColor;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/Fill.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/Fill.php
new file mode 100644
index 0000000..19de25d
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/Fill.php
@@ -0,0 +1,129 @@
+foregroundGradient;
+ }
+
+ public function getBackgroundColor() : ColorInterface
+ {
+ return $this->backgroundColor;
+ }
+
+ public function getForegroundColor() : ColorInterface
+ {
+ if (null === $this->foregroundColor) {
+ throw new RuntimeException('Fill uses a gradient, thus no foreground color is available');
+ }
+
+ return $this->foregroundColor;
+ }
+
+ public function getForegroundGradient() : Gradient
+ {
+ if (null === $this->foregroundGradient) {
+ throw new RuntimeException('Fill uses a single color, thus no foreground gradient is available');
+ }
+
+ return $this->foregroundGradient;
+ }
+
+ public function getTopLeftEyeFill() : EyeFill
+ {
+ return $this->topLeftEyeFill;
+ }
+
+ public function getTopRightEyeFill() : EyeFill
+ {
+ return $this->topRightEyeFill;
+ }
+
+ public function getBottomLeftEyeFill() : EyeFill
+ {
+ return $this->bottomLeftEyeFill;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/Gradient.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/Gradient.php
new file mode 100644
index 0000000..eea4031
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/Gradient.php
@@ -0,0 +1,31 @@
+startColor;
+ }
+
+ public function getEndColor() : ColorInterface
+ {
+ return $this->endColor;
+ }
+
+ public function getType() : GradientType
+ {
+ return $this->type;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/GradientType.php b/system/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/GradientType.php
new file mode 100644
index 0000000..c1ca754
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/GradientType.php
@@ -0,0 +1,22 @@
+module = $module ?: SquareModule::instance();
+ $this->eye = $eye ?: new ModuleEye($this->module);
+ $this->fill = $fill ?: Fill::default();
+ }
+
+ public function withSize(int $size) : self
+ {
+ $style = clone $this;
+ $style->size = $size;
+ return $style;
+ }
+
+ public function withMargin(int $margin) : self
+ {
+ $style = clone $this;
+ $style->margin = $margin;
+ return $style;
+ }
+
+ public function getSize() : int
+ {
+ return $this->size;
+ }
+
+ public function getMargin() : int
+ {
+ return $this->margin;
+ }
+
+ public function getModule() : ModuleInterface
+ {
+ return $this->module;
+ }
+
+ public function getEye() : EyeInterface
+ {
+ return $this->eye;
+ }
+
+ public function getFill() : Fill
+ {
+ return $this->fill;
+ }
+}
diff --git a/system/vendor/bacon/bacon-qr-code/src/Writer.php b/system/vendor/bacon/bacon-qr-code/src/Writer.php
new file mode 100644
index 0000000..d7f7ebb
--- /dev/null
+++ b/system/vendor/bacon/bacon-qr-code/src/Writer.php
@@ -0,0 +1,63 @@
+renderer->render(Encoder::encode($content, $ecLevel, $encoding, $forcedVersion));
+ }
+
+ /**
+ * Writes QR code to a file.
+ *
+ * @see Writer::writeString()
+ */
+ public function writeFile(
+ string $content,
+ string $filename,
+ string $encoding = Encoder::DEFAULT_BYTE_MODE_ENCODING,
+ ?ErrorCorrectionLevel $ecLevel = null,
+ ?Version $forcedVersion = null
+ ) : void {
+ file_put_contents($filename, $this->writeString($content, $encoding, $ecLevel, $forcedVersion));
+ }
+}
diff --git a/system/vendor/composer/ClassLoader.php b/system/vendor/composer/ClassLoader.php
index fce8549..7824d8f 100644
--- a/system/vendor/composer/ClassLoader.php
+++ b/system/vendor/composer/ClassLoader.php
@@ -37,57 +37,126 @@ namespace Composer\Autoload;
*
* @author Fabien Potencier
* @author Jordi Boggiano
- * @see http://www.php-fig.org/psr/psr-0/
- * @see http://www.php-fig.org/psr/psr-4/
+ * @see https://www.php-fig.org/psr/psr-0/
+ * @see https://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
+ /** @var \Closure(string):void */
+ private static $includeFile;
+
+ /** @var string|null */
+ private $vendorDir;
+
// PSR-4
+ /**
+ * @var array>
+ */
private $prefixLengthsPsr4 = array();
+ /**
+ * @var array>
+ */
private $prefixDirsPsr4 = array();
+ /**
+ * @var list
+ */
private $fallbackDirsPsr4 = array();
// PSR-0
+ /**
+ * List of PSR-0 prefixes
+ *
+ * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
+ *
+ * @var array>>
+ */
private $prefixesPsr0 = array();
+ /**
+ * @var list
+ */
private $fallbackDirsPsr0 = array();
+ /** @var bool */
private $useIncludePath = false;
+
+ /**
+ * @var array
+ */
private $classMap = array();
+
+ /** @var bool */
private $classMapAuthoritative = false;
+
+ /**
+ * @var array
+ */
private $missingClasses = array();
+
+ /** @var string|null */
private $apcuPrefix;
+ /**
+ * @var array
+ */
+ private static $registeredLoaders = array();
+
+ /**
+ * @param string|null $vendorDir
+ */
+ public function __construct($vendorDir = null)
+ {
+ $this->vendorDir = $vendorDir;
+ self::initializeIncludeClosure();
+ }
+
+ /**
+ * @return array>
+ */
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
- return call_user_func_array('array_merge', $this->prefixesPsr0);
+ return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
}
return array();
}
+ /**
+ * @return array>
+ */
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
+ /**
+ * @return list
+ */
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
+ /**
+ * @return list
+ */
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
+ /**
+ * @return array Array of classname => path
+ */
public function getClassMap()
{
return $this->classMap;
}
/**
- * @param array $classMap Class to filename map
+ * @param array $classMap Class to filename map
+ *
+ * @return void
*/
public function addClassMap(array $classMap)
{
@@ -102,22 +171,25 @@ class ClassLoader
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
- * @param string $prefix The prefix
- * @param array|string $paths The PSR-0 root directories
- * @param bool $prepend Whether to prepend the directories
+ * @param string $prefix The prefix
+ * @param list|string $paths The PSR-0 root directories
+ * @param bool $prepend Whether to prepend the directories
+ *
+ * @return void
*/
public function add($prefix, $paths, $prepend = false)
{
+ $paths = (array) $paths;
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
- (array) $paths,
+ $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
- (array) $paths
+ $paths
);
}
@@ -126,19 +198,19 @@ class ClassLoader
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
- $this->prefixesPsr0[$first][$prefix] = (array) $paths;
+ $this->prefixesPsr0[$first][$prefix] = $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
- (array) $paths,
+ $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
- (array) $paths
+ $paths
);
}
}
@@ -147,25 +219,28 @@ class ClassLoader
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
- * @param string $prefix The prefix/namespace, with trailing '\\'
- * @param array|string $paths The PSR-4 base directories
- * @param bool $prepend Whether to prepend the directories
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param list|string $paths The PSR-4 base directories
+ * @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
+ *
+ * @return void
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
+ $paths = (array) $paths;
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
- (array) $paths,
+ $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
- (array) $paths
+ $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
@@ -175,18 +250,18 @@ class ClassLoader
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
- $this->prefixDirsPsr4[$prefix] = (array) $paths;
+ $this->prefixDirsPsr4[$prefix] = $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
- (array) $paths,
+ $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
- (array) $paths
+ $paths
);
}
}
@@ -195,8 +270,10 @@ class ClassLoader
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
- * @param string $prefix The prefix
- * @param array|string $paths The PSR-0 base directories
+ * @param string $prefix The prefix
+ * @param list|string $paths The PSR-0 base directories
+ *
+ * @return void
*/
public function set($prefix, $paths)
{
@@ -211,10 +288,12 @@ class ClassLoader
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
- * @param string $prefix The prefix/namespace, with trailing '\\'
- * @param array|string $paths The PSR-4 base directories
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param list|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
+ *
+ * @return void
*/
public function setPsr4($prefix, $paths)
{
@@ -234,6 +313,8 @@ class ClassLoader
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
+ *
+ * @return void
*/
public function setUseIncludePath($useIncludePath)
{
@@ -256,6 +337,8 @@ class ClassLoader
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
+ *
+ * @return void
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
@@ -276,6 +359,8 @@ class ClassLoader
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
+ *
+ * @return void
*/
public function setApcuPrefix($apcuPrefix)
{
@@ -296,33 +381,55 @@ class ClassLoader
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
+ *
+ * @return void
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+
+ if (null === $this->vendorDir) {
+ return;
+ }
+
+ if ($prepend) {
+ self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
+ } else {
+ unset(self::$registeredLoaders[$this->vendorDir]);
+ self::$registeredLoaders[$this->vendorDir] = $this;
+ }
}
/**
* Unregisters this instance as an autoloader.
+ *
+ * @return void
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
+
+ if (null !== $this->vendorDir) {
+ unset(self::$registeredLoaders[$this->vendorDir]);
+ }
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
- * @return bool|null True if loaded, null otherwise
+ * @return true|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
- includeFile($file);
+ $includeFile = self::$includeFile;
+ $includeFile($file);
return true;
}
+
+ return null;
}
/**
@@ -367,6 +474,21 @@ class ClassLoader
return $file;
}
+ /**
+ * Returns the currently registered loaders keyed by their corresponding vendor directories.
+ *
+ * @return array
+ */
+ public static function getRegisteredLoaders()
+ {
+ return self::$registeredLoaders;
+ }
+
+ /**
+ * @param string $class
+ * @param string $ext
+ * @return string|false
+ */
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
@@ -432,14 +554,26 @@ class ClassLoader
return false;
}
-}
-/**
- * Scope isolated include.
- *
- * Prevents access to $this/self from included files.
- */
-function includeFile($file)
-{
- include $file;
+ /**
+ * @return void
+ */
+ private static function initializeIncludeClosure()
+ {
+ if (self::$includeFile !== null) {
+ return;
+ }
+
+ /**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ *
+ * @param string $file
+ * @return void
+ */
+ self::$includeFile = \Closure::bind(static function($file) {
+ include $file;
+ }, null, null);
+ }
}
diff --git a/system/vendor/composer/InstalledVersions.php b/system/vendor/composer/InstalledVersions.php
new file mode 100644
index 0000000..51e734a
--- /dev/null
+++ b/system/vendor/composer/InstalledVersions.php
@@ -0,0 +1,359 @@
+
+ * Jordi Boggiano
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer;
+
+use Composer\Autoload\ClassLoader;
+use Composer\Semver\VersionParser;
+
+/**
+ * This class is copied in every Composer installed project and available to all
+ *
+ * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
+ *
+ * To require its presence, you can require `composer-runtime-api ^2.0`
+ *
+ * @final
+ */
+class InstalledVersions
+{
+ /**
+ * @var mixed[]|null
+ * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}|array{}|null
+ */
+ private static $installed;
+
+ /**
+ * @var bool|null
+ */
+ private static $canGetVendors;
+
+ /**
+ * @var array[]
+ * @psalm-var array}>
+ */
+ private static $installedByVendor = array();
+
+ /**
+ * Returns a list of all package names which are present, either by being installed, replaced or provided
+ *
+ * @return string[]
+ * @psalm-return list
+ */
+ public static function getInstalledPackages()
+ {
+ $packages = array();
+ foreach (self::getInstalled() as $installed) {
+ $packages[] = array_keys($installed['versions']);
+ }
+
+ if (1 === \count($packages)) {
+ return $packages[0];
+ }
+
+ return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
+ }
+
+ /**
+ * Returns a list of all package names with a specific type e.g. 'library'
+ *
+ * @param string $type
+ * @return string[]
+ * @psalm-return list
+ */
+ public static function getInstalledPackagesByType($type)
+ {
+ $packagesByType = array();
+
+ foreach (self::getInstalled() as $installed) {
+ foreach ($installed['versions'] as $name => $package) {
+ if (isset($package['type']) && $package['type'] === $type) {
+ $packagesByType[] = $name;
+ }
+ }
+ }
+
+ return $packagesByType;
+ }
+
+ /**
+ * Checks whether the given package is installed
+ *
+ * This also returns true if the package name is provided or replaced by another package
+ *
+ * @param string $packageName
+ * @param bool $includeDevRequirements
+ * @return bool
+ */
+ public static function isInstalled($packageName, $includeDevRequirements = true)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (isset($installed['versions'][$packageName])) {
+ return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Checks whether the given package satisfies a version constraint
+ *
+ * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
+ *
+ * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
+ *
+ * @param VersionParser $parser Install composer/semver to have access to this class and functionality
+ * @param string $packageName
+ * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
+ * @return bool
+ */
+ public static function satisfies(VersionParser $parser, $packageName, $constraint)
+ {
+ $constraint = $parser->parseConstraints((string) $constraint);
+ $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
+
+ return $provided->matches($constraint);
+ }
+
+ /**
+ * Returns a version constraint representing all the range(s) which are installed for a given package
+ *
+ * It is easier to use this via isInstalled() with the $constraint argument if you need to check
+ * whether a given version of a package is installed, and not just whether it exists
+ *
+ * @param string $packageName
+ * @return string Version constraint usable with composer/semver
+ */
+ public static function getVersionRanges($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+
+ $ranges = array();
+ if (isset($installed['versions'][$packageName]['pretty_version'])) {
+ $ranges[] = $installed['versions'][$packageName]['pretty_version'];
+ }
+ if (array_key_exists('aliases', $installed['versions'][$packageName])) {
+ $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
+ }
+ if (array_key_exists('replaced', $installed['versions'][$packageName])) {
+ $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
+ }
+ if (array_key_exists('provided', $installed['versions'][$packageName])) {
+ $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
+ }
+
+ return implode(' || ', $ranges);
+ }
+
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+
+ /**
+ * @param string $packageName
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
+ */
+ public static function getVersion($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+
+ if (!isset($installed['versions'][$packageName]['version'])) {
+ return null;
+ }
+
+ return $installed['versions'][$packageName]['version'];
+ }
+
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+
+ /**
+ * @param string $packageName
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
+ */
+ public static function getPrettyVersion($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+
+ if (!isset($installed['versions'][$packageName]['pretty_version'])) {
+ return null;
+ }
+
+ return $installed['versions'][$packageName]['pretty_version'];
+ }
+
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+
+ /**
+ * @param string $packageName
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
+ */
+ public static function getReference($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+
+ if (!isset($installed['versions'][$packageName]['reference'])) {
+ return null;
+ }
+
+ return $installed['versions'][$packageName]['reference'];
+ }
+
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+
+ /**
+ * @param string $packageName
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
+ */
+ public static function getInstallPath($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+
+ return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
+ }
+
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+
+ /**
+ * @return array
+ * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
+ */
+ public static function getRootPackage()
+ {
+ $installed = self::getInstalled();
+
+ return $installed[0]['root'];
+ }
+
+ /**
+ * Returns the raw installed.php data for custom implementations
+ *
+ * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
+ * @return array[]
+ * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}
+ */
+ public static function getRawData()
+ {
+ @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
+
+ if (null === self::$installed) {
+ // only require the installed.php file if this file is loaded from its dumped location,
+ // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
+ if (substr(__DIR__, -8, 1) !== 'C') {
+ self::$installed = include __DIR__ . '/installed.php';
+ } else {
+ self::$installed = array();
+ }
+ }
+
+ return self::$installed;
+ }
+
+ /**
+ * Returns the raw data of all installed.php which are currently loaded for custom implementations
+ *
+ * @return array[]
+ * @psalm-return list}>
+ */
+ public static function getAllRawData()
+ {
+ return self::getInstalled();
+ }
+
+ /**
+ * Lets you reload the static array from another file
+ *
+ * This is only useful for complex integrations in which a project needs to use
+ * this class but then also needs to execute another project's autoloader in process,
+ * and wants to ensure both projects have access to their version of installed.php.
+ *
+ * A typical case would be PHPUnit, where it would need to make sure it reads all
+ * the data it needs from this class, then call reload() with
+ * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
+ * the project in which it runs can then also use this class safely, without
+ * interference between PHPUnit's dependencies and the project's dependencies.
+ *
+ * @param array[] $data A vendor/composer/installed.php data set
+ * @return void
+ *
+ * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $data
+ */
+ public static function reload($data)
+ {
+ self::$installed = $data;
+ self::$installedByVendor = array();
+ }
+
+ /**
+ * @return array[]
+ * @psalm-return list}>
+ */
+ private static function getInstalled()
+ {
+ if (null === self::$canGetVendors) {
+ self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
+ }
+
+ $installed = array();
+
+ if (self::$canGetVendors) {
+ foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
+ if (isset(self::$installedByVendor[$vendorDir])) {
+ $installed[] = self::$installedByVendor[$vendorDir];
+ } elseif (is_file($vendorDir.'/composer/installed.php')) {
+ /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */
+ $required = require $vendorDir.'/composer/installed.php';
+ $installed[] = self::$installedByVendor[$vendorDir] = $required;
+ if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
+ self::$installed = $installed[count($installed) - 1];
+ }
+ }
+ }
+ }
+
+ if (null === self::$installed) {
+ // only require the installed.php file if this file is loaded from its dumped location,
+ // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
+ if (substr(__DIR__, -8, 1) !== 'C') {
+ /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */
+ $required = require __DIR__ . '/installed.php';
+ self::$installed = $required;
+ } else {
+ self::$installed = array();
+ }
+ }
+
+ if (self::$installed !== array()) {
+ $installed[] = self::$installed;
+ }
+
+ return $installed;
+ }
+}
diff --git a/system/vendor/composer/autoload_classmap.php b/system/vendor/composer/autoload_classmap.php
index 21753fd..1db71a5 100644
--- a/system/vendor/composer/autoload_classmap.php
+++ b/system/vendor/composer/autoload_classmap.php
@@ -2,16 +2,114 @@
// autoload_classmap.php @generated by Composer
-$vendorDir = dirname(dirname(__FILE__));
+$vendorDir = dirname(__DIR__);
$baseDir = dirname(dirname($vendorDir));
return array(
+ 'BaconQrCode\\Common\\BitArray' => $vendorDir . '/bacon/bacon-qr-code/src/Common/BitArray.php',
+ 'BaconQrCode\\Common\\BitMatrix' => $vendorDir . '/bacon/bacon-qr-code/src/Common/BitMatrix.php',
+ 'BaconQrCode\\Common\\BitUtils' => $vendorDir . '/bacon/bacon-qr-code/src/Common/BitUtils.php',
+ 'BaconQrCode\\Common\\CharacterSetEci' => $vendorDir . '/bacon/bacon-qr-code/src/Common/CharacterSetEci.php',
+ 'BaconQrCode\\Common\\EcBlock' => $vendorDir . '/bacon/bacon-qr-code/src/Common/EcBlock.php',
+ 'BaconQrCode\\Common\\EcBlocks' => $vendorDir . '/bacon/bacon-qr-code/src/Common/EcBlocks.php',
+ 'BaconQrCode\\Common\\ErrorCorrectionLevel' => $vendorDir . '/bacon/bacon-qr-code/src/Common/ErrorCorrectionLevel.php',
+ 'BaconQrCode\\Common\\FormatInformation' => $vendorDir . '/bacon/bacon-qr-code/src/Common/FormatInformation.php',
+ 'BaconQrCode\\Common\\Mode' => $vendorDir . '/bacon/bacon-qr-code/src/Common/Mode.php',
+ 'BaconQrCode\\Common\\ReedSolomonCodec' => $vendorDir . '/bacon/bacon-qr-code/src/Common/ReedSolomonCodec.php',
+ 'BaconQrCode\\Common\\Version' => $vendorDir . '/bacon/bacon-qr-code/src/Common/Version.php',
+ 'BaconQrCode\\Encoder\\BlockPair' => $vendorDir . '/bacon/bacon-qr-code/src/Encoder/BlockPair.php',
+ 'BaconQrCode\\Encoder\\ByteMatrix' => $vendorDir . '/bacon/bacon-qr-code/src/Encoder/ByteMatrix.php',
+ 'BaconQrCode\\Encoder\\Encoder' => $vendorDir . '/bacon/bacon-qr-code/src/Encoder/Encoder.php',
+ 'BaconQrCode\\Encoder\\MaskUtil' => $vendorDir . '/bacon/bacon-qr-code/src/Encoder/MaskUtil.php',
+ 'BaconQrCode\\Encoder\\MatrixUtil' => $vendorDir . '/bacon/bacon-qr-code/src/Encoder/MatrixUtil.php',
+ 'BaconQrCode\\Encoder\\QrCode' => $vendorDir . '/bacon/bacon-qr-code/src/Encoder/QrCode.php',
+ 'BaconQrCode\\Exception\\ExceptionInterface' => $vendorDir . '/bacon/bacon-qr-code/src/Exception/ExceptionInterface.php',
+ 'BaconQrCode\\Exception\\InvalidArgumentException' => $vendorDir . '/bacon/bacon-qr-code/src/Exception/InvalidArgumentException.php',
+ 'BaconQrCode\\Exception\\OutOfBoundsException' => $vendorDir . '/bacon/bacon-qr-code/src/Exception/OutOfBoundsException.php',
+ 'BaconQrCode\\Exception\\RuntimeException' => $vendorDir . '/bacon/bacon-qr-code/src/Exception/RuntimeException.php',
+ 'BaconQrCode\\Exception\\UnexpectedValueException' => $vendorDir . '/bacon/bacon-qr-code/src/Exception/UnexpectedValueException.php',
+ 'BaconQrCode\\Exception\\WriterException' => $vendorDir . '/bacon/bacon-qr-code/src/Exception/WriterException.php',
+ 'BaconQrCode\\Renderer\\Color\\Alpha' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Color/Alpha.php',
+ 'BaconQrCode\\Renderer\\Color\\Cmyk' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Color/Cmyk.php',
+ 'BaconQrCode\\Renderer\\Color\\ColorInterface' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Color/ColorInterface.php',
+ 'BaconQrCode\\Renderer\\Color\\Gray' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Color/Gray.php',
+ 'BaconQrCode\\Renderer\\Color\\Rgb' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Color/Rgb.php',
+ 'BaconQrCode\\Renderer\\Eye\\CompositeEye' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Eye/CompositeEye.php',
+ 'BaconQrCode\\Renderer\\Eye\\EyeInterface' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Eye/EyeInterface.php',
+ 'BaconQrCode\\Renderer\\Eye\\ModuleEye' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Eye/ModuleEye.php',
+ 'BaconQrCode\\Renderer\\Eye\\PointyEye' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Eye/PointyEye.php',
+ 'BaconQrCode\\Renderer\\Eye\\SimpleCircleEye' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Eye/SimpleCircleEye.php',
+ 'BaconQrCode\\Renderer\\Eye\\SquareEye' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Eye/SquareEye.php',
+ 'BaconQrCode\\Renderer\\GDLibRenderer' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/GDLibRenderer.php',
+ 'BaconQrCode\\Renderer\\ImageRenderer' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/ImageRenderer.php',
+ 'BaconQrCode\\Renderer\\Image\\EpsImageBackEnd' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Image/EpsImageBackEnd.php',
+ 'BaconQrCode\\Renderer\\Image\\ImageBackEndInterface' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Image/ImageBackEndInterface.php',
+ 'BaconQrCode\\Renderer\\Image\\ImagickImageBackEnd' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Image/ImagickImageBackEnd.php',
+ 'BaconQrCode\\Renderer\\Image\\SvgImageBackEnd' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Image/SvgImageBackEnd.php',
+ 'BaconQrCode\\Renderer\\Image\\TransformationMatrix' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Image/TransformationMatrix.php',
+ 'BaconQrCode\\Renderer\\Module\\DotsModule' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Module/DotsModule.php',
+ 'BaconQrCode\\Renderer\\Module\\EdgeIterator\\Edge' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/Edge.php',
+ 'BaconQrCode\\Renderer\\Module\\EdgeIterator\\EdgeIterator' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/EdgeIterator.php',
+ 'BaconQrCode\\Renderer\\Module\\ModuleInterface' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Module/ModuleInterface.php',
+ 'BaconQrCode\\Renderer\\Module\\RoundnessModule' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Module/RoundnessModule.php',
+ 'BaconQrCode\\Renderer\\Module\\SquareModule' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Module/SquareModule.php',
+ 'BaconQrCode\\Renderer\\Path\\Close' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Path/Close.php',
+ 'BaconQrCode\\Renderer\\Path\\Curve' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Path/Curve.php',
+ 'BaconQrCode\\Renderer\\Path\\EllipticArc' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Path/EllipticArc.php',
+ 'BaconQrCode\\Renderer\\Path\\Line' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Path/Line.php',
+ 'BaconQrCode\\Renderer\\Path\\Move' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Path/Move.php',
+ 'BaconQrCode\\Renderer\\Path\\OperationInterface' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Path/OperationInterface.php',
+ 'BaconQrCode\\Renderer\\Path\\Path' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/Path/Path.php',
+ 'BaconQrCode\\Renderer\\PlainTextRenderer' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/PlainTextRenderer.php',
+ 'BaconQrCode\\Renderer\\RendererInterface' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/RendererInterface.php',
+ 'BaconQrCode\\Renderer\\RendererStyle\\EyeFill' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/RendererStyle/EyeFill.php',
+ 'BaconQrCode\\Renderer\\RendererStyle\\Fill' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/RendererStyle/Fill.php',
+ 'BaconQrCode\\Renderer\\RendererStyle\\Gradient' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/RendererStyle/Gradient.php',
+ 'BaconQrCode\\Renderer\\RendererStyle\\GradientType' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/RendererStyle/GradientType.php',
+ 'BaconQrCode\\Renderer\\RendererStyle\\RendererStyle' => $vendorDir . '/bacon/bacon-qr-code/src/Renderer/RendererStyle/RendererStyle.php',
+ 'BaconQrCode\\Writer' => $vendorDir . '/bacon/bacon-qr-code/src/Writer.php',
+ 'Composer\\CaBundle\\CaBundle' => $vendorDir . '/composer/ca-bundle/src/CaBundle.php',
+ 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
+ 'DASPRiD\\Enum\\AbstractEnum' => $vendorDir . '/dasprid/enum/src/AbstractEnum.php',
+ 'DASPRiD\\Enum\\EnumMap' => $vendorDir . '/dasprid/enum/src/EnumMap.php',
+ 'DASPRiD\\Enum\\Exception\\CloneNotSupportedException' => $vendorDir . '/dasprid/enum/src/Exception/CloneNotSupportedException.php',
+ 'DASPRiD\\Enum\\Exception\\ExceptionInterface' => $vendorDir . '/dasprid/enum/src/Exception/ExceptionInterface.php',
+ 'DASPRiD\\Enum\\Exception\\ExpectationException' => $vendorDir . '/dasprid/enum/src/Exception/ExpectationException.php',
+ 'DASPRiD\\Enum\\Exception\\IllegalArgumentException' => $vendorDir . '/dasprid/enum/src/Exception/IllegalArgumentException.php',
+ 'DASPRiD\\Enum\\Exception\\MismatchException' => $vendorDir . '/dasprid/enum/src/Exception/MismatchException.php',
+ 'DASPRiD\\Enum\\Exception\\SerializeNotSupportedException' => $vendorDir . '/dasprid/enum/src/Exception/SerializeNotSupportedException.php',
+ 'DASPRiD\\Enum\\Exception\\UnserializeNotSupportedException' => $vendorDir . '/dasprid/enum/src/Exception/UnserializeNotSupportedException.php',
+ 'DASPRiD\\Enum\\NullValue' => $vendorDir . '/dasprid/enum/src/NullValue.php',
'Kanti\\CacheOneFile' => $vendorDir . '/kanti/hub-updater/src/CacheOneFile.php',
- 'Kanti\\HelperClass' => $vendorDir . '/kanti/hub-updater/src/HelperClass.php',
'Kanti\\HubUpdater' => $vendorDir . '/kanti/hub-updater/src/HubUpdater.php',
'Michelf\\Markdown' => $vendorDir . '/michelf/php-markdown/Michelf/Markdown.php',
'Michelf\\MarkdownExtra' => $vendorDir . '/michelf/php-markdown/Michelf/MarkdownExtra.php',
'Michelf\\MarkdownInterface' => $vendorDir . '/michelf/php-markdown/Michelf/MarkdownInterface.php',
+ 'ParagonIE\\ConstantTime\\Base32' => $vendorDir . '/paragonie/constant_time_encoding/src/Base32.php',
+ 'ParagonIE\\ConstantTime\\Base32Hex' => $vendorDir . '/paragonie/constant_time_encoding/src/Base32Hex.php',
+ 'ParagonIE\\ConstantTime\\Base64' => $vendorDir . '/paragonie/constant_time_encoding/src/Base64.php',
+ 'ParagonIE\\ConstantTime\\Base64DotSlash' => $vendorDir . '/paragonie/constant_time_encoding/src/Base64DotSlash.php',
+ 'ParagonIE\\ConstantTime\\Base64DotSlashOrdered' => $vendorDir . '/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php',
+ 'ParagonIE\\ConstantTime\\Base64UrlSafe' => $vendorDir . '/paragonie/constant_time_encoding/src/Base64UrlSafe.php',
+ 'ParagonIE\\ConstantTime\\Binary' => $vendorDir . '/paragonie/constant_time_encoding/src/Binary.php',
+ 'ParagonIE\\ConstantTime\\EncoderInterface' => $vendorDir . '/paragonie/constant_time_encoding/src/EncoderInterface.php',
+ 'ParagonIE\\ConstantTime\\Encoding' => $vendorDir . '/paragonie/constant_time_encoding/src/Encoding.php',
+ 'ParagonIE\\ConstantTime\\Hex' => $vendorDir . '/paragonie/constant_time_encoding/src/Hex.php',
+ 'ParagonIE\\ConstantTime\\RFC4648' => $vendorDir . '/paragonie/constant_time_encoding/src/RFC4648.php',
+ 'PragmaRX\\Google2FA\\Exceptions\\Contracts\\Google2FA' => $vendorDir . '/pragmarx/google2fa/src/Exceptions/Contracts/Google2FA.php',
+ 'PragmaRX\\Google2FA\\Exceptions\\Contracts\\IncompatibleWithGoogleAuthenticator' => $vendorDir . '/pragmarx/google2fa/src/Exceptions/Contracts/IncompatibleWithGoogleAuthenticator.php',
+ 'PragmaRX\\Google2FA\\Exceptions\\Contracts\\InvalidAlgorithm' => $vendorDir . '/pragmarx/google2fa/src/Exceptions/Contracts/InvalidAlgorithm.php',
+ 'PragmaRX\\Google2FA\\Exceptions\\Contracts\\InvalidCharacters' => $vendorDir . '/pragmarx/google2fa/src/Exceptions/Contracts/InvalidCharacters.php',
+ 'PragmaRX\\Google2FA\\Exceptions\\Contracts\\SecretKeyTooShort' => $vendorDir . '/pragmarx/google2fa/src/Exceptions/Contracts/SecretKeyTooShort.php',
+ 'PragmaRX\\Google2FA\\Exceptions\\Google2FAException' => $vendorDir . '/pragmarx/google2fa/src/Exceptions/Google2FAException.php',
+ 'PragmaRX\\Google2FA\\Exceptions\\IncompatibleWithGoogleAuthenticatorException' => $vendorDir . '/pragmarx/google2fa/src/Exceptions/IncompatibleWithGoogleAuthenticatorException.php',
+ 'PragmaRX\\Google2FA\\Exceptions\\InvalidAlgorithmException' => $vendorDir . '/pragmarx/google2fa/src/Exceptions/InvalidAlgorithmException.php',
+ 'PragmaRX\\Google2FA\\Exceptions\\InvalidCharactersException' => $vendorDir . '/pragmarx/google2fa/src/Exceptions/InvalidCharactersException.php',
+ 'PragmaRX\\Google2FA\\Exceptions\\SecretKeyTooShortException' => $vendorDir . '/pragmarx/google2fa/src/Exceptions/SecretKeyTooShortException.php',
+ 'PragmaRX\\Google2FA\\Google2FA' => $vendorDir . '/pragmarx/google2fa/src/Google2FA.php',
+ 'PragmaRX\\Google2FA\\Support\\Base32' => $vendorDir . '/pragmarx/google2fa/src/Support/Base32.php',
+ 'PragmaRX\\Google2FA\\Support\\Constants' => $vendorDir . '/pragmarx/google2fa/src/Support/Constants.php',
+ 'PragmaRX\\Google2FA\\Support\\QRCode' => $vendorDir . '/pragmarx/google2fa/src/Support/QRCode.php',
'Suin\\RSSWriter\\Channel' => $vendorDir . '/suin/php-rss-writer/src/Suin/RSSWriter/Channel.php',
'Suin\\RSSWriter\\ChannelInterface' => $vendorDir . '/suin/php-rss-writer/src/Suin/RSSWriter/ChannelInterface.php',
'Suin\\RSSWriter\\Feed' => $vendorDir . '/suin/php-rss-writer/src/Suin/RSSWriter/Feed.php',
@@ -20,5 +118,7 @@ return array(
'Suin\\RSSWriter\\ItemInterface' => $vendorDir . '/suin/php-rss-writer/src/Suin/RSSWriter/ItemInterface.php',
'Suin\\RSSWriter\\SimpleXMLElement' => $vendorDir . '/suin/php-rss-writer/src/Suin/RSSWriter/SimpleXMLElement.php',
'URLify' => $vendorDir . '/jbroadway/urlify/URLify.php',
- 'URLifyTest' => $vendorDir . '/jbroadway/urlify/tests/URLifyTest.php',
+ 'voku\\helper\\ASCII' => $vendorDir . '/voku/portable-ascii/src/voku/helper/ASCII.php',
+ 'voku\\helper\\StopWords' => $vendorDir . '/voku/stop-words/src/voku/helper/StopWords.php',
+ 'voku\\helper\\StopWordsLanguageNotExists' => $vendorDir . '/voku/stop-words/src/voku/helper/StopWordsLanguageNotExists.php',
);
diff --git a/system/vendor/composer/autoload_files.php b/system/vendor/composer/autoload_files.php
index 00cf5d7..46cd6f2 100644
--- a/system/vendor/composer/autoload_files.php
+++ b/system/vendor/composer/autoload_files.php
@@ -2,7 +2,7 @@
// autoload_files.php @generated by Composer
-$vendorDir = dirname(dirname(__FILE__));
+$vendorDir = dirname(__DIR__);
$baseDir = dirname(dirname($vendorDir));
return array(
diff --git a/system/vendor/composer/autoload_namespaces.php b/system/vendor/composer/autoload_namespaces.php
index 6cd4d04..a93b136 100644
--- a/system/vendor/composer/autoload_namespaces.php
+++ b/system/vendor/composer/autoload_namespaces.php
@@ -2,7 +2,7 @@
// autoload_namespaces.php @generated by Composer
-$vendorDir = dirname(dirname(__FILE__));
+$vendorDir = dirname(__DIR__);
$baseDir = dirname(dirname($vendorDir));
return array(
diff --git a/system/vendor/composer/autoload_psr4.php b/system/vendor/composer/autoload_psr4.php
index 07c859d..4386688 100644
--- a/system/vendor/composer/autoload_psr4.php
+++ b/system/vendor/composer/autoload_psr4.php
@@ -2,10 +2,16 @@
// autoload_psr4.php @generated by Composer
-$vendorDir = dirname(dirname(__FILE__));
+$vendorDir = dirname(__DIR__);
$baseDir = dirname(dirname($vendorDir));
return array(
+ 'voku\\' => array($vendorDir . '/voku/portable-ascii/src/voku', $vendorDir . '/voku/stop-words/src/voku'),
+ 'PragmaRX\\Google2FA\\' => array($vendorDir . '/pragmarx/google2fa/src'),
+ 'ParagonIE\\ConstantTime\\' => array($vendorDir . '/paragonie/constant_time_encoding/src'),
'Michelf\\' => array($vendorDir . '/michelf/php-markdown/Michelf'),
'Kanti\\' => array($vendorDir . '/kanti/hub-updater/src'),
+ 'DASPRiD\\Enum\\' => array($vendorDir . '/dasprid/enum/src'),
+ 'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
+ 'BaconQrCode\\' => array($vendorDir . '/bacon/bacon-qr-code/src'),
);
diff --git a/system/vendor/composer/autoload_real.php b/system/vendor/composer/autoload_real.php
index 437265b..efcb232 100644
--- a/system/vendor/composer/autoload_real.php
+++ b/system/vendor/composer/autoload_real.php
@@ -22,52 +22,29 @@ class ComposerAutoloaderInitd88c6c25320034df85dd42f1462fbda7
return self::$loader;
}
+ require __DIR__ . '/platform_check.php';
+
spl_autoload_register(array('ComposerAutoloaderInitd88c6c25320034df85dd42f1462fbda7', 'loadClassLoader'), true, true);
- self::$loader = $loader = new \Composer\Autoload\ClassLoader();
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInitd88c6c25320034df85dd42f1462fbda7', 'loadClassLoader'));
- $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
- if ($useStaticLoader) {
- require_once __DIR__ . '/autoload_static.php';
-
- call_user_func(\Composer\Autoload\ComposerStaticInitd88c6c25320034df85dd42f1462fbda7::getInitializer($loader));
- } else {
- $map = require __DIR__ . '/autoload_namespaces.php';
- foreach ($map as $namespace => $path) {
- $loader->set($namespace, $path);
- }
-
- $map = require __DIR__ . '/autoload_psr4.php';
- foreach ($map as $namespace => $path) {
- $loader->setPsr4($namespace, $path);
- }
-
- $classMap = require __DIR__ . '/autoload_classmap.php';
- if ($classMap) {
- $loader->addClassMap($classMap);
- }
- }
+ require __DIR__ . '/autoload_static.php';
+ call_user_func(\Composer\Autoload\ComposerStaticInitd88c6c25320034df85dd42f1462fbda7::getInitializer($loader));
$loader->register(true);
- if ($useStaticLoader) {
- $includeFiles = Composer\Autoload\ComposerStaticInitd88c6c25320034df85dd42f1462fbda7::$files;
- } else {
- $includeFiles = require __DIR__ . '/autoload_files.php';
- }
- foreach ($includeFiles as $fileIdentifier => $file) {
- composerRequired88c6c25320034df85dd42f1462fbda7($fileIdentifier, $file);
+ $filesToLoad = \Composer\Autoload\ComposerStaticInitd88c6c25320034df85dd42f1462fbda7::$files;
+ $requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
+ if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
+ $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
+
+ require $file;
+ }
+ }, null, null);
+ foreach ($filesToLoad as $fileIdentifier => $file) {
+ $requireFile($fileIdentifier, $file);
}
return $loader;
}
}
-
-function composerRequired88c6c25320034df85dd42f1462fbda7($fileIdentifier, $file)
-{
- if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
- require $file;
-
- $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
- }
-}
diff --git a/system/vendor/composer/autoload_static.php b/system/vendor/composer/autoload_static.php
index b537df5..e3dc482 100644
--- a/system/vendor/composer/autoload_static.php
+++ b/system/vendor/composer/autoload_static.php
@@ -16,6 +16,15 @@ class ComposerStaticInitd88c6c25320034df85dd42f1462fbda7
);
public static $prefixLengthsPsr4 = array (
+ 'v' =>
+ array (
+ 'voku\\' => 5,
+ ),
+ 'P' =>
+ array (
+ 'PragmaRX\\Google2FA\\' => 19,
+ 'ParagonIE\\ConstantTime\\' => 23,
+ ),
'M' =>
array (
'Michelf\\' => 8,
@@ -24,9 +33,34 @@ class ComposerStaticInitd88c6c25320034df85dd42f1462fbda7
array (
'Kanti\\' => 6,
),
+ 'D' =>
+ array (
+ 'DASPRiD\\Enum\\' => 13,
+ ),
+ 'C' =>
+ array (
+ 'Composer\\CaBundle\\' => 18,
+ ),
+ 'B' =>
+ array (
+ 'BaconQrCode\\' => 12,
+ ),
);
public static $prefixDirsPsr4 = array (
+ 'voku\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/voku/portable-ascii/src/voku',
+ 1 => __DIR__ . '/..' . '/voku/stop-words/src/voku',
+ ),
+ 'PragmaRX\\Google2FA\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/pragmarx/google2fa/src',
+ ),
+ 'ParagonIE\\ConstantTime\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src',
+ ),
'Michelf\\' =>
array (
0 => __DIR__ . '/..' . '/michelf/php-markdown/Michelf',
@@ -35,6 +69,18 @@ class ComposerStaticInitd88c6c25320034df85dd42f1462fbda7
array (
0 => __DIR__ . '/..' . '/kanti/hub-updater/src',
),
+ 'DASPRiD\\Enum\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/dasprid/enum/src',
+ ),
+ 'Composer\\CaBundle\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
+ ),
+ 'BaconQrCode\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/bacon/bacon-qr-code/src',
+ ),
);
public static $prefixesPsr0 = array (
@@ -55,12 +101,110 @@ class ComposerStaticInitd88c6c25320034df85dd42f1462fbda7
);
public static $classMap = array (
+ 'BaconQrCode\\Common\\BitArray' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Common/BitArray.php',
+ 'BaconQrCode\\Common\\BitMatrix' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Common/BitMatrix.php',
+ 'BaconQrCode\\Common\\BitUtils' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Common/BitUtils.php',
+ 'BaconQrCode\\Common\\CharacterSetEci' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Common/CharacterSetEci.php',
+ 'BaconQrCode\\Common\\EcBlock' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Common/EcBlock.php',
+ 'BaconQrCode\\Common\\EcBlocks' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Common/EcBlocks.php',
+ 'BaconQrCode\\Common\\ErrorCorrectionLevel' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Common/ErrorCorrectionLevel.php',
+ 'BaconQrCode\\Common\\FormatInformation' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Common/FormatInformation.php',
+ 'BaconQrCode\\Common\\Mode' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Common/Mode.php',
+ 'BaconQrCode\\Common\\ReedSolomonCodec' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Common/ReedSolomonCodec.php',
+ 'BaconQrCode\\Common\\Version' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Common/Version.php',
+ 'BaconQrCode\\Encoder\\BlockPair' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Encoder/BlockPair.php',
+ 'BaconQrCode\\Encoder\\ByteMatrix' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Encoder/ByteMatrix.php',
+ 'BaconQrCode\\Encoder\\Encoder' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Encoder/Encoder.php',
+ 'BaconQrCode\\Encoder\\MaskUtil' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Encoder/MaskUtil.php',
+ 'BaconQrCode\\Encoder\\MatrixUtil' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Encoder/MatrixUtil.php',
+ 'BaconQrCode\\Encoder\\QrCode' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Encoder/QrCode.php',
+ 'BaconQrCode\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Exception/ExceptionInterface.php',
+ 'BaconQrCode\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Exception/InvalidArgumentException.php',
+ 'BaconQrCode\\Exception\\OutOfBoundsException' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Exception/OutOfBoundsException.php',
+ 'BaconQrCode\\Exception\\RuntimeException' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Exception/RuntimeException.php',
+ 'BaconQrCode\\Exception\\UnexpectedValueException' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Exception/UnexpectedValueException.php',
+ 'BaconQrCode\\Exception\\WriterException' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Exception/WriterException.php',
+ 'BaconQrCode\\Renderer\\Color\\Alpha' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Color/Alpha.php',
+ 'BaconQrCode\\Renderer\\Color\\Cmyk' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Color/Cmyk.php',
+ 'BaconQrCode\\Renderer\\Color\\ColorInterface' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Color/ColorInterface.php',
+ 'BaconQrCode\\Renderer\\Color\\Gray' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Color/Gray.php',
+ 'BaconQrCode\\Renderer\\Color\\Rgb' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Color/Rgb.php',
+ 'BaconQrCode\\Renderer\\Eye\\CompositeEye' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Eye/CompositeEye.php',
+ 'BaconQrCode\\Renderer\\Eye\\EyeInterface' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Eye/EyeInterface.php',
+ 'BaconQrCode\\Renderer\\Eye\\ModuleEye' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Eye/ModuleEye.php',
+ 'BaconQrCode\\Renderer\\Eye\\PointyEye' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Eye/PointyEye.php',
+ 'BaconQrCode\\Renderer\\Eye\\SimpleCircleEye' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Eye/SimpleCircleEye.php',
+ 'BaconQrCode\\Renderer\\Eye\\SquareEye' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Eye/SquareEye.php',
+ 'BaconQrCode\\Renderer\\GDLibRenderer' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/GDLibRenderer.php',
+ 'BaconQrCode\\Renderer\\ImageRenderer' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/ImageRenderer.php',
+ 'BaconQrCode\\Renderer\\Image\\EpsImageBackEnd' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Image/EpsImageBackEnd.php',
+ 'BaconQrCode\\Renderer\\Image\\ImageBackEndInterface' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Image/ImageBackEndInterface.php',
+ 'BaconQrCode\\Renderer\\Image\\ImagickImageBackEnd' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Image/ImagickImageBackEnd.php',
+ 'BaconQrCode\\Renderer\\Image\\SvgImageBackEnd' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Image/SvgImageBackEnd.php',
+ 'BaconQrCode\\Renderer\\Image\\TransformationMatrix' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Image/TransformationMatrix.php',
+ 'BaconQrCode\\Renderer\\Module\\DotsModule' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Module/DotsModule.php',
+ 'BaconQrCode\\Renderer\\Module\\EdgeIterator\\Edge' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/Edge.php',
+ 'BaconQrCode\\Renderer\\Module\\EdgeIterator\\EdgeIterator' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/EdgeIterator.php',
+ 'BaconQrCode\\Renderer\\Module\\ModuleInterface' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Module/ModuleInterface.php',
+ 'BaconQrCode\\Renderer\\Module\\RoundnessModule' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Module/RoundnessModule.php',
+ 'BaconQrCode\\Renderer\\Module\\SquareModule' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Module/SquareModule.php',
+ 'BaconQrCode\\Renderer\\Path\\Close' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Path/Close.php',
+ 'BaconQrCode\\Renderer\\Path\\Curve' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Path/Curve.php',
+ 'BaconQrCode\\Renderer\\Path\\EllipticArc' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Path/EllipticArc.php',
+ 'BaconQrCode\\Renderer\\Path\\Line' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Path/Line.php',
+ 'BaconQrCode\\Renderer\\Path\\Move' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Path/Move.php',
+ 'BaconQrCode\\Renderer\\Path\\OperationInterface' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Path/OperationInterface.php',
+ 'BaconQrCode\\Renderer\\Path\\Path' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/Path/Path.php',
+ 'BaconQrCode\\Renderer\\PlainTextRenderer' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/PlainTextRenderer.php',
+ 'BaconQrCode\\Renderer\\RendererInterface' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/RendererInterface.php',
+ 'BaconQrCode\\Renderer\\RendererStyle\\EyeFill' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/RendererStyle/EyeFill.php',
+ 'BaconQrCode\\Renderer\\RendererStyle\\Fill' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/RendererStyle/Fill.php',
+ 'BaconQrCode\\Renderer\\RendererStyle\\Gradient' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/RendererStyle/Gradient.php',
+ 'BaconQrCode\\Renderer\\RendererStyle\\GradientType' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/RendererStyle/GradientType.php',
+ 'BaconQrCode\\Renderer\\RendererStyle\\RendererStyle' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Renderer/RendererStyle/RendererStyle.php',
+ 'BaconQrCode\\Writer' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/Writer.php',
+ 'Composer\\CaBundle\\CaBundle' => __DIR__ . '/..' . '/composer/ca-bundle/src/CaBundle.php',
+ 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
+ 'DASPRiD\\Enum\\AbstractEnum' => __DIR__ . '/..' . '/dasprid/enum/src/AbstractEnum.php',
+ 'DASPRiD\\Enum\\EnumMap' => __DIR__ . '/..' . '/dasprid/enum/src/EnumMap.php',
+ 'DASPRiD\\Enum\\Exception\\CloneNotSupportedException' => __DIR__ . '/..' . '/dasprid/enum/src/Exception/CloneNotSupportedException.php',
+ 'DASPRiD\\Enum\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/dasprid/enum/src/Exception/ExceptionInterface.php',
+ 'DASPRiD\\Enum\\Exception\\ExpectationException' => __DIR__ . '/..' . '/dasprid/enum/src/Exception/ExpectationException.php',
+ 'DASPRiD\\Enum\\Exception\\IllegalArgumentException' => __DIR__ . '/..' . '/dasprid/enum/src/Exception/IllegalArgumentException.php',
+ 'DASPRiD\\Enum\\Exception\\MismatchException' => __DIR__ . '/..' . '/dasprid/enum/src/Exception/MismatchException.php',
+ 'DASPRiD\\Enum\\Exception\\SerializeNotSupportedException' => __DIR__ . '/..' . '/dasprid/enum/src/Exception/SerializeNotSupportedException.php',
+ 'DASPRiD\\Enum\\Exception\\UnserializeNotSupportedException' => __DIR__ . '/..' . '/dasprid/enum/src/Exception/UnserializeNotSupportedException.php',
+ 'DASPRiD\\Enum\\NullValue' => __DIR__ . '/..' . '/dasprid/enum/src/NullValue.php',
'Kanti\\CacheOneFile' => __DIR__ . '/..' . '/kanti/hub-updater/src/CacheOneFile.php',
- 'Kanti\\HelperClass' => __DIR__ . '/..' . '/kanti/hub-updater/src/HelperClass.php',
'Kanti\\HubUpdater' => __DIR__ . '/..' . '/kanti/hub-updater/src/HubUpdater.php',
'Michelf\\Markdown' => __DIR__ . '/..' . '/michelf/php-markdown/Michelf/Markdown.php',
'Michelf\\MarkdownExtra' => __DIR__ . '/..' . '/michelf/php-markdown/Michelf/MarkdownExtra.php',
'Michelf\\MarkdownInterface' => __DIR__ . '/..' . '/michelf/php-markdown/Michelf/MarkdownInterface.php',
+ 'ParagonIE\\ConstantTime\\Base32' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base32.php',
+ 'ParagonIE\\ConstantTime\\Base32Hex' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base32Hex.php',
+ 'ParagonIE\\ConstantTime\\Base64' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base64.php',
+ 'ParagonIE\\ConstantTime\\Base64DotSlash' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base64DotSlash.php',
+ 'ParagonIE\\ConstantTime\\Base64DotSlashOrdered' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php',
+ 'ParagonIE\\ConstantTime\\Base64UrlSafe' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base64UrlSafe.php',
+ 'ParagonIE\\ConstantTime\\Binary' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Binary.php',
+ 'ParagonIE\\ConstantTime\\EncoderInterface' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/EncoderInterface.php',
+ 'ParagonIE\\ConstantTime\\Encoding' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Encoding.php',
+ 'ParagonIE\\ConstantTime\\Hex' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Hex.php',
+ 'ParagonIE\\ConstantTime\\RFC4648' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/RFC4648.php',
+ 'PragmaRX\\Google2FA\\Exceptions\\Contracts\\Google2FA' => __DIR__ . '/..' . '/pragmarx/google2fa/src/Exceptions/Contracts/Google2FA.php',
+ 'PragmaRX\\Google2FA\\Exceptions\\Contracts\\IncompatibleWithGoogleAuthenticator' => __DIR__ . '/..' . '/pragmarx/google2fa/src/Exceptions/Contracts/IncompatibleWithGoogleAuthenticator.php',
+ 'PragmaRX\\Google2FA\\Exceptions\\Contracts\\InvalidAlgorithm' => __DIR__ . '/..' . '/pragmarx/google2fa/src/Exceptions/Contracts/InvalidAlgorithm.php',
+ 'PragmaRX\\Google2FA\\Exceptions\\Contracts\\InvalidCharacters' => __DIR__ . '/..' . '/pragmarx/google2fa/src/Exceptions/Contracts/InvalidCharacters.php',
+ 'PragmaRX\\Google2FA\\Exceptions\\Contracts\\SecretKeyTooShort' => __DIR__ . '/..' . '/pragmarx/google2fa/src/Exceptions/Contracts/SecretKeyTooShort.php',
+ 'PragmaRX\\Google2FA\\Exceptions\\Google2FAException' => __DIR__ . '/..' . '/pragmarx/google2fa/src/Exceptions/Google2FAException.php',
+ 'PragmaRX\\Google2FA\\Exceptions\\IncompatibleWithGoogleAuthenticatorException' => __DIR__ . '/..' . '/pragmarx/google2fa/src/Exceptions/IncompatibleWithGoogleAuthenticatorException.php',
+ 'PragmaRX\\Google2FA\\Exceptions\\InvalidAlgorithmException' => __DIR__ . '/..' . '/pragmarx/google2fa/src/Exceptions/InvalidAlgorithmException.php',
+ 'PragmaRX\\Google2FA\\Exceptions\\InvalidCharactersException' => __DIR__ . '/..' . '/pragmarx/google2fa/src/Exceptions/InvalidCharactersException.php',
+ 'PragmaRX\\Google2FA\\Exceptions\\SecretKeyTooShortException' => __DIR__ . '/..' . '/pragmarx/google2fa/src/Exceptions/SecretKeyTooShortException.php',
+ 'PragmaRX\\Google2FA\\Google2FA' => __DIR__ . '/..' . '/pragmarx/google2fa/src/Google2FA.php',
+ 'PragmaRX\\Google2FA\\Support\\Base32' => __DIR__ . '/..' . '/pragmarx/google2fa/src/Support/Base32.php',
+ 'PragmaRX\\Google2FA\\Support\\Constants' => __DIR__ . '/..' . '/pragmarx/google2fa/src/Support/Constants.php',
+ 'PragmaRX\\Google2FA\\Support\\QRCode' => __DIR__ . '/..' . '/pragmarx/google2fa/src/Support/QRCode.php',
'Suin\\RSSWriter\\Channel' => __DIR__ . '/..' . '/suin/php-rss-writer/src/Suin/RSSWriter/Channel.php',
'Suin\\RSSWriter\\ChannelInterface' => __DIR__ . '/..' . '/suin/php-rss-writer/src/Suin/RSSWriter/ChannelInterface.php',
'Suin\\RSSWriter\\Feed' => __DIR__ . '/..' . '/suin/php-rss-writer/src/Suin/RSSWriter/Feed.php',
@@ -69,7 +213,9 @@ class ComposerStaticInitd88c6c25320034df85dd42f1462fbda7
'Suin\\RSSWriter\\ItemInterface' => __DIR__ . '/..' . '/suin/php-rss-writer/src/Suin/RSSWriter/ItemInterface.php',
'Suin\\RSSWriter\\SimpleXMLElement' => __DIR__ . '/..' . '/suin/php-rss-writer/src/Suin/RSSWriter/SimpleXMLElement.php',
'URLify' => __DIR__ . '/..' . '/jbroadway/urlify/URLify.php',
- 'URLifyTest' => __DIR__ . '/..' . '/jbroadway/urlify/tests/URLifyTest.php',
+ 'voku\\helper\\ASCII' => __DIR__ . '/..' . '/voku/portable-ascii/src/voku/helper/ASCII.php',
+ 'voku\\helper\\StopWords' => __DIR__ . '/..' . '/voku/stop-words/src/voku/helper/StopWords.php',
+ 'voku\\helper\\StopWordsLanguageNotExists' => __DIR__ . '/..' . '/voku/stop-words/src/voku/helper/StopWordsLanguageNotExists.php',
);
public static function getInitializer(ClassLoader $loader)
diff --git a/system/vendor/composer/ca-bundle/LICENSE b/system/vendor/composer/ca-bundle/LICENSE
new file mode 100644
index 0000000..c5b5220
--- /dev/null
+++ b/system/vendor/composer/ca-bundle/LICENSE
@@ -0,0 +1,19 @@
+Copyright (C) 2016 Composer
+
+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.
diff --git a/system/vendor/composer/ca-bundle/README.md b/system/vendor/composer/ca-bundle/README.md
new file mode 100644
index 0000000..d8205ec
--- /dev/null
+++ b/system/vendor/composer/ca-bundle/README.md
@@ -0,0 +1,85 @@
+composer/ca-bundle
+==================
+
+Small utility library that lets you find a path to the system CA bundle,
+and includes a fallback to the Mozilla CA bundle.
+
+Originally written as part of [composer/composer](https://github.com/composer/composer),
+now extracted and made available as a stand-alone library.
+
+
+Installation
+------------
+
+Install the latest version with:
+
+```bash
+$ composer require composer/ca-bundle
+```
+
+
+Requirements
+------------
+
+* PHP 5.3.2 is required but using the latest version of PHP is highly recommended.
+
+
+Basic usage
+-----------
+
+### `Composer\CaBundle\CaBundle`
+
+- `CaBundle::getSystemCaRootBundlePath()`: Returns the system CA bundle path, or a path to the bundled one as fallback
+- `CaBundle::getBundledCaBundlePath()`: Returns the path to the bundled CA file
+- `CaBundle::validateCaFile($filename)`: Validates a CA file using openssl_x509_parse only if it is safe to use
+- `CaBundle::isOpensslParseSafe()`: Test if it is safe to use the PHP function openssl_x509_parse()
+- `CaBundle::reset()`: Resets the static caches
+
+
+#### To use with curl
+
+```php
+$curl = curl_init("https://example.org/");
+
+$caPathOrFile = \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath();
+if (is_dir($caPathOrFile)) {
+ curl_setopt($curl, CURLOPT_CAPATH, $caPathOrFile);
+} else {
+ curl_setopt($curl, CURLOPT_CAINFO, $caPathOrFile);
+}
+
+$result = curl_exec($curl);
+```
+
+#### To use with php streams
+
+```php
+$opts = array(
+ 'http' => array(
+ 'method' => "GET"
+ )
+);
+
+$caPathOrFile = \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath();
+if (is_dir($caPathOrFile)) {
+ $opts['ssl']['capath'] = $caPathOrFile;
+} else {
+ $opts['ssl']['cafile'] = $caPathOrFile;
+}
+
+$context = stream_context_create($opts);
+$result = file_get_contents('https://example.com', false, $context);
+```
+
+#### To use with Guzzle
+
+```php
+$client = new \GuzzleHttp\Client([
+ \GuzzleHttp\RequestOptions::VERIFY => \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath()
+]);
+```
+
+License
+-------
+
+composer/ca-bundle is licensed under the MIT License, see the LICENSE file for details.
diff --git a/system/vendor/composer/ca-bundle/composer.json b/system/vendor/composer/ca-bundle/composer.json
new file mode 100644
index 0000000..a998783
--- /dev/null
+++ b/system/vendor/composer/ca-bundle/composer.json
@@ -0,0 +1,54 @@
+{
+ "name": "composer/ca-bundle",
+ "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
+ "type": "library",
+ "license": "MIT",
+ "keywords": [
+ "cabundle",
+ "cacert",
+ "certificate",
+ "ssl",
+ "tls"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "support": {
+ "irc": "irc://irc.freenode.org/composer",
+ "issues": "https://github.com/composer/ca-bundle/issues"
+ },
+ "require": {
+ "ext-openssl": "*",
+ "ext-pcre": "*",
+ "php": "^7.2 || ^8.0"
+ },
+ "require-dev": {
+ "symfony/phpunit-bridge": "^4.2 || ^5",
+ "phpstan/phpstan": "^1.10",
+ "psr/log": "^1.0",
+ "symfony/process": "^4.0 || ^5.0 || ^6.0 || ^7.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\CaBundle\\": "src"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Composer\\CaBundle\\": "tests"
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ }
+ },
+ "scripts": {
+ "test": "vendor/bin/simple-phpunit",
+ "phpstan": "vendor/bin/phpstan analyse"
+ }
+}
diff --git a/system/vendor/composer/ca-bundle/res/cacert.pem b/system/vendor/composer/ca-bundle/res/cacert.pem
new file mode 100644
index 0000000..f78a610
--- /dev/null
+++ b/system/vendor/composer/ca-bundle/res/cacert.pem
@@ -0,0 +1,3581 @@
+##
+## Bundle of CA Root Certificates
+##
+## Certificate data from Mozilla as of: Mon Mar 11 15:25:27 2024 GMT
+##
+## This is a bundle of X.509 certificates of public Certificate Authorities
+## (CA). These were automatically extracted from Mozilla's root certificates
+## file (certdata.txt). This file can be found in the mozilla source tree:
+## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt
+##
+## It contains the certificates in PEM format and therefore
+## can be directly used with curl / libcurl / php_curl, or with
+## an Apache+mod_ssl webserver for SSL client authentication.
+## Just configure this file as the SSLCACertificateFile.
+##
+## Conversion done with mk-ca-bundle.pl version 1.29.
+## SHA256: 4d96bd539f4719e9ace493757afbe4a23ee8579de1c97fbebc50bba3c12e8c1e
+##
+
+
+GlobalSign Root CA
+==================
+-----BEGIN CERTIFICATE-----
+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx
+GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds
+b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV
+BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD
+VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa
+DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc
+THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb
+Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP
+c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX
+gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF
+AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj
+Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG
+j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH
+hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC
+X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
+-----END CERTIFICATE-----
+
+Entrust.net Premium 2048 Secure Server CA
+=========================================
+-----BEGIN CERTIFICATE-----
+MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u
+ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp
+bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV
+BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx
+NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3
+d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl
+MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u
+ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL
+Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr
+hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW
+nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi
+VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ
+KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy
+T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
+zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT
+J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e
+nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE=
+-----END CERTIFICATE-----
+
+Baltimore CyberTrust Root
+=========================
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE
+ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li
+ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC
+SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs
+dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME
+uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB
+UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C
+G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9
+XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr
+l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI
+VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB
+BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh
+cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5
+hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa
+Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
+RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
+-----END CERTIFICATE-----
+
+Entrust Root Certification Authority
+====================================
+-----BEGIN CERTIFICATE-----
+MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV
+BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw
+b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG
+A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0
+MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu
+MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu
+Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v
+dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz
+A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww
+Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68
+j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN
+rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw
+DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1
+MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH
+hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
+A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM
+Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa
+v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS
+W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0
+tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8
+-----END CERTIFICATE-----
+
+Comodo AAA Services root
+========================
+-----BEGIN CERTIFICATE-----
+MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
+R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
+TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw
+MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl
+c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV
+BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG
+C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs
+i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW
+Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH
+Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK
+Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f
+BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl
+cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz
+LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm
+7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
+Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z
+8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C
+12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
+-----END CERTIFICATE-----
+
+QuoVadis Root CA 2
+==================
+-----BEGIN CERTIFICATE-----
+MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
+EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx
+ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6
+XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk
+lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB
+lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy
+lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt
+66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn
+wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh
+D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy
+BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie
+J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud
+DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU
+a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
+ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv
+Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3
+UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm
+VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK
++JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW
+IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1
+WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X
+f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II
+4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8
+VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
+-----END CERTIFICATE-----
+
+QuoVadis Root CA 3
+==================
+-----BEGIN CERTIFICATE-----
+MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
+EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx
+OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg
+DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij
+KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K
+DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv
+BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp
+p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8
+nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX
+MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM
+Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz
+uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT
+BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj
+YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
+aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB
+BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD
+VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4
+ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE
+AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV
+qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s
+hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z
+POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2
+Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp
+8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC
+bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu
+g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p
+vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
+qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
+-----END CERTIFICATE-----
+
+XRamp Global CA Root
+====================
+-----BEGIN CERTIFICATE-----
+MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE
+BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj
+dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx
+HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg
+U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
+dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu
+IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx
+foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE
+zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs
+AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry
+xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
+EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap
+oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC
+AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc
+/Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
+qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n
+nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz
+8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw=
+-----END CERTIFICATE-----
+
+Go Daddy Class 2 CA
+===================
+-----BEGIN CERTIFICATE-----
+MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY
+VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG
+A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
+RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD
+ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
+2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32
+qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j
+YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY
+vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O
+BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o
+atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu
+MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim
+PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
+I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
+HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI
+Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b
+vZ8=
+-----END CERTIFICATE-----
+
+Starfield Class 2 CA
+====================
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc
+U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo
+MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG
+A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG
+SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY
+bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ
+JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm
+epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN
+F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF
+MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f
+hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo
+bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g
+QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs
+afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM
+PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
+xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD
+KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3
+QBFGmh95DmK/D5fs4C8fF5Q=
+-----END CERTIFICATE-----
+
+DigiCert Assured ID Root CA
+===========================
+-----BEGIN CERTIFICATE-----
+MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
+IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx
+MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
+ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO
+9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy
+UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW
+/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy
+oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf
+GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF
+66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq
+hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc
+EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn
+SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i
+8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
+-----END CERTIFICATE-----
+
+DigiCert Global Root CA
+=======================
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
+HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw
+MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
+dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn
+TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5
+BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H
+4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y
+7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB
+o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm
+8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF
+BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr
+EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt
+tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886
+UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
+CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
+-----END CERTIFICATE-----
+
+DigiCert High Assurance EV Root CA
+==================================
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw
+KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw
+MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
+MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu
+Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t
+Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS
+OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3
+MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ
+NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe
+h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB
+Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY
+JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ
+V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp
+myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK
+mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
+vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K
+-----END CERTIFICATE-----
+
+SwissSign Gold CA - G2
+======================
+-----BEGIN CERTIFICATE-----
+MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw
+EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN
+MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp
+c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq
+t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C
+jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg
+vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF
+ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR
+AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend
+jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO
+peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR
+7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi
+GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64
+OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
+L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm
+5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr
+44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf
+Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m
+Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp
+mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk
+vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf
+KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br
+NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj
+viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
+-----END CERTIFICATE-----
+
+SwissSign Silver CA - G2
+========================
+-----BEGIN CERTIFICATE-----
+MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT
+BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X
+DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3
+aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG
+9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644
+N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm
++/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH
+6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu
+MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h
+qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5
+FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs
+ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc
+celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X
+CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB
+tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
+cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P
+4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F
+kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L
+3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx
+/uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa
+DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP
+e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu
+WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ
+DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub
+DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
+-----END CERTIFICATE-----
+
+SecureTrust CA
+==============
+-----BEGIN CERTIFICATE-----
+MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG
+EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy
+dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe
+BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX
+OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t
+DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH
+GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b
+01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH
+ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj
+aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
+KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu
+SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf
+mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ
+nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
+3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
+-----END CERTIFICATE-----
+
+Secure Global CA
+================
+-----BEGIN CERTIFICATE-----
+MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG
+EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH
+bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg
+MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg
+Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx
+YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ
+bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g
+8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV
+HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi
+0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
+EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn
+oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA
+MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+
+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn
+CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5
+3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
+f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
+-----END CERTIFICATE-----
+
+COMODO Certification Authority
+==============================
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE
+BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
+A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1
+dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb
+MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD
+T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH
++7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww
+xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV
+4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA
+1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI
+rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k
+b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC
+AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP
+OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
+RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc
+IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN
++8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ==
+-----END CERTIFICATE-----
+
+COMODO ECC Certification Authority
+==================================
+-----BEGIN CERTIFICATE-----
+MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC
+R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
+ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix
+GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
+Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo
+b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X
+4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni
+wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG
+FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA
+U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
+-----END CERTIFICATE-----
+
+Certigna
+========
+-----BEGIN CERTIFICATE-----
+MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw
+EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3
+MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI
+Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q
+XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH
+GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p
+ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg
+DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf
+Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ
+tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ
+BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J
+SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA
+hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+
+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu
+PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY
+1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
+WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
+-----END CERTIFICATE-----
+
+ePKI Root Certification Authority
+=================================
+-----BEGIN CERTIFICATE-----
+MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG
+EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg
+Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx
+MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq
+MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs
+IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi
+lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv
+qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX
+12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O
+WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+
+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao
+lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/
+vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi
+Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi
+MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
+ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0
+1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq
+KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV
+xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP
+NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r
+GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE
+xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx
+gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy
+sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD
+BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw=
+-----END CERTIFICATE-----
+
+certSIGN ROOT CA
+================
+-----BEGIN CERTIFICATE-----
+MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD
+VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa
+Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE
+CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I
+JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH
+rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2
+ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD
+0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943
+AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B
+Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB
+AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8
+SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0
+x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt
+vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz
+TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD
+-----END CERTIFICATE-----
+
+NetLock Arany (Class Gold) Főtanúsítvány
+========================================
+-----BEGIN CERTIFICATE-----
+MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G
+A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610
+dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB
+cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx
+MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO
+ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv
+biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6
+c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu
+0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw
+/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk
+H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw
+fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1
+neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW
+qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta
+YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
+bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna
+NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu
+dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
+-----END CERTIFICATE-----
+
+SecureSign RootCA11
+===================
+-----BEGIN CERTIFICATE-----
+MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi
+SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS
+b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw
+KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1
+cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL
+TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO
+wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq
+g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP
+O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA
+bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX
+t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh
+OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r
+bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ
+Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01
+y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061
+lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I=
+-----END CERTIFICATE-----
+
+Microsec e-Szigno Root CA 2009
+==============================
+-----BEGIN CERTIFICATE-----
+MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER
+MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv
+c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
+dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE
+BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt
+U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA
+fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG
+0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA
+pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm
+1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC
+AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf
+QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE
+FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o
+lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX
+I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
+tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02
+yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi
+LXpUq3DDfSJlgnCW
+-----END CERTIFICATE-----
+
+GlobalSign Root CA - R3
+=======================
+-----BEGIN CERTIFICATE-----
+MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv
+YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
+bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
+aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
+bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt
+iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ
+0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3
+rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl
+OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2
+xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
+FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7
+lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8
+EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E
+bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18
+YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r
+kpeDMdmztcpHWD9f
+-----END CERTIFICATE-----
+
+Izenpe.com
+==========
+-----BEGIN CERTIFICATE-----
+MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG
+EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz
+MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu
+QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ
+03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK
+ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU
++zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC
+PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT
+OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK
+F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK
+0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+
+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB
+leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID
+AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+
+SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG
+NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
+MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
+BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l
+Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga
+kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q
+hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs
+g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5
+aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5
+nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC
+ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo
+Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z
+WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
+-----END CERTIFICATE-----
+
+Go Daddy Root Certificate Authority - G2
+========================================
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
+B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu
+MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
+MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
+b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G
+A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq
+9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD
++qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd
+fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl
+NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9
+BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac
+vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r
+5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV
+N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
+LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1
+-----END CERTIFICATE-----
+
+Starfield Root Certificate Authority - G2
+=========================================
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
+B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
+b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0
+eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw
+DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg
+VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB
+dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv
+W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs
+bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk
+N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf
+ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU
+JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol
+TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx
+4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw
+F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
+pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ
+c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
+-----END CERTIFICATE-----
+
+Starfield Services Root Certificate Authority - G2
+==================================================
+-----BEGIN CERTIFICATE-----
+MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
+B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
+b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl
+IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV
+BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT
+dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg
+Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2
+h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa
+hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP
+LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB
+rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG
+SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP
+E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy
+xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
+iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza
+YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6
+-----END CERTIFICATE-----
+
+AffirmTrust Commercial
+======================
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS
+BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw
+MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
+bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb
+DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV
+C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6
+BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww
+MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV
+HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG
+hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi
+qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv
+0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh
+sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
+-----END CERTIFICATE-----
+
+AffirmTrust Networking
+======================
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS
+BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw
+MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
+bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE
+Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI
+dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24
+/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb
+h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV
+HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu
+UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6
+12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23
+WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9
+/ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
+-----END CERTIFICATE-----
+
+AffirmTrust Premium
+===================
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS
+BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy
+OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy
+dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn
+BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV
+5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs
++7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd
+GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R
+p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI
+S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04
+6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5
+/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo
++Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv
+MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
+Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC
+6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S
+L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK
++4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV
+BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg
+IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60
+g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb
+zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw==
+-----END CERTIFICATE-----
+
+AffirmTrust Premium ECC
+=======================
+-----BEGIN CERTIFICATE-----
+MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV
+BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx
+MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U
+cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ
+N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW
+BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK
+BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X
+57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM
+eQ==
+-----END CERTIFICATE-----
+
+Certum Trusted Network CA
+=========================
+-----BEGIN CERTIFICATE-----
+MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK
+ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy
+MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU
+ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC
+l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J
+J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4
+fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0
+cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB
+Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw
+DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj
+jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1
+mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj
+Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
+03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
+-----END CERTIFICATE-----
+
+TWCA Root Certification Authority
+=================================
+-----BEGIN CERTIFICATE-----
+MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ
+VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG
+EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB
+IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx
+QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC
+oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP
+4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r
+y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB
+BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG
+9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC
+mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW
+QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY
+T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny
+Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
+-----END CERTIFICATE-----
+
+Security Communication RootCA2
+==============================
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
+U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh
+dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC
+SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy
+aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++
++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R
+3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV
+spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K
+EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8
+QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
+CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj
+u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk
+3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q
+tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29
+mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
+-----END CERTIFICATE-----
+
+Actalis Authentication Root CA
+==============================
+-----BEGIN CERTIFICATE-----
+MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM
+BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE
+AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky
+MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz
+IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
+IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ
+wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa
+by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6
+zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f
+YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2
+oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l
+EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7
+hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8
+EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5
+jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY
+iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
+ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI
+WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0
+JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx
+K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+
+Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC
+4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo
+2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz
+lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem
+OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9
+vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
+-----END CERTIFICATE-----
+
+Buypass Class 2 Root CA
+=======================
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
+QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X
+DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
+eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw
+DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1
+g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn
+9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b
+/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU
+CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff
+awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI
+zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn
+Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX
+Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs
+M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
+VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
+AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
+A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI
+osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S
+aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd
+DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD
+LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0
+oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC
+wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS
+CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN
+rJgWVqA=
+-----END CERTIFICATE-----
+
+Buypass Class 3 Root CA
+=======================
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
+QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X
+DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
+eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw
+DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH
+sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR
+5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh
+7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ
+ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH
+2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV
+/afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ
+RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA
+Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq
+j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
+VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
+AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
+cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G
+uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG
+Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8
+ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2
+KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz
+6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug
+UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe
+eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi
+Cp/HuZc=
+-----END CERTIFICATE-----
+
+T-TeleSec GlobalRoot Class 3
+============================
+-----BEGIN CERTIFICATE-----
+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
+IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
+cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx
+MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
+dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
+ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK
+9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU
+NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF
+iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W
+0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA
+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr
+AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb
+fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT
+ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h
+P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
+e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw==
+-----END CERTIFICATE-----
+
+D-TRUST Root Class 3 CA 2 2009
+==============================
+-----BEGIN CERTIFICATE-----
+MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK
+DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe
+Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE
+LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD
+ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA
+BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv
+KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z
+p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC
+AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ
+4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y
+eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw
+MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G
+PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw
+OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm
+2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
+o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV
+dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph
+X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I=
+-----END CERTIFICATE-----
+
+D-TRUST Root Class 3 CA 2 EV 2009
+=================================
+-----BEGIN CERTIFICATE-----
+MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
+DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
+OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
+DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
+OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS
+egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh
+zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T
+7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60
+sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35
+11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv
+cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v
+ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El
+MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp
+b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh
+c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+
+PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05
+nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX
+ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA
+NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv
+w9y4AyHqnxbxLFS1
+-----END CERTIFICATE-----
+
+CA Disig Root R2
+================
+-----BEGIN CERTIFICATE-----
+MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw
+EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp
+ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx
+EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp
+c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC
+w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia
+xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7
+A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S
+GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV
+g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa
+5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE
+koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A
+Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i
+Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u
+Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
+tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV
+sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je
+dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8
+1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx
+mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01
+utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0
+sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg
+UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV
+7+ZtsH8tZ/3zbBt1RqPlShfppNcL
+-----END CERTIFICATE-----
+
+ACCVRAIZ1
+=========
+-----BEGIN CERTIFICATE-----
+MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB
+SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1
+MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH
+UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM
+jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0
+RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD
+aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ
+0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG
+WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7
+8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR
+5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J
+9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK
+Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw
+Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu
+Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2
+VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM
+Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA
+QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh
+AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA
+YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj
+AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA
+IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk
+aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0
+dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2
+MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI
+hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E
+R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN
+YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49
+nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ
+TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3
+sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h
+I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg
+Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd
+3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p
+EfbRD0tVNEYqi4Y7
+-----END CERTIFICATE-----
+
+TWCA Global Root CA
+===================
+-----BEGIN CERTIFICATE-----
+MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT
+CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD
+QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK
+EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg
+Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C
+nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV
+r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR
+Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV
+tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W
+KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99
+sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p
+yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn
+kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI
+zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC
+AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g
+cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn
+LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M
+8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg
+/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg
+lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP
+A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m
+i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8
+EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3
+zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0=
+-----END CERTIFICATE-----
+
+TeliaSonera Root CA v1
+======================
+-----BEGIN CERTIFICATE-----
+MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE
+CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4
+MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW
+VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+
+6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA
+3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k
+B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn
+Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH
+oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3
+F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ
+oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7
+gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc
+TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB
+AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW
+DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm
+zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx
+0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW
+pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV
+G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc
+c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT
+JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2
+qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6
+Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems
+WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
+-----END CERTIFICATE-----
+
+T-TeleSec GlobalRoot Class 2
+============================
+-----BEGIN CERTIFICATE-----
+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
+IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
+cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx
+MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
+dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
+ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ
+SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F
+vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970
+2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV
+WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA
+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy
+YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4
+r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf
+vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR
+3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN
+9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg==
+-----END CERTIFICATE-----
+
+Atos TrustedRoot 2011
+=====================
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU
+cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4
+MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG
+A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV
+hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr
+54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+
+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320
+HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR
+z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R
+l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ
+bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
+CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h
+k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh
+TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9
+61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G
+3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
+-----END CERTIFICATE-----
+
+QuoVadis Root CA 1 G3
+=====================
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG
+A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
+b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN
+MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg
+RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE
+PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm
+PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6
+Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN
+ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l
+g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV
+7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX
+9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f
+iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg
+t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI
+hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC
+MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3
+GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct
+Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP
++V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh
+3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa
+wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6
+O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0
+FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV
+hMJKzRwuJIczYOXD
+-----END CERTIFICATE-----
+
+QuoVadis Root CA 2 G3
+=====================
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG
+A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
+b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN
+MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg
+RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh
+ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY
+NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t
+oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o
+MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l
+V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo
+L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ
+sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD
+6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh
+lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI
+hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66
+AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K
+pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9
+x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz
+dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X
+U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw
+mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD
+zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN
+JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr
+O3jtZsSOeWmD3n+M
+-----END CERTIFICATE-----
+
+QuoVadis Root CA 3 G3
+=====================
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG
+A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
+b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN
+MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg
+RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286
+IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL
+Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe
+6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3
+I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U
+VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7
+5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi
+Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM
+dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt
+rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI
+hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px
+KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS
+t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ
+TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du
+DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib
+Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD
+hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX
+0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW
+dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2
+PpxxVJkES/1Y+Zj0
+-----END CERTIFICATE-----
+
+DigiCert Assured ID Root G2
+===========================
+-----BEGIN CERTIFICATE-----
+MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
+IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw
+MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
+ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH
+35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq
+bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw
+VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP
+YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn
+lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO
+w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv
+0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz
+d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW
+hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M
+jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
+IhNzbM8m9Yop5w==
+-----END CERTIFICATE-----
+
+DigiCert Assured ID Root G3
+===========================
+-----BEGIN CERTIFICATE-----
+MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD
+VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
+MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ
+BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb
+RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs
+KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF
+UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy
+YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy
+1vUhZscv6pZjamVFkpUBtA==
+-----END CERTIFICATE-----
+
+DigiCert Global Root G2
+=======================
+-----BEGIN CERTIFICATE-----
+MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
+HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx
+MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
+dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ
+kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO
+3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV
+BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM
+UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB
+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu
+5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr
+F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U
+WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH
+QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/
+iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
+MrY=
+-----END CERTIFICATE-----
+
+DigiCert Global Root G3
+=======================
+-----BEGIN CERTIFICATE-----
+MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD
+VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw
+MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k
+aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C
+AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O
+YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP
+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp
+Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y
+3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34
+VOKa5Vt8sycX
+-----END CERTIFICATE-----
+
+DigiCert Trusted Root G4
+========================
+-----BEGIN CERTIFICATE-----
+MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw
+HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
+MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp
+pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o
+k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa
+vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY
+QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6
+MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm
+mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7
+f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH
+dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8
+oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
+DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
+ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY
+ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr
+yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy
+7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah
+ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN
+5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb
+/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa
+5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK
+G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP
+82Z+
+-----END CERTIFICATE-----
+
+COMODO RSA Certification Authority
+==================================
+-----BEGIN CERTIFICATE-----
+MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE
+BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
+A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC
+R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
+ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn
+dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ
+FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+
+5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG
+x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX
+2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL
+OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3
+sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C
+GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5
+WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
+FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w
+DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt
+rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+
+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg
+tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW
+sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp
+pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA
+zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq
+ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52
+7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I
+LaZRfyHBNVOFBkpdn627G190
+-----END CERTIFICATE-----
+
+USERTrust RSA Certification Authority
+=====================================
+-----BEGIN CERTIFICATE-----
+MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE
+BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
+ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE
+BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
+ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz
+0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j
+Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn
+RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O
++T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq
+/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE
+Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM
+lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8
+yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+
+eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
+BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
+MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW
+FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ
+7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ
+Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM
+8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi
+FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi
+yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c
+J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw
+sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx
+Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9
+-----END CERTIFICATE-----
+
+USERTrust ECC Certification Authority
+=====================================
+-----BEGIN CERTIFICATE-----
+MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC
+VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
+aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC
+VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
+aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2
+0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez
+nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV
+HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB
+HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu
+9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
+-----END CERTIFICATE-----
+
+GlobalSign ECC Root CA - R5
+===========================
+-----BEGIN CERTIFICATE-----
+MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb
+R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
+EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
+R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
+EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6
+SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS
+h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
+BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx
+uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7
+yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3
+-----END CERTIFICATE-----
+
+IdenTrust Commercial Root CA 1
+==============================
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG
+EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS
+b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES
+MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB
+IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld
+hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/
+mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi
+1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C
+XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl
+3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy
+NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV
+WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg
+xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix
+uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
+AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI
+hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH
+6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg
+ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt
+ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV
+YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX
+feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro
+kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe
+2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz
+Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R
+cGzM7vRX+Bi6hG6H
+-----END CERTIFICATE-----
+
+IdenTrust Public Sector Root CA 1
+=================================
+-----BEGIN CERTIFICATE-----
+MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG
+EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv
+ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV
+UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS
+b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy
+P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6
+Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI
+rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf
+qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS
+mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn
+ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh
+LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v
+iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL
+4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B
+Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw
+DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj
+t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A
+mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt
+GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt
+m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx
+NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4
+Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI
+ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC
+ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ
+3Wl9af0AVqW3rLatt8o+Ae+c
+-----END CERTIFICATE-----
+
+Entrust Root Certification Authority - G2
+=========================================
+-----BEGIN CERTIFICATE-----
+MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV
+BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy
+bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug
+b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw
+HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT
+DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx
+OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s
+eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP
+/vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz
+HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU
+s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y
+TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx
+AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6
+0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z
+iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
+Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi
+nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+
+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO
+e4pIb4tF9g==
+-----END CERTIFICATE-----
+
+Entrust Root Certification Authority - EC1
+==========================================
+-----BEGIN CERTIFICATE-----
+MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx
+FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn
+YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl
+ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw
+FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs
+LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg
+dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt
+IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy
+AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef
+9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
+FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h
+vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8
+kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
+-----END CERTIFICATE-----
+
+CFCA EV ROOT
+============
+-----BEGIN CERTIFICATE-----
+MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE
+CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB
+IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw
+MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD
+DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV
+BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD
+7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN
+uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW
+ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7
+xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f
+py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K
+gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol
+hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ
+tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf
+BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB
+/wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB
+ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q
+ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua
+4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG
+E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX
+BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn
+aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy
+PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX
+kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C
+ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
+-----END CERTIFICATE-----
+
+OISTE WISeKey Global Root GB CA
+===============================
+-----BEGIN CERTIFICATE-----
+MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG
+EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl
+ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw
+MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD
+VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds
+b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX
+scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP
+rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk
+9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o
+Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg
+GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
+/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI
+hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD
+dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0
+VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui
+HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic
+Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM=
+-----END CERTIFICATE-----
+
+SZAFIR ROOT CA2
+===============
+-----BEGIN CERTIFICATE-----
+MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG
+A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV
+BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ
+BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD
+VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q
+qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK
+DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE
+2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ
+ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi
+ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
+AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC
+AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5
+O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67
+oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul
+4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6
++/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw==
+-----END CERTIFICATE-----
+
+Certum Trusted Network CA 2
+===========================
+-----BEGIN CERTIFICATE-----
+MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE
+BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1
+bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y
+ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ
+TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl
+cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB
+IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9
+7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o
+CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b
+Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p
+uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130
+GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ
+9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB
+Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye
+hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM
+BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI
+hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW
+Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA
+L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo
+clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM
+pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb
+w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo
+J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm
+ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX
+is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7
+zAYspsbiDrW5viSP
+-----END CERTIFICATE-----
+
+Hellenic Academic and Research Institutions RootCA 2015
+=======================================================
+-----BEGIN CERTIFICATE-----
+MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT
+BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0
+aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl
+YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx
+MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg
+QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV
+BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw
+MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv
+bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh
+iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+
+6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd
+FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr
+i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F
+GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2
+fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu
+iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc
+Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI
+hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+
+D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM
+d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y
+d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn
+82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb
+davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F
+Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt
+J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa
+JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q
+p/UsQu0yrbYhnr68
+-----END CERTIFICATE-----
+
+Hellenic Academic and Research Institutions ECC RootCA 2015
+===========================================================
+-----BEGIN CERTIFICATE-----
+MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0
+aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u
+cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj
+aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw
+MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj
+IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD
+VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290
+Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP
+dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK
+Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
+BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA
+GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn
+dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR
+-----END CERTIFICATE-----
+
+ISRG Root X1
+============
+-----BEGIN CERTIFICATE-----
+MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE
+BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD
+EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG
+EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT
+DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r
+Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1
+3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K
+b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN
+Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ
+4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf
+1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu
+hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH
+usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r
+OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G
+A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY
+9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
+ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV
+0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt
+hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw
+TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx
+e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA
+JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD
+YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n
+JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ
+m+kXQ99b21/+jh5Xos1AnX5iItreGCc=
+-----END CERTIFICATE-----
+
+AC RAIZ FNMT-RCM
+================
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT
+AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw
+MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD
+TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
+ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf
+qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr
+btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL
+j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou
+08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw
+WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT
+tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ
+47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC
+ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa
+i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
+FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o
+dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD
+nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s
+D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ
+j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT
+Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW
++YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7
+Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d
+8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm
+5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG
+rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM=
+-----END CERTIFICATE-----
+
+Amazon Root CA 1
+================
+-----BEGIN CERTIFICATE-----
+MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD
+VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1
+MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
+bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH
+FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ
+gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t
+dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce
+VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB
+/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3
+DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM
+CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy
+8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa
+2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2
+xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5
+-----END CERTIFICATE-----
+
+Amazon Root CA 2
+================
+-----BEGIN CERTIFICATE-----
+MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD
+VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1
+MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
+bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
+ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4
+kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp
+N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9
+AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd
+fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx
+kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS
+btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0
+Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN
+c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+
+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw
+DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA
+A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE
+YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW
+xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ
+gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW
+aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV
+Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3
+KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi
+JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw=
+-----END CERTIFICATE-----
+
+Amazon Root CA 3
+================
+-----BEGIN CERTIFICATE-----
+MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG
+EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy
+NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
+MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB
+f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr
+Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43
+rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc
+eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw==
+-----END CERTIFICATE-----
+
+Amazon Root CA 4
+================
+-----BEGIN CERTIFICATE-----
+MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG
+EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy
+NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
+MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN
+/sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri
+83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
+HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA
+MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1
+AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA==
+-----END CERTIFICATE-----
+
+TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
+=============================================
+-----BEGIN CERTIFICATE-----
+MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT
+D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr
+IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g
+TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp
+ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD
+VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt
+c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth
+bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11
+IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8
+6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc
+wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0
+3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9
+WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU
+ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
+KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh
+AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc
+lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R
+e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j
+q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
+-----END CERTIFICATE-----
+
+GDCA TrustAUTH R5 ROOT
+======================
+-----BEGIN CERTIFICATE-----
+MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCQ04xMjAw
+BgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8wHQYDVQQD
+DBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVow
+YjELMAkGA1UEBhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ
+IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJjDp6L3TQs
+AlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBjTnnEt1u9ol2x8kECK62p
+OqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+uKU49tm7srsHwJ5uu4/Ts765/94Y9cnrr
+pftZTqfrlYwiOXnhLQiPzLyRuEH3FMEjqcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ
+9Cy5WmYqsBebnh52nUpmMUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQ
+xXABZG12ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloPzgsM
+R6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3GkL30SgLdTMEZeS1SZ
+D2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeCjGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4
+oR24qoAATILnsn8JuLwwoC8N9VKejveSswoAHQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx
+9hoh49pwBiFYFIeFd3mqgnkCAwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlR
+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg
+p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZmDRd9FBUb1Ov9
+H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5COmSdI31R9KrO9b7eGZONn35
+6ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ryL3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd
++PwyvzeG5LuOmCd+uh8W4XAR8gPfJWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQ
+HtZa37dG/OaG+svgIHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBD
+F8Io2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV09tL7ECQ
+8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQXR4EzzffHqhmsYzmIGrv
+/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrqT8p+ck0LcIymSLumoRT2+1hEmRSuqguT
+aaApJUqlyyvdimYHFngVV3Eb7PVHhPOeMTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g==
+-----END CERTIFICATE-----
+
+SSL.com Root Certification Authority RSA
+========================================
+-----BEGIN CERTIFICATE-----
+MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxDjAM
+BgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24x
+MTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYw
+MjEyMTczOTM5WhcNNDEwMjEyMTczOTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx
+EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NM
+LmNvbSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcNAQEBBQAD
+ggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2RxFdHaxh3a3by/ZPkPQ/C
+Fp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aXqhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8
+P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcCC52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/ge
+oeOy3ZExqysdBP+lSgQ36YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkp
+k8zruFvh/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrFYD3Z
+fBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93EJNyAKoFBbZQ+yODJ
+gUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVcUS4cK38acijnALXRdMbX5J+tB5O2
+UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi8
+1xtZPCvM8hnIk2snYxnP/Okm+Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4s
+bE6x/c+cCbqiM+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4GA1UdDwEB/wQE
+AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGVcpNxJK1ok1iOMq8bs3AD/CUr
+dIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBcHadm47GUBwwyOabqG7B52B2ccETjit3E+ZUf
+ijhDPwGFpUenPUayvOUiaPd7nNgsPgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAsl
+u1OJD7OAUN5F7kR/q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjq
+erQ0cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jra6x+3uxj
+MxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90IH37hVZkLId6Tngr75qNJ
+vTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/YK9f1JmzJBjSWFupwWRoyeXkLtoh/D1JI
+Pb9s2KJELtFOt3JY04kTlf5Eq/jXixtunLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406y
+wKBjYZC6VWg3dGq2ktufoYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NI
+WuuA8ShYIc2wBlX7Jz9TkHCpBB5XJ7k=
+-----END CERTIFICATE-----
+
+SSL.com Root Certification Authority ECC
+========================================
+-----BEGIN CERTIFICATE-----
+MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMCVVMxDjAMBgNV
+BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xMTAv
+BgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEy
+MTgxNDAzWhcNNDEwMjEyMTgxNDAzWjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAO
+BgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv
+bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuBBAAiA2IA
+BEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI7Z4INcgn64mMU1jrYor+
+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPgCemB+vNH06NjMGEwHQYDVR0OBBYEFILR
+hXMw5zUE044CkvvlpNHEIejNMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTT
+jgKS++Wk0cQh6M0wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCW
+e+0F+S8Tkdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+gA0z
+5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl
+-----END CERTIFICATE-----
+
+SSL.com EV Root Certification Authority RSA R2
+==============================================
+-----BEGIN CERTIFICATE-----
+MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVTMQ4w
+DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9u
+MTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy
+MB4XDTE3MDUzMTE4MTQzN1oXDTQyMDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQI
+DAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYD
+VQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMIICIjAN
+BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvqM0fNTPl9fb69LT3w23jh
+hqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssufOePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7w
+cXHswxzpY6IXFJ3vG2fThVUCAtZJycxa4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTO
+Zw+oz12WGQvE43LrrdF9HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+
+B6KjBSYRaZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcAb9Zh
+CBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQGp8hLH94t2S42Oim
+9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQVPWKchjgGAGYS5Fl2WlPAApiiECto
+RHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMOpgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+Slm
+JuwgUHfbSguPvuUCYHBBXtSuUDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48
++qvWBkofZ6aYMBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV
+HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa49QaAJadz20Zp
+qJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBWs47LCp1Jjr+kxJG7ZhcFUZh1
+++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nx
+Y/hoLVUE0fKNsKTPvDxeH3jnpaAgcLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2G
+guDKBAdRUNf/ktUM79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDz
+OFSz/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXtll9ldDz7
+CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEmKf7GUmG6sXP/wwyc5Wxq
+lD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKKQbNmC1r7fSOl8hqw/96bg5Qu0T/fkreR
+rwU7ZcegbLHNYhLDkBvjJc40vG93drEQw/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1
+hlMYegouCRw2n5H9gooiS9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX
+9hwJ1C07mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w==
+-----END CERTIFICATE-----
+
+SSL.com EV Root Certification Authority ECC
+===========================================
+-----BEGIN CERTIFICATE-----
+MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMCVVMxDjAMBgNV
+BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xNDAy
+BgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYw
+MjEyMTgxNTIzWhcNNDEwMjEyMTgxNTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx
+EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NM
+LmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMAVIbc/R/fALhBYlzccBYy
+3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1KthkuWnBaBu2+8KGwytAJKaNjMGEwHQYDVR0O
+BBYEFFvKXuXe0oGqzagtZFG22XKbl+ZPMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe
+5d7SgarNqC1kUbbZcpuX5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJ
+N+vp1RPZytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZgh5Mm
+m7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg==
+-----END CERTIFICATE-----
+
+GlobalSign Root CA - R6
+=======================
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEgMB4GA1UECxMX
+R2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds
+b2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQxMjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9i
+YWxTaWduIFJvb3QgQ0EgLSBSNjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFs
+U2lnbjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQss
+grRIxutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1kZguSgMpE
+3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxDaNc9PIrFsmbVkJq3MQbF
+vuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJwLnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqM
+PKq0pPbzlUoSB239jLKJz9CgYXfIWHSw1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+
+azayOeSsJDa38O+2HBNXk7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05O
+WgtH8wY2SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/hbguy
+CLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4nWUx2OVvq+aWh2IMP
+0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpYrZxCRXluDocZXFSxZba/jJvcE+kN
+b7gu3GduyYsRtYQUigAZcIN5kZeR1BonvzceMgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQE
+AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNV
+HSMEGDAWgBSubAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN
+nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGtIxg93eFyRJa0
+lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr6155wsTLxDKZmOMNOsIeDjHfrY
+BzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLjvUYAGm0CuiVdjaExUd1URhxN25mW7xocBFym
+Fe944Hn+Xds+qkxV/ZoVqW/hpvvfcDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr
+3TsTjxKM4kEaSHpzoHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB1
+0jZpnOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfspA9MRf/T
+uTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+vJJUEeKgDu+6B5dpffItK
+oZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+t
+JDfLRVpOoERIyNiwmcUVhAn21klJwGW45hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA=
+-----END CERTIFICATE-----
+
+OISTE WISeKey Global Root GC CA
+===============================
+-----BEGIN CERTIFICATE-----
+MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQswCQYDVQQGEwJD
+SDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEo
+MCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRa
+Fw00MjA1MDkwOTU4MzNaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQL
+ExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh
+bCBSb290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4nieUqjFqdr
+VCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4Wp2OQ0jnUsYd4XxiWD1Ab
+NTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
+BgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7TrYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0E
+AwMDaAAwZQIwJsdpW9zV57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtk
+AjEA2zQgMgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9
+-----END CERTIFICATE-----
+
+UCA Global G2 Root
+==================
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQG
+EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBHbG9iYWwgRzIgUm9vdDAeFw0x
+NjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0xCzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlU
+cnVzdDEbMBkGA1UEAwwSVUNBIEdsb2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+MIICCgKCAgEAxeYrb3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmT
+oni9kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzmVHqUwCoV
+8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/RVogvGjqNO7uCEeBHANBS
+h6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDcC/Vkw85DvG1xudLeJ1uK6NjGruFZfc8o
+LTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIjtm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/
+R+zvWr9LesGtOxdQXGLYD0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBe
+KW4bHAyvj5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6DlNaBa
+4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6iIis7nCs+dwp4wwc
+OxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznPO6Q0ibd5Ei9Hxeepl2n8pndntd97
+8XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
+BBYEFIHEjMz15DD/pQwIX4wVZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo
+5sOASD0Ee/ojL3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5
+1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl1qnN3e92mI0A
+Ds0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oUb3n09tDh05S60FdRvScFDcH9
+yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LVPtateJLbXDzz2K36uGt/xDYotgIVilQsnLAX
+c47QN6MUPJiVAAwpBVueSUmxX8fjy88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHo
+jhJi6IjMtX9Gl8CbEGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZk
+bxqgDMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI+Vg7RE+x
+ygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGyYiGqhkCyLmTTX8jjfhFn
+RR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bXUB+K+wb1whnw0A==
+-----END CERTIFICATE-----
+
+UCA Extended Validation Root
+============================
+-----BEGIN CERTIFICATE-----
+MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQG
+EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9u
+IFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMxMDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8G
+A1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrs
+iWogD4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvSsPGP2KxF
+Rv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aopO2z6+I9tTcg1367r3CTu
+eUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dksHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR
+59mzLC52LqGj3n5qiAno8geK+LLNEOfic0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH
+0mK1lTnj8/FtDw5lhIpjVMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KR
+el7sFsLzKuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/TuDv
+B0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41Gsx2VYVdWf6/wFlth
+WG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs1+lvK9JKBZP8nm9rZ/+I8U6laUpS
+NwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQDfwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS
+3H5aBZ8eNJr34RQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL
+BQADggIBADaNl8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR
+ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQVBcZEhrxH9cM
+aVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5c6sq1WnIeJEmMX3ixzDx/BR4
+dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb
++7lsq+KePRXBOy5nAliRn+/4Qh8st2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOW
+F3sGPjLtx7dCvHaj2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwi
+GpWOvpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2CxR9GUeOc
+GMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmxcmtpzyKEC2IPrNkZAJSi
+djzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbMfjKaiJUINlK73nZfdklJrX+9ZSCyycEr
+dhh2n1ax
+-----END CERTIFICATE-----
+
+Certigna Root CA
+================
+-----BEGIN CERTIFICATE-----
+MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAwWjELMAkGA1UE
+BhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAwMiA0ODE0NjMwODEwMDAzNjEZ
+MBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0xMzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjda
+MFoxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYz
+MDgxMDAwMzYxGTAXBgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sOty3tRQgX
+stmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9MCiBtnyN6tMbaLOQdLNyz
+KNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPuI9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8
+JXrJhFwLrN1CTivngqIkicuQstDuI7pmTLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16
+XdG+RCYyKfHx9WzMfgIhC59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq
+4NYKpkDfePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3YzIoej
+wpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWTCo/1VTp2lc5ZmIoJ
+lXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1kJWumIWmbat10TWuXekG9qxf5kBdI
+jzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp/
+/TBt2dzhauH8XwIDAQABo4IBGjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
+HQYDVR0OBBYEFBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of
+1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczovL3d3d3cuY2Vy
+dGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilodHRwOi8vY3JsLmNlcnRpZ25h
+LmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYraHR0cDovL2NybC5kaGlteW90aXMuY29tL2Nl
+cnRpZ25hcm9vdGNhLmNybDANBgkqhkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOIt
+OoldaDgvUSILSo3L6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxP
+TGRGHVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH60BGM+RFq
+7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncBlA2c5uk5jR+mUYyZDDl3
+4bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdio2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd
+8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS
+6Cvu5zHbugRqh5jnxV/vfaci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaY
+tlu3zM63Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayhjWZS
+aX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw3kAP+HwV96LOPNde
+E4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0=
+-----END CERTIFICATE-----
+
+emSign Root CA - G1
+===================
+-----BEGIN CERTIFICATE-----
+MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJJTjET
+MBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRl
+ZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBHMTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgx
+ODMwMDBaMGcxCzAJBgNVBAYTAklOMRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVk
+aHJhIFRlY2hub2xvZ2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQzf2N4aLTN
+LnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO8oG0x5ZOrRkVUkr+PHB1
+cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aqd7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHW
+DV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhMtTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ
+6DqS0hdW5TUaQBw+jSztOd9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrH
+hQIDAQABo0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQDAgEG
+MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31xPaOfG1vR2vjTnGs2
+vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjMwiI/aTvFthUvozXGaCocV685743Q
+NcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6dGNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q
++Mri/Tm3R7nrft8EI6/6nAYH6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeih
+U80Bv2noWgbyRQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx
+iN66zB+Afko=
+-----END CERTIFICATE-----
+
+emSign ECC Root CA - G3
+=======================
+-----BEGIN CERTIFICATE-----
+MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQGEwJJTjETMBEG
+A1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEg
+MB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4
+MTgzMDAwWjBrMQswCQYDVQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11
+ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g
+RzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0WXTsuwYc
+58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xySfvalY8L1X44uT6EYGQIr
+MgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuBzhccLikenEhjQjAOBgNVHQ8BAf8EBAMC
+AQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+D
+CBeQyh+KTOgNG3qxrdWBCUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7
+jHvrZQnD+JbNR6iC8hZVdyR+EhCVBCyj
+-----END CERTIFICATE-----
+
+emSign Root CA - C1
+===================
+-----BEGIN CERTIFICATE-----
+MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMx
+EzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNp
+Z24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UE
+BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQD
+ExNlbVNpZ24gUm9vdCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+up
+ufGZBczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZHdPIWoU/
+Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH3DspVpNqs8FqOp099cGX
+OFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvHGPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4V
+I5b2P/AgNBbeCsbEBEV5f6f9vtKppa+cxSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleooms
+lMuoaJuvimUnzYnu3Yy1aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+
+XJGFehiqTbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD
+ggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87/kOXSTKZEhVb3xEp
+/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4kqNPEjE2NuLe/gDEo2APJ62gsIq1
+NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrGYQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9
+wC68AivTxEDkigcxHpvOJpkT+xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQ
+BmIMMMAVSKeoWXzhriKi4gp6D/piq1JM4fHfyr6DDUI=
+-----END CERTIFICATE-----
+
+emSign ECC Root CA - C3
+=======================
+-----BEGIN CERTIFICATE-----
+MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQGEwJVUzETMBEG
+A1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMxIDAeBgNVBAMTF2VtU2lnbiBF
+Q0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UE
+BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQD
+ExdlbVNpZ24gRUNDIFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd
+6bciMK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4OjavtisIGJAnB9
+SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0OBBYEFPtaSNCAIEDyqOkA
+B2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gA
+MGUCMQC02C8Cif22TGK6Q04ThHK1rt0c3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwU
+ZOR8loMRnLDRWmFLpg9J0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ==
+-----END CERTIFICATE-----
+
+Hongkong Post Root CA 3
+=======================
+-----BEGIN CERTIFICATE-----
+MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQELBQAwbzELMAkG
+A1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJSG9uZyBLb25nMRYwFAYDVQQK
+Ew1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2
+MDMwMjI5NDZaFw00MjA2MDMwMjI5NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtv
+bmcxEjAQBgNVBAcTCUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMX
+SG9uZ2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz
+iNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFOdem1p+/l6TWZ5Mwc50tf
+jTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mIVoBc+L0sPOFMV4i707mV78vH9toxdCim
+5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOe
+sL4jpNrcyCse2m5FHomY2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj
+0mRiikKYvLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+TtbNe/
+JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZbx39ri1UbSsUgYT2u
+y1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+l2oBlKN8W4UdKjk60FSh0Tlxnf0h
++bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YKTE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsG
+xVd7GYYKecsAyVKvQv83j+GjHno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwID
+AQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e
+i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEwDQYJKoZIhvcN
+AQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG7BJ8dNVI0lkUmcDrudHr9Egw
+W62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCkMpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWld
+y8joRTnU+kLBEUx3XZL7av9YROXrgZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov
++BS5gLNdTaqX4fnkGMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDc
+eqFS3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJmOzj/2ZQw
+9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+l6mc1X5VTMbeRRAc6uk7
+nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6cJfTzPV4e0hz5sy229zdcxsshTrD3mUcY
+hcErulWuBurQB7Lcq9CClnXO0lD+mefPL5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB
+60PZ2Pierc+xYw5F9KBaLJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fq
+dBb9HxEGmpv0
+-----END CERTIFICATE-----
+
+Entrust Root Certification Authority - G4
+=========================================
+-----BEGIN CERTIFICATE-----
+MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAwgb4xCzAJBgNV
+BAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3Qu
+bmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1
+dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1
+dGhvcml0eSAtIEc0MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYT
+AlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0
+L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhv
+cml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhv
+cml0eSAtIEc0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3D
+umSXbcr3DbVZwbPLqGgZ2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV
+3imz/f3ET+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j5pds
+8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAMC1rlLAHGVK/XqsEQ
+e9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73TDtTUXm6Hnmo9RR3RXRv06QqsYJn7
+ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNXwbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5X
+xNMhIWNlUpEbsZmOeX7m640A2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV
+7rtNOzK+mndmnqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8
+dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwlN4y6mACXi0mW
+Hv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNjc0kCAwEAAaNCMEAwDwYDVR0T
+AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9n
+MA0GCSqGSIb3DQEBCwUAA4ICAQAS5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4Q
+jbRaZIxowLByQzTSGwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht
+7LGrhFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/B7NTeLUK
+YvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uIAeV8KEsD+UmDfLJ/fOPt
+jqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbwH5Lk6rWS02FREAutp9lfx1/cH6NcjKF+
+m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKW
+RGhXxNUzzxkvFMSUHHuk2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjA
+JOgc47OlIQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk5F6G
++TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuYn/PIjhs4ViFqUZPT
+kcpG2om3PVODLAgfi49T3f+sHw==
+-----END CERTIFICATE-----
+
+Microsoft ECC Root Certificate Authority 2017
+=============================================
+-----BEGIN CERTIFICATE-----
+MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV
+UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQgRUND
+IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4
+MjMxNjA0WjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw
+NAYDVQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQ
+BgcqhkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZRogPZnZH6
+thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYbhGBKia/teQ87zvH2RPUB
+eMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIy5lycFIM
++Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlf
+Xu5gKcs68tvWMoQZP3zVL8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaR
+eNtUjGUBiudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M=
+-----END CERTIFICATE-----
+
+Microsoft RSA Root Certificate Authority 2017
+=============================================
+-----BEGIN CERTIFICATE-----
+MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBlMQswCQYDVQQG
+EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQg
+UlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIw
+NzE4MjMwMDIzWjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u
+MTYwNAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcw
+ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZNt9GkMml
+7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0ZdDMbRnMlfl7rEqUrQ7e
+S0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw7
+1VdyvD/IybLeS2v4I2wDwAW9lcfNcztmgGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+
+dkC0zVJhUXAoP8XFWvLJjEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49F
+yGcohJUcaDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaGYaRS
+MLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6W6IYZVcSn2i51BVr
+lMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4KUGsTuqwPN1q3ErWQgR5WrlcihtnJ
+0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH+FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJ
+ClTUFLkqqNfs+avNJVgyeY+QW5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYw
+DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC
+NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZCLgLNFgVZJ8og
+6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OCgMNPOsduET/m4xaRhPtthH80
+dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk
++ONVFT24bcMKpBLBaYVu32TxU5nhSnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex
+/2kskZGT4d9Mozd2TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDy
+AmH3pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGRxpl/j8nW
+ZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiAppGWSZI1b7rCoucL5mxAyE
+7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKT
+c0QWbej09+CVgI+WXTik9KveCjCHk9hNAHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D
+5KbvtwEwXlGjefVwaaZBRA+GsCyRxj3qrg+E
+-----END CERTIFICATE-----
+
+e-Szigno Root CA 2017
+=====================
+-----BEGIN CERTIFICATE-----
+MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNVBAYTAkhVMREw
+DwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUt
+MjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJvb3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZa
+Fw00MjA4MjIxMjA3MDZaMHExCzAJBgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UE
+CgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3pp
+Z25vIFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtvxie+RJCx
+s1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+HWyx7xf58etqjYzBhMA8G
+A1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSHERUI0arBeAyxr87GyZDv
+vzAEwDAfBgNVHSMEGDAWgBSHERUI0arBeAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEA
+tVfd14pVCzbhhkT61NlojbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxO
+svxyqltZ+efcMQ==
+-----END CERTIFICATE-----
+
+certSIGN Root CA G2
+===================
+-----BEGIN CERTIFICATE-----
+MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNVBAYTAlJPMRQw
+EgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjAeFw0xNzAy
+MDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJBgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lH
+TiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBAMDFdRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05
+N0IwvlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZuIt4Imfk
+abBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhpn+Sc8CnTXPnGFiWeI8Mg
+wT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKscpc/I1mbySKEwQdPzH/iV8oScLumZfNp
+dWO9lfsbl83kqK/20U6o2YpxJM02PbyWxPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91Qqh
+ngLjYl/rNUssuHLoPj1PrCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732
+jcZZroiFDsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fxDTvf
+95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgyLcsUDFDYg2WD7rlc
+z8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6CeWRgKRM+o/1Pcmqr4tTluCRVLERL
+iohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1Ud
+DgQWBBSCIS1mxteg4BXrzkwJd8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOB
+ywaK8SJJ6ejqkX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC
+b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQlqiCA2ClV9+BB
+/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0OJD7uNGzcgbJceaBxXntC6Z5
+8hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+cNywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5
+BiKDUyUM/FHE5r7iOZULJK2v0ZXkltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklW
+atKcsWMy5WHgUyIOpwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tU
+Sxfj03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZkPuXaTH4M
+NMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE1LlSVHJ7liXMvGnjSG4N
+0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MXQRBdJ3NghVdJIgc=
+-----END CERTIFICATE-----
+
+Trustwave Global Certification Authority
+========================================
+-----BEGIN CERTIFICATE-----
+MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJV
+UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2
+ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u
+IEF1dGhvcml0eTAeFw0xNzA4MjMxOTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJV
+UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2
+ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u
+IEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALldUShLPDeS0YLOvR29
+zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0XznswuvCAAJWX/NKSqIk4cXGIDtiLK0thAf
+LdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4Bq
+stTnoApTAbqOl5F2brz81Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9o
+WN0EACyW80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotPJqX+
+OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1lRtzuzWniTY+HKE40
+Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfwhI0Vcnyh78zyiGG69Gm7DIwLdVcE
+uE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm
++9jaJXLE9gCxInm943xZYkqcBW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqj
+ifLJS3tBEW1ntwiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud
+EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1UdDwEB/wQEAwIB
+BjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W0OhUKDtkLSGm+J1WE2pIPU/H
+PinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfeuyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0H
+ZJDmHvUqoai7PF35owgLEQzxPy0QlG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla
+4gt5kNdXElE1GYhBaCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5R
+vbbEsLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPTMaCm/zjd
+zyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qequ5AvzSxnI9O4fKSTx+O
+856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxhVicGaeVyQYHTtgGJoC86cnn+OjC/QezH
+Yj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu
+3R3y4G5OBVixwJAWKqQ9EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP
+29FpHOTKyeC2nOnOcXHebD8WpHk=
+-----END CERTIFICATE-----
+
+Trustwave Global ECC P256 Certification Authority
+=================================================
+-----BEGIN CERTIFICATE-----
+MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYDVQQGEwJVUzER
+MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI
+b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYD
+VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy
+dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1
+NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH77bOYj
+43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoNFWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqm
+P62jQzBBMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt
+0UrrdaVKEJmzsaGLSvcwCgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjz
+RM4q3wghDDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7
+-----END CERTIFICATE-----
+
+Trustwave Global ECC P384 Certification Authority
+=================================================
+-----BEGIN CERTIFICATE-----
+MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYDVQQGEwJVUzER
+MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI
+b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYD
+VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy
+dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4
+NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuBBAAiA2IABGvaDXU1CDFH
+Ba5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJj9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr
+/TklZvFe/oyujUF5nQlgziip04pt89ZF1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNV
+HQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNn
+ADBkAjA3AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsCMGcl
+CrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVuSw==
+-----END CERTIFICATE-----
+
+NAVER Global Root Certification Authority
+=========================================
+-----BEGIN CERTIFICATE-----
+MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEMBQAwaTELMAkG
+A1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRGT1JNIENvcnAuMTIwMAYDVQQD
+DClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4
+NDJaFw0zNzA4MTgyMzU5NTlaMGkxCzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVT
+UyBQTEFURk9STSBDb3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVAiQqrDZBb
+UGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH38dq6SZeWYp34+hInDEW
++j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lEHoSTGEq0n+USZGnQJoViAbbJAh2+g1G7
+XNr4rRVqmfeSVPc0W+m/6imBEtRTkZazkVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2
+aacp+yPOiNgSnABIqKYPszuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4
+Yb8ObtoqvC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHfnZ3z
+VHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaGYQ5fG8Ir4ozVu53B
+A0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo0es+nPxdGoMuK8u180SdOqcXYZai
+cdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3aCJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejy
+YhbLgGvtPe31HzClrkvJE+2KAQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNV
+HQ4EFgQU0p+I36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB
+Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoNqo0hV4/GPnrK
+21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatjcu3cvuzHV+YwIHHW1xDBE1UB
+jCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm+LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bx
+hYTeodoS76TiEJd6eN4MUZeoIUCLhr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTg
+E34h5prCy8VCZLQelHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTH
+D8z7p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8piKCk5XQ
+A76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLRLBT/DShycpWbXgnbiUSY
+qqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oG
+I/hGoiLtk/bdmuYqh7GYVPEi92tF4+KOdh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmg
+kpzNNIaRkPpkUZ3+/uul9XXeifdy
+-----END CERTIFICATE-----
+
+AC RAIZ FNMT-RCM SERVIDORES SEGUROS
+===================================
+-----BEGIN CERTIFICATE-----
+MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQswCQYDVQQGEwJF
+UzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgwFgYDVQRhDA9WQVRFUy1RMjgy
+NjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1SQ00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4
+MTIyMDA5MzczM1oXDTQzMTIyMDA5MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQt
+UkNNMQ4wDAYDVQQLDAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNB
+QyBSQUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuBBAAiA2IA
+BPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LHsbI6GA60XYyzZl2hNPk2
+LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oKUm8BA06Oi6NCMEAwDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqG
+SM49BAMDA2kAMGYCMQCuSuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoD
+zBOQn5ICMQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJyv+c=
+-----END CERTIFICATE-----
+
+GlobalSign Root R46
+===================
+-----BEGIN CERTIFICATE-----
+MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUAMEYxCzAJBgNV
+BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJv
+b3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAX
+BgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08Es
+CVeJOaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQGvGIFAha/
+r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud316HCkD7rRlr+/fKYIje
+2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo0q3v84RLHIf8E6M6cqJaESvWJ3En7YEt
+bWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSEy132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvj
+K8Cd+RTyG/FWaha/LIWFzXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD4
+12lPFzYE+cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCNI/on
+ccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzsx2sZy/N78CsHpdls
+eVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqaByFrgY/bxFn63iLABJzjqls2k+g9
+vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYD
+VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEM
+BQADggIBAHx47PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg
+JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti2kM3S+LGteWy
+gxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIkpnnpHs6i58FZFZ8d4kuaPp92
+CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRFFRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZm
+OUdkLG5NrmJ7v2B0GbhWrJKsFjLtrWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qq
+JZ4d16GLuc1CLgSkZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwye
+qiv5u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP4vkYxboz
+nxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6N3ec592kD3ZDZopD8p/7
+DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3vouXsXgxT7PntgMTzlSdriVZzH81Xwj3
+QEUxeCp6
+-----END CERTIFICATE-----
+
+GlobalSign Root E46
+===================
+-----BEGIN CERTIFICATE-----
+MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYxCzAJBgNVBAYT
+AkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJvb3Qg
+RTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNV
+BAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcq
+hkjOPQIBBgUrgQQAIgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkB
+jtjqR+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGddyXqBPCCj
+QjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQxCpCPtsad0kRL
+gLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZk
+vLtoURMMA/cVi4RguYv/Uo7njLwcAjA8+RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+
+CAezNIm8BZ/3Hobui3A=
+-----END CERTIFICATE-----
+
+GLOBALTRUST 2020
+================
+-----BEGIN CERTIFICATE-----
+MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkGA1UEBhMCQVQx
+IzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVT
+VCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYxMDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAh
+BgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAy
+MDIwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWi
+D59bRatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9ZYybNpyrO
+VPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3QWPKzv9pj2gOlTblzLmM
+CcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPwyJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCm
+fecqQjuCgGOlYx8ZzHyyZqjC0203b+J+BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKA
+A1GqtH6qRNdDYfOiaxaJSaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9OR
+JitHHmkHr96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj04KlG
+DfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9MedKZssCz3AwyIDMvU
+clOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIwq7ejMZdnrY8XD2zHc+0klGvIg5rQ
+mjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1Ud
+IwQYMBaAFNwuH9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA
+VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJCXtzoRlgHNQIw
+4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd6IwPS3BD0IL/qMy/pJTAvoe9
+iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf+I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS
+8cE54+X1+NZK3TTN+2/BT+MAi1bikvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2
+HcqtbepBEX4tdJP7wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxS
+vTOBTI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6CMUO+1918
+oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn4rnvyOL2NSl6dPrFf4IF
+YqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+IaFvowdlxfv1k7/9nR4hYJS8+hge9+6jl
+gqispdNpQ80xiEmEU5LAsTkbOYMBMMTyqfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg==
+-----END CERTIFICATE-----
+
+ANF Secure Server Root CA
+=========================
+-----BEGIN CERTIFICATE-----
+MIIF7zCCA9egAwIBAgIIDdPjvGz5a7EwDQYJKoZIhvcNAQELBQAwgYQxEjAQBgNVBAUTCUc2MzI4
+NzUxMDELMAkGA1UEBhMCRVMxJzAlBgNVBAoTHkFORiBBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lv
+bjEUMBIGA1UECxMLQU5GIENBIFJhaXoxIjAgBgNVBAMTGUFORiBTZWN1cmUgU2VydmVyIFJvb3Qg
+Q0EwHhcNMTkwOTA0MTAwMDM4WhcNMzkwODMwMTAwMDM4WjCBhDESMBAGA1UEBRMJRzYzMjg3NTEw
+MQswCQYDVQQGEwJFUzEnMCUGA1UEChMeQU5GIEF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uMRQw
+EgYDVQQLEwtBTkYgQ0EgUmFpejEiMCAGA1UEAxMZQU5GIFNlY3VyZSBTZXJ2ZXIgUm9vdCBDQTCC
+AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANvrayvmZFSVgpCjcqQZAZ2cC4Ffc0m6p6zz
+BE57lgvsEeBbphzOG9INgxwruJ4dfkUyYA8H6XdYfp9qyGFOtibBTI3/TO80sh9l2Ll49a2pcbnv
+T1gdpd50IJeh7WhM3pIXS7yr/2WanvtH2Vdy8wmhrnZEE26cLUQ5vPnHO6RYPUG9tMJJo8gN0pcv
+B2VSAKduyK9o7PQUlrZXH1bDOZ8rbeTzPvY1ZNoMHKGESy9LS+IsJJ1tk0DrtSOOMspvRdOoiXse
+zx76W0OLzc2oD2rKDF65nkeP8Nm2CgtYZRczuSPkdxl9y0oukntPLxB3sY0vaJxizOBQ+OyRp1RM
+VwnVdmPF6GUe7m1qzwmd+nxPrWAI/VaZDxUse6mAq4xhj0oHdkLePfTdsiQzW7i1o0TJrH93PB0j
+7IKppuLIBkwC/qxcmZkLLxCKpvR/1Yd0DVlJRfbwcVw5Kda/SiOL9V8BY9KHcyi1Swr1+KuCLH5z
+JTIdC2MKF4EA/7Z2Xue0sUDKIbvVgFHlSFJnLNJhiQcND85Cd8BEc5xEUKDbEAotlRyBr+Qc5RQe
+8TZBAQIvfXOn3kLMTOmJDVb3n5HUA8ZsyY/b2BzgQJhdZpmYgG4t/wHFzstGH6wCxkPmrqKEPMVO
+Hj1tyRRM4y5Bu8o5vzY8KhmqQYdOpc5LMnndkEl/AgMBAAGjYzBhMB8GA1UdIwQYMBaAFJxf0Gxj
+o1+TypOYCK2Mh6UsXME3MB0GA1UdDgQWBBScX9BsY6Nfk8qTmAitjIelLFzBNzAOBgNVHQ8BAf8E
+BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEATh65isagmD9uw2nAalxJ
+UqzLK114OMHVVISfk/CHGT0sZonrDUL8zPB1hT+L9IBdeeUXZ701guLyPI59WzbLWoAAKfLOKyzx
+j6ptBZNscsdW699QIyjlRRA96Gejrw5VD5AJYu9LWaL2U/HANeQvwSS9eS9OICI7/RogsKQOLHDt
+dD+4E5UGUcjohybKpFtqFiGS3XNgnhAY3jyB6ugYw3yJ8otQPr0R4hUDqDZ9MwFsSBXXiJCZBMXM
+5gf0vPSQ7RPi6ovDj6MzD8EpTBNO2hVWcXNyglD2mjN8orGoGjR0ZVzO0eurU+AagNjqOknkJjCb
+5RyKqKkVMoaZkgoQI1YS4PbOTOK7vtuNknMBZi9iPrJyJ0U27U1W45eZ/zo1PqVUSlJZS2Db7v54
+EX9K3BR5YLZrZAPbFYPhor72I5dQ8AkzNqdxliXzuUJ92zg/LFis6ELhDtjTO0wugumDLmsx2d1H
+hk9tl5EuT+IocTUW0fJz/iUrB0ckYyfI+PbZa/wSMVYIwFNCr5zQM378BvAxRAMU8Vjq8moNqRGy
+g77FGr8H6lnco4g175x2MjxNBiLOFeXdntiP2t7SxDnlF4HPOEfrf4htWRvfn0IUrn7PqLBmZdo3
+r5+qPeoott7VMVgWglvquxl1AnMaykgaIZOQCo6ThKd9OyMYkomgjaw=
+-----END CERTIFICATE-----
+
+Certum EC-384 CA
+================
+-----BEGIN CERTIFICATE-----
+MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQswCQYDVQQGEwJQ
+TDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2
+MDcyNDU0WhcNNDMwMzI2MDcyNDU0WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERh
+dGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx
+GTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATEKI6rGFtq
+vm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7TmFy8as10CW4kjPMIRBSqn
+iBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68KjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
+VR0OBBYEFI0GZnQkdjrzife81r1HfS+8EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNo
+ADBlAjADVS2m5hjEfO/JUG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0
+QoSZ/6vnnvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k=
+-----END CERTIFICATE-----
+
+Certum Trusted Root CA
+======================
+-----BEGIN CERTIFICATE-----
+MIIFwDCCA6igAwIBAgIQHr9ZULjJgDdMBvfrVU+17TANBgkqhkiG9w0BAQ0FADB6MQswCQYDVQQG
+EwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0g
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0Ew
+HhcNMTgwMzE2MTIxMDEzWhcNNDMwMzE2MTIxMDEzWjB6MQswCQYDVQQGEwJQTDEhMB8GA1UEChMY
+QXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQDRLY67tzbqbTeRn06TpwXkKQMlzhyC93yZn0EGze2jusDbCSzBfN8p
+fktlL5On1AFrAygYo9idBcEq2EXxkd7fO9CAAozPOA/qp1x4EaTByIVcJdPTsuclzxFUl6s1wB52
+HO8AU5853BSlLCIls3Jy/I2z5T4IHhQqNwuIPMqw9MjCoa68wb4pZ1Xi/K1ZXP69VyywkI3C7Te2
+fJmItdUDmj0VDT06qKhF8JVOJVkdzZhpu9PMMsmN74H+rX2Ju7pgE8pllWeg8xn2A1bUatMn4qGt
+g/BKEiJ3HAVz4hlxQsDsdUaakFjgao4rpUYwBI4Zshfjvqm6f1bxJAPXsiEodg42MEx51UGamqi4
+NboMOvJEGyCI98Ul1z3G4z5D3Yf+xOr1Uz5MZf87Sst4WmsXXw3Hw09Omiqi7VdNIuJGmj8PkTQk
+fVXjjJU30xrwCSss0smNtA0Aq2cpKNgB9RkEth2+dv5yXMSFytKAQd8FqKPVhJBPC/PgP5sZ0jeJ
+P/J7UhyM9uH3PAeXjA6iWYEMspA90+NZRu0PqafegGtaqge2Gcu8V/OXIXoMsSt0Puvap2ctTMSY
+njYJdmZm/Bo/6khUHL4wvYBQv3y1zgD2DGHZ5yQD4OMBgQ692IU0iL2yNqh7XAjlRICMb/gv1SHK
+HRzQ+8S1h9E6Tsd2tTVItQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSM+xx1
+vALTn04uSNn5YFSqxLNP+jAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQENBQADggIBAEii1QAL
+LtA/vBzVtVRJHlpr9OTy4EA34MwUe7nJ+jW1dReTagVphZzNTxl4WxmB82M+w85bj/UvXgF2Ez8s
+ALnNllI5SW0ETsXpD4YN4fqzX4IS8TrOZgYkNCvozMrnadyHncI013nR03e4qllY/p0m+jiGPp2K
+h2RX5Rc64vmNueMzeMGQ2Ljdt4NR5MTMI9UGfOZR0800McD2RrsLrfw9EAUqO0qRJe6M1ISHgCq8
+CYyqOhNf6DR5UMEQGfnTKB7U0VEwKbOukGfWHwpjscWpxkIxYxeU72nLL/qMFH3EQxiJ2fAyQOaA
+4kZf5ePBAFmo+eggvIksDkc0C+pXwlM2/KfUrzHN/gLldfq5Jwn58/U7yn2fqSLLiMmq0Uc9Nneo
+WWRrJ8/vJ8HjJLWG965+Mk2weWjROeiQWMODvA8s1pfrzgzhIMfatz7DP78v3DSk+yshzWePS/Tj
+6tQ/50+6uaWTRRxmHyH6ZF5v4HaUMst19W7l9o/HuKTMqJZ9ZPskWkoDbGs4xugDQ5r3V7mzKWmT
+OPQD8rv7gmsHINFSH5pkAnuYZttcTVoP0ISVoDwUQwbKytu4QTbaakRnh6+v40URFWkIsr4WOZck
+bxJF0WddCajJFdr60qZfE2Efv4WstK2tBZQIgx51F9NxO5NQI1mg7TyRVJ12AMXDuDjb
+-----END CERTIFICATE-----
+
+TunTrust Root CA
+================
+-----BEGIN CERTIFICATE-----
+MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQELBQAwYTELMAkG
+A1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUgQ2VydGlmaWNhdGlvbiBFbGVj
+dHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJvb3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQw
+NDI2MDg1NzU2WjBhMQswCQYDVQQGEwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBD
+ZXJ0aWZpY2F0aW9uIEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIw
+DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZn56eY+hz
+2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd2JQDoOw05TDENX37Jk0b
+bjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgFVwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7
+NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZGoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAd
+gjH8KcwAWJeRTIAAHDOFli/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViW
+VSHbhlnUr8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2eY8f
+Tpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIbMlEsPvLfe/ZdeikZ
+juXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISgjwBUFfyRbVinljvrS5YnzWuioYas
+DXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwS
+VXAkPcvCFDVDXSdOvsC9qnyW5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI
+04Y+oXNZtPdEITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0
+90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+zxiD2BkewhpMl
+0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYuQEkHDVneixCwSQXi/5E/S7fd
+Ao74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRY
+YdZ2vyJ/0Adqp2RT8JeNnYA/u8EH22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJp
+adbGNjHh/PqAulxPxOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65x
+xBzndFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5Xc0yGYuP
+jCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7bnV2UqL1g52KAdoGDDIzM
+MEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQCvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9z
+ZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZHu/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3r
+AZ3r2OvEhJn7wAzMMujjd9qDRIueVSjAi1jTkD5OGwDxFa2DK5o=
+-----END CERTIFICATE-----
+
+HARICA TLS RSA Root CA 2021
+===========================
+-----BEGIN CERTIFICATE-----
+MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQG
+EwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u
+cyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0EgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUz
+OFoXDTQ1MDIxMzEwNTUzN1owbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRl
+bWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNB
+IFJvb3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569lmwVnlskN
+JLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE4VGC/6zStGndLuwRo0Xu
+a2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uva9of08WRiFukiZLRgeaMOVig1mlDqa2Y
+Ulhu2wr7a89o+uOkXjpFc5gH6l8Cct4MpbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K
+5FrZx40d/JiZ+yykgmvwKh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEv
+dmn8kN3bLW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcYAuUR
+0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqBAGMUuTNe3QvboEUH
+GjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYqE613TBoYm5EPWNgGVMWX+Ko/IIqm
+haZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHrW2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQ
+CPxrvrNQKlr9qEgYRtaQQJKQCoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8G
+A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE
+AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAUX15QvWiWkKQU
+EapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3f5Z2EMVGpdAgS1D0NTsY9FVq
+QRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxajaH6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxD
+QpSbIPDRzbLrLFPCU3hKTwSUQZqPJzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcR
+j88YxeMn/ibvBZ3PzzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5
+vZStjBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0/L5H9MG0
+qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pTBGIBnfHAT+7hOtSLIBD6
+Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79aPib8qXPMThcFarmlwDB31qlpzmq6YR/
+PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YWxw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnn
+kf3/W9b3raYvAwtt41dU63ZTGI0RmLo=
+-----END CERTIFICATE-----
+
+HARICA TLS ECC Root CA 2021
+===========================
+-----BEGIN CERTIFICATE-----
+MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQswCQYDVQQGEwJH
+UjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBD
+QTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoX
+DTQ1MDIxMzExMDEwOVowbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWlj
+IGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJv
+b3QgQ0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7KKrxcm1l
+AEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9YSTHMmE5gEYd103KUkE+b
+ECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW
+0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAi
+rcJRQO9gcS3ujwLEXQNwSaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/Qw
+CZ61IygNnxS2PFOiTAZpffpskcYqSUXm7LcT4Tps
+-----END CERTIFICATE-----
+
+Autoridad de Certificacion Firmaprofesional CIF A62634068
+=========================================================
+-----BEGIN CERTIFICATE-----
+MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCRVMxQjBA
+BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
+MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIw
+QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB
+NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD
+Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P
+B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY
+7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH
+ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI
+plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX
+MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX
+LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK
+bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU
+vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMB0GA1Ud
+DgQWBBRlzeurNR4APn7VdMActHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4w
+gZswgZgGBFUdIAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j
+b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABCAG8AbgBhAG4A
+bwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAwADEANzAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9miWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL
+4QjbEwj4KKE1soCzC1HA01aajTNFSa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDb
+LIpgD7dvlAceHabJhfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1il
+I45PVf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZEEAEeiGaP
+cjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV1aUsIC+nmCjuRfzxuIgA
+LI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2tCsvMo2ebKHTEm9caPARYpoKdrcd7b/+A
+lun4jWq9GJAd/0kakFI3ky88Al2CdgtR5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH
+9IBk9W6VULgRfhVwOEqwf9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpf
+NIbnYrX9ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNKGbqE
+ZycPvEJdvSRUDewdcAZfpLz6IHxV
+-----END CERTIFICATE-----
+
+vTrus ECC Root CA
+=================
+-----BEGIN CERTIFICATE-----
+MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMwRzELMAkGA1UE
+BhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBS
+b290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDczMTA3MjY0NFowRzELMAkGA1UEBhMCQ04xHDAa
+BgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBSb290IENBMHYw
+EAYHKoZIzj0CAQYFK4EEACIDYgAEZVBKrox5lkqqHAjDo6LN/llWQXf9JpRCux3NCNtzslt188+c
+ToL0v/hhJoVs1oVbcnDS/dtitN9Ti72xRFhiQgnH+n9bEOf+QP3A2MMrMudwpremIFUde4BdS49n
+TPEQo0IwQDAdBgNVHQ4EFgQUmDnNvtiyjPeyq+GtJK97fKHbH88wDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIwV53dVvHH4+m4SVBrm2nDb+zDfSXkV5UT
+QJtS0zvzQBm8JsctBp61ezaf9SXUY2sAAjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQL
+YgmRWAD5Tfs0aNoJrSEGGJTO
+-----END CERTIFICATE-----
+
+vTrus Root CA
+=============
+-----BEGIN CERTIFICATE-----
+MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQELBQAwQzELMAkG
+A1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xFjAUBgNVBAMTDXZUcnVzIFJv
+b3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMxMDcyNDA1WjBDMQswCQYDVQQGEwJDTjEcMBoG
+A1UEChMTaVRydXNDaGluYSBDby4sTHRkLjEWMBQGA1UEAxMNdlRydXMgUm9vdCBDQTCCAiIwDQYJ
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAL1VfGHTuB0EYgWgrmy3cLRB6ksDXhA/kFocizuwZots
+SKYcIrrVQJLuM7IjWcmOvFjai57QGfIvWcaMY1q6n6MLsLOaXLoRuBLpDLvPbmyAhykUAyyNJJrI
+ZIO1aqwTLDPxn9wsYTwaP3BVm60AUn/PBLn+NvqcwBauYv6WTEN+VRS+GrPSbcKvdmaVayqwlHeF
+XgQPYh1jdfdr58tbmnDsPmcF8P4HCIDPKNsFxhQnL4Z98Cfe/+Z+M0jnCx5Y0ScrUw5XSmXX+6KA
+YPxMvDVTAWqXcoKv8R1w6Jz1717CbMdHflqUhSZNO7rrTOiwCcJlwp2dCZtOtZcFrPUGoPc2BX70
+kLJrxLT5ZOrpGgrIDajtJ8nU57O5q4IikCc9Kuh8kO+8T/3iCiSn3mUkpF3qwHYw03dQ+A0Em5Q2
+AXPKBlim0zvc+gRGE1WKyURHuFE5Gi7oNOJ5y1lKCn+8pu8fA2dqWSslYpPZUxlmPCdiKYZNpGvu
+/9ROutW04o5IWgAZCfEF2c6Rsffr6TlP9m8EQ5pV9T4FFL2/s1m02I4zhKOQUqqzApVg+QxMaPnu
+1RcN+HFXtSXkKe5lXa/R7jwXC1pDxaWG6iSe4gUH3DRCEpHWOXSuTEGC2/KmSNGzm/MzqvOmwMVO
+9fSddmPmAsYiS8GVP1BkLFTltvA8Kc9XAgMBAAGjQjBAMB0GA1UdDgQWBBRUYnBj8XWEQ1iO0RYg
+scasGrz2iTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOC
+AgEAKbqSSaet8PFww+SX8J+pJdVrnjT+5hpk9jprUrIQeBqfTNqK2uwcN1LgQkv7bHbKJAs5EhWd
+nxEt/Hlk3ODg9d3gV8mlsnZwUKT+twpw1aA08XXXTUm6EdGz2OyC/+sOxL9kLX1jbhd47F18iMjr
+jld22VkE+rxSH0Ws8HqA7Oxvdq6R2xCOBNyS36D25q5J08FsEhvMKar5CKXiNxTKsbhm7xqC5PD4
+8acWabfbqWE8n/Uxy+QARsIvdLGx14HuqCaVvIivTDUHKgLKeBRtRytAVunLKmChZwOgzoy8sHJn
+xDHO2zTlJQNgJXtxmOTAGytfdELSS8VZCAeHvsXDf+eW2eHcKJfWjwXj9ZtOyh1QRwVTsMo554Wg
+icEFOwE30z9J4nfrI8iIZjs9OXYhRvHsXyO466JmdXTBQPfYaJqT4i2pLr0cox7IdMakLXogqzu4
+sEb9b91fUlV1YvCXoHzXOP0l382gmxDPi7g4Xl7FtKYCNqEeXxzP4padKar9mK5S4fNBUvupLnKW
+nyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1PTi07NEPhmg4NpGaXutIc
+SkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929vensBxXVsFy6K2ir40zSbofitzmdHxghm+H
+l3s=
+-----END CERTIFICATE-----
+
+ISRG Root X2
+============
+-----BEGIN CERTIFICATE-----
+MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQswCQYDVQQGEwJV
+UzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElT
+UkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVT
+MSkwJwYDVQQKEyBJbnRlcm5ldCBTZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNS
+RyBSb290IFgyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0H
+ttwW+1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9ItgKbppb
+d9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZIzj0EAwMDaAAwZQIwe3lORlCEwkSHRhtF
+cP9Ymd70/aTSVaYgLXTWNLxBo1BfASdWtL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5
+U6VR5CmD1/iQMVtCnwr1/q4AaOeMSQ+2b1tbFfLn
+-----END CERTIFICATE-----
+
+HiPKI Root CA - G1
+==================
+-----BEGIN CERTIFICATE-----
+MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQG
+EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xGzAZBgNVBAMMEkhpUEtJ
+IFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRaFw0zNzEyMzExNTU5NTlaME8xCzAJBgNVBAYT
+AlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQS0kg
+Um9vdCBDQSAtIEcxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9B5/UnMyDHPkvRN0
+o9QwqNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh8Ge6zCFovkRTv4354twvVcg3Px+k
+wJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux55199QmQ5eiY29yTw1S+6lZgRZq2XNdZ1AYDgr/SE
+YYwNHl98h5ZeQa/rh+r4XfEuiAU+TCK72h8q3VJGZDnzQs7ZngyzsHeXZJzA9KMuH5UHsBffMNsA
+GJZMoYFL3QRtU6M9/Aes1MU3guvklQgZKILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfd
+hSi8MEyr48KxRURHH+CKFgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXTT3OUM3ECoWqj
+1jOXTyFjHluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK9p/7qxj3ccC2HTHsOyDry+K4
+9a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8b3ti6RZsR1pl8w4Rm0bZ/W3c1pzAtH2lsN0/
+Vm+h+fbkEkj9Bn8SV7apI09bA8PgcSojt/ewsTu8mL3WmKgMa/aOEmem8rJY5AIJEzypuxC00jBF
+8ez3ABHfZfjcK0NVvxaXxA/VLGGEqnKG/uY6fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaNCMEAwDwYD
+VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ncX+l6o/vY9cdVouslGDDjYr7AwDgYDVR0PAQH/BAQD
+AgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBQUfB13HAE4/+qddRxosuej6ip0691x1TPOhwEmSKsxBHi
+7zNKpiMdDg1H2DfHb680f0+BazVP6XKlMeJ45/dOlBhbQH3PayFUhuaVevvGyuqcSE5XCV0vrPSl
+tJczWNWseanMX/mF+lLFjfiRFOs6DRfQUsJ748JzjkZ4Bjgs6FzaZsT0pPBWGTMpWmWSBUdGSquE
+wx4noR8RkpkndZMPvDY7l1ePJlsMu5wP1G4wB9TcXzZoZjmDlicmisjEOf6aIW/Vcobpf2Lll07Q
+JNBAsNB1CI69aO4I1258EHBGG3zgiLKecoaZAeO/n0kZtCW+VmWuF2PlHt/o/0elv+EmBYTksMCv
+5wiZqAxeJoBF1PhoL5aPruJKHJwWDBNvOIf2u8g0X5IDUXlwpt/L9ZlNec1OvFefQ05rLisY+Gpz
+jLrFNe85akEez3GoorKGB1s6yeHvP2UEgEcyRHCVTjFnanRbEEV16rCf0OY1/k6fi8wrkkVbbiVg
+hUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+vhV4nYWBSipX3tUZQ9rb
+yltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQUYDksswBVLuT1sw5XxJFBAJw/6KXf6vb/
+yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ==
+-----END CERTIFICATE-----
+
+GlobalSign ECC Root CA - R4
+===========================
+-----BEGIN CERTIFICATE-----
+MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYDVQQLExtHbG9i
+YWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds
+b2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgwMTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9i
+YWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds
+b2JhbFNpZ24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkW
+ymOxuYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNVHQ8BAf8E
+BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/+wpu+74zyTyjhNUwCgYI
+KoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147bmF0774BxL4YSFlhgjICICadVGNA3jdg
+UM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm
+-----END CERTIFICATE-----
+
+GTS Root R1
+===========
+-----BEGIN CERTIFICATE-----
+MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQGEwJV
+UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg
+UjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE
+ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM
+f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7wCl7raKb0
+xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjwTcLCeoiKu7rPWRnWr4+w
+B7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0PfyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXW
+nOunVmSPlk9orj2XwoSPwLxAwAtcvfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk
+9+aCEI3oncKKiPo4Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zq
+kUspzBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92wO1A
+K/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70paDPvOmbsB4om3xPX
+V2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDW
+cfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T
+AQH/BAUwAwEB/zAdBgNVHQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQAD
+ggIBAJ+qQibbC5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe
+QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuyh6f88/qBVRRi
+ClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM47HLwEXWdyzRSjeZ2axfG34ar
+J45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8JZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYci
+NuaCp+0KueIHoI17eko8cdLiA6EfMgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5me
+LMFrUKTX5hgUvYU/Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJF
+fbdT6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ0E6yove+
+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm2tIMPNuzjsmhDYAPexZ3
+FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bbbP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3
+gm3c
+-----END CERTIFICATE-----
+
+GTS Root R2
+===========
+-----BEGIN CERTIFICATE-----
+MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQGEwJV
+UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg
+UjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE
+ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv
+CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY6Dlo7JUl
+e3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAuMC6C/Pq8tBcKSOWIm8Wb
+a96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS
++LFjKBC4swm4VndAoiaYecb+3yXuPuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7M
+kogwTZq9TwtImoS1mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJG
+r61K8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RWIr9q
+S34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKaG73VululycslaVNV
+J1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCqgc7dGtxRcw1PcOnlthYhGXmy5okL
+dWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T
+AQH/BAUwAwEB/zAdBgNVHQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQAD
+ggIBAB/Kzt3HvqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8
+0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyCB19m3H0Q/gxh
+swWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2uNmSRXbBoGOqKYcl3qJfEycel
+/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMgyALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVn
+jWQye+mew4K6Ki3pHrTgSAai/GevHyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y5
+9PYjJbigapordwj6xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M
+7YNRTOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924SgJPFI/2R8
+0L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV7LXTWtiBmelDGDfrs7vR
+WGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjW
+HYbL
+-----END CERTIFICATE-----
+
+GTS Root R3
+===========
+-----BEGIN CERTIFICATE-----
+MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJVUzEi
+MCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMw
+HhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZ
+R29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjO
+PQIBBgUrgQQAIgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout
+736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL24CejQjBA
+MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTB8Sa6oC2uhYHP0/Eq
+Er24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azT
+L818+FsuVbu/3ZL3pAzcMeGiAjEA/JdmZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV
+11RZt+cRLInUue4X
+-----END CERTIFICATE-----
+
+GTS Root R4
+===========
+-----BEGIN CERTIFICATE-----
+MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJVUzEi
+MCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQw
+HhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZ
+R29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjO
+PQIBBgUrgQQAIgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu
+hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvRHYqjQjBA
+MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSATNbrdP9JNqPV2Py1
+PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/C
+r8deVl5c1RxYIigL9zC2L7F8AjEA8GE8p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh
+4rsUecrNIdSUtUlD
+-----END CERTIFICATE-----
+
+Telia Root CA v2
+================
+-----BEGIN CERTIFICATE-----
+MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQxCzAJBgNVBAYT
+AkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2
+MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQK
+DBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZI
+hvcNAQEBBQADggIPADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ7
+6zBqAMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9vVYiQJ3q
+9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9lRdU2HhE8Qx3FZLgmEKn
+pNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTODn3WhUidhOPFZPY5Q4L15POdslv5e2QJl
+tI5c0BE0312/UqeBAMN/mUWZFdUXyApT7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW
+5olWK8jjfN7j/4nlNW4o6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNr
+RBH0pUPCTEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6WT0E
+BXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63RDolUK5X6wK0dmBR4
+M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZIpEYslOqodmJHixBTB0hXbOKSTbau
+BcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGjYzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7W
+xy+G2CQ5MB0GA1UdDgQWBBRyrOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ
+8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi0f6X+J8wfBj5
+tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMMA8iZGok1GTzTyVR8qPAs5m4H
+eW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBSSRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+C
+y748fdHif64W1lZYudogsYMVoe+KTTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygC
+QMez2P2ccGrGKMOF6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15
+h2Er3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMtTy3EHD70
+sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pTVmBds9hCG1xLEooc6+t9
+xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAWysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQ
+raVplI/owd8k+BsHMYeB2F326CjYSlKArBPuUBQemMc=
+-----END CERTIFICATE-----
+
+D-TRUST BR Root CA 1 2020
+=========================
+-----BEGIN CERTIFICATE-----
+MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE
+RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEJSIFJvb3QgQ0EgMSAy
+MDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNV
+BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7
+dPYSzuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0QVK5buXu
+QqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/VbNafAkl1bK6CKBrqx9t
+MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu
+bmV0L2NybC9kLXRydXN0X2JyX3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj
+dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP
+PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD
+AwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFWwKrY7RjEsK70Pvom
+AjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHVdWNbFJWcHwHP2NVypw87
+-----END CERTIFICATE-----
+
+D-TRUST EV Root CA 1 2020
+=========================
+-----BEGIN CERTIFICATE-----
+MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE
+RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEVWIFJvb3QgQ0EgMSAy
+MDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNV
+BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8
+ZRCC/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rDwpdhQntJ
+raOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3OqQo5FD4pPfsazK2/umL
+MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu
+bmV0L2NybC9kLXRydXN0X2V2X3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj
+dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP
+PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD
+AwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CAy/m0sRtW9XLS/BnR
+AjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJbgfM0agPnIjhQW+0ZT0MW
+-----END CERTIFICATE-----
+
+DigiCert TLS ECC P384 Root G5
+=============================
+-----BEGIN CERTIFICATE-----
+MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURpZ2lDZXJ0IFRMUyBFQ0MgUDM4
+NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMx
+FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQg
+Um9vdCBHNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1Tzvd
+lHJS7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp0zVozptj
+n4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICISB4CIfBFqMA4GA1UdDwEB
+/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQCJao1H5+z8blUD2Wds
+Jk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQLgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIx
+AJSdYsiJvRmEFOml+wG4DXZDjC5Ty3zfDBeWUA==
+-----END CERTIFICATE-----
+
+DigiCert TLS RSA4096 Root G5
+============================
+-----BEGIN CERTIFICATE-----
+MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBNMQswCQYDVQQG
+EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0
+MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcNNDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2
+IFJvb3QgRzUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS8
+7IE+ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG02C+JFvuU
+AT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgpwgscONyfMXdcvyej/Ces
+tyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZMpG2T6T867jp8nVid9E6P/DsjyG244gXa
+zOvswzH016cpVIDPRFtMbzCe88zdH5RDnU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnV
+DdXifBBiqmvwPXbzP6PosMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9q
+TXeXAaDxZre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cdLvvy
+z6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvXKyY//SovcfXWJL5/
+MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNeXoVPzthwiHvOAbWWl9fNff2C+MIk
+wcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPLtgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4E
+FgQUUTMc7TZArxfTJc1paPKvTiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8w
+DQYJKoZIhvcNAQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw
+GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7HPNtQOa27PShN
+lnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLFO4uJ+DQtpBflF+aZfTCIITfN
+MBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQREtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/
+u4cnYiWB39yhL/btp/96j1EuMPikAdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9G
+OUrYU9DzLjtxpdRv/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh
+47a+p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilwMUc/dNAU
+FvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WFqUITVuwhd4GTWgzqltlJ
+yqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCKovfepEWFJqgejF0pW8hL2JpqA15w8oVP
+bEtoL8pU9ozaMv7Da4M/OMZ+
+-----END CERTIFICATE-----
+
+Certainly Root R1
+=================
+-----BEGIN CERTIFICATE-----
+MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAwPTELMAkGA1UE
+BhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2VydGFpbmx5IFJvb3QgUjEwHhcN
+MjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2Vy
+dGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBANA21B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O
+5MQTvqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbedaFySpvXl
+8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b01C7jcvk2xusVtyWMOvwl
+DbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGI
+XsXwClTNSaa/ApzSRKft43jvRl5tcdF5cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkN
+KPl6I7ENPT2a/Z2B7yyQwHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQ
+AjeZjOVJ6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA2Cnb
+rlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyHWyf5QBGenDPBt+U1
+VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMReiFPCyEQtkA6qyI6BJyLm4SGcprS
+p6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
+DgQWBBTgqj8ljZ9EXME66C6ud0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAsz
+HQNTVfSVcOQrPbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d
+8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi1wrykXprOQ4v
+MMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrdrRT90+7iIgXr0PK3aBLXWopB
+GsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9ditaY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+
+gjwN/KUD+nsa2UUeYNrEjvn8K8l7lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgH
+JBu6haEaBQmAupVjyTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7
+fpYnKx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLyyCwzk5Iw
+x06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5nwXARPbv0+Em34yaXOp/S
+X3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6OV+KmalBWQewLK8=
+-----END CERTIFICATE-----
+
+Certainly Root E1
+=================
+-----BEGIN CERTIFICATE-----
+MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQswCQYDVQQGEwJV
+UzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBFMTAeFw0yMTA0
+MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlu
+bHkxGjAYBgNVBAMTEUNlcnRhaW5seSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4
+fxzf7flHh4axpMCK+IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9
+YBk2QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8EBAMCAQYw
+DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4hevIIgcwCgYIKoZIzj0E
+AwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozmut6Dacpps6kFtZaSF4fC0urQe87YQVt8
+rgIwRt7qy12a7DLCZRawTDBcMPPaTnOGBtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR
+-----END CERTIFICATE-----
+
+Security Communication RootCA3
+==============================
+-----BEGIN CERTIFICATE-----
+MIIFfzCCA2egAwIBAgIJAOF8N0D9G/5nMA0GCSqGSIb3DQEBDAUAMF0xCzAJBgNVBAYTAkpQMSUw
+IwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScwJQYDVQQDEx5TZWN1cml0eSBD
+b21tdW5pY2F0aW9uIFJvb3RDQTMwHhcNMTYwNjE2MDYxNzE2WhcNMzgwMTE4MDYxNzE2WjBdMQsw
+CQYDVQQGEwJKUDElMCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UE
+AxMeU2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+MIICCgKCAgEA48lySfcw3gl8qUCBWNO0Ot26YQ+TUG5pPDXC7ltzkBtnTCHsXzW7OT4rCmDvu20r
+hvtxosis5FaU+cmvsXLUIKx00rgVrVH+hXShuRD+BYD5UpOzQD11EKzAlrenfna84xtSGc4RHwsE
+NPXY9Wk8d/Nk9A2qhd7gCVAEF5aEt8iKvE1y/By7z/MGTfmfZPd+pmaGNXHIEYBMwXFAWB6+oHP2
+/D5Q4eAvJj1+XCO1eXDe+uDRpdYMQXF79+qMHIjH7Iv10S9VlkZ8WjtYO/u62C21Jdp6Ts9EriGm
+npjKIG58u4iFW/vAEGK78vknR+/RiTlDxN/e4UG/VHMgly1s2vPUB6PmudhvrvyMGS7TZ2crldtY
+XLVqAvO4g160a75BflcJdURQVc1aEWEhCmHCqYj9E7wtiS/NYeCVvsq1e+F7NGcLH7YMx3weGVPK
+p7FKFSBWFHA9K4IsD50VHUeAR/94mQ4xr28+j+2GaR57GIgUssL8gjMunEst+3A7caoreyYn8xrC
+3PsXuKHqy6C0rtOUfnrQq8PsOC0RLoi/1D+tEjtCrI8Cbn3M0V9hvqG8OmpI6iZVIhZdXw3/JzOf
+GAN0iltSIEdrRU0id4xVJ/CvHozJgyJUt5rQT9nO/NkuHJYosQLTA70lUhw0Zk8jq/R3gpYd0Vcw
+CBEF/VfR2ccCAwEAAaNCMEAwHQYDVR0OBBYEFGQUfPxYchamCik0FW8qy7z8r6irMA4GA1UdDwEB
+/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDAUAA4ICAQDcAiMI4u8hOscNtybS
+YpOnpSNyByCCYN8Y11StaSWSntkUz5m5UoHPrmyKO1o5yGwBQ8IibQLwYs1OY0PAFNr0Y/Dq9HHu
+Tofjcan0yVflLl8cebsjqodEV+m9NU1Bu0soo5iyG9kLFwfl9+qd9XbXv8S2gVj/yP9kaWJ5rW4O
+H3/uHWnlt3Jxs/6lATWUVCvAUm2PVcTJ0rjLyjQIUYWg9by0F1jqClx6vWPGOi//lkkZhOpn2ASx
+YfQAW0q3nHE3GYV5v4GwxxMOdnE+OoAGrgYWp421wsTL/0ClXI2lyTrtcoHKXJg80jQDdwj98ClZ
+XSEIx2C/pHF7uNkegr4Jr2VvKKu/S7XuPghHJ6APbw+LP6yVGPO5DtxnVW5inkYO0QR4ynKudtml
++LLfiAlhi+8kTtFZP1rUPcmTPCtk9YENFpb3ksP+MW/oKjJ0DvRMmEoYDjBU1cXrvMUVnuiZIesn
+KwkK2/HmcBhWuwzkvvnoEKQTkrgc4NtnHVMDpCKn3F2SEDzq//wbEBrD2NCcnWXL0CsnMQMeNuE9
+dnUM/0Umud1RvCPHX9jYhxBAEg09ODfnRDwYwFMJZI//1ZqmfHAuc1Uh6N//g7kdPjIe1qZ9LPFm
+6Vwdp6POXiUyK+OVrCoHzrQoeIY8LaadTdJ0MN1kURXbg4NR16/9M51NZg==
+-----END CERTIFICATE-----
+
+Security Communication ECC RootCA1
+==================================
+-----BEGIN CERTIFICATE-----
+MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYTAkpQMSUwIwYD
+VQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYDVQQDEyJTZWN1cml0eSBDb21t
+dW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYxNjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTEL
+MAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNV
+BAMTIlNlY3VyaXR5IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+CnnfdldB9sELLo
+5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpKULGjQjBAMB0GA1UdDgQW
+BBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAK
+BggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3L
+snNdo4gIxwwCMQDAqy0Obe0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70e
+N9k=
+-----END CERTIFICATE-----
+
+BJCA Global Root CA1
+====================
+-----BEGIN CERTIFICATE-----
+MIIFdDCCA1ygAwIBAgIQVW9l47TZkGobCdFsPsBsIDANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQG
+EwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJVFkxHTAbBgNVBAMMFEJK
+Q0EgR2xvYmFsIFJvb3QgQ0ExMB4XDTE5MTIxOTAzMTYxN1oXDTQ0MTIxMjAzMTYxN1owVDELMAkG
+A1UEBhMCQ04xJjAkBgNVBAoMHUJFSUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQD
+DBRCSkNBIEdsb2JhbCBSb290IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPFm
+CL3ZxRVhy4QEQaVpN3cdwbB7+sN3SJATcmTRuHyQNZ0YeYjjlwE8R4HyDqKYDZ4/N+AZspDyRhyS
+sTphzvq3Rp4Dhtczbu33RYx2N95ulpH3134rhxfVizXuhJFyV9xgw8O558dnJCNPYwpj9mZ9S1Wn
+P3hkSWkSl+BMDdMJoDIwOvqfwPKcxRIqLhy1BDPapDgRat7GGPZHOiJBhyL8xIkoVNiMpTAK+BcW
+yqw3/XmnkRd4OJmtWO2y3syJfQOcs4ll5+M7sSKGjwZteAf9kRJ/sGsciQ35uMt0WwfCyPQ10WRj
+eulumijWML3mG90Vr4TqnMfK9Q7q8l0ph49pczm+LiRvRSGsxdRpJQaDrXpIhRMsDQa4bHlW/KNn
+MoH1V6XKV0Jp6VwkYe/iMBhORJhVb3rCk9gZtt58R4oRTklH2yiUAguUSiz5EtBP6DF+bHq/pj+b
+OT0CFqMYs2esWz8sgytnOYFcuX6U1WTdno9uruh8W7TXakdI136z1C2OVnZOz2nxbkRs1CTqjSSh
+GL+9V/6pmTW12xB3uD1IutbB5/EjPtffhZ0nPNRAvQoMvfXnjSXWgXSHRtQpdaJCbPdzied9v3pK
+H9MiyRVVz99vfFXQpIsHETdfg6YmV6YBW37+WGgHqel62bno/1Afq8K0wM7o6v0PvY1NuLxxAgMB
+AAGjQjBAMB0GA1UdDgQWBBTF7+3M2I0hxkjk49cULqcWk+WYATAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAUoKsITQfI/Ki2Pm4rzc2IInRNwPWaZ+4
+YRC6ojGYWUfo0Q0lHhVBDOAqVdVXUsv45Mdpox1NcQJeXyFFYEhcCY5JEMEE3KliawLwQ8hOnThJ
+dMkycFRtwUf8jrQ2ntScvd0g1lPJGKm1Vrl2i5VnZu69mP6u775u+2D2/VnGKhs/I0qUJDAnyIm8
+60Qkmss9vk/Ves6OF8tiwdneHg56/0OGNFK8YT88X7vZdrRTvJez/opMEi4r89fO4aL/3Xtw+zuh
+TaRjAv04l5U/BXCga99igUOLtFkNSoxUnMW7gZ/NfaXvCyUeOiDbHPwfmGcCCtRzRBPbUYQaVQNW
+4AB+dAb/OMRyHdOoP2gxXdMJxy6MW2Pg6Nwe0uxhHvLe5e/2mXZgLR6UcnHGCyoyx5JO1UbXHfmp
+GQrI+pXObSOYqgs4rZpWDW+N8TEAiMEXnM0ZNjX+VVOg4DwzX5Ze4jLp3zO7Bkqp2IRzznfSxqxx
+4VyjHQy7Ct9f4qNx2No3WqB4K/TUfet27fJhcKVlmtOJNBir+3I+17Q9eVzYH6Eze9mCUAyTF6ps
+3MKCuwJXNq+YJyo5UOGwifUll35HaBC07HPKs5fRJNz2YqAo07WjuGS3iGJCz51TzZm+ZGiPTx4S
+SPfSKcOYKMryMguTjClPPGAyzQWWYezyr/6zcCwupvI=
+-----END CERTIFICATE-----
+
+BJCA Global Root CA2
+====================
+-----BEGIN CERTIFICATE-----
+MIICJTCCAaugAwIBAgIQLBcIfWQqwP6FGFkGz7RK6zAKBggqhkjOPQQDAzBUMQswCQYDVQQGEwJD
+TjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJVFkxHTAbBgNVBAMMFEJKQ0Eg
+R2xvYmFsIFJvb3QgQ0EyMB4XDTE5MTIxOTAzMTgyMVoXDTQ0MTIxMjAzMTgyMVowVDELMAkGA1UE
+BhMCQ04xJjAkBgNVBAoMHUJFSUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRC
+SkNBIEdsb2JhbCBSb290IENBMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ3LgJGNU2e1uVCxA/jl
+SR9BIgmwUVJY1is0j8USRhTFiy8shP8sbqjV8QnjAyEUxEM9fMEsxEtqSs3ph+B99iK++kpRuDCK
+/eHeGBIK9ke35xe/J4rUQUyWPGCWwf0VHKNCMEAwHQYDVR0OBBYEFNJKsVF/BvDRgh9Obl+rg/xI
+1LCRMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8
+W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8g
+UXOQwKhbYdDFUDn9hf7B43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w==
+-----END CERTIFICATE-----
+
+Sectigo Public Server Authentication Root E46
+=============================================
+-----BEGIN CERTIFICATE-----
+MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQswCQYDVQQGEwJH
+QjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBTZXJ2
+ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5
+WjBfMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0
+aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUr
+gQQAIgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccCWvkEN/U0
+NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+6xnOQ6OjQjBAMB0GA1Ud
+DgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
+/zAKBggqhkjOPQQDAwNnADBkAjAn7qRaqCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RH
+lAFWovgzJQxC36oCMB3q4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21U
+SAGKcw==
+-----END CERTIFICATE-----
+
+Sectigo Public Server Authentication Root R46
+=============================================
+-----BEGIN CERTIFICATE-----
+MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBfMQswCQYDVQQG
+EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT
+ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwHhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1
+OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T
+ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3
+DQEBAQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDaef0rty2k
+1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnzSDBh+oF8HqcIStw+Kxwf
+GExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xfiOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMP
+FF1bFOdLvt30yNoDN9HWOaEhUTCDsG3XME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vu
+ZDCQOc2TZYEhMbUjUDM3IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5Qaz
+Yw6A3OASVYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgESJ/A
+wSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu+Zd4KKTIRJLpfSYF
+plhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt8uaZFURww3y8nDnAtOFr94MlI1fZ
+EoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+LHaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW
+6aWWrL3DkJiy4Pmi1KZHQ3xtzwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWI
+IUkwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c
+mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQYKlJfp/imTYp
+E0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52gDY9hAaLMyZlbcp+nv4fjFg4
+exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZAFv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M
+0ejf5lG5Nkc/kLnHvALcWxxPDkjBJYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI
+84HxZmduTILA7rpXDhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9m
+pFuiTdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5dHn5Hrwd
+Vw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65LvKRRFHQV80MNNVIIb/b
+E/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmm
+J1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAYQqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL
+-----END CERTIFICATE-----
+
+SSL.com TLS RSA Root CA 2022
+============================
+-----BEGIN CERTIFICATE-----
+MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQG
+EwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxTU0wuY29tIFRMUyBSU0Eg
+Um9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloXDTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMC
+VVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJv
+b3QgQ0EgMjAyMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u
+9nTPL3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OYt6/wNr/y
+7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0insS657Lb85/bRi3pZ7Qcac
+oOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3PnxEX4MN8/HdIGkWCVDi1FW24IBydm5M
+R7d1VVm0U3TZlMZBrViKMWYPHqIbKUBOL9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDG
+D6C1vBdOSHtRwvzpXGk3R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEW
+TO6Af77wdr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS+YCk
+8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYSd66UNHsef8JmAOSq
+g+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoGAtUjHBPW6dvbxrB6y3snm/vg1UYk
+7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2fgTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1Ud
+EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsu
+N+7jhHonLs0ZNbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlt
+hEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsMQtfhWsSWTVTN
+j8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvfR4iyrT7gJ4eLSYwfqUdYe5by
+iB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJDPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjU
+o3KUQyxi4U5cMj29TH0ZR6LDSeeWP4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqo
+ENjwuSfr98t67wVylrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7Egkaib
+MOlqbLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2wAgDHbICi
+vRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3qr5nsLFR+jM4uElZI7xc7
+P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sjiMho6/4UIyYOf8kpIEFR3N+2ivEC+5BB0
+9+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA=
+-----END CERTIFICATE-----
+
+SSL.com TLS ECC Root CA 2022
+============================
+-----BEGIN CERTIFICATE-----
+MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQswCQYDVQQGEwJV
+UzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxTU0wuY29tIFRMUyBFQ0MgUm9v
+dCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMx
+GDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3Qg
+Q0EgMjAyMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWy
+JGYmacCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFNSeR7T5v1
+5wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSJjy+j6CugFFR7
+81a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NWuCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGG
+MAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w
+7deedWo1dlJF4AIxAMeNb0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5
+Zn6g6g==
+-----END CERTIFICATE-----
+
+Atos TrustedRoot Root CA ECC TLS 2021
+=====================================
+-----BEGIN CERTIFICATE-----
+MIICFTCCAZugAwIBAgIQPZg7pmY9kGP3fiZXOATvADAKBggqhkjOPQQDAzBMMS4wLAYDVQQDDCVB
+dG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgRUNDIFRMUyAyMDIxMQ0wCwYDVQQKDARBdG9zMQswCQYD
+VQQGEwJERTAeFw0yMTA0MjIwOTI2MjNaFw00MTA0MTcwOTI2MjJaMEwxLjAsBgNVBAMMJUF0b3Mg
+VHJ1c3RlZFJvb3QgUm9vdCBDQSBFQ0MgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYT
+AkRFMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEloZYKDcKZ9Cg3iQZGeHkBQcfl+3oZIK59sRxUM6K
+DP/XtXa7oWyTbIOiaG6l2b4siJVBzV3dscqDY4PMwL502eCdpO5KTlbgmClBk1IQ1SQ4AjJn8ZQS
+b+/Xxd4u/RmAo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR2KCXWfeBmmnoJsmo7jjPX
+NtNPojAOBgNVHQ8BAf8EBAMCAYYwCgYIKoZIzj0EAwMDaAAwZQIwW5kp85wxtolrbNa9d+F851F+
+uDrNozZffPc8dz7kUK2o59JZDCaOMDtuCCrCp1rIAjEAmeMM56PDr9NJLkaCI2ZdyQAUEv049OGY
+a3cpetskz2VAv9LcjBHo9H1/IISpQuQo
+-----END CERTIFICATE-----
+
+Atos TrustedRoot Root CA RSA TLS 2021
+=====================================
+-----BEGIN CERTIFICATE-----
+MIIFZDCCA0ygAwIBAgIQU9XP5hmTC/srBRLYwiqipDANBgkqhkiG9w0BAQwFADBMMS4wLAYDVQQD
+DCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgUlNBIFRMUyAyMDIxMQ0wCwYDVQQKDARBdG9zMQsw
+CQYDVQQGEwJERTAeFw0yMTA0MjIwOTIxMTBaFw00MTA0MTcwOTIxMDlaMEwxLjAsBgNVBAMMJUF0
+b3MgVHJ1c3RlZFJvb3QgUm9vdCBDQSBSU0EgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNV
+BAYTAkRFMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtoAOxHm9BYx9sKOdTSJNy/BB
+l01Z4NH+VoyX8te9j2y3I49f1cTYQcvyAh5x5en2XssIKl4w8i1mx4QbZFc4nXUtVsYvYe+W/CBG
+vevUez8/fEc4BKkbqlLfEzfTFRVOvV98r61jx3ncCHvVoOX3W3WsgFWZkmGbzSoXfduP9LVq6hdK
+ZChmFSlsAvFr1bqjM9xaZ6cF4r9lthawEO3NUDPJcFDsGY6wx/J0W2tExn2WuZgIWWbeKQGb9Cpt
+0xU6kGpn8bRrZtkh68rZYnxGEFzedUlnnkL5/nWpo63/dgpnQOPF943HhZpZnmKaau1Fh5hnstVK
+PNe0OwANwI8f4UDErmwh3El+fsqyjW22v5MvoVw+j8rtgI5Y4dtXz4U2OLJxpAmMkokIiEjxQGMY
+sluMWuPD0xeqqxmjLBvk1cbiZnrXghmmOxYsL3GHX0WelXOTwkKBIROW1527k2gV+p2kHYzygeBY
+Br3JtuP2iV2J+axEoctr+hbxx1A9JNr3w+SH1VbxT5Aw+kUJWdo0zuATHAR8ANSbhqRAvNncTFd+
+rrcztl524WWLZt+NyteYr842mIycg5kDcPOvdO3GDjbnvezBc6eUWsuSZIKmAMFwoW4sKeFYV+xa
+fJlrJaSQOoD0IJ2azsct+bJLKZWD6TWNp0lIpw9MGZHQ9b8Q4HECAwEAAaNCMEAwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQUdEmZ0f+0emhFdcN+tNzMzjkz2ggwDgYDVR0PAQH/BAQDAgGGMA0G
+CSqGSIb3DQEBDAUAA4ICAQAjQ1MkYlxt/T7Cz1UAbMVWiLkO3TriJQ2VSpfKgInuKs1l+NsW4AmS
+4BjHeJi78+xCUvuppILXTdiK/ORO/auQxDh1MoSf/7OwKwIzNsAQkG8dnK/haZPso0UvFJ/1TCpl
+Q3IM98P4lYsU84UgYt1UU90s3BiVaU+DR3BAM1h3Egyi61IxHkzJqM7F78PRreBrAwA0JrRUITWX
+AdxfG/F851X6LWh3e9NpzNMOa7pNdkTWwhWaJuywxfW70Xp0wmzNxbVe9kzmWy2B27O3Opee7c9G
+slA9hGCZcbUztVdF5kJHdWoOsAgMrr3e97sPWD2PAzHoPYJQyi9eDF20l74gNAf0xBLh7tew2Vkt
+afcxBPTy+av5EzH4AXcOPUIjJsyacmdRIXrMPIWo6iFqO9taPKU0nprALN+AnCng33eU0aKAQv9q
+TFsR0PXNor6uzFFcw9VUewyu1rkGd4Di7wcaaMxZUa1+XGdrudviB0JbuAEFWDlN5LuYo7Ey7Nmj
+1m+UI/87tyll5gfp77YZ6ufCOB0yiJA8EytuzO+rdwY0d4RPcuSBhPm5dDTedk+SKlOxJTnbPP/l
+PqYO5Wue/9vsL3SD3460s6neFE3/MaNFcyT6lSnMEpcEoji2jbDwN/zIIX8/syQbPYtuzE2wFg2W
+HYMfRsCbvUOZ58SWLs5fyQ==
+-----END CERTIFICATE-----
+
+TrustAsia Global Root CA G3
+===========================
+-----BEGIN CERTIFICATE-----
+MIIFpTCCA42gAwIBAgIUZPYOZXdhaqs7tOqFhLuxibhxkw8wDQYJKoZIhvcNAQEMBQAwWjELMAkG
+A1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIEluYy4xJDAiBgNVBAMM
+G1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHMzAeFw0yMTA1MjAwMjEwMTlaFw00NjA1MTkwMjEw
+MTlaMFoxCzAJBgNVBAYTAkNOMSUwIwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMu
+MSQwIgYDVQQDDBtUcnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzMwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQDAMYJhkuSUGwoqZdC+BqmHO1ES6nBBruL7dOoKjbmzTNyPtxNST1QY4Sxz
+lZHFZjtqz6xjbYdT8PfxObegQ2OwxANdV6nnRM7EoYNl9lA+sX4WuDqKAtCWHwDNBSHvBm3dIZwZ
+Q0WhxeiAysKtQGIXBsaqvPPW5vxQfmZCHzyLpnl5hkA1nyDvP+uLRx+PjsXUjrYsyUQE49RDdT/V
+P68czH5GX6zfZBCK70bwkPAPLfSIC7Epqq+FqklYqL9joDiR5rPmd2jE+SoZhLsO4fWvieylL1Ag
+dB4SQXMeJNnKziyhWTXAyB1GJ2Faj/lN03J5Zh6fFZAhLf3ti1ZwA0pJPn9pMRJpxx5cynoTi+jm
+9WAPzJMshH/x/Gr8m0ed262IPfN2dTPXS6TIi/n1Q1hPy8gDVI+lhXgEGvNz8teHHUGf59gXzhqc
+D0r83ERoVGjiQTz+LISGNzzNPy+i2+f3VANfWdP3kXjHi3dqFuVJhZBFcnAvkV34PmVACxmZySYg
+WmjBNb9Pp1Hx2BErW+Canig7CjoKH8GB5S7wprlppYiU5msTf9FkPz2ccEblooV7WIQn3MSAPmea
+mseaMQ4w7OYXQJXZRe0Blqq/DPNL0WP3E1jAuPP6Z92bfW1K/zJMtSU7/xxnD4UiWQWRkUF3gdCF
+TIcQcf+eQxuulXUtgQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEDk5PIj
+7zjKsK5Xf/IhMBY027ySMB0GA1UdDgQWBBRA5OTyI+84yrCuV3/yITAWNNu8kjAOBgNVHQ8BAf8E
+BAMCAQYwDQYJKoZIhvcNAQEMBQADggIBACY7UeFNOPMyGLS0XuFlXsSUT9SnYaP4wM8zAQLpw6o1
+D/GUE3d3NZ4tVlFEbuHGLige/9rsR82XRBf34EzC4Xx8MnpmyFq2XFNFV1pF1AWZLy4jVe5jaN/T
+G3inEpQGAHUNcoTpLrxaatXeL1nHo+zSh2bbt1S1JKv0Q3jbSwTEb93mPmY+KfJLaHEih6D4sTNj
+duMNhXJEIlU/HHzp/LgV6FL6qj6jITk1dImmasI5+njPtqzn59ZW/yOSLlALqbUHM/Q4X6RJpstl
+cHboCoWASzY9M/eVVHUl2qzEc4Jl6VL1XP04lQJqaTDFHApXB64ipCz5xUG3uOyfT0gA+QEEVcys
++TIxxHWVBqB/0Y0n3bOppHKH/lmLmnp0Ft0WpWIp6zqW3IunaFnT63eROfjXy9mPX1onAX1daBli
+2MjN9LdyR75bl87yraKZk62Uy5P2EgmVtqvXO9A/EcswFi55gORngS1d7XB4tmBZrOFdRWOPyN9y
+aFvqHbgB8X7754qz41SgOAngPN5C8sLtLpvzHzW2NtjjgKGLzZlkD8Kqq7HK9W+eQ42EVJmzbsAS
+ZthwEPEGNTNDqJwuuhQxzhB/HIbjj9LV+Hfsm6vxL2PZQl/gZ4FkkfGXL/xuJvYz+NO1+MRiqzFR
+JQJ6+N1rZdVtTTDIZbpoFGWsJwt0ivKH
+-----END CERTIFICATE-----
+
+TrustAsia Global Root CA G4
+===========================
+-----BEGIN CERTIFICATE-----
+MIICVTCCAdygAwIBAgIUTyNkuI6XY57GU4HBdk7LKnQV1tcwCgYIKoZIzj0EAwMwWjELMAkGA1UE
+BhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIEluYy4xJDAiBgNVBAMMG1Ry
+dXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHNDAeFw0yMTA1MjAwMjEwMjJaFw00NjA1MTkwMjEwMjJa
+MFoxCzAJBgNVBAYTAkNOMSUwIwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQw
+IgYDVQQDDBtUcnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi
+AATxs8045CVD5d4ZCbuBeaIVXxVjAd7Cq92zphtnS4CDr5nLrBfbK5bKfFJV4hrhPVbwLxYI+hW8
+m7tH5j/uqOFMjPXTNvk4XatwmkcN4oFBButJ+bAp3TPsUKV/eSm4IJijYzBhMA8GA1UdEwEB/wQF
+MAMBAf8wHwYDVR0jBBgwFoAUpbtKl86zK3+kMd6Xg1mDpm9xy94wHQYDVR0OBBYEFKW7SpfOsyt/
+pDHel4NZg6ZvccveMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjBe8usGzEkxn0AA
+bbd+NvBNEU/zy4k6LHiRUKNbwMp1JvK/kF0LgoxgKJ/GcJpo5PECMFxYDlZ2z1jD1xCMuo6u47xk
+dUfFVZDj/bpV6wfEU6s3qe4hsiFbYI89MvHVI5TWWA==
+-----END CERTIFICATE-----
+
+CommScope Public Trust ECC Root-01
+==================================
+-----BEGIN CERTIFICATE-----
+MIICHTCCAaOgAwIBAgIUQ3CCd89NXTTxyq4yLzf39H91oJ4wCgYIKoZIzj0EAwMwTjELMAkGA1UE
+BhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBUcnVz
+dCBFQ0MgUm9vdC0wMTAeFw0yMTA0MjgxNzM1NDNaFw00NjA0MjgxNzM1NDJaME4xCzAJBgNVBAYT
+AlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3Qg
+RUNDIFJvb3QtMDEwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARLNumuV16ocNfQj3Rid8NeeqrltqLx
+eP0CflfdkXmcbLlSiFS8LwS+uM32ENEp7LXQoMPwiXAZu1FlxUOcw5tjnSCDPgYLpkJEhRGnSjot
+6dZoL0hOUysHP029uax3OVejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
+A1UdDgQWBBSOB2LAUN3GGQYARnQE9/OufXVNMDAKBggqhkjOPQQDAwNoADBlAjEAnDPfQeMjqEI2
+Jpc1XHvr20v4qotzVRVcrHgpD7oh2MSg2NED3W3ROT3Ek2DS43KyAjB8xX6I01D1HiXo+k515liW
+pDVfG2XqYZpwI7UNo5uSUm9poIyNStDuiw7LR47QjRE=
+-----END CERTIFICATE-----
+
+CommScope Public Trust ECC Root-02
+==================================
+-----BEGIN CERTIFICATE-----
+MIICHDCCAaOgAwIBAgIUKP2ZYEFHpgE6yhR7H+/5aAiDXX0wCgYIKoZIzj0EAwMwTjELMAkGA1UE
+BhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBUcnVz
+dCBFQ0MgUm9vdC0wMjAeFw0yMTA0MjgxNzQ0NTRaFw00NjA0MjgxNzQ0NTNaME4xCzAJBgNVBAYT
+AlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3Qg
+RUNDIFJvb3QtMDIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAR4MIHoYx7l63FRD/cHB8o5mXxO1Q/M
+MDALj2aTPs+9xYa9+bG3tD60B8jzljHz7aRP+KNOjSkVWLjVb3/ubCK1sK9IRQq9qEmUv4RDsNuE
+SgMjGWdqb8FuvAY5N9GIIvejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
+A1UdDgQWBBTmGHX/72DehKT1RsfeSlXjMjZ59TAKBggqhkjOPQQDAwNnADBkAjAmc0l6tqvmSfR9
+Uj/UQQSugEODZXW5hYA4O9Zv5JOGq4/nich/m35rChJVYaoR4HkCMHfoMXGsPHED1oQmHhS48zs7
+3u1Z/GtMMH9ZzkXpc2AVmkzw5l4lIhVtwodZ0LKOag==
+-----END CERTIFICATE-----
+
+CommScope Public Trust RSA Root-01
+==================================
+-----BEGIN CERTIFICATE-----
+MIIFbDCCA1SgAwIBAgIUPgNJgXUWdDGOTKvVxZAplsU5EN0wDQYJKoZIhvcNAQELBQAwTjELMAkG
+A1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBU
+cnVzdCBSU0EgUm9vdC0wMTAeFw0yMTA0MjgxNjQ1NTRaFw00NjA0MjgxNjQ1NTNaME4xCzAJBgNV
+BAYTAlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1
+c3QgUlNBIFJvb3QtMDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwSGWjDR1C45Ft
+nYSkYZYSwu3D2iM0GXb26v1VWvZVAVMP8syMl0+5UMuzAURWlv2bKOx7dAvnQmtVzslhsuitQDy6
+uUEKBU8bJoWPQ7VAtYXR1HHcg0Hz9kXHgKKEUJdGzqAMxGBWBB0HW0alDrJLpA6lfO741GIDuZNq
+ihS4cPgugkY4Iw50x2tBt9Apo52AsH53k2NC+zSDO3OjWiE260f6GBfZumbCk6SP/F2krfxQapWs
+vCQz0b2If4b19bJzKo98rwjyGpg/qYFlP8GMicWWMJoKz/TUyDTtnS+8jTiGU+6Xn6myY5QXjQ/c
+Zip8UlF1y5mO6D1cv547KI2DAg+pn3LiLCuz3GaXAEDQpFSOm117RTYm1nJD68/A6g3czhLmfTif
+BSeolz7pUcZsBSjBAg/pGG3svZwG1KdJ9FQFa2ww8esD1eo9anbCyxooSU1/ZOD6K9pzg4H/kQO9
+lLvkuI6cMmPNn7togbGEW682v3fuHX/3SZtS7NJ3Wn2RnU3COS3kuoL4b/JOHg9O5j9ZpSPcPYeo
+KFgo0fEbNttPxP/hjFtyjMcmAyejOQoBqsCyMWCDIqFPEgkBEa801M/XrmLTBQe0MXXgDW1XT2mH
++VepuhX2yFJtocucH+X8eKg1mp9BFM6ltM6UCBwJrVbl2rZJmkrqYxhTnCwuwwIDAQABo0IwQDAP
+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUN12mmnQywsL5x6YVEFm4
+5P3luG0wDQYJKoZIhvcNAQELBQADggIBAK+nz97/4L1CjU3lIpbfaOp9TSp90K09FlxD533Ahuh6
+NWPxzIHIxgvoLlI1pKZJkGNRrDSsBTtXAOnTYtPZKdVUvhwQkZyybf5Z/Xn36lbQnmhUQo8mUuJM
+3y+Xpi/SB5io82BdS5pYV4jvguX6r2yBS5KPQJqTRlnLX3gWsWc+QgvfKNmwrZggvkN80V4aCRck
+jXtdlemrwWCrWxhkgPut4AZ9HcpZuPN4KWfGVh2vtrV0KnahP/t1MJ+UXjulYPPLXAziDslg+Mkf
+Foom3ecnf+slpoq9uC02EJqxWE2aaE9gVOX2RhOOiKy8IUISrcZKiX2bwdgt6ZYD9KJ0DLwAHb/W
+NyVntHKLr4W96ioDj8z7PEQkguIBpQtZtjSNMgsSDesnwv1B10A8ckYpwIzqug/xBpMu95yo9GA+
+o/E4Xo4TwbM6l4c/ksp4qRyv0LAbJh6+cOx69TOY6lz/KwsETkPdY34Op054A5U+1C0wlREQKC6/
+oAI+/15Z0wUOlV9TRe9rh9VIzRamloPh37MG88EU26fsHItdkJANclHnYfkUyq+Dj7+vsQpZXdxc
+1+SWrVtgHdqul7I52Qb1dgAT+GhMIbA1xNxVssnBQVocicCMb3SgazNNtQEo/a2tiRc7ppqEvOuM
+6sRxJKi6KfkIsidWNTJf6jn7MZrVGczw
+-----END CERTIFICATE-----
+
+CommScope Public Trust RSA Root-02
+==================================
+-----BEGIN CERTIFICATE-----
+MIIFbDCCA1SgAwIBAgIUVBa/O345lXGN0aoApYYNK496BU4wDQYJKoZIhvcNAQELBQAwTjELMAkG
+A1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBU
+cnVzdCBSU0EgUm9vdC0wMjAeFw0yMTA0MjgxNzE2NDNaFw00NjA0MjgxNzE2NDJaME4xCzAJBgNV
+BAYTAlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1
+c3QgUlNBIFJvb3QtMDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDh+g77aAASyE3V
+rCLENQE7xVTlWXZjpX/rwcRqmL0yjReA61260WI9JSMZNRTpf4mnG2I81lDnNJUDMrG0kyI9p+Kx
+7eZ7Ti6Hmw0zdQreqjXnfuU2mKKuJZ6VszKWpCtYHu8//mI0SFHRtI1CrWDaSWqVcN3SAOLMV2MC
+e5bdSZdbkk6V0/nLKR8YSvgBKtJjCW4k6YnS5cciTNxzhkcAqg2Ijq6FfUrpuzNPDlJwnZXjfG2W
+Wy09X6GDRl224yW4fKcZgBzqZUPckXk2LHR88mcGyYnJ27/aaL8j7dxrrSiDeS/sOKUNNwFnJ5rp
+M9kzXzehxfCrPfp4sOcsn/Y+n2Dg70jpkEUeBVF4GiwSLFworA2iI540jwXmojPOEXcT1A6kHkIf
+hs1w/tkuFT0du7jyU1fbzMZ0KZwYszZ1OC4PVKH4kh+Jlk+71O6d6Ts2QrUKOyrUZHk2EOH5kQMr
+eyBUzQ0ZGshBMjTRsJnhkB4BQDa1t/qp5Xd1pCKBXbCL5CcSD1SIxtuFdOa3wNemKfrb3vOTlycE
+VS8KbzfFPROvCgCpLIscgSjX74Yxqa7ybrjKaixUR9gqiC6vwQcQeKwRoi9C8DfF8rhW3Q5iLc4t
+Vn5V8qdE9isy9COoR+jUKgF4z2rDN6ieZdIs5fq6M8EGRPbmz6UNp2YINIos8wIDAQABo0IwQDAP
+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUR9DnsSL/nSz12Vdgs7Gx
+cJXvYXowDQYJKoZIhvcNAQELBQADggIBAIZpsU0v6Z9PIpNojuQhmaPORVMbc0RTAIFhzTHjCLqB
+KCh6krm2qMhDnscTJk3C2OVVnJJdUNjCK9v+5qiXz1I6JMNlZFxHMaNlNRPDk7n3+VGXu6TwYofF
+1gbTl4MgqX67tiHCpQ2EAOHyJxCDut0DgdXdaMNmEMjRdrSzbymeAPnCKfWxkxlSaRosTKCL4BWa
+MS/TiJVZbuXEs1DIFAhKm4sTg7GkcrI7djNB3NyqpgdvHSQSn8h2vS/ZjvQs7rfSOBAkNlEv41xd
+gSGn2rtO/+YHqP65DSdsu3BaVXoT6fEqSWnHX4dXTEN5bTpl6TBcQe7rd6VzEojov32u5cSoHw2O
+HG1QAk8mGEPej1WFsQs3BWDJVTkSBKEqz3EWnzZRSb9wO55nnPt7eck5HHisd5FUmrh1CoFSl+Nm
+YWvtPjgelmFV4ZFUjO2MJB+ByRCac5krFk5yAD9UG/iNuovnFNa2RU9g7Jauwy8CTl2dlklyALKr
+dVwPaFsdZcJfMw8eD/A7hvWwTruc9+olBdytoptLFwG+Qt81IR2tq670v64fG9PiO/yzcnMcmyiQ
+iRM9HcEARwmWmjgb3bHPDcK0RPOWlc4yOo80nOAXx17Org3bhzjlP1v9mxnhMUF6cKojawHhRUzN
+lM47ni3niAIi9G7oyOzWPPO5std3eqx7
+-----END CERTIFICATE-----
+
+Telekom Security TLS ECC Root 2020
+==================================
+-----BEGIN CERTIFICATE-----
+MIICQjCCAcmgAwIBAgIQNjqWjMlcsljN0AFdxeVXADAKBggqhkjOPQQDAzBjMQswCQYDVQQGEwJE
+RTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBHbWJIMSswKQYDVQQDDCJUZWxl
+a29tIFNlY3VyaXR5IFRMUyBFQ0MgUm9vdCAyMDIwMB4XDTIwMDgyNTA3NDgyMFoXDTQ1MDgyNTIz
+NTk1OVowYzELMAkGA1UEBhMCREUxJzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkg
+R21iSDErMCkGA1UEAwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgRUNDIFJvb3QgMjAyMDB2MBAGByqG
+SM49AgEGBSuBBAAiA2IABM6//leov9Wq9xCazbzREaK9Z0LMkOsVGJDZos0MKiXrPk/OtdKPD/M1
+2kOLAoC+b1EkHQ9rK8qfwm9QMuU3ILYg/4gND21Ju9sGpIeQkpT0CdDPf8iAC8GXs7s1J8nCG6NC
+MEAwHQYDVR0OBBYEFONyzG6VmUex5rNhTNHLq+O6zd6fMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
+AQH/BAQDAgEGMAoGCCqGSM49BAMDA2cAMGQCMHVSi7ekEE+uShCLsoRbQuHmKjYC2qBuGT8lv9pZ
+Mo7k+5Dck2TOrbRBR2Diz6fLHgIwN0GMZt9Ba9aDAEH9L1r3ULRn0SyocddDypwnJJGDSA3PzfdU
+ga/sf+Rn27iQ7t0l
+-----END CERTIFICATE-----
+
+Telekom Security TLS RSA Root 2023
+==================================
+-----BEGIN CERTIFICATE-----
+MIIFszCCA5ugAwIBAgIQIZxULej27HF3+k7ow3BXlzANBgkqhkiG9w0BAQwFADBjMQswCQYDVQQG
+EwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBHbWJIMSswKQYDVQQDDCJU
+ZWxla29tIFNlY3VyaXR5IFRMUyBSU0EgUm9vdCAyMDIzMB4XDTIzMDMyODEyMTY0NVoXDTQ4MDMy
+NzIzNTk1OVowYzELMAkGA1UEBhMCREUxJzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJp
+dHkgR21iSDErMCkGA1UEAwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgUlNBIFJvb3QgMjAyMzCCAiIw
+DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAO01oYGA88tKaVvC+1GDrib94W7zgRJ9cUD/h3VC
+KSHtgVIs3xLBGYSJwb3FKNXVS2xE1kzbB5ZKVXrKNoIENqil/Cf2SfHVcp6R+SPWcHu79ZvB7JPP
+GeplfohwoHP89v+1VmLhc2o0mD6CuKyVU/QBoCcHcqMAU6DksquDOFczJZSfvkgdmOGjup5czQRx
+UX11eKvzWarE4GC+j4NSuHUaQTXtvPM6Y+mpFEXX5lLRbtLevOP1Czvm4MS9Q2QTps70mDdsipWo
+l8hHD/BeEIvnHRz+sTugBTNoBUGCwQMrAcjnj02r6LX2zWtEtefdi+zqJbQAIldNsLGyMcEWzv/9
+FIS3R/qy8XDe24tsNlikfLMR0cN3f1+2JeANxdKz+bi4d9s3cXFH42AYTyS2dTd4uaNir73Jco4v
+zLuu2+QVUhkHM/tqty1LkCiCc/4YizWN26cEar7qwU02OxY2kTLvtkCJkUPg8qKrBC7m8kwOFjQg
+rIfBLX7JZkcXFBGk8/ehJImr2BrIoVyxo/eMbcgByU/J7MT8rFEz0ciD0cmfHdRHNCk+y7AO+oML
+KFjlKdw/fKifybYKu6boRhYPluV75Gp6SG12mAWl3G0eQh5C2hrgUve1g8Aae3g1LDj1H/1Joy7S
+WWO/gLCMk3PLNaaZlSJhZQNg+y+TS/qanIA7AgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAdBgNV
+HQ4EFgQUtqeXgj10hZv3PJ+TmpV5dVKMbUcwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS2
+p5eCPXSFm/c8n5OalXl1UoxtRzANBgkqhkiG9w0BAQwFAAOCAgEAqMxhpr51nhVQpGv7qHBFfLp+
+sVr8WyP6Cnf4mHGCDG3gXkaqk/QeoMPhk9tLrbKmXauw1GLLXrtm9S3ul0A8Yute1hTWjOKWi0Fp
+kzXmuZlrYrShF2Y0pmtjxrlO8iLpWA1WQdH6DErwM807u20hOq6OcrXDSvvpfeWxm4bu4uB9tPcy
+/SKE8YXJN3nptT+/XOR0so8RYgDdGGah2XsjX/GO1WfoVNpbOms2b/mBsTNHM3dA+VKq3dSDz4V4
+mZqTuXNnQkYRIer+CqkbGmVps4+uFrb2S1ayLfmlyOw7YqPta9BO1UAJpB+Y1zqlklkg5LB9zVtz
+aL1txKITDmcZuI1CfmwMmm6gJC3VRRvcxAIU/oVbZZfKTpBQCHpCNfnqwmbU+AGuHrS+w6jv/naa
+oqYfRvaE7fzbzsQCzndILIyy7MMAo+wsVRjBfhnu4S/yrYObnqsZ38aKL4x35bcF7DvB7L6Gs4a8
+wPfc5+pbrrLMtTWGS9DiP7bY+A4A7l3j941Y/8+LN+ljX273CXE2whJdV/LItM3z7gLfEdxquVeE
+HVlNjM7IDiPCtyaaEBRx/pOyiriA8A4QntOoUAw3gi/q4Iqd4Sw5/7W0cwDk90imc6y/st53BIe0
+o82bNSQ3+pCTE4FCxpgmdTdmQRCsu/WU48IxK63nI1bMNSWSs1A=
+-----END CERTIFICATE-----
diff --git a/system/vendor/composer/ca-bundle/src/CaBundle.php b/system/vendor/composer/ca-bundle/src/CaBundle.php
new file mode 100644
index 0000000..f6f2afe
--- /dev/null
+++ b/system/vendor/composer/ca-bundle/src/CaBundle.php
@@ -0,0 +1,325 @@
+
+ *
+ * For the full copyright and license information, please view
+ * the LICENSE file that was distributed with this source code.
+ */
+
+namespace Composer\CaBundle;
+
+use Psr\Log\LoggerInterface;
+use Symfony\Component\Process\PhpProcess;
+
+/**
+ * @author Chris Smith
+ * @author Jordi Boggiano
+ */
+class CaBundle
+{
+ /** @var string|null */
+ private static $caPath;
+ /** @var array */
+ private static $caFileValidity = array();
+
+ /**
+ * Returns the system CA bundle path, or a path to the bundled one
+ *
+ * This method was adapted from Sslurp.
+ * https://github.com/EvanDotPro/Sslurp
+ *
+ * (c) Evan Coury
+ *
+ * For the full copyright and license information, please see below:
+ *
+ * Copyright (c) 2013, Evan Coury
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * * 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.
+ *
+ * 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 OWNER 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.
+ *
+ * @param LoggerInterface $logger optional logger for information about which CA files were loaded
+ * @return string path to a CA bundle file or directory
+ */
+ public static function getSystemCaRootBundlePath(?LoggerInterface $logger = null)
+ {
+ if (self::$caPath !== null) {
+ return self::$caPath;
+ }
+ $caBundlePaths = array();
+
+ // If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that.
+ // This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
+ $caBundlePaths[] = self::getEnvVariable('SSL_CERT_FILE');
+
+ // If SSL_CERT_DIR env variable points to a valid certificate/bundle, use that.
+ // This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
+ $caBundlePaths[] = self::getEnvVariable('SSL_CERT_DIR');
+
+ $caBundlePaths[] = ini_get('openssl.cafile');
+ $caBundlePaths[] = ini_get('openssl.capath');
+
+ $otherLocations = array(
+ '/etc/pki/tls/certs/ca-bundle.crt', // Fedora, RHEL, CentOS (ca-certificates package)
+ '/etc/ssl/certs/ca-certificates.crt', // Debian, Ubuntu, Gentoo, Arch Linux (ca-certificates package)
+ '/etc/ssl/ca-bundle.pem', // SUSE, openSUSE (ca-certificates package)
+ '/usr/local/share/certs/ca-root-nss.crt', // FreeBSD (ca_root_nss_package)
+ '/usr/ssl/certs/ca-bundle.crt', // Cygwin
+ '/opt/local/share/curl/curl-ca-bundle.crt', // OS X macports, curl-ca-bundle package
+ '/usr/local/share/curl/curl-ca-bundle.crt', // Default cURL CA bunde path (without --with-ca-bundle option)
+ '/usr/share/ssl/certs/ca-bundle.crt', // Really old RedHat?
+ '/etc/ssl/cert.pem', // OpenBSD
+ '/usr/local/etc/ssl/cert.pem', // FreeBSD 10.x
+ '/usr/local/etc/openssl/cert.pem', // OS X homebrew, openssl package
+ '/usr/local/etc/openssl@1.1/cert.pem', // OS X homebrew, openssl@1.1 package
+ '/opt/homebrew/etc/openssl@3/cert.pem', // macOS silicon homebrew, openssl@3 package
+ '/opt/homebrew/etc/openssl@1.1/cert.pem', // macOS silicon homebrew, openssl@1.1 package
+ );
+
+ foreach($otherLocations as $location) {
+ $otherLocations[] = dirname($location);
+ }
+
+ $caBundlePaths = array_merge($caBundlePaths, $otherLocations);
+
+ foreach ($caBundlePaths as $caBundle) {
+ if ($caBundle && self::caFileUsable($caBundle, $logger)) {
+ return self::$caPath = $caBundle;
+ }
+
+ if ($caBundle && self::caDirUsable($caBundle, $logger)) {
+ return self::$caPath = $caBundle;
+ }
+ }
+
+ return self::$caPath = static::getBundledCaBundlePath(); // Bundled CA file, last resort
+ }
+
+ /**
+ * Returns the path to the bundled CA file
+ *
+ * In case you don't want to trust the user or the system, you can use this directly
+ *
+ * @return string path to a CA bundle file
+ */
+ public static function getBundledCaBundlePath()
+ {
+ $caBundleFile = __DIR__.'/../res/cacert.pem';
+
+ // cURL does not understand 'phar://' paths
+ // see https://github.com/composer/ca-bundle/issues/10
+ if (0 === strpos($caBundleFile, 'phar://')) {
+ $tempCaBundleFile = tempnam(sys_get_temp_dir(), 'openssl-ca-bundle-');
+ if (false === $tempCaBundleFile) {
+ throw new \RuntimeException('Could not create a temporary file to store the bundled CA file');
+ }
+
+ file_put_contents(
+ $tempCaBundleFile,
+ file_get_contents($caBundleFile)
+ );
+
+ register_shutdown_function(function() use ($tempCaBundleFile) {
+ @unlink($tempCaBundleFile);
+ });
+
+ $caBundleFile = $tempCaBundleFile;
+ }
+
+ return $caBundleFile;
+ }
+
+ /**
+ * Validates a CA file using opensl_x509_parse only if it is safe to use
+ *
+ * @param string $filename
+ * @param LoggerInterface $logger optional logger for information about which CA files were loaded
+ *
+ * @return bool
+ */
+ public static function validateCaFile($filename, ?LoggerInterface $logger = null)
+ {
+ static $warned = false;
+
+ if (isset(self::$caFileValidity[$filename])) {
+ return self::$caFileValidity[$filename];
+ }
+
+ $contents = file_get_contents($filename);
+
+ if (is_string($contents) && strlen($contents) > 0) {
+ $contents = preg_replace("/^(\\-+(?:BEGIN|END))\\s+TRUSTED\\s+(CERTIFICATE\\-+)\$/m", '$1 $2', $contents);
+ if (null === $contents) {
+ // regex extraction failed
+ $isValid = false;
+ } else {
+ $isValid = (bool) openssl_x509_parse($contents);
+ }
+ } else {
+ $isValid = false;
+ }
+
+ if ($logger) {
+ $logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid'));
+ }
+
+ return self::$caFileValidity[$filename] = $isValid;
+ }
+
+ /**
+ * Test if it is safe to use the PHP function openssl_x509_parse().
+ *
+ * This checks if OpenSSL extensions is vulnerable to remote code execution
+ * via the exploit documented as CVE-2013-6420.
+ *
+ * @return bool
+ */
+ public static function isOpensslParseSafe()
+ {
+ return true;
+ }
+
+ /**
+ * Resets the static caches
+ * @return void
+ */
+ public static function reset()
+ {
+ self::$caFileValidity = array();
+ self::$caPath = null;
+ }
+
+ /**
+ * @param string $name
+ * @return string|false
+ */
+ private static function getEnvVariable($name)
+ {
+ if (isset($_SERVER[$name])) {
+ return (string) $_SERVER[$name];
+ }
+
+ if (PHP_SAPI === 'cli' && ($value = getenv($name)) !== false && $value !== null) {
+ return (string) $value;
+ }
+
+ return false;
+ }
+
+ /**
+ * @param string|false $certFile
+ * @param LoggerInterface|null $logger
+ * @return bool
+ */
+ private static function caFileUsable($certFile, ?LoggerInterface $logger = null)
+ {
+ return $certFile
+ && self::isFile($certFile, $logger)
+ && self::isReadable($certFile, $logger)
+ && self::validateCaFile($certFile, $logger);
+ }
+
+ /**
+ * @param string|false $certDir
+ * @param LoggerInterface|null $logger
+ * @return bool
+ */
+ private static function caDirUsable($certDir, ?LoggerInterface $logger = null)
+ {
+ return $certDir
+ && self::isDir($certDir, $logger)
+ && self::isReadable($certDir, $logger)
+ && self::glob($certDir . '/*', $logger);
+ }
+
+ /**
+ * @param string $certFile
+ * @param LoggerInterface|null $logger
+ * @return bool
+ */
+ private static function isFile($certFile, ?LoggerInterface $logger = null)
+ {
+ $isFile = @is_file($certFile);
+ if (!$isFile && $logger) {
+ $logger->debug(sprintf('Checked CA file %s does not exist or it is not a file.', $certFile));
+ }
+
+ return $isFile;
+ }
+
+ /**
+ * @param string $certDir
+ * @param LoggerInterface|null $logger
+ * @return bool
+ */
+ private static function isDir($certDir, ?LoggerInterface $logger = null)
+ {
+ $isDir = @is_dir($certDir);
+ if (!$isDir && $logger) {
+ $logger->debug(sprintf('Checked directory %s does not exist or it is not a directory.', $certDir));
+ }
+
+ return $isDir;
+ }
+
+ /**
+ * @param string $certFileOrDir
+ * @param LoggerInterface|null $logger
+ * @return bool
+ */
+ private static function isReadable($certFileOrDir, ?LoggerInterface $logger = null)
+ {
+ $isReadable = @is_readable($certFileOrDir);
+ if (!$isReadable && $logger) {
+ $logger->debug(sprintf('Checked file or directory %s is not readable.', $certFileOrDir));
+ }
+
+ return $isReadable;
+ }
+
+ /**
+ * @param string $pattern
+ * @param LoggerInterface|null $logger
+ * @return bool
+ */
+ private static function glob($pattern, ?LoggerInterface $logger = null)
+ {
+ $certs = glob($pattern);
+ if ($certs === false) {
+ if ($logger) {
+ $logger->debug(sprintf("An error occurred while trying to find certificates for pattern: %s", $pattern));
+ }
+ return false;
+ }
+
+ if (count($certs) === 0) {
+ if ($logger) {
+ $logger->debug(sprintf("No CA files found for pattern: %s", $pattern));
+ }
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/system/vendor/composer/installed.json b/system/vendor/composer/installed.json
index 7bc9df3..584f5a3 100644
--- a/system/vendor/composer/installed.json
+++ b/system/vendor/composer/installed.json
@@ -1,249 +1,734 @@
-[
- {
- "name": "ircmaxell/password-compat",
- "version": "v1.0.4",
- "version_normalized": "1.0.4.0",
- "source": {
- "type": "git",
- "url": "https://github.com/ircmaxell/password_compat.git",
- "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/5c5cde8822a69545767f7c7f3058cb15ff84614c",
- "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c",
- "shasum": ""
- },
- "require-dev": {
- "phpunit/phpunit": "4.*"
- },
- "time": "2014-11-20T16:49:30+00:00",
- "type": "library",
- "installation-source": "dist",
- "autoload": {
- "files": [
- "lib/password.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
+{
+ "packages": [
+ {
+ "name": "bacon/bacon-qr-code",
+ "version": "v3.0.0",
+ "version_normalized": "3.0.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Bacon/BaconQrCode.git",
+ "reference": "510de6eca6248d77d31b339d62437cc995e2fb41"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/510de6eca6248d77d31b339d62437cc995e2fb41",
+ "reference": "510de6eca6248d77d31b339d62437cc995e2fb41",
+ "shasum": ""
+ },
+ "require": {
+ "dasprid/enum": "^1.0.3",
+ "ext-iconv": "*",
+ "php": "^8.1"
+ },
+ "require-dev": {
+ "phly/keep-a-changelog": "^2.12",
+ "phpunit/phpunit": "^10.5.11 || 11.0.4",
+ "spatie/phpunit-snapshot-assertions": "^5.1.5",
+ "squizlabs/php_codesniffer": "^3.9"
+ },
+ "suggest": {
+ "ext-imagick": "to generate QR code images"
+ },
+ "time": "2024-04-18T11:16:25+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "BaconQrCode\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-2-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Ben Scholzen 'DASPRiD'",
+ "email": "mail@dasprids.de",
+ "homepage": "https://dasprids.de/",
+ "role": "Developer"
+ }
+ ],
+ "description": "BaconQrCode is a QR code generator for PHP.",
+ "homepage": "https://github.com/Bacon/BaconQrCode",
+ "support": {
+ "issues": "https://github.com/Bacon/BaconQrCode/issues",
+ "source": "https://github.com/Bacon/BaconQrCode/tree/v3.0.0"
+ },
+ "install-path": "../bacon/bacon-qr-code"
+ },
+ {
+ "name": "composer/ca-bundle",
+ "version": "1.5.0",
+ "version_normalized": "1.5.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/ca-bundle.git",
+ "reference": "0c5ccfcfea312b5c5a190a21ac5cef93f74baf99"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/ca-bundle/zipball/0c5ccfcfea312b5c5a190a21ac5cef93f74baf99",
+ "reference": "0c5ccfcfea312b5c5a190a21ac5cef93f74baf99",
+ "shasum": ""
+ },
+ "require": {
+ "ext-openssl": "*",
+ "ext-pcre": "*",
+ "php": "^7.2 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.10",
+ "psr/log": "^1.0",
+ "symfony/phpunit-bridge": "^4.2 || ^5",
+ "symfony/process": "^4.0 || ^5.0 || ^6.0 || ^7.0"
+ },
+ "time": "2024-03-15T14:00:32+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Composer\\CaBundle\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
+ "keywords": [
+ "cabundle",
+ "cacert",
+ "certificate",
+ "ssl",
+ "tls"
+ ],
+ "support": {
+ "irc": "irc://irc.freenode.org/composer",
+ "issues": "https://github.com/composer/ca-bundle/issues",
+ "source": "https://github.com/composer/ca-bundle/tree/1.5.0"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "install-path": "./ca-bundle"
+ },
+ {
+ "name": "dasprid/enum",
+ "version": "1.0.5",
+ "version_normalized": "1.0.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/DASPRiD/Enum.git",
+ "reference": "6faf451159fb8ba4126b925ed2d78acfce0dc016"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/6faf451159fb8ba4126b925ed2d78acfce0dc016",
+ "reference": "6faf451159fb8ba4126b925ed2d78acfce0dc016",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1 <9.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7 | ^8 | ^9",
+ "squizlabs/php_codesniffer": "*"
+ },
+ "time": "2023-08-25T16:18:39+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "DASPRiD\\Enum\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-2-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Ben Scholzen 'DASPRiD'",
+ "email": "mail@dasprids.de",
+ "homepage": "https://dasprids.de/",
+ "role": "Developer"
+ }
+ ],
+ "description": "PHP 7.1 enum implementation",
+ "keywords": [
+ "enum",
+ "map"
+ ],
+ "support": {
+ "issues": "https://github.com/DASPRiD/Enum/issues",
+ "source": "https://github.com/DASPRiD/Enum/tree/1.0.5"
+ },
+ "install-path": "../dasprid/enum"
+ },
+ {
+ "name": "ircmaxell/password-compat",
+ "version": "v1.0.4",
+ "version_normalized": "1.0.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ircmaxell/password_compat.git",
+ "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/5c5cde8822a69545767f7c7f3058cb15ff84614c",
+ "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c",
+ "shasum": ""
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*"
+ },
+ "time": "2014-11-20T16:49:30+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "files": [
+ "lib/password.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Anthony Ferrara",
+ "email": "ircmaxell@php.net",
+ "homepage": "http://blog.ircmaxell.com"
+ }
+ ],
+ "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash",
+ "homepage": "https://github.com/ircmaxell/password_compat",
+ "keywords": [
+ "hashing",
+ "password"
+ ],
+ "install-path": "../ircmaxell/password-compat"
+ },
+ {
+ "name": "jbroadway/urlify",
+ "version": "1.2.4-stable",
+ "version_normalized": "1.2.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/jbroadway/urlify.git",
+ "reference": "d0fafbaa1dc14e8039cdf5c72a932a8d1de1750e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/jbroadway/urlify/zipball/d0fafbaa1dc14e8039cdf5c72a932a8d1de1750e",
+ "reference": "d0fafbaa1dc14e8039cdf5c72a932a8d1de1750e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2",
+ "voku/portable-ascii": "^2.0",
+ "voku/stop-words": "^2.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^8.5"
+ },
+ "time": "2022-06-15T16:46:46+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-0": {
+ "URLify": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause-Clear"
+ ],
+ "authors": [
+ {
+ "name": "Johnny Broadway",
+ "email": "johnny@johnnybroadway.com",
+ "homepage": "http://www.johnnybroadway.com/"
+ }
+ ],
+ "description": "A fast PHP slug generator and transliteration library that converts non-ascii characters for use in URLs.",
+ "homepage": "https://github.com/jbroadway/urlify",
+ "keywords": [
+ "ascii",
+ "blogging",
+ "blogs",
+ "downcode",
+ "encode",
+ "iconv",
+ "link",
+ "seo",
+ "slug",
+ "slugify",
+ "slugs",
+ "translit",
+ "transliterate",
+ "transliteration",
+ "unicode",
+ "url",
+ "urlify"
+ ],
+ "support": {
+ "issues": "https://github.com/jbroadway/urlify/issues",
+ "source": "https://github.com/jbroadway/urlify/tree/1.2.4-stable"
+ },
+ "install-path": "../jbroadway/urlify"
+ },
+ {
+ "name": "kanti/hub-updater",
+ "version": "v0.5.1",
+ "version_normalized": "0.5.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Kanti/hub-updater.git",
+ "reference": "014b33c1e3880bd8e037a960a89e7116eb08a26e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Kanti/hub-updater/zipball/014b33c1e3880bd8e037a960a89e7116eb08a26e",
+ "reference": "014b33c1e3880bd8e037a960a89e7116eb08a26e",
+ "shasum": ""
+ },
+ "require": {
+ "composer/ca-bundle": "^1.0",
+ "php": ">=5.3.6"
+ },
+ "require-dev": {
+ "codeclimate/php-test-reporter": "0.*",
+ "friendsofphp/php-cs-fixer": "1.*",
+ "phpro/grumphp": "0.*",
+ "phpunit/phpunit": "4.*",
+ "sebastian/phpcpd": "2.*",
+ "squizlabs/php_codesniffer": "2.*"
+ },
+ "time": "2016-08-02T19:12:55+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Kanti\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "GPL-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Kanti",
+ "email": "git@kanti.de",
+ "homepage": "https://kanti.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "Simple Github Updater for Web Projects",
+ "support": {
+ "forum": "https://github.com/Kanti/hub-updater/issues",
+ "issues": "https://github.com/Kanti/hub-updater/issues",
+ "source": "https://github.com/Kanti/hub-updater"
+ },
+ "abandoned": true,
+ "install-path": "../kanti/hub-updater"
+ },
+ {
+ "name": "michelf/php-markdown",
+ "version": "1.9.1",
+ "version_normalized": "1.9.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/michelf/php-markdown.git",
+ "reference": "5024d623c1a057dcd2d076d25b7d270a1d0d55f3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/michelf/php-markdown/zipball/5024d623c1a057dcd2d076d25b7d270a1d0d55f3",
+ "reference": "5024d623c1a057dcd2d076d25b7d270a1d0d55f3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": ">=4.3 <5.8"
+ },
+ "time": "2021-11-24T02:52:38+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Michelf\\": "Michelf/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Michel Fortin",
+ "email": "michel.fortin@michelf.ca",
+ "homepage": "https://michelf.ca/",
+ "role": "Developer"
+ },
+ {
+ "name": "John Gruber",
+ "homepage": "https://daringfireball.net/"
+ }
+ ],
+ "description": "PHP Markdown",
+ "homepage": "https://michelf.ca/projects/php-markdown/",
+ "keywords": [
+ "markdown"
+ ],
+ "support": {
+ "issues": "https://github.com/michelf/php-markdown/issues",
+ "source": "https://github.com/michelf/php-markdown/tree/1.9.1"
+ },
+ "install-path": "../michelf/php-markdown"
+ },
+ {
+ "name": "paragonie/constant_time_encoding",
+ "version": "v2.7.0",
+ "version_normalized": "2.7.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/paragonie/constant_time_encoding.git",
+ "reference": "52a0d99e69f56b9ec27ace92ba56897fe6993105"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/52a0d99e69f56b9ec27ace92ba56897fe6993105",
+ "reference": "52a0d99e69f56b9ec27ace92ba56897fe6993105",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7|^8"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^6|^7|^8|^9",
+ "vimeo/psalm": "^1|^2|^3|^4"
+ },
+ "time": "2024-05-08T12:18:48+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "ParagonIE\\ConstantTime\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Paragon Initiative Enterprises",
+ "email": "security@paragonie.com",
+ "homepage": "https://paragonie.com",
+ "role": "Maintainer"
+ },
+ {
+ "name": "Steve 'Sc00bz' Thomas",
+ "email": "steve@tobtu.com",
+ "homepage": "https://www.tobtu.com",
+ "role": "Original Developer"
+ }
+ ],
+ "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
+ "keywords": [
+ "base16",
+ "base32",
+ "base32_decode",
+ "base32_encode",
+ "base64",
+ "base64_decode",
+ "base64_encode",
+ "bin2hex",
+ "encoding",
+ "hex",
+ "hex2bin",
+ "rfc4648"
+ ],
+ "support": {
+ "email": "info@paragonie.com",
+ "issues": "https://github.com/paragonie/constant_time_encoding/issues",
+ "source": "https://github.com/paragonie/constant_time_encoding"
+ },
+ "install-path": "../paragonie/constant_time_encoding"
+ },
+ {
+ "name": "pragmarx/google2fa",
+ "version": "v8.0.1",
+ "version_normalized": "8.0.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/antonioribeiro/google2fa.git",
+ "reference": "80c3d801b31fe165f8fe99ea085e0a37834e1be3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/antonioribeiro/google2fa/zipball/80c3d801b31fe165f8fe99ea085e0a37834e1be3",
+ "reference": "80c3d801b31fe165f8fe99ea085e0a37834e1be3",
+ "shasum": ""
+ },
+ "require": {
+ "paragonie/constant_time_encoding": "^1.0|^2.0",
+ "php": "^7.1|^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^0.12.18",
+ "phpunit/phpunit": "^7.5.15|^8.5|^9.0"
+ },
+ "time": "2022-06-13T21:57:56+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "PragmaRX\\Google2FA\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Antonio Carlos Ribeiro",
+ "email": "acr@antoniocarlosribeiro.com",
+ "role": "Creator & Designer"
+ }
+ ],
+ "description": "A One Time Password Authentication package, compatible with Google Authenticator.",
+ "keywords": [
+ "2fa",
+ "Authentication",
+ "Two Factor Authentication",
+ "google2fa"
+ ],
+ "support": {
+ "issues": "https://github.com/antonioribeiro/google2fa/issues",
+ "source": "https://github.com/antonioribeiro/google2fa/tree/v8.0.1"
+ },
+ "install-path": "../pragmarx/google2fa"
+ },
+ {
+ "name": "suin/php-rss-writer",
+ "version": "1.6.0",
+ "version_normalized": "1.6.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/suin/php-rss-writer.git",
+ "reference": "78f45e44a2a7cb0d82e4b9efb6f7b7a075b9051c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/suin/php-rss-writer/zipball/78f45e44a2a7cb0d82e4b9efb6f7b7a075b9051c",
+ "reference": "78f45e44a2a7cb0d82e4b9efb6f7b7a075b9051c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "eher/phpunit": ">=1.6",
+ "mockery/mockery": ">=0.7.2",
+ "suin/xoopsunit": ">=1.2"
+ },
+ "time": "2017-07-13T10:47:50+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-0": {
+ "Suin\\RSSWriter": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "suin",
+ "email": "suinyeze@gmail.com"
+ }
+ ],
+ "description": "Yet another simple RSS writer library for PHP 5.4 or later.",
+ "homepage": "https://github.com/suin/php-rss-writer",
+ "keywords": [
+ "feed",
+ "generator",
+ "php",
+ "rss",
+ "writer"
+ ],
+ "support": {
+ "issues": "https://github.com/suin/php-rss-writer/issues",
+ "source": "https://github.com/suin/php-rss-writer/tree/master"
+ },
+ "install-path": "../suin/php-rss-writer"
+ },
+ {
+ "name": "voku/portable-ascii",
+ "version": "2.0.1",
+ "version_normalized": "2.0.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/voku/portable-ascii.git",
+ "reference": "b56450eed252f6801410d810c8e1727224ae0743"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b56450eed252f6801410d810c8e1727224ae0743",
+ "reference": "b56450eed252f6801410d810c8e1727224ae0743",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.0.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0"
+ },
+ "suggest": {
+ "ext-intl": "Use Intl for transliterator_transliterate() support"
+ },
+ "time": "2022-03-08T17:03:00+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "voku\\": "src/voku/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Lars Moelleken",
+ "homepage": "http://www.moelleken.org/"
+ }
+ ],
+ "description": "Portable ASCII library - performance optimized (ascii) string functions for php.",
+ "homepage": "https://github.com/voku/portable-ascii",
+ "keywords": [
+ "ascii",
+ "clean",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/voku/portable-ascii/issues",
+ "source": "https://github.com/voku/portable-ascii/tree/2.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://www.paypal.me/moelleken",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/voku",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/portable-ascii",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://www.patreon.com/voku",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii",
+ "type": "tidelift"
+ }
+ ],
+ "install-path": "../voku/portable-ascii"
+ },
+ {
+ "name": "voku/stop-words",
+ "version": "2.0.1",
+ "version_normalized": "2.0.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/voku/stop-words.git",
+ "reference": "8e63c0af20f800b1600783764e0ce19e53969f71"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/voku/stop-words/zipball/8e63c0af20f800b1600783764e0ce19e53969f71",
+ "reference": "8e63c0af20f800b1600783764e0ce19e53969f71",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.0.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~6.0"
+ },
+ "time": "2018-11-23T01:37:27+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "voku\\": "src/voku/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Lars Moelleken",
+ "homepage": "http://www.moelleken.org/"
+ }
+ ],
+ "description": "Stop-Words via PHP",
+ "keywords": [
+ "stop words",
+ "stop-words"
+ ],
+ "support": {
+ "issues": "https://github.com/voku/stop-words/issues",
+ "source": "https://github.com/voku/stop-words/tree/master"
+ },
+ "install-path": "../voku/stop-words"
+ }
],
- "authors": [
- {
- "name": "Anthony Ferrara",
- "email": "ircmaxell@php.net",
- "homepage": "http://blog.ircmaxell.com"
- }
- ],
- "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash",
- "homepage": "https://github.com/ircmaxell/password_compat",
- "keywords": [
- "hashing",
- "password"
- ]
- },
- {
- "name": "jbroadway/urlify",
- "version": "1.1.3-stable",
- "version_normalized": "1.1.3.0",
- "source": {
- "type": "git",
- "url": "https://github.com/jbroadway/urlify.git",
- "reference": "37fe4e7680a1c8cd68ac43a27dac7ef4be476300"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/jbroadway/urlify/zipball/37fe4e7680a1c8cd68ac43a27dac7ef4be476300",
- "reference": "37fe4e7680a1c8cd68ac43a27dac7ef4be476300",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.0"
- },
- "require-dev": {
- "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5"
- },
- "time": "2019-06-13T18:30:56+00:00",
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0-dev"
- }
- },
- "installation-source": "dist",
- "autoload": {
- "psr-0": {
- "URLify": ""
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause-Clear"
- ],
- "authors": [
- {
- "name": "Johnny Broadway",
- "email": "johnny@johnnybroadway.com",
- "homepage": "http://www.johnnybroadway.com/"
- }
- ],
- "description": "PHP port of URLify.js from the Django project. Transliterates non-ascii characters for use in URLs.",
- "homepage": "https://github.com/jbroadway/urlify",
- "keywords": [
- "encode",
- "iconv",
- "link",
- "slug",
- "translit",
- "transliterate",
- "transliteration",
- "url",
- "urlify"
- ]
- },
- {
- "name": "kanti/hub-updater",
- "version": "v0.4.1",
- "version_normalized": "0.4.1.0",
- "source": {
- "type": "git",
- "url": "https://github.com/Kanti/hub-updater.git",
- "reference": "c9cdc7ce407c2a3596961e2193673303789e084d"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/Kanti/hub-updater/zipball/c9cdc7ce407c2a3596961e2193673303789e084d",
- "reference": "c9cdc7ce407c2a3596961e2193673303789e084d",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.0"
- },
- "require-dev": {
- "codeclimate/php-test-reporter": "dev-master",
- "phpunit/phpunit": "4.*",
- "sebastian/phpcpd": "*",
- "squizlabs/php_codesniffer": "*"
- },
- "time": "2015-11-28T18:52:10+00:00",
- "type": "library",
- "installation-source": "dist",
- "autoload": {
- "psr-4": {
- "Kanti\\": "src"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "GPL-2.0"
- ],
- "authors": [
- {
- "name": "Kanti",
- "email": "git@kanti.de",
- "homepage": "https://kanti.de",
- "role": "Developer"
- }
- ],
- "description": "Simple Github Updater for Web Projects",
- "abandoned": true
- },
- {
- "name": "michelf/php-markdown",
- "version": "1.9.0",
- "version_normalized": "1.9.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/michelf/php-markdown.git",
- "reference": "c83178d49e372ca967d1a8c77ae4e051b3a3c75c"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/michelf/php-markdown/zipball/c83178d49e372ca967d1a8c77ae4e051b3a3c75c",
- "reference": "c83178d49e372ca967d1a8c77ae4e051b3a3c75c",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.0"
- },
- "require-dev": {
- "phpunit/phpunit": ">=4.3 <5.8"
- },
- "time": "2019-12-02T02:32:27+00:00",
- "type": "library",
- "installation-source": "dist",
- "autoload": {
- "psr-4": {
- "Michelf\\": "Michelf/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Michel Fortin",
- "email": "michel.fortin@michelf.ca",
- "homepage": "https://michelf.ca/",
- "role": "Developer"
- },
- {
- "name": "John Gruber",
- "homepage": "https://daringfireball.net/"
- }
- ],
- "description": "PHP Markdown",
- "homepage": "https://michelf.ca/projects/php-markdown/",
- "keywords": [
- "markdown"
- ]
- },
- {
- "name": "suin/php-rss-writer",
- "version": "1.3.2",
- "version_normalized": "1.3.2.0",
- "source": {
- "type": "git",
- "url": "https://github.com/suin/php-rss-writer.git",
- "reference": "51840d2fad4087a4bdd93fb6937aa4b324b5c94f"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/suin/php-rss-writer/zipball/51840d2fad4087a4bdd93fb6937aa4b324b5c94f",
- "reference": "51840d2fad4087a4bdd93fb6937aa4b324b5c94f",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.0"
- },
- "time": "2016-03-01T12:09:17+00:00",
- "type": "library",
- "installation-source": "dist",
- "autoload": {
- "psr-0": {
- "Suin\\RSSWriter": "src"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Hidehito Nozawa aka Suin",
- "email": "suinyeze@gmail.com"
- }
- ],
- "description": "Yet another simple RSS writer library for PHP 5.3 or later.",
- "homepage": "https://github.com/suin/php-rss-writer",
- "keywords": [
- "feed",
- "generator",
- "php",
- "rss",
- "writer"
- ]
- }
-]
+ "dev": true,
+ "dev-package-names": []
+}
diff --git a/system/vendor/composer/installed.php b/system/vendor/composer/installed.php
new file mode 100644
index 0000000..43bd660
--- /dev/null
+++ b/system/vendor/composer/installed.php
@@ -0,0 +1,131 @@
+ array(
+ 'name' => '__root__',
+ 'pretty_version' => '1.0.0+no-version-set',
+ 'version' => '1.0.0.0',
+ 'reference' => null,
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../../../',
+ 'aliases' => array(),
+ 'dev' => true,
+ ),
+ 'versions' => array(
+ '__root__' => array(
+ 'pretty_version' => '1.0.0+no-version-set',
+ 'version' => '1.0.0.0',
+ 'reference' => null,
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../../../',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'bacon/bacon-qr-code' => array(
+ 'pretty_version' => 'v3.0.0',
+ 'version' => '3.0.0.0',
+ 'reference' => '510de6eca6248d77d31b339d62437cc995e2fb41',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../bacon/bacon-qr-code',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'composer/ca-bundle' => array(
+ 'pretty_version' => '1.5.0',
+ 'version' => '1.5.0.0',
+ 'reference' => '0c5ccfcfea312b5c5a190a21ac5cef93f74baf99',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/./ca-bundle',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'dasprid/enum' => array(
+ 'pretty_version' => '1.0.5',
+ 'version' => '1.0.5.0',
+ 'reference' => '6faf451159fb8ba4126b925ed2d78acfce0dc016',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../dasprid/enum',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'ircmaxell/password-compat' => array(
+ 'pretty_version' => 'v1.0.4',
+ 'version' => '1.0.4.0',
+ 'reference' => '5c5cde8822a69545767f7c7f3058cb15ff84614c',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../ircmaxell/password-compat',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'jbroadway/urlify' => array(
+ 'pretty_version' => '1.2.4-stable',
+ 'version' => '1.2.4.0',
+ 'reference' => 'd0fafbaa1dc14e8039cdf5c72a932a8d1de1750e',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../jbroadway/urlify',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'kanti/hub-updater' => array(
+ 'pretty_version' => 'v0.5.1',
+ 'version' => '0.5.1.0',
+ 'reference' => '014b33c1e3880bd8e037a960a89e7116eb08a26e',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../kanti/hub-updater',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'michelf/php-markdown' => array(
+ 'pretty_version' => '1.9.1',
+ 'version' => '1.9.1.0',
+ 'reference' => '5024d623c1a057dcd2d076d25b7d270a1d0d55f3',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../michelf/php-markdown',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'paragonie/constant_time_encoding' => array(
+ 'pretty_version' => 'v2.7.0',
+ 'version' => '2.7.0.0',
+ 'reference' => '52a0d99e69f56b9ec27ace92ba56897fe6993105',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../paragonie/constant_time_encoding',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'pragmarx/google2fa' => array(
+ 'pretty_version' => 'v8.0.1',
+ 'version' => '8.0.1.0',
+ 'reference' => '80c3d801b31fe165f8fe99ea085e0a37834e1be3',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../pragmarx/google2fa',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'suin/php-rss-writer' => array(
+ 'pretty_version' => '1.6.0',
+ 'version' => '1.6.0.0',
+ 'reference' => '78f45e44a2a7cb0d82e4b9efb6f7b7a075b9051c',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../suin/php-rss-writer',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'voku/portable-ascii' => array(
+ 'pretty_version' => '2.0.1',
+ 'version' => '2.0.1.0',
+ 'reference' => 'b56450eed252f6801410d810c8e1727224ae0743',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../voku/portable-ascii',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'voku/stop-words' => array(
+ 'pretty_version' => '2.0.1',
+ 'version' => '2.0.1.0',
+ 'reference' => '8e63c0af20f800b1600783764e0ce19e53969f71',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../voku/stop-words',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ ),
+);
diff --git a/system/vendor/composer/platform_check.php b/system/vendor/composer/platform_check.php
new file mode 100644
index 0000000..4c3a5d6
--- /dev/null
+++ b/system/vendor/composer/platform_check.php
@@ -0,0 +1,26 @@
+= 80100)) {
+ $issues[] = 'Your Composer dependencies require a PHP version ">= 8.1.0". You are running ' . PHP_VERSION . '.';
+}
+
+if ($issues) {
+ if (!headers_sent()) {
+ header('HTTP/1.1 500 Internal Server Error');
+ }
+ if (!ini_get('display_errors')) {
+ if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
+ fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
+ } elseif (!headers_sent()) {
+ echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
+ }
+ }
+ trigger_error(
+ 'Composer detected issues in your platform: ' . implode(' ', $issues),
+ E_USER_ERROR
+ );
+}
diff --git a/system/vendor/dasprid/enum/LICENSE b/system/vendor/dasprid/enum/LICENSE
new file mode 100644
index 0000000..d45a356
--- /dev/null
+++ b/system/vendor/dasprid/enum/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2017, Ben Scholzen 'DASPRiD'
+All rights reserved.
+
+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.
+
+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 OWNER 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.
diff --git a/system/vendor/dasprid/enum/README.md b/system/vendor/dasprid/enum/README.md
new file mode 100644
index 0000000..da37045
--- /dev/null
+++ b/system/vendor/dasprid/enum/README.md
@@ -0,0 +1,164 @@
+# PHP 7.1 enums
+
+[](https://github.com/DASPRiD/Enum/actions?query=workflow%3Atests)
+[](https://coveralls.io/github/DASPRiD/Enum?branch=master)
+[](https://packagist.org/packages/dasprid/enum)
+[](https://packagist.org/packages/dasprid/enum)
+[](https://packagist.org/packages/dasprid/enum)
+
+It is a well known fact that PHP is missing a basic enum type, ignoring the rather incomplete `SplEnum` implementation
+which is only available as a PECL extension. There are also quite a few other userland enum implementations around,
+but all of them have one or another compromise. This library tries to close that gap as far as PHP allows it to.
+
+## Usage
+
+### Basics
+
+At its core, there is the `DASPRiD\Enum\AbstractEnum` class, which by default will work with constants like any other
+enum implementation you might know. The first clear difference is that you should define all the constants as protected
+(so nobody outside your class can read them but the `AbstractEnum` can still do so). The other even mightier difference
+is that, for simple enums, the value of the constant doesn't matter at all. Let's have a look at a simple example:
+
+```php
+use DASPRiD\Enum\AbstractEnum;
+
+/**
+ * @method static self MONDAY()
+ * @method static self TUESDAY()
+ * @method static self WEDNESDAY()
+ * @method static self THURSDAY()
+ * @method static self FRIDAY()
+ * @method static self SATURDAY()
+ * @method static self SUNDAY()
+ */
+final class WeekDay extends AbstractEnum
+{
+ protected const MONDAY = null;
+ protected const TUESDAY = null;
+ protected const WEDNESDAY = null;
+ protected const THURSDAY = null;
+ protected const FRIDAY = null;
+ protected const SATURDAY = null;
+ protected const SUNDAY = null;
+}
+```
+
+If you need to provide constants for either internal use or public use, you can mark them as either private or public,
+in which case they will be ignored by the enum, which only considers protected constants as valid values. As you can
+see, we specifically defined the generated magic methods in a class level doc block, so anyone using this class will
+automatically have proper auto-completion in their IDE. Now since you have defined the enum, you can simply use it like
+that:
+
+```php
+function tellItLikeItIs(WeekDay $weekDay)
+{
+ switch ($weekDay) {
+ case WeekDay::MONDAY():
+ echo 'Mondays are bad.';
+ break;
+
+ case WeekDay::FRIDAY():
+ echo 'Fridays are better.';
+ break;
+
+ case WeekDay::SATURDAY():
+ case WeekDay::SUNDAY():
+ echo 'Weekends are best.';
+ break;
+
+ default:
+ echo 'Midweek days are so-so.';
+ }
+}
+
+tellItLikeItIs(WeekDay::MONDAY());
+tellItLikeItIs(WeekDay::WEDNESDAY());
+tellItLikeItIs(WeekDay::FRIDAY());
+tellItLikeItIs(WeekDay::SATURDAY());
+tellItLikeItIs(WeekDay::SUNDAY());
+```
+
+### More complex example
+
+Of course, all enums are singletons, which are not cloneable or serializable. Thus you can be sure that there is always
+just one instance of the same type. Of course, the values of constants are not completely useless, let's have a look at
+a more complex example:
+
+```php
+use DASPRiD\Enum\AbstractEnum;
+
+/**
+ * @method static self MERCURY()
+ * @method static self VENUS()
+ * @method static self EARTH()
+ * @method static self MARS()
+ * @method static self JUPITER()
+ * @method static self SATURN()
+ * @method static self URANUS()
+ * @method static self NEPTUNE()
+ */
+final class Planet extends AbstractEnum
+{
+ protected const MERCURY = [3.303e+23, 2.4397e6];
+ protected const VENUS = [4.869e+24, 6.0518e6];
+ protected const EARTH = [5.976e+24, 6.37814e6];
+ protected const MARS = [6.421e+23, 3.3972e6];
+ protected const JUPITER = [1.9e+27, 7.1492e7];
+ protected const SATURN = [5.688e+26, 6.0268e7];
+ protected const URANUS = [8.686e+25, 2.5559e7];
+ protected const NEPTUNE = [1.024e+26, 2.4746e7];
+
+ /**
+ * Universal gravitational constant.
+ *
+ * @var float
+ */
+ private const G = 6.67300E-11;
+
+ /**
+ * Mass in kilograms.
+ *
+ * @var float
+ */
+ private $mass;
+
+ /**
+ * Radius in meters.
+ *
+ * @var float
+ */
+ private $radius;
+
+ protected function __construct(float $mass, float $radius)
+ {
+ $this->mass = $mass;
+ $this->radius = $radius;
+ }
+
+ public function mass() : float
+ {
+ return $this->mass;
+ }
+
+ public function radius() : float
+ {
+ return $this->radius;
+ }
+
+ public function surfaceGravity() : float
+ {
+ return self::G * $this->mass / ($this->radius * $this->radius);
+ }
+
+ public function surfaceWeight(float $otherMass) : float
+ {
+ return $otherMass * $this->surfaceGravity();
+ }
+}
+
+$myMass = 80;
+
+foreach (Planet::values() as $planet) {
+ printf("Your weight on %s is %f\n", $planet, $planet->surfaceWeight($myMass));
+}
+```
diff --git a/system/vendor/dasprid/enum/composer.json b/system/vendor/dasprid/enum/composer.json
new file mode 100644
index 0000000..133e279
--- /dev/null
+++ b/system/vendor/dasprid/enum/composer.json
@@ -0,0 +1,34 @@
+{
+ "name": "dasprid/enum",
+ "description": "PHP 7.1 enum implementation",
+ "license": "BSD-2-Clause",
+ "authors": [
+ {
+ "name": "Ben Scholzen 'DASPRiD'",
+ "email": "mail@dasprids.de",
+ "homepage": "https://dasprids.de/",
+ "role": "Developer"
+ }
+ ],
+ "keywords": [
+ "enum",
+ "map"
+ ],
+ "require": {
+ "php": ">=7.1 <9.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7 | ^8 | ^9",
+ "squizlabs/php_codesniffer": "*"
+ },
+ "autoload": {
+ "psr-4": {
+ "DASPRiD\\Enum\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "DASPRiD\\EnumTest\\": "test/"
+ }
+ }
+}
diff --git a/system/vendor/dasprid/enum/src/AbstractEnum.php b/system/vendor/dasprid/enum/src/AbstractEnum.php
new file mode 100644
index 0000000..79fe81c
--- /dev/null
+++ b/system/vendor/dasprid/enum/src/AbstractEnum.php
@@ -0,0 +1,241 @@
+>
+ */
+ private static $values = [];
+
+ /**
+ * @var array
+ */
+ private static $allValuesLoaded = [];
+
+ /**
+ * @var array
+ */
+ private static $constants = [];
+
+ /**
+ * The constructor is private by default to avoid arbitrary enum creation.
+ *
+ * When creating your own constructor for a parameterized enum, make sure to declare it as protected, so that
+ * the static methods are able to construct it. Avoid making it public, as that would allow creation of
+ * non-singleton enum instances.
+ */
+ private function __construct()
+ {
+ }
+
+ /**
+ * Magic getter which forwards all calls to {@see self::valueOf()}.
+ *
+ * @return static
+ */
+ final public static function __callStatic(string $name, array $arguments) : self
+ {
+ return static::valueOf($name);
+ }
+
+ /**
+ * Returns an enum with the specified name.
+ *
+ * The name must match exactly an identifier used to declare an enum in this type (extraneous whitespace characters
+ * are not permitted).
+ *
+ * @return static
+ * @throws IllegalArgumentException if the enum has no constant with the specified name
+ */
+ final public static function valueOf(string $name) : self
+ {
+ if (isset(self::$values[static::class][$name])) {
+ return self::$values[static::class][$name];
+ }
+
+ $constants = self::constants();
+
+ if (array_key_exists($name, $constants)) {
+ return self::createValue($name, $constants[$name][0], $constants[$name][1]);
+ }
+
+ throw new IllegalArgumentException(sprintf('No enum constant %s::%s', static::class, $name));
+ }
+
+ /**
+ * @return static
+ */
+ private static function createValue(string $name, int $ordinal, array $arguments) : self
+ {
+ $instance = new static(...$arguments);
+ $instance->name = $name;
+ $instance->ordinal = $ordinal;
+ self::$values[static::class][$name] = $instance;
+ return $instance;
+ }
+
+ /**
+ * Obtains all possible types defined by this enum.
+ *
+ * @return static[]
+ */
+ final public static function values() : array
+ {
+ if (isset(self::$allValuesLoaded[static::class])) {
+ return self::$values[static::class];
+ }
+
+ if (! isset(self::$values[static::class])) {
+ self::$values[static::class] = [];
+ }
+
+ foreach (self::constants() as $name => $constant) {
+ if (array_key_exists($name, self::$values[static::class])) {
+ continue;
+ }
+
+ static::createValue($name, $constant[0], $constant[1]);
+ }
+
+ uasort(self::$values[static::class], function (self $a, self $b) {
+ return $a->ordinal() <=> $b->ordinal();
+ });
+
+ self::$allValuesLoaded[static::class] = true;
+ return self::$values[static::class];
+ }
+
+ private static function constants() : array
+ {
+ if (isset(self::$constants[static::class])) {
+ return self::$constants[static::class];
+ }
+
+ self::$constants[static::class] = [];
+ $reflectionClass = new ReflectionClass(static::class);
+ $ordinal = -1;
+
+ foreach ($reflectionClass->getReflectionConstants() as $reflectionConstant) {
+ if (! $reflectionConstant->isProtected()) {
+ continue;
+ }
+
+ $value = $reflectionConstant->getValue();
+
+ self::$constants[static::class][$reflectionConstant->name] = [
+ ++$ordinal,
+ is_array($value) ? $value : []
+ ];
+ }
+
+ return self::$constants[static::class];
+ }
+
+ /**
+ * Returns the name of this enum constant, exactly as declared in its enum declaration.
+ *
+ * Most programmers should use the {@see self::__toString()} method in preference to this one, as the toString
+ * method may return a more user-friendly name. This method is designed primarily for use in specialized situations
+ * where correctness depends on getting the exact name, which will not vary from release to release.
+ */
+ final public function name() : string
+ {
+ return $this->name;
+ }
+
+ /**
+ * Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial
+ * constant is assigned an ordinal of zero).
+ *
+ * Most programmers will have no use for this method. It is designed for use by sophisticated enum-based data
+ * structures.
+ */
+ final public function ordinal() : int
+ {
+ return $this->ordinal;
+ }
+
+ /**
+ * Compares this enum with the specified object for order.
+ *
+ * Returns negative integer, zero or positive integer as this object is less than, equal to or greater than the
+ * specified object.
+ *
+ * Enums are only comparable to other enums of the same type. The natural order implemented by this method is the
+ * order in which the constants are declared.
+ *
+ * @throws MismatchException if the passed enum is not of the same type
+ */
+ final public function compareTo(self $other) : int
+ {
+ if (! $other instanceof static) {
+ throw new MismatchException(sprintf(
+ 'The passed enum %s is not of the same type as %s',
+ get_class($other),
+ static::class
+ ));
+ }
+
+ return $this->ordinal - $other->ordinal;
+ }
+
+ /**
+ * Forbid cloning enums.
+ *
+ * @throws CloneNotSupportedException
+ */
+ final public function __clone()
+ {
+ throw new CloneNotSupportedException();
+ }
+
+ /**
+ * Forbid serializing enums.
+ *
+ * @throws SerializeNotSupportedException
+ */
+ final public function __sleep() : array
+ {
+ throw new SerializeNotSupportedException();
+ }
+
+ /**
+ * Forbid unserializing enums.
+ *
+ * @throws UnserializeNotSupportedException
+ */
+ final public function __wakeup() : void
+ {
+ throw new UnserializeNotSupportedException();
+ }
+
+ /**
+ * Turns the enum into a string representation.
+ *
+ * You may override this method to give a more user-friendly version.
+ */
+ public function __toString() : string
+ {
+ return $this->name;
+ }
+}
diff --git a/system/vendor/dasprid/enum/src/EnumMap.php b/system/vendor/dasprid/enum/src/EnumMap.php
new file mode 100644
index 0000000..95b8856
--- /dev/null
+++ b/system/vendor/dasprid/enum/src/EnumMap.php
@@ -0,0 +1,385 @@
+
+ */
+ private $keyUniverse;
+
+ /**
+ * Array representation of this map. The ith element is the value to which universe[i] is currently mapped, or null
+ * if it isn't mapped to anything, or NullValue if it's mapped to null.
+ *
+ * @var array
+ */
+ private $values;
+
+ /**
+ * @var int
+ */
+ private $size = 0;
+
+ /**
+ * Creates a new enum map.
+ *
+ * @param string $keyType the type of the keys, must extend AbstractEnum
+ * @param string $valueType the type of the values
+ * @param bool $allowNullValues whether to allow null values
+ * @throws IllegalArgumentException when key type does not extend AbstractEnum
+ */
+ public function __construct(string $keyType, string $valueType, bool $allowNullValues)
+ {
+ if (! is_subclass_of($keyType, AbstractEnum::class)) {
+ throw new IllegalArgumentException(sprintf(
+ 'Class %s does not extend %s',
+ $keyType,
+ AbstractEnum::class
+ ));
+ }
+
+ $this->keyType = $keyType;
+ $this->valueType = $valueType;
+ $this->allowNullValues = $allowNullValues;
+ $this->keyUniverse = $keyType::values();
+ $this->values = array_fill(0, count($this->keyUniverse), null);
+ }
+
+ public function __serialize(): array
+ {
+ $values = [];
+
+ foreach ($this->values as $ordinal => $value) {
+ if (null === $value) {
+ continue;
+ }
+
+ $values[$ordinal] = $this->unmaskNull($value);
+ }
+
+ return [
+ 'keyType' => $this->keyType,
+ 'valueType' => $this->valueType,
+ 'allowNullValues' => $this->allowNullValues,
+ 'values' => $values,
+ ];
+ }
+
+ public function __unserialize(array $data): void
+ {
+ $this->unserialize(serialize($data));
+ }
+
+ /**
+ * Checks whether the map types match the supplied ones.
+ *
+ * You should call this method when an EnumMap is passed to you and you want to ensure that it's made up of the
+ * correct types.
+ *
+ * @throws ExpectationException when supplied key type mismatches local key type
+ * @throws ExpectationException when supplied value type mismatches local value type
+ * @throws ExpectationException when the supplied map allows null values, abut should not
+ */
+ public function expect(string $keyType, string $valueType, bool $allowNullValues) : void
+ {
+ if ($keyType !== $this->keyType) {
+ throw new ExpectationException(sprintf(
+ 'Callee expected an EnumMap with key type %s, but got %s',
+ $keyType,
+ $this->keyType
+ ));
+ }
+
+ if ($valueType !== $this->valueType) {
+ throw new ExpectationException(sprintf(
+ 'Callee expected an EnumMap with value type %s, but got %s',
+ $keyType,
+ $this->keyType
+ ));
+ }
+
+ if ($allowNullValues !== $this->allowNullValues) {
+ throw new ExpectationException(sprintf(
+ 'Callee expected an EnumMap with nullable flag %s, but got %s',
+ ($allowNullValues ? 'true' : 'false'),
+ ($this->allowNullValues ? 'true' : 'false')
+ ));
+ }
+ }
+
+ /**
+ * Returns the number of key-value mappings in this map.
+ */
+ public function size() : int
+ {
+ return $this->size;
+ }
+
+ /**
+ * Returns true if this map maps one or more keys to the specified value.
+ */
+ public function containsValue($value) : bool
+ {
+ return in_array($this->maskNull($value), $this->values, true);
+ }
+
+ /**
+ * Returns true if this map contains a mapping for the specified key.
+ */
+ public function containsKey(AbstractEnum $key) : bool
+ {
+ $this->checkKeyType($key);
+ return null !== $this->values[$key->ordinal()];
+ }
+
+ /**
+ * Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.
+ *
+ * More formally, if this map contains a mapping from a key to a value, then this method returns the value;
+ * otherwise it returns null (there can be at most one such mapping).
+ *
+ * A return value of null does not necessarily indicate that the map contains no mapping for the key; it's also
+ * possible that hte map explicitly maps the key to null. The {@see self::containsKey()} operation may be used to
+ * distinguish these two cases.
+ *
+ * @return mixed
+ */
+ public function get(AbstractEnum $key)
+ {
+ $this->checkKeyType($key);
+ return $this->unmaskNull($this->values[$key->ordinal()]);
+ }
+
+ /**
+ * Associates the specified value with the specified key in this map.
+ *
+ * If the map previously contained a mapping for this key, the old value is replaced.
+ *
+ * @return mixed the previous value associated with the specified key, or null if there was no mapping for the key.
+ * (a null return can also indicate that the map previously associated null with the specified key.)
+ * @throws IllegalArgumentException when the passed values does not match the internal value type
+ */
+ public function put(AbstractEnum $key, $value)
+ {
+ $this->checkKeyType($key);
+
+ if (! $this->isValidValue($value)) {
+ throw new IllegalArgumentException(sprintf('Value is not of type %s', $this->valueType));
+ }
+
+ $index = $key->ordinal();
+ $oldValue = $this->values[$index];
+ $this->values[$index] = $this->maskNull($value);
+
+ if (null === $oldValue) {
+ ++$this->size;
+ }
+
+ return $this->unmaskNull($oldValue);
+ }
+
+ /**
+ * Removes the mapping for this key frm this map if present.
+ *
+ * @return mixed the previous value associated with the specified key, or null if there was no mapping for the key.
+ * (a null return can also indicate that the map previously associated null with the specified key.)
+ */
+ public function remove(AbstractEnum $key)
+ {
+ $this->checkKeyType($key);
+
+ $index = $key->ordinal();
+ $oldValue = $this->values[$index];
+ $this->values[$index] = null;
+
+ if (null !== $oldValue) {
+ --$this->size;
+ }
+
+ return $this->unmaskNull($oldValue);
+ }
+
+ /**
+ * Removes all mappings from this map.
+ */
+ public function clear() : void
+ {
+ $this->values = array_fill(0, count($this->keyUniverse), null);
+ $this->size = 0;
+ }
+
+ /**
+ * Compares the specified map with this map for quality.
+ *
+ * Returns true if the two maps represent the same mappings.
+ */
+ public function equals(self $other) : bool
+ {
+ if ($this === $other) {
+ return true;
+ }
+
+ if ($this->size !== $other->size) {
+ return false;
+ }
+
+ return $this->values === $other->values;
+ }
+
+ /**
+ * Returns the values contained in this map.
+ *
+ * The array will contain the values in the order their corresponding keys appear in the map, which is their natural
+ * order (the order in which the num constants are declared).
+ */
+ public function values() : array
+ {
+ return array_values(array_map(function ($value) {
+ return $this->unmaskNull($value);
+ }, array_filter($this->values, function ($value) : bool {
+ return null !== $value;
+ })));
+ }
+
+ public function serialize() : string
+ {
+ return serialize($this->__serialize());
+ }
+
+ public function unserialize($serialized) : void
+ {
+ $data = unserialize($serialized);
+ $this->__construct($data['keyType'], $data['valueType'], $data['allowNullValues']);
+
+ foreach ($this->keyUniverse as $key) {
+ if (array_key_exists($key->ordinal(), $data['values'])) {
+ $this->put($key, $data['values'][$key->ordinal()]);
+ }
+ }
+ }
+
+ public function getIterator() : Traversable
+ {
+ foreach ($this->keyUniverse as $key) {
+ if (null === $this->values[$key->ordinal()]) {
+ continue;
+ }
+
+ yield $key => $this->unmaskNull($this->values[$key->ordinal()]);
+ }
+ }
+
+ private function maskNull($value)
+ {
+ if (null === $value) {
+ return NullValue::instance();
+ }
+
+ return $value;
+ }
+
+ private function unmaskNull($value)
+ {
+ if ($value instanceof NullValue) {
+ return null;
+ }
+
+ return $value;
+ }
+
+ /**
+ * @throws IllegalArgumentException when the passed key does not match the internal key type
+ */
+ private function checkKeyType(AbstractEnum $key) : void
+ {
+ if (get_class($key) !== $this->keyType) {
+ throw new IllegalArgumentException(sprintf(
+ 'Object of type %s is not the same type as %s',
+ get_class($key),
+ $this->keyType
+ ));
+ }
+ }
+
+ private function isValidValue($value) : bool
+ {
+ if (null === $value) {
+ if ($this->allowNullValues) {
+ return true;
+ }
+
+ return false;
+ }
+
+ switch ($this->valueType) {
+ case 'mixed':
+ return true;
+
+ case 'bool':
+ case 'boolean':
+ return is_bool($value);
+
+ case 'int':
+ case 'integer':
+ return is_int($value);
+
+ case 'float':
+ case 'double':
+ return is_float($value);
+
+ case 'string':
+ return is_string($value);
+
+ case 'object':
+ return is_object($value);
+
+ case 'array':
+ return is_array($value);
+ }
+
+ return $value instanceof $this->valueType;
+ }
+}
diff --git a/system/vendor/dasprid/enum/src/Exception/CloneNotSupportedException.php b/system/vendor/dasprid/enum/src/Exception/CloneNotSupportedException.php
new file mode 100644
index 0000000..4b37dbe
--- /dev/null
+++ b/system/vendor/dasprid/enum/src/Exception/CloneNotSupportedException.php
@@ -0,0 +1,10 @@
+ array ( /* German */
- 'Ä' => 'Ae', 'Ö' => 'Oe', 'Ü' => 'Ue', 'ä' => 'ae', 'ö' => 'oe', 'ü' => 'ue', 'ß' => 'ss',
- 'ẞ' => 'SS'
- ),
- 'latin' => array (
- 'À' => 'A', 'Á' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'A', 'Å' => 'A','Ă' => 'A', 'Æ' => 'AE', 'Ç' =>
- 'C', 'È' => 'E', 'É' => 'E', 'Ê' => 'E', 'Ë' => 'E', 'Ì' => 'I', 'Í' => 'I', 'Î' => 'I',
- 'Ï' => 'I', 'Ð' => 'D', 'Ñ' => 'N', 'Ò' => 'O', 'Ó' => 'O', 'Ô' => 'O', 'Õ' => 'O', 'Ö' =>
- 'O', 'Ő' => 'O', 'Ø' => 'O', 'Œ' => 'OE' ,'Ș' => 'S','Ț' => 'T', 'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ü' => 'U', 'Ű' => 'U',
- 'Ý' => 'Y', 'Þ' => 'TH', 'ß' => 'ss', 'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' =>
- 'a', 'å' => 'a', 'ă' => 'a', 'æ' => 'ae', 'ç' => 'c', 'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e',
- 'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', 'ð' => 'd', 'ñ' => 'n', 'ò' => 'o', 'ó' =>
- 'o', 'ô' => 'o', 'õ' => 'o', 'ö' => 'o', 'ő' => 'o', 'ø' => 'o', 'œ' => 'oe', 'ș' => 's', 'ț' => 't', 'ù' => 'u', 'ú' => 'u',
- 'û' => 'u', 'ü' => 'u', 'ű' => 'u', 'ý' => 'y', 'þ' => 'th', 'ÿ' => 'y'
- ),
- 'latin_symbols' => array (
- '©' => '(c)'
- ),
- 'el' => array ( /* Greek */
- 'α' => 'a', 'β' => 'b', 'γ' => 'g', 'δ' => 'd', 'ε' => 'e', 'ζ' => 'z', 'η' => 'h', 'θ' => '8',
- 'ι' => 'i', 'κ' => 'k', 'λ' => 'l', 'μ' => 'm', 'ν' => 'n', 'ξ' => '3', 'ο' => 'o', 'π' => 'p',
- 'ρ' => 'r', 'σ' => 's', 'τ' => 't', 'υ' => 'y', 'φ' => 'f', 'χ' => 'x', 'ψ' => 'ps', 'ω' => 'w',
- 'ά' => 'a', 'έ' => 'e', 'ί' => 'i', 'ό' => 'o', 'ύ' => 'y', 'ή' => 'h', 'ώ' => 'w', 'ς' => 's',
- 'ϊ' => 'i', 'ΰ' => 'y', 'ϋ' => 'y', 'ΐ' => 'i',
- 'Α' => 'A', 'Β' => 'B', 'Γ' => 'G', 'Δ' => 'D', 'Ε' => 'E', 'Ζ' => 'Z', 'Η' => 'H', 'Θ' => '8',
- 'Ι' => 'I', 'Κ' => 'K', 'Λ' => 'L', 'Μ' => 'M', 'Ν' => 'N', 'Ξ' => '3', 'Ο' => 'O', 'Π' => 'P',
- 'Ρ' => 'R', 'Σ' => 'S', 'Τ' => 'T', 'Υ' => 'Y', 'Φ' => 'F', 'Χ' => 'X', 'Ψ' => 'PS', 'Ω' => 'W',
- 'Ά' => 'A', 'Έ' => 'E', 'Ί' => 'I', 'Ό' => 'O', 'Ύ' => 'Y', 'Ή' => 'H', 'Ώ' => 'W', 'Ϊ' => 'I',
- 'Ϋ' => 'Y'
- ),
- 'tr' => array ( /* Turkish */
- 'ş' => 's', 'Ş' => 'S', 'ı' => 'i', 'İ' => 'I', 'ç' => 'c', 'Ç' => 'C', 'ü' => 'u', 'Ü' => 'U',
- 'ö' => 'o', 'Ö' => 'O', 'ğ' => 'g', 'Ğ' => 'G'
- ),
- 'bg' => array( /* Bulgarian */
- 'Щ' => 'Sht', 'Ш' => 'Sh', 'Ч' => 'Ch', 'Ц' => 'C', 'Ю' => 'Yu', 'Я' => 'Ya',
- 'Ж' => 'J', 'А' => 'A', 'Б' => 'B', 'В' => 'V', 'Г' => 'G', 'Д' => 'D',
- 'Е' => 'E', 'З' => 'Z', 'И' => 'I', 'Й' => 'Y', 'К' => 'K', 'Л' => 'L',
- 'М' => 'M', 'Н' => 'N', 'О' => 'O', 'П' => 'P', 'Р' => 'R', 'С' => 'S',
- 'Т' => 'T', 'У' => 'U', 'Ф' => 'F', 'Х' => 'H', 'Ь' => '', 'Ъ' => 'A',
- 'щ' => 'sht', 'ш' => 'sh', 'ч' => 'ch', 'ц' => 'c', 'ю' => 'yu', 'я' => 'ya',
- 'ж' => 'j', 'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd',
- 'е' => 'e', 'з' => 'z', 'и' => 'i', 'й' => 'y', 'к' => 'k', 'л' => 'l',
- 'м' => 'm', 'н' => 'n', 'о' => 'o', 'п' => 'p', 'р' => 'r', 'с' => 's',
- 'т' => 't', 'у' => 'u', 'ф' => 'f', 'х' => 'h', 'ь' => '', 'ъ' => 'a'
- ),
- 'ru' => array ( /* Russian */
- 'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd', 'е' => 'e', 'ё' => 'yo', 'ж' => 'zh',
- 'з' => 'z', 'и' => 'i', 'й' => 'i', 'к' => 'k', 'л' => 'l', 'м' => 'm', 'н' => 'n', 'о' => 'o',
- 'п' => 'p', 'р' => 'r', 'с' => 's', 'т' => 't', 'у' => 'u', 'ф' => 'f', 'х' => 'h', 'ц' => 'c',
- 'ч' => 'ch', 'ш' => 'sh', 'щ' => 'sh', 'ъ' => '', 'ы' => 'y', 'ь' => '', 'э' => 'e', 'ю' => 'yu',
- 'я' => 'ya',
- 'А' => 'A', 'Б' => 'B', 'В' => 'V', 'Г' => 'G', 'Д' => 'D', 'Е' => 'E', 'Ё' => 'Yo', 'Ж' => 'Zh',
- 'З' => 'Z', 'И' => 'I', 'Й' => 'I', 'К' => 'K', 'Л' => 'L', 'М' => 'M', 'Н' => 'N', 'О' => 'O',
- 'П' => 'P', 'Р' => 'R', 'С' => 'S', 'Т' => 'T', 'У' => 'U', 'Ф' => 'F', 'Х' => 'H', 'Ц' => 'C',
- 'Ч' => 'Ch', 'Ш' => 'Sh', 'Щ' => 'Sh', 'Ъ' => '', 'Ы' => 'Y', 'Ь' => '', 'Э' => 'E', 'Ю' => 'Yu',
- 'Я' => 'Ya',
- '№' => ''
- ),
- 'uk' => array ( /* Ukrainian */
- 'Є' => 'Ye', 'І' => 'I', 'Ї' => 'Yi', 'Ґ' => 'G', 'є' => 'ye', 'і' => 'i', 'ї' => 'yi', 'ґ' => 'g'
- ),
- 'kk' => array ( /* Kazakh */
- 'Ә' => 'A', 'Ғ' => 'G', 'Қ' => 'Q', 'Ң' => 'N', 'Ө' => 'O', 'Ұ' => 'U', 'Ү' => 'U', 'Һ' => 'H',
- 'ә' => 'a', 'ғ' => 'g', 'қ' => 'q', 'ң' => 'n', 'ө' => 'o', 'ұ' => 'u', 'ү' => 'u', 'һ' => 'h',
- ),
- 'cs' => array ( /* Czech */
- 'č' => 'c', 'ď' => 'd', 'ě' => 'e', 'ň' => 'n', 'ř' => 'r', 'š' => 's', 'ť' => 't', 'ů' => 'u',
- 'ž' => 'z', 'Č' => 'C', 'Ď' => 'D', 'Ě' => 'E', 'Ň' => 'N', 'Ř' => 'R', 'Š' => 'S', 'Ť' => 'T',
- 'Ů' => 'U', 'Ž' => 'Z'
- ),
- 'pl' => array ( /* Polish */
- 'ą' => 'a', 'ć' => 'c', 'ę' => 'e', 'ł' => 'l', 'ń' => 'n', 'ó' => 'o', 'ś' => 's', 'ź' => 'z',
- 'ż' => 'z', 'Ą' => 'A', 'Ć' => 'C', 'Ę' => 'e', 'Ł' => 'L', 'Ń' => 'N', 'Ó' => 'O', 'Ś' => 'S',
- 'Ź' => 'Z', 'Ż' => 'Z'
- ),
- 'ro' => array ( /* Romanian */
- 'ă' => 'a', 'â' => 'a', 'î' => 'i', 'ș' => 's', 'ț' => 't', 'Ţ' => 'T', 'ţ' => 't'
- ),
- 'lv' => array ( /* Latvian */
- 'ā' => 'a', 'č' => 'c', 'ē' => 'e', 'ģ' => 'g', 'ī' => 'i', 'ķ' => 'k', 'ļ' => 'l', 'ņ' => 'n',
- 'š' => 's', 'ū' => 'u', 'ž' => 'z', 'Ā' => 'A', 'Č' => 'C', 'Ē' => 'E', 'Ģ' => 'G', 'Ī' => 'i',
- 'Ķ' => 'k', 'Ļ' => 'L', 'Ņ' => 'N', 'Š' => 'S', 'Ū' => 'u', 'Ž' => 'Z'
- ),
- 'lt' => array ( /* Lithuanian */
- 'ą' => 'a', 'č' => 'c', 'ę' => 'e', 'ė' => 'e', 'į' => 'i', 'š' => 's', 'ų' => 'u', 'ū' => 'u', 'ž' => 'z',
- 'Ą' => 'A', 'Č' => 'C', 'Ę' => 'E', 'Ė' => 'E', 'Į' => 'I', 'Š' => 'S', 'Ų' => 'U', 'Ū' => 'U', 'Ž' => 'Z'
- ),
- 'vi' => array ( /* Vietnamese */
- 'Á' => 'A', 'À' => 'A', 'Ả' => 'A', 'Ã' => 'A', 'Ạ' => 'A', 'Ă' => 'A', 'Ắ' => 'A', 'Ằ' => 'A', 'Ẳ' => 'A', 'Ẵ' => 'A', 'Ặ' => 'A', 'Â' => 'A', 'Ấ' => 'A', 'Ầ' => 'A', 'Ẩ' => 'A', 'Ẫ' => 'A', 'Ậ' => 'A',
- 'á' => 'a', 'à' => 'a', 'ả' => 'a', 'ã' => 'a', 'ạ' => 'a', 'ă' => 'a', 'ắ' => 'a', 'ằ' => 'a', 'ẳ' => 'a', 'ẵ' => 'a', 'ặ' => 'a', 'â' => 'a', 'ấ' => 'a', 'ầ' => 'a', 'ẩ' => 'a', 'ẫ' => 'a', 'ậ' => 'a',
- 'É' => 'E', 'È' => 'E', 'Ẻ' => 'E', 'Ẽ' => 'E', 'Ẹ' => 'E', 'Ê' => 'E', 'Ế' => 'E', 'Ề' => 'E', 'Ể' => 'E', 'Ễ' => 'E', 'Ệ' => 'E',
- 'é' => 'e', 'è' => 'e', 'ẻ' => 'e', 'ẽ' => 'e', 'ẹ' => 'e', 'ê' => 'e', 'ế' => 'e', 'ề' => 'e', 'ể' => 'e', 'ễ' => 'e', 'ệ' => 'e',
- 'Í' => 'I', 'Ì' => 'I', 'Ỉ' => 'I', 'Ĩ' => 'I', 'Ị' => 'I', 'í' => 'i', 'ì' => 'i', 'ỉ' => 'i', 'ĩ' => 'i', 'ị' => 'i',
- 'Ó' => 'O', 'Ò' => 'O', 'Ỏ' => 'O', 'Õ' => 'O', 'Ọ' => 'O', 'Ô' => 'O', 'Ố' => 'O', 'Ồ' => 'O', 'Ổ' => 'O', 'Ỗ' => 'O', 'Ộ' => 'O', 'Ơ' => 'O', 'Ớ' => 'O', 'Ờ' => 'O', 'Ở' => 'O', 'Ỡ' => 'O', 'Ợ' => 'O',
- 'ó' => 'o', 'ò' => 'o', 'ỏ' => 'o', 'õ' => 'o', 'ọ' => 'o', 'ô' => 'o', 'ố' => 'o', 'ồ' => 'o', 'ổ' => 'o', 'ỗ' => 'o', 'ộ' => 'o', 'ơ' => 'o', 'ớ' => 'o', 'ờ' => 'o', 'ở' => 'o', 'ỡ' => 'o', 'ợ' => 'o',
- 'Ú' => 'U', 'Ù' => 'U', 'Ủ' => 'U', 'Ũ' => 'U', 'Ụ' => 'U', 'Ư' => 'U', 'Ứ' => 'U', 'Ừ' => 'U', 'Ử' => 'U', 'Ữ' => 'U', 'Ự' => 'U',
- 'ú' => 'u', 'ù' => 'u', 'ủ' => 'u', 'ũ' => 'u', 'ụ' => 'u', 'ư' => 'u', 'ứ' => 'u', 'ừ' => 'u', 'ử' => 'u', 'ữ' => 'u', 'ự' => 'u',
- 'Ý' => 'Y', 'Ỳ' => 'Y', 'Ỷ' => 'Y', 'Ỹ' => 'Y', 'Ỵ' => 'Y', 'ý' => 'y', 'ỳ' => 'y', 'ỷ' => 'y', 'ỹ' => 'y', 'ỵ' => 'y',
- 'Đ' => 'D', 'đ' => 'd'
- ),
- 'ar' => array ( /* Arabic */
- 'أ' => 'a', 'ب' => 'b', 'ت' => 't', 'ث' => 'th', 'ج' => 'g', 'ح' => 'h', 'خ' => 'kh', 'د' => 'd',
- 'ذ' => 'th', 'ر' => 'r', 'ز' => 'z', 'س' => 's', 'ش' => 'sh', 'ص' => 's', 'ض' => 'd', 'ط' => 't',
- 'ظ' => 'th', 'ع' => 'aa', 'غ' => 'gh', 'ف' => 'f', 'ق' => 'k', 'ك' => 'k', 'ل' => 'l', 'م' => 'm',
- 'ن' => 'n', 'ه' => 'h', 'و' => 'o', 'ي' => 'y',
- 'ا' => 'a', 'إ' => 'a', 'آ' => 'a', 'ؤ' => 'o', 'ئ' => 'y', 'ء' => 'aa',
- '٠' => '0', '١' => '1', '٢' => '2', '٣' => '3', '٤' => '4', '٥' => '5', '٦' => '6', '٧' => '7', '٨' => '8', '٩' => '9',
- ),
- 'fa' => array ( /* Persian */
- 'گ' => 'g', 'ژ' => 'j', 'پ' => 'p', 'چ' => 'ch', 'ی' => 'y', 'ک' => 'k',
- '۰' => '0', '۱' => '1', '۲' => '2', '۳' => '3', '۴' => '4', '۵' => '5', '۶' => '6', '۷' => '7', '۸' => '8', '۹' => '9',
- ),
- 'sr' => array ( /* Serbian */
- 'ђ' => 'dj', 'ј' => 'j', 'љ' => 'lj', 'њ' => 'nj', 'ћ' => 'c', 'џ' => 'dz', 'đ' => 'dj',
- 'Ђ' => 'Dj', 'Ј' => 'j', 'Љ' => 'Lj', 'Њ' => 'Nj', 'Ћ' => 'C', 'Џ' => 'Dz', 'Đ' => 'Dj'
- ),
- 'az' => array ( /* Azerbaijani */
- 'ç' => 'c', 'ə' => 'e', 'ğ' => 'g', 'ı' => 'i', 'ö' => 'o', 'ş' => 's', 'ü' => 'u',
- 'Ç' => 'C', 'Ə' => 'E', 'Ğ' => 'G', 'İ' => 'I', 'Ö' => 'O', 'Ş' => 'S', 'Ü' => 'U'
- ),
- 'sk' => array ( /* Slovak */
- 'ĺ' => 'l', 'ľ' => 'l', 'ŕ' => 'r'
- )
- );
+ /**
+ * The language-mapping array.
+ *
+ * ISO 639-1 codes: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
+ *
+ * @var array[]
+ */
+ public static $maps = [];
- /**
- * List of words to remove from URLs.
- */
- public static $remove_list = array (
- 'a', 'an', 'as', 'at', 'before', 'but', 'by', 'for', 'from',
- 'is', 'in', 'into', 'like', 'of', 'off', 'on', 'onto', 'per',
- 'since', 'than', 'the', 'this', 'that', 'to', 'up', 'via',
- 'with'
- );
+ /**
+ * List of words to remove from URLs.
+ *
+ * @var array[]
+ */
+ public static $remove_list = [];
- /**
- * The character map.
- */
- private static $map = array ();
+ /**
+ * An array of strings that will convert into the separator-char - used by "URLify::filter()".
+ *
+ * @var string[]
+ */
+ private static $arrayToSeparator = [];
- /**
- * The character list as a string.
- */
- private static $chars = '';
-
- /**
- * The character list as a regular expression.
- */
- private static $regex = '';
-
- /**
- * The current language
- */
- private static $language = '';
-
- /**
- * Initializes the character map.
- * @param string $language
- */
- private static function init ($language = "")
+ /**
+ * Add new strings the will be replaced with the separator.
+ *
+ * @param array $array An array of things that should replaced by the separator.
+ * @param bool $merge Keep the previous (default) array-to-separator array.
+ *
+ * @return void
+ *
+ * @psalm-param string[] $array
+ */
+ public static function add_array_to_separator(array $array, bool $merge = true)
{
- if (count (self::$map) > 0 && (($language == "") || ($language == self::$language))) {
- return;
- }
+ if ($merge === true) {
+ self::$arrayToSeparator = \array_unique(
+ \array_merge(
+ self::$arrayToSeparator,
+ $array
+ )
+ );
+ } else {
+ self::$arrayToSeparator = $array;
+ }
+ }
- /* Is a specific map associated with $language ? */
- if (isset(self::$maps[$language]) && is_array(self::$maps[$language])) {
- /* Move this map to end. This means it will have priority over others */
- $m = self::$maps[$language];
- unset(self::$maps[$language]);
- self::$maps[$language] = $m;
- }
- /* Reset static vars */
- self::$language = $language;
- self::$map = array();
- self::$chars = '';
-
- foreach (self::$maps as $map) {
- foreach ($map as $orig => $conv) {
- self::$map[$orig] = $conv;
- self::$chars .= $orig;
- }
- }
-
- self::$regex = '/[' . preg_quote(self::$chars, '/') . ']/u';
- }
-
- /**
- * Add new characters to the list. `$map` should be a hash.
- * @param array $map
- */
- public static function add_chars ($map)
+ /**
+ * Add new characters to the list. `$map` should be a hash.
+ *
+ * @param array $map
+ * @param string|null $language
+ *
+ * @return void
+ *
+ * @psalm-param array $map
+ */
+ public static function add_chars(array $map, string $language = null)
{
- if (! is_array ($map)) {
- throw new LogicException ('$map must be an associative array.');
- }
- self::$maps[] = $map;
- self::$map = array ();
- self::$chars = '';
- }
+ $language_key = $language ?? \uniqid('urlify', true);
- /**
- * Append words to the remove list. Accepts either single words
- * or an array of words.
- * @param mixed $words
- */
- public static function remove_words ($words)
+ if (isset(self::$maps[$language_key])) {
+ self::$maps[$language_key] = \array_merge($map, self::$maps[$language_key]);
+ } else {
+ self::$maps[$language_key] = $map;
+ }
+ }
+
+ /**
+ * @return void
+ */
+ public static function reset_chars()
{
- $words = is_array ($words) ? $words : array ($words);
- self::$remove_list = array_unique (array_merge (self::$remove_list, $words));
- }
+ self::$maps = [];
+ }
- /**
- * Transliterates characters to their ASCII equivalents.
+ /**
+ * Transliterates characters to their ASCII equivalents.
* $language specifies a priority for a specific language.
* The latter is useful if languages have different rules for the same character.
- * @param string $text
+ *
+ * @param string $string The input string.
+ * @param string $language Your primary language.
+ * @param string $unknown Character use if character unknown. (default is ?).
+ *
+ * @return string
+ */
+ public static function downcode(
+ string $string,
+ string $language = 'en',
+ string $unknown = ''
+ ): string {
+ $string = self::expandString($string, $language);
+
+ foreach (self::$maps as $mapsInner) {
+ foreach ($mapsInner as $orig => $replace) {
+ $string = \str_replace($orig, $replace, $string);
+ }
+ }
+
+ $string = \voku\helper\ASCII::to_ascii(
+ $string,
+ $language,
+ false,
+ true
+ );
+
+ return \voku\helper\ASCII::to_transliterate(
+ $string,
+ $unknown,
+ false
+ );
+ }
+
+ /**
+ * Convert a String to URL slug. Wraps filter() with a simpler
+ * set of defaults for typical usage in generating blog post slugs.
+ *
+ * @param string $string The text you want to convert.
+ * @param int $maxLength Max. length of the output string, set to "0" (zero) to
+ * disable it
+ * @param string $separator Define a new separator for the words.
+ * @param string $language The language you want to convert to.
+ */
+ public static function slug(
+ string $string,
+ int $maxLength = 200,
+ string $separator = '-',
+ string $language = 'en'
+ ): string {
+ return self::filter ($string, $maxLength, $language, false, false, true, $separator);
+ }
+
+ /**
+ * Convert a String to URL.
+ *
+ * e.g.: "Petty theft" to "Petty-theft"
+ *
+ * @param string $string The text you want to convert.
+ * @param int $maxLength Max. length of the output string, set to "0" (zero) to
+ * disable it
+ * @param string $language The language you want to convert to.
+ * @param bool $fileName
+ * Keep the "." from the extension e.g.: "imaäe.jpg" =>
+ * "image.jpg"
+ *
+ * @param bool $removeWords
+ * Remove some "words" from the string.
+ * Info: Set extra words via remove_words() .
+ *
+ * @param bool $strToLower Use strtolower() at the end.
+ * @param bool|string $separator Define a new separator for the words.
+ *
+ * @return string
+ */
+ public static function filter(
+ string $string,
+ int $maxLength = 200,
+ string $language = 'en',
+ bool $fileName = false,
+ bool $removeWords = false,
+ bool $strToLower = true,
+ $separator = '-'
+ ): string {
+ if ($string === '') {
+ return '';
+ }
+
+ // fallback
+ if ($language === '') {
+ $language = 'en';
+ }
+
+ // separator-fallback
+ if ($separator === false) {
+ $separator = '_';
+ }
+ if ($separator === true || $separator === '') {
+ $separator = '-';
+ }
+
+ // escaped separator
+ $separatorEscaped = \preg_quote($separator, '/');
+
+ // use defaults, if there are no values
+ if (self::$arrayToSeparator === []) {
+ self::reset_array_to_separator();
+ }
+
+ // remove apostrophes which are not used as quotes around a string
+ if (\strpos($string, "'") !== false) {
+ $stringTmp = \preg_replace("/(\w)'(\w)/u", '${1}${2}', $string);
+ if ($stringTmp !== null) {
+ $string = (string) $stringTmp;
+ }
+ }
+
+ // replace with $separator
+ $string = (string) \preg_replace(
+ self::$arrayToSeparator,
+ $separator,
+ $string
+ );
+
+ // remove all other html-tags
+ if (
+ \strpos($string, '<') !== false
+ ||
+ \strpos($string, '>') !== false
+ ) {
+ $string = \strip_tags($string);
+ }
+
+ // use special language replacer
+ $string = self::downcode($string, $language);
+
+ // replace with $separator, again
+ $string = (string) \preg_replace(
+ self::$arrayToSeparator,
+ $separator,
+ $string
+ );
+
+ // remove all these words from the string before urlifying
+ $removeWordsSearch = '//';
+ if ($removeWords === true) {
+ $removeList = self::get_remove_list($language);
+ if ($removeList !== []) {
+ $removeWordsSearch = '/\b(?:' . \implode('|', $removeList) . ')\b/ui';
+ }
+ }
+
+ // keep the "." from e.g.: a file-extension?
+ if ($fileName) {
+ $removePatternAddOn = '.';
+ } else {
+ $removePatternAddOn = '';
+ }
+
+ $string = (string) \preg_replace(
+ [
+ // 1) remove un-needed chars
+ '/[^' . $separatorEscaped . $removePatternAddOn . '\-a-zA-Z0-9\s]/u',
+ // 2) convert spaces to $separator
+ '/[\s]+/u',
+ // 3) remove some extras words
+ $removeWordsSearch,
+ // 4) remove double $separator's
+ '/[' . ($separatorEscaped ?: ' ') . ']+/u',
+ // 5) remove $separator at the end
+ '/[' . ($separatorEscaped ?: ' ') . ']+$/u',
+ ],
+ [
+ '',
+ $separator,
+ '',
+ $separator,
+ '',
+ ],
+ $string
+ );
+
+ // "substr" only if "$length" is set
+ if (
+ $maxLength
+ &&
+ $maxLength > 0
+ &&
+ \strlen($string) > $maxLength
+ ) {
+ $string = (string) \substr(\trim($string, $separator), 0, $maxLength);
+ }
+
+ // convert to lowercase
+ if ($strToLower === true) {
+ $string = \strtolower($string);
+ }
+
+ // trim "$separator" from beginning and end of the string
+ return \trim($string, $separator);
+ }
+
+ /**
+ * Append words to the remove list. Accepts either single words or an array of words.
+ *
+ * @param string|string[] $words
+ * @param string $language
+ * @param bool $merge Keep the previous (default) remove-words array.
+ *
+ * @return void
+ */
+ public static function remove_words($words, string $language = 'en', bool $merge = true)
+ {
+ if (\is_array($words) === false) {
+ $words = [$words];
+ }
+
+ foreach ($words as $removeWordKey => $removeWord) {
+ $words[$removeWordKey] = \preg_quote($removeWord, '/');
+ }
+
+ if ($merge === true) {
+ self::$remove_list[$language] = \array_unique(
+ \array_merge(
+ self::get_remove_list($language),
+ $words
+ )
+ );
+ } else {
+ self::$remove_list[$language] = $words;
+ }
+ }
+
+ /**
+ * Reset the internal "self::$arrayToSeparator" to the default values.
+ *
+ * @return void
+ */
+ public static function reset_array_to_separator()
+ {
+ self::$arrayToSeparator = [
+ '/"|&|<|>|–|—/i', // ", &, <, >, –, —
+ '/⁻|-|—|_|"|`|´|\'/',
+ "#/\r\n|\r|\n|#isU",
+ ];
+ }
+
+ /**
+ * reset the word-remove-array
+ *
* @param string $language
+ *
+ * @return void
+ */
+ public static function reset_remove_list(string $language = 'en')
+ {
+ if ($language === '') {
+ return;
+ }
+
+ $language_orig = $language;
+ $language = self::get_language_for_reset_remove_list($language);
+ if ($language === '') {
+ return;
+ }
+
+ $stopWords = new \voku\helper\StopWords();
+
+ try {
+ self::$remove_list[$language_orig] = $stopWords->getStopWordsFromLanguage($language);
+ } catch (\voku\helper\StopWordsLanguageNotExists $e) {
+ self::$remove_list[$language_orig] = [];
+ }
+ }
+
+ /**
+ * Alias of `URLify::downcode()`.
+ *
+ * @param string $string
+ * @param string $language
+ *
* @return string
- */
- public static function downcode ($text, $language = "")
+ */
+ public static function transliterate(string $string, string $language = 'en'): string
{
- self::init ($language);
+ return self::downcode($string, $language);
+ }
- if (preg_match_all (self::$regex, $text, $matches)) {
- for ($i = 0; $i < count ($matches[0]); $i++) {
- $char = $matches[0][$i];
- if (isset (self::$map[$char])) {
- $text = str_replace ($char, self::$map[$char], $text);
- }
- }
- }
- return $text;
- }
+ /**
+ * Expands the given string replacing some special parts for words.
+ * e.g. "lorem@ipsum.com" is replaced by "lorem at ipsum dot com".
+ *
+ * Most of these transformations have been inspired by the pelle/slugger
+ * project, distributed under the Eclipse Public License.
+ * Copyright 2012 Pelle Braendgaard
+ *
+ * @param string $string The string to expand
+ * @param string $language
+ *
+ * @return string The result of expanding the string
+ */
+ protected static function expandString(string $string, string $language = 'en'): string
+ {
+ $string = self::expandCurrencies($string, $language);
- /**
- * Filters a string, e.g., "Petty theft" to "petty-theft"
- * @param string $text The text to return filtered
- * @param int $length The length (after filtering) of the string to be returned
- * @param string $language The transliteration language, passed down to downcode()
- * @param bool $file_name Whether there should be and additional filter considering this is a filename
- * @param bool $use_remove_list Whether you want to remove specific elements previously set in self::$remove_list
- * @param bool $lower_case Whether you want the filter to maintain casing or lowercase everything (default)
- * @param bool $treat_underscore_as_space Treat underscore as space, so it will replaced with "-"
+ return self::expandSymbols($string, $language);
+ }
+
+ /**
+ * @param string $language
+ *
* @return string
- */
- public static function filter ($text, $length = 60, $language = "", $file_name = false, $use_remove_list = true, $lower_case = true, $treat_underscore_as_space = true)
+ */
+ private static function get_language_for_reset_remove_list(string $language)
{
- $text = self::downcode ($text,$language);
+ if ($language === '') {
+ return '';
+ }
- if ($use_remove_list) {
- // remove all these words from the string before urlifying
- $text = preg_replace ('/\b(' . join ('|', self::$remove_list) . ')\b/i', '', $text);
- }
+ if (
+ \strpos($language, '_') === false
+ &&
+ \strpos($language, '-') === false
+ ) {
+ $language = \strtolower($language);
+ } else {
+ $regex = '/(?[a-z]{2}).*/i';
+ $language = \strtolower((string) \preg_replace($regex, '$1', $language));
+ }
- // if downcode doesn't hit, the char will be stripped here
- $remove_pattern = ($file_name) ? '/[^_\-.\-a-zA-Z0-9\s]/u' : '/[^\s_\-a-zA-Z0-9]/u';
- $text = preg_replace ($remove_pattern, '', $text); // remove unneeded chars
- if ($treat_underscore_as_space) {
- $text = str_replace ('_', ' ', $text); // treat underscores as spaces
- }
- $text = preg_replace ('/^\s+|\s+$/u', '', $text); // trim leading/trailing spaces
- $text = preg_replace ('/[-\s]+/u', '-', $text); // convert spaces to hyphens
- if ($lower_case) {
- $text = strtolower ($text); // convert to lowercase
- }
+ return $language;
+ }
- return trim (substr ($text, 0, $length), '-'); // trim to first $length chars
- }
-
- /**
- * Alias of `URLify::downcode()`.
- */
- public static function transliterate ($text)
+ /**
+ * Expands the numeric currencies in euros, dollars, pounds
+ * and yens that the given string may include.
+ *
+ * @param string $string
+ * @param string $language
+ *
+ * @return string
+ */
+ private static function expandCurrencies(string $string, string $language = 'en')
{
- return self::downcode ($text);
- }
+ if (
+ \strpos($string, '€') === false
+ &&
+ \strpos($string, '$') === false
+ &&
+ \strpos($string, '£') === false
+ &&
+ \strpos($string, '¥') === false
+ ) {
+ return $string;
+ }
+
+ if ($language === 'de') {
+ return (string) \preg_replace(
+ [
+ '/(?:\s|^)(\d+)(?: )*€(?:\s|$)/',
+ '/(?:\s|^)\$(?: )*(\d+)(?:\s|$)/',
+ '/(?:\s|^)£(?: )*(\d+)(?:\s|$)/',
+ '/(?:\s|^)¥(?: )*(\d+)(?:\s|$)/',
+ '/(?:\s|^)(\d+)[.|,](\d+)(?: )*€(?:\s|$)/',
+ '/(?:\s|^)\$(?: )*(\d+)[.|,](\d+)(?:\s|$)/',
+ '/(?:\s|^)£(?: )*(\d+)[.|,](\d+)(?:\s|$)/',
+ ],
+ [
+ ' \1 Euro ',
+ ' \1 Dollar ',
+ ' \1 Pound ',
+ ' \1 Yen ',
+ ' \1 Euro \2 Cent ',
+ ' \1 Dollar \2 Cent ',
+ ' \1 Pound \2 Pence ',
+ ],
+ $string
+ );
+ }
+
+ return (string) \preg_replace(
+ [
+ '/(?:\s|^)1(?: )*€(?:\s|$)/',
+ '/(?:\s|^)(\d+)(?: )*€(?:\s|$)/',
+ '/(?:\s|^)\$(?: )*1(?:\s|$)/',
+ '/(?:\s|^)\$(?: )*(\d+)(?:\s|$)/',
+ '/(?:\s|^)£(?: )*1(?:\s|$)/',
+ '/(?:\s|^)£(?: )*(\d+)(?:\s|$)/',
+ '/(?:\s|^)¥(?: )*(\d+)(?:\s|$)/',
+ '/(?:\s|^)1[.|,](\d+)(?: )*€(?:\s|$)/',
+ '/(?:\s|^)(\d+)[.|,](\d+)(?: )*€(?:\s|$)/',
+ '/(?:\s|^)1[.|,](\d+)(?: )*$(?:\s|$)/',
+ '/(?:\s|^)\$(?: )*(\d+)[.|,](\d+)(?:\s|$)/',
+ '/(?:\s|^)1[.|,](\d+)(?: )*£(?:\s|$)/',
+ '/(?:\s|^)£(?: )*(\d+)[.|,](\d+)(?:\s|$)/',
+ ],
+ [
+ ' 1 Euro ',
+ ' \1 Euros ',
+ ' 1 Dollar ',
+ ' \1 Dollars ',
+ ' 1 Pound ',
+ ' \1 Pounds ',
+ ' \1 Yen ',
+ ' 1 Euros \1 Cents ',
+ ' \1 Euros \2 Cents ',
+ ' 1 Dollars \1 Cents ',
+ ' \1 Dollars \2 Cents ',
+ ' 1 Pounds \1 Pence ',
+ ' \1 Pounds \2 Pence ',
+ ],
+ $string
+ );
+ }
+
+ /**
+ * Expands the special symbols that the given string may include, such as '@', '.', '#' and '%'.
+ *
+ * @param string $string
+ * @param string $language
+ *
+ * @return string
+ */
+ private static function expandSymbols(string $string, string $language = 'en')
+ {
+ if (
+ \strpos($string, '©') === false
+ &&
+ \strpos($string, '®') === false
+ &&
+ \strpos($string, '@') === false
+ &&
+ \strpos($string, '&') === false
+ &&
+ \strpos($string, '%') === false
+ &&
+ \strpos($string, '=') === false
+ ) {
+ return $string;
+ }
+
+ $maps = \voku\helper\ASCII::charsArray(true);
+
+ return (string) \preg_replace(
+ [
+ '/\s*©\s*/',
+ '/\s*®\s*/',
+ '/\s*@\s*/',
+ '/\s*&\s*/',
+ '/\s*%\s*/',
+ '/(\s*=\s*)/',
+ ],
+ [
+ $maps['latin_symbols']['©'],
+ $maps['latin_symbols']['®'],
+ $maps['latin_symbols']['@'],
+ $maps[$language]['&'] ?? '&',
+ $maps[$language]['%'] ?? '%',
+ $maps[$language]['='] ?? '=',
+ ],
+ $string
+ );
+ }
+
+ /**
+ * return the "self::$remove_list[$language]" array
+ *
+ * @param string $language
+ *
+ * @return array
+ */
+ private static function get_remove_list(string $language = 'en')
+ {
+ // check for language
+ if ($language === '') {
+ return [];
+ }
+
+ // set remove-array
+ if (!isset(self::$remove_list[$language])) {
+ self::reset_remove_list($language);
+ }
+
+ // check for array
+ if (
+ !isset(self::$remove_list[$language])
+ ||
+ empty(self::$remove_list[$language])
+ ) {
+ return [];
+ }
+
+ return self::$remove_list[$language];
+ }
}
diff --git a/system/vendor/jbroadway/urlify/composer.json b/system/vendor/jbroadway/urlify/composer.json
index 38846a2..2851ee5 100644
--- a/system/vendor/jbroadway/urlify/composer.json
+++ b/system/vendor/jbroadway/urlify/composer.json
@@ -1,8 +1,8 @@
{
"name": "jbroadway/urlify",
"type": "library",
- "description": "PHP port of URLify.js from the Django project. Transliterates non-ascii characters for use in URLs.",
- "keywords": ["urlify","transliterate","translit","transliteration","url","encode","slug","link","iconv"],
+ "description": "A fast PHP slug generator and transliteration library that converts non-ascii characters for use in URLs.",
+ "keywords": ["urlify","transliterate","translit","transliteration","url","encode","downcode","slug","slugify","slugs","link","iconv","blogging","blogs","unicode","ascii","seo"],
"homepage": "https://github.com/jbroadway/urlify",
"license": "BSD-3-Clause-Clear",
"authors": [
@@ -13,10 +13,12 @@
}
],
"require": {
- "php": ">=5.3.0"
+ "php": ">=7.2",
+ "voku/portable-ascii": "^2.0",
+ "voku/stop-words": "^2.0"
},
"require-dev": {
- "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5"
+ "phpunit/phpunit": "^8.5"
},
"autoload": {
"psr-0": { "URLify": "" }
diff --git a/system/vendor/jbroadway/urlify/scripts/downcode.php b/system/vendor/jbroadway/urlify/scripts/downcode.php
index f2a7fda..018e7d4 100644
--- a/system/vendor/jbroadway/urlify/scripts/downcode.php
+++ b/system/vendor/jbroadway/urlify/scripts/downcode.php
@@ -1,20 +1,25 @@
2) {
- die ("Usage (argument): php " . basename(__FILE__) . " \"\"\nUsage (pipe): | php " . basename(__FILE__) . "\n");
+require_once \dirname(__DIR__) . '/vendor/autoload.php';
+require_once \dirname(__DIR__) . '/URLify.php';
+
+// Print usage and exit if arguments are invalid
+if ($argc < 1 || $argc > 2) {
+ die('Usage (argument): php ' . \basename(__FILE__) . " \"\"\nUsage (pipe): | php " . \basename(__FILE__) . "\n");
}
-//Process the provided argument
-if($argc === 2) {
- $s = $argv[1];
-//Or read from stdin if the argument wasn't present
+// Process the provided argument
+$piped = false;
+if ($argc === 2) {
+ $s = $argv[1];
+// Or read from stdin if the argument wasn't present
} else {
- $piped = true;
- $s = file_get_contents("php://stdin");
+ $piped = true;
+ $s = \file_get_contents('php://stdin');
}
-echo URLify::downcode ($s) . ($piped ? "\n" : "");
+echo URLify::downcode($s) . ($piped ? "\n" : '');
diff --git a/system/vendor/jbroadway/urlify/scripts/filter.php b/system/vendor/jbroadway/urlify/scripts/filter.php
index aec6a0a..d20c315 100644
--- a/system/vendor/jbroadway/urlify/scripts/filter.php
+++ b/system/vendor/jbroadway/urlify/scripts/filter.php
@@ -1,20 +1,25 @@
2) {
- die ("Usage (argument): php " . basename(__FILE__) . " \"\"\nUsage (pipe): | php " . basename(__FILE__) . "\n");
+require_once \dirname(__DIR__) . '/vendor/autoload.php';
+require_once \dirname(__DIR__) . '/URLify.php';
+
+// Print usage and exit if arguments are invalid
+if ($argc < 1 || $argc > 2) {
+ die('Usage (argument): php ' . \basename(__FILE__) . " \"\"\nUsage (pipe): | php " . \basename(__FILE__) . "\n");
}
-//Process the provided argument
-if($argc === 2) {
- $s = $argv[1];
-//Or read from stdin if the argument wasn't present
+// Process the provided argument
+$piped = false;
+if ($argc === 2) {
+ $s = $argv[1];
+// Or read from stdin if the argument wasn't present
} else {
- $piped = true;
- $s = file_get_contents("php://stdin");
+ $piped = true;
+ $s = \file_get_contents('php://stdin');
}
-echo URLify::filter ($s) . ($piped ? "\n" : "");
+echo URLify::filter($s) . ($piped ? "\n" : '');
diff --git a/system/vendor/jbroadway/urlify/scripts/transliterate.php b/system/vendor/jbroadway/urlify/scripts/transliterate.php
index 258581b..1970b50 100644
--- a/system/vendor/jbroadway/urlify/scripts/transliterate.php
+++ b/system/vendor/jbroadway/urlify/scripts/transliterate.php
@@ -1,20 +1,25 @@
2) {
- die ("Usage (argument): php " . basename(__FILE__) . " \"\"\nUsage (pipe): | php " . basename(__FILE__) . "\n");
+require_once \dirname(__DIR__) . '/vendor/autoload.php';
+require_once \dirname(__DIR__) . '/URLify.php';
+
+// Print usage and exit if arguments are invalid
+if ($argc < 1 || $argc > 2) {
+ die('Usage (argument): php ' . \basename(__FILE__) . " \"\"\nUsage (pipe): | php " . \basename(__FILE__) . "\n");
}
-//Process the provided argument
-if($argc === 2) {
- $s = $argv[1];
-//Or read from stdin if the argument wasn't present
+// Process the provided argument
+$piped = false;
+if ($argc === 2) {
+ $s = $argv[1];
+// Or read from stdin if the argument wasn't present
} else {
- $piped = true;
- $s = file_get_contents("php://stdin");
+ $piped = true;
+ $s = \file_get_contents('php://stdin');
}
-echo URLify::transliterate($s) . ($piped ? "\n" : "");
+echo URLify::transliterate($s) . ($piped ? "\n" : '');
diff --git a/system/vendor/kanti/hub-updater/.travis.yml b/system/vendor/kanti/hub-updater/.travis.yml
index da6df2d..de6ba1c 100644
--- a/system/vendor/kanti/hub-updater/.travis.yml
+++ b/system/vendor/kanti/hub-updater/.travis.yml
@@ -1,6 +1,9 @@
# Required to run your project under the correct environment.
language: php
+addons:
+ code_climate:
+ repo_token: 857af03b99f4c907a8cf99f7e80f4beb4df5977847fad17445c6f3a7110d83a7
# allow_failures: Allow this build to fail under the specified environments.
# fast_finish: If your build fails do not continue trying to build, just stop.
@@ -10,28 +13,29 @@ matrix:
fast_finish: true
include:
- php: 5.3
- env: CODECLIMATE=yes
- php: 5.4
- php: 5.5
+ env: CODECLIMATE=yes
- php: 5.6
- php: 7.0
+ - php: 7.1
- php: hhvm
- php: nightly
# Commands to be run before your environment runs.
install:
- - composer install --dev --no-interaction
+ - composer install --dev --no-interaction --prefer-dist
- phpenv rehash
# Commands you want to run that will verify your build.
script:
- - ./vendor/bin/phpunit -c tests/phpunit.xml
- ./vendor/bin/phpcs --standard=PSR2 ./src ./tests -n
- ./vendor/bin/phpcpd ./src ./tests -n
+ - ./vendor/bin/phpunit -c tests/phpunit.xml
- >
if [[ "$CODECLIMATE" == "yes" ]]; then
- CODECLIMATE_REPO_TOKEN=857af03b99f4c907a8cf99f7e80f4beb4df5977847fad17445c6f3a7110d83a7 ./vendor/bin/test-reporter
+ CODECLIMATE_REPO_TOKEN=857af03b99f4c907a8cf99f7e80f4beb4df5977847fad17445c6f3a7110d83a7 ./vendor/bin/test-reporter -vvv
fi
# Customize when the notification emails are sent.
diff --git a/system/vendor/kanti/hub-updater/composer.json b/system/vendor/kanti/hub-updater/composer.json
index 5c5075d..b1ee8b3 100644
--- a/system/vendor/kanti/hub-updater/composer.json
+++ b/system/vendor/kanti/hub-updater/composer.json
@@ -10,20 +10,27 @@
"role": "Developer"
}
],
+ "config": {
+ "platform": {
+ "php": "5.3.6"
+ }
+ },
"support": {
"forum": "https://github.com/Kanti/hub-updater/issues",
"issues": "https://github.com/Kanti/hub-updater/issues",
"source": "https://github.com/Kanti/hub-updater"
},
- "minimum-stability": "dev",
"require": {
- "php": ">=5.3.0"
+ "php": ">=5.3.6",
+ "composer/ca-bundle": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "4.*",
- "squizlabs/php_codesniffer": "*",
- "sebastian/phpcpd": "*",
- "codeclimate/php-test-reporter": "dev-master"
+ "squizlabs/php_codesniffer": "2.*",
+ "friendsofphp/php-cs-fixer": "1.*",
+ "sebastian/phpcpd": "2.*",
+ "codeclimate/php-test-reporter": "0.*",
+ "phpro/grumphp": "0.*"
},
"autoload": {
"psr-4": {
diff --git a/system/vendor/kanti/hub-updater/grumphp.yml b/system/vendor/kanti/hub-updater/grumphp.yml
new file mode 100644
index 0000000..1342b89
--- /dev/null
+++ b/system/vendor/kanti/hub-updater/grumphp.yml
@@ -0,0 +1,20 @@
+parameters:
+ git_dir: .
+ bin_dir: vendor/bin
+ tasks:
+ phpcsfixer:
+ level: psr2
+ verbose: true
+ phpcs:
+ standard: PSR2
+ show_warnings: false
+ metadata:
+ priority: 300
+ phpunit:
+ config_file: tests/phpunit.xml
+ group: [fast]
+ metadata:
+ priority: 200
+ composer:
+ no_check_lock: true
+ yamllint: ~
diff --git a/system/vendor/kanti/hub-updater/src/CacheOneFile.php b/system/vendor/kanti/hub-updater/src/CacheOneFile.php
index e55e499..05eb98d 100644
--- a/system/vendor/kanti/hub-updater/src/CacheOneFile.php
+++ b/system/vendor/kanti/hub-updater/src/CacheOneFile.php
@@ -13,9 +13,9 @@ class CacheOneFile
$this->holdTime = $holdTime;
}
- public function is()
+ public function has()
{
- if (!HelperClass::fileExists($this->fileName)) {
+ if (!file_exists($this->fileName)) {
return false;
}
clearstatcache();
@@ -37,11 +37,11 @@ class CacheOneFile
array_pop($parts);
$directory = '';
foreach ($parts as $part) {
- $check_path = $directory . $part;
- if (is_dir($check_path . DIRECTORY_SEPARATOR) === false) {
- mkdir($check_path, 0755);
+ $checkPath = $directory . $part;
+ if (is_dir($checkPath . DIRECTORY_SEPARATOR) === false) {
+ mkdir($checkPath, 0755);
}
- $directory = $check_path . DIRECTORY_SEPARATOR;
+ $directory = $checkPath . DIRECTORY_SEPARATOR;
}
call_user_func_array('file_put_contents', $args);
}
diff --git a/system/vendor/kanti/hub-updater/src/HubUpdater.php b/system/vendor/kanti/hub-updater/src/HubUpdater.php
index f43536b..c5bdd88 100644
--- a/system/vendor/kanti/hub-updater/src/HubUpdater.php
+++ b/system/vendor/kanti/hub-updater/src/HubUpdater.php
@@ -1,9 +1,16 @@
"downloadInfo.json",
"holdTime" => 43200,
@@ -17,65 +24,79 @@ class HubUpdater
"cache" => "cache/",
"save" => "",
"prerelease" => false,
+ "auth" => null,
"exceptions" => false,
);
-
+ /**
+ * @var array
+ */
protected $allRelease = array();
+ /**
+ * @var array
+ */
+ protected $newestInfo = null;
+ /**
+ * @var array
+ */
+ protected $currentInfo = null;
+ /**
+ * @var null|resource
+ */
protected $streamContext = null;
+ /**
+ * @var null|resource
+ */
+ protected $streamContext2 = null;
+
+ /**
+ * HubUpdater constructor.
+ * @param array|string $option
+ * @throws \Exception
+ */
public function __construct($option)
{
- //options
- if (is_array($option)) {
- if (!isset($option['name']) || empty($option['name'])) {
- throw new \Exception('No Name in Option Set');
- }
- $this->options = $option + $this->options;
- } elseif (is_string($option)) {
- if (empty($option)) {
- throw new \Exception('No Name Set');
- }
- $this->options['name'] = $option;
- } else {
- throw new \Exception('No Option Set');
+ if (!in_array('https', stream_get_wrappers())) {
+ throw new \Exception("No HTTPS Wrapper Exception");
}
+ $this->setOptions($option);
$this->options['save'] = rtrim($this->options['save'], '/');
if ($this->options['save'] !== '') {
$this->options['save'] .= '/';
- if (!HelperClass::fileExists($this->options['save'])) {
+ if (!file_exists($this->options['save'])) {
mkdir($this->options['save']);
}
}
$this->options['cache'] = $this->options['save'] . rtrim($this->options['cache'], '/');
if ($this->options['cache'] !== '') {
$this->options['cache'] .= '/';
- if (!HelperClass::fileExists($this->options['cache'])) {
- mkdir(dirname($_SERVER["SCRIPT_FILENAME"]) . "/" . $this->options['cache']);
- }
- }
- $caBundleDir = dirname(__FILE__);
- if (HelperClass::isInPhar()) {
- $caBundleDir = dirname($_SERVER["SCRIPT_FILENAME"]) . "/" . $this->options['cache'];
- if (!HelperClass::fileExists($this->options['cache'] . "ca_bundle.crt")) {
- copy(dirname(__FILE__) . "/ca_bundle.crt", $caBundleDir . "ca_bundle.crt");
+ if (!file_exists($this->options['cache'])) {
+ mkdir($this->options['cache']);
}
}
$this->cachedInfo = new CacheOneFile(
- dirname($_SERVER["SCRIPT_FILENAME"]) . "/" . $this->options['cache'] . $this->options['cacheFile'],
+ $this->options['cache'] . $this->options['cacheFile'],
$this->options['holdTime']
);
+ $additionalHeader = '';
+ if ($this->options['auth']) {
+ $additionalHeader .= "Authorization: Basic " . base64_encode($this->options['auth']) . "\r\n";
+ }
+
+ $caFilePath = CaBundle::getSystemCaRootBundlePath();
$this->streamContext = stream_context_create(
array(
'http' => array(
'header' => "User-Agent: Awesome-Update-My-Self-" . $this->options['name'] . "\r\n"
- . "Accept: application/vnd.github.v3+json\r\n",
+ . "Accept: application/vnd.github.v3+json\r\n"
+ . $additionalHeader,
),
'ssl' => array(
- 'cafile' => $caBundleDir . '/ca_bundle.crt',
+ 'cafile' => $caFilePath,
'verify_peer' => true,
),
)
@@ -83,116 +104,90 @@ class HubUpdater
$this->streamContext2 = stream_context_create(
array(
'http' => array(
- 'header' => "User-Agent: Awesome-Update-My-Self-" . $this->options['name'] . "\r\n",
+ 'header' => "User-Agent: Awesome-Update-My-Self-" . $this->options['name'] . "\r\n"
+ . $additionalHeader,
),
'ssl' => array(
- 'cafile' => $caBundleDir . '/ca_bundle.crt',
+ 'cafile' => $caFilePath,
'verify_peer' => true,
),
)
);
- $this->allRelease = $this->getRemoteInfos();
+ $this->allRelease = $this->getRemoteInfo();
}
- protected function getRemoteInfos()
+ protected function getRemoteInfo()
{
- $path = "https://api.github.com/repos/" . $this->options['name'] . "/releases";
- if ($this->cachedInfo->is()) {
- $fileContent = $this->cachedInfo->get();
- } else {
- if (!in_array('https', stream_get_wrappers())) {
- if ($this->options["exceptions"]) {
- throw new \Exception("No HTTPS Wrapper Exception");
- } else {
- return array();
- }
- }
- $fileContent = @file_get_contents($path, false, $this->streamContext);
-
- if ($fileContent === false) {
- if ($this->options["exceptions"]) {
- throw new \Exception("No Internet Exception");
- } else {
- return array();
- }
- }
- $json = json_decode($fileContent, true);
- if (isset($json['message'])) {
- if ($this->options["exceptions"]) {
- throw new \Exception("API Exception[" . $json['message'] . "]");
- } else {
- $json = array();
- }
- }
- if (defined("JSON_PRETTY_PRINT")) {
- $fileContent = json_encode($json, JSON_PRETTY_PRINT);
- } else {
- $fileContent = json_encode($json);
- }
- $this->cachedInfo->set($fileContent);
-
- return $json;
+ if ($this->cachedInfo->has()) {
+ return json_decode($this->cachedInfo->get(), true);
}
+ $path = "https://api.github.com/repos/" . $this->options['name'] . "/releases";
+ $fileContent = @file_get_contents($path, false, $this->streamContext);
- return json_decode($fileContent, true);
+ if ($fileContent === false) {
+ if ($this->options["exceptions"]) {
+ throw new \Exception("HTTP Exception");
+ }
+ return array();
+ }
+ $json = json_decode($fileContent, true);
+ if (isset($json['message'])) {
+ if ($this->options["exceptions"]) {
+ throw new \Exception("API Exception[" . $json['message'] . "]");
+ }
+ $json = array();
+ }
+ $fileContent = json_encode($json, static::JSON_PRETTY_PRINT);
+ $this->cachedInfo->set($fileContent);
+
+ return $json;
}
+ /**
+ * @return bool
+ */
public function able()
{
- if (!in_array('https', stream_get_wrappers())) {
- return false;
- }
if (empty($this->allRelease)) {
return false;
}
+ $newestInfo = $this->getNewestInfo();
- $this->getNewestInfo();
-
- if (HelperClass::fileExists($this->options['cache'] . $this->options['versionFile'])) {
- $fileContent = file_get_contents(dirname($_SERVER["SCRIPT_FILENAME"]) . "/" . $this->options['cache'] . $this->options['versionFile']);
+ if (file_exists($this->options['cache'] . $this->options['versionFile'])) {
+ $fileContent = file_get_contents($this->options['cache'] . $this->options['versionFile']);
$current = json_decode($fileContent, true);
- if (isset($current['id']) && $current['id'] == $this->newestInfo['id']) {
+ if (isset($current['id']) && $current['id'] == $newestInfo['id']) {
return false;
}
- if (isset($current['tag_name']) && $current['tag_name'] == $this->newestInfo['tag_name']) {
+ if (isset($current['tag_name']) && $current['tag_name'] == $newestInfo['tag_name']) {
return false;
}
}
-
return true;
}
+ /**
+ * @return bool
+ */
public function update()
{
$newestRelease = $this->getNewestInfo();
if ($this->able()) {
if ($this->download($newestRelease['zipball_url'])) {
if ($this->unZip()) {
- unlink(dirname($_SERVER["SCRIPT_FILENAME"]) . "/" . $this->options['cache'] . $this->options['zipFile']);
- if (defined("JSON_PRETTY_PRINT")) {
- file_put_contents(
- dirname($_SERVER["SCRIPT_FILENAME"]) . "/" . $this->options['cache'] . $this->options['versionFile'],
- json_encode(array(
- "id" => $newestRelease['id'],
- "tag_name" => $newestRelease['tag_name']
- ), JSON_PRETTY_PRINT)
- );
- } else {
- file_put_contents(
- dirname($_SERVER["SCRIPT_FILENAME"]) . "/" . $this->options['cache'] . $this->options['versionFile'],
- json_encode(array(
- "id" => $newestRelease['id'],
- "tag_name" => $newestRelease['tag_name']
- ))
- );
- }
-
+ unlink($this->options['cache'] . $this->options['zipFile']);
+ file_put_contents(
+ $this->options['cache'] . $this->options['versionFile'],
+ json_encode(array(
+ "id" => $newestRelease['id'],
+ "tag_name" => $newestRelease['tag_name']
+ ), static::JSON_PRETTY_PRINT)
+ );
return true;
}
}
}
-
return false;
}
@@ -201,116 +196,147 @@ class HubUpdater
$file = @fopen($url, 'r', false, $this->streamContext2);
if ($file == false) {
if ($this->options["exceptions"]) {
- throw new \Exception("Download faild Exception");
- } else {
- return false;
+ throw new \Exception("Download failed Exception");
}
+ return false;
}
- file_put_contents(
- dirname($_SERVER['SCRIPT_FILENAME']) . "/" . $this->options['cache'] . $this->options['zipFile'],
- $file
- );
+ file_put_contents($this->options['cache'] . $this->options['zipFile'], $file);
fclose($file);
-
return true;
}
- protected function unZip()
+ protected function shouldBeCopied($file)
{
- $path = dirname($_SERVER['SCRIPT_FILENAME']) . "/" . $this->options['cache'] . $this->options['zipFile'];
- $updateIgnore = array();
- if (HelperClass::fileExists($this->options['updateignore'])) {
+ static $updateIgnore = array();
+ if (empty($updateIgnore) && file_exists($this->options['updateignore'])) {
$updateIgnore = file($this->options['updateignore']);
foreach ($updateIgnore as &$ignore) {
$ignore = $this->options['save'] . trim($ignore);
}
}
-
- $zip = new \ZipArchive();
- if ($zip->open($path) === true) {
- $cutLength = strlen($zip->getNameIndex(0));
- for ($i = 1; $i < $zip->numFiles; $i++) {//iterate throw the Zip
- $name = $this->options['save'] . substr($zip->getNameIndex($i), $cutLength);
-
- $do = true;
-
- foreach ($updateIgnore as $ignore) {
- if (substr($name, 0, strlen($ignore)) == $ignore) {
- $do = false;
- break;
- }
- }
-
- if ($do) {
- $stat = $zip->statIndex($i);
- if ($stat["crc"] == 0) {
- if (!HelperClass::fileExists($name)) {
- mkdir(dirname($_SERVER["SCRIPT_FILENAME"]) . "/" . $name);
- }
- } else {
- copy(
- "zip://" . $path . "#" . $zip->getNameIndex($i),
- dirname($_SERVER["SCRIPT_FILENAME"]) . "/" . $name
- );
- }
- }
+ foreach ($updateIgnore as $ignore) {
+ if (substr($file, 0, strlen($ignore)) == $ignore) {
+ return false;
}
- $zip->close();
-
- return true;
- } else {
- return false;
}
+ return true;
}
+ protected function unZip()
+ {
+ $path = getcwd() . "/" . $this->options['cache'] . $this->options['zipFile'];
+
+ $zip = new \ZipArchive();
+ if ($zip->open($path) !== true) {
+ return false;
+ }
+ $cutLength = strlen($zip->getNameIndex(0));
+ for ($i = 1; $i < $zip->numFiles; $i++) {
+ $name = $this->options['save'] . substr($zip->getNameIndex($i), $cutLength);
+
+ if ($this->shouldBeCopied($name)) {
+ $stat = $zip->statIndex($i);
+ if ($stat["crc"] == 0) { //is dir
+ if (!file_exists($name)) {
+ mkdir($name);
+ }
+ continue;
+ }
+ copy("zip://" . $path . "#" . $zip->getNameIndex($i), $name);
+ }
+ }
+ return $zip->close();
+ }
+
+ /**
+ * @return mixed|null
+ */
public function getCurrentInfo()
{
- if (isset($this->currentInfo)) {
- return $this->currentInfo;
- }
-
- $this->currentInfo = null;
- if (HelperClass::fileExists($this->options['cache'] . $this->options['versionFile'])) {
- $fileContent = file_get_contents(dirname($_SERVER["SCRIPT_FILENAME"]) . "/" . $this->options['cache'] . $this->options['versionFile']);
+ if (is_null($this->currentInfo) && file_exists($this->options['cache'] . $this->options['versionFile'])) {
+ $fileContent = file_get_contents($this->options['cache'] . $this->options['versionFile']);
$current = json_decode($fileContent, true);
foreach ($this->allRelease as $release) {
if (isset($current['id']) && $current['id'] == $release['id']) {
- $this->currentInfo = $release;
- break;
+ return $this->currentInfo = $release;
}
if (isset($current['tag_name']) && $current['tag_name'] == $release['tag_name']) {
- $this->currentInfo = $release;
- break;
+ return $this->currentInfo = $release;
}
}
}
return $this->currentInfo;
}
+ /**
+ * @return array|mixed
+ * @throws \Exception
+ */
public function getNewestInfo()
{
- if (isset($this->newestInfo)) {
- return $this->newestInfo;
- }
-
- foreach ($this->allRelease as $release) {
- if (!$this->options['prerelease'] && $release['prerelease']) {
- continue;
+ if (is_null($this->newestInfo)) {
+ foreach ($this->allRelease as $release) {
+ if (isset($release['prerelease']) && $release['prerelease'] && !$this->options['prerelease']) {
+ continue;
+ }
+ if (isset($release['target_commitish']) && $this->options['branch'] !== $release['target_commitish']) {
+ continue;
+ }
+ return $this->newestInfo = $release;
}
- if ($this->options['branch'] !== $release['target_commitish']) {
- continue;
- }
- $this->newestInfo = $release;
- break;
- }
- if (!isset($this->newestInfo)) {
if ($this->options["exceptions"]) {
throw new \Exception("no suitable release found");
- } else {
- return array();
}
+ $this->newestInfo = array();
}
return $this->newestInfo;
}
+
+ /**
+ * @return array
+ */
+ public function getOptions()
+ {
+ return $this->options;
+ }
+
+ /**
+ * @return array
+ */
+ public function getAllRelease()
+ {
+ return $this->allRelease;
+ }
+
+ /**
+ * @internal
+ * @param $option
+ * @throws \Exception
+ */
+ protected function setOptions($option)
+ {
+ if (is_array($option)) {
+ if (!isset($option['name']) || empty($option['name'])) {
+ throw new \Exception('No Name in Option Set');
+ }
+ $this->options = $option + $this->options;
+ return;
+ } elseif (is_string($option)) {
+ if (empty($option)) {
+ throw new \Exception('No Name Set');
+ }
+ $this->options['name'] = $option;
+ return;
+ }
+ throw new \Exception('No Option Set type ' . gettype($option) . ' not supported');
+ }
+
+ /**
+ * @return null|resource
+ */
+ public function getStreamContext()
+ {
+ return $this->streamContext;
+ }
}
diff --git a/system/vendor/michelf/php-markdown/.travis.yml b/system/vendor/michelf/php-markdown/.travis.yml
index d467147..440045b 100644
--- a/system/vendor/michelf/php-markdown/.travis.yml
+++ b/system/vendor/michelf/php-markdown/.travis.yml
@@ -1,25 +1,29 @@
language: php
-sudo: false
+matrix:
+ include:
+ - php: hhvm-3.18
+ dist: trusty
+ - php: 5.3
+ dist: precise
+ - php: 5.4
+ dist: trusty
+ - php: 5.5
+ dist: trusty
+ - php: 5.6
+ dist: xenial
+ - php: 7.0
+ dist: xenial
+ - php: 7.1
+ dist: bionic
+ - php: 7.2
+ dist: bionic
+ - php: 7.3
+ dist: bionic
+ - php: 7.4
+ dist: bionic
-cache:
- directories:
- - $HOME/.composer/
-
-# Run tests against all these PHP versions
-# TODO: When it becomes possible in TravisCI, switch 7.4snapshot to plain 7.4
-php:
- - 5.4
- - 5.5
- - 5.6
- - 7.0
- - 7.1
- - 7.2
- - 7.3
- - 7.4snapshot
- - hhvm
-
-before_script:
+install:
- composer install --prefer-dist
script:
diff --git a/system/vendor/michelf/php-markdown/License.md b/system/vendor/michelf/php-markdown/License.md
index 16bbd54..25d1e16 100644
--- a/system/vendor/michelf/php-markdown/License.md
+++ b/system/vendor/michelf/php-markdown/License.md
@@ -1,5 +1,5 @@
PHP Markdown Lib
-Copyright (c) 2004-2019 Michel Fortin
+Copyright (c) 2004-2021 Michel Fortin
All rights reserved.
diff --git a/system/vendor/michelf/php-markdown/Michelf/Markdown.php b/system/vendor/michelf/php-markdown/Michelf/Markdown.php
index 43b3c79..f644080 100644
--- a/system/vendor/michelf/php-markdown/Michelf/Markdown.php
+++ b/system/vendor/michelf/php-markdown/Michelf/Markdown.php
@@ -4,7 +4,7 @@
*
* @package php-markdown
* @author Michel Fortin
- * @copyright 2004-2019 Michel Fortin
+ * @copyright 2004-2021 Michel Fortin
* @copyright (Original Markdown) 2004-2006 John Gruber
*/
@@ -18,7 +18,7 @@ class Markdown implements MarkdownInterface {
* Define the package version
* @var string
*/
- const MARKDOWNLIB_VERSION = "1.9.0";
+ const MARKDOWNLIB_VERSION = "1.9.1";
/**
* Simple function interface - Initialize the parser and return the result
@@ -354,7 +354,7 @@ class Markdown implements MarkdownInterface {
$block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'.
'script|noscript|style|form|fieldset|iframe|math|svg|'.
'article|section|nav|aside|hgroup|header|footer|'.
- 'figure';
+ 'figure|details|summary';
// Regular expression for the content of a block tag.
$nested_tags_level = 4;
diff --git a/system/vendor/michelf/php-markdown/Michelf/MarkdownExtra.php b/system/vendor/michelf/php-markdown/Michelf/MarkdownExtra.php
index c11a233..627d4e3 100644
--- a/system/vendor/michelf/php-markdown/Michelf/MarkdownExtra.php
+++ b/system/vendor/michelf/php-markdown/Michelf/MarkdownExtra.php
@@ -4,7 +4,7 @@
*
* @package php-markdown
* @author Michel Fortin
- * @copyright 2004-2019 Michel Fortin
+ * @copyright 2004-2021 Michel Fortin
* @copyright (Original Markdown) 2004-2006 John Gruber
*/
@@ -139,7 +139,6 @@ class MarkdownExtra extends \Michelf\Markdown {
);
$this->span_gamut += array(
"doFootnotes" => 5,
- "doStrikethrough" => 55,
"doAbbreviations" => 70,
);
@@ -346,7 +345,7 @@ class MarkdownExtra extends \Michelf\Markdown {
* Tags that are always treated as block tags
* @var string
*/
- protected $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend|article|section|nav|aside|hgroup|header|footer|figcaption|figure';
+ protected $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend|article|section|nav|aside|hgroup|header|footer|figcaption|figure|details|summary';
/**
* Tags treated as block tags only if the opening tag is alone on its line
@@ -933,6 +932,7 @@ class MarkdownExtra extends \Michelf\Markdown {
protected function _doAnchors_inline_callback($matches) {
$link_text = $this->runSpanGamut($matches[2]);
$url = $matches[3] === '' ? $matches[4] : $matches[3];
+ $title_quote =& $matches[6];
$title =& $matches[7];
$attr = $this->doExtraAttributes("a", $dummy =& $matches[8]);
@@ -945,7 +945,7 @@ class MarkdownExtra extends \Michelf\Markdown {
$url = $this->encodeURLAttribute($url);
$result = "encodeAttribute($title);
$result .= " title=\"$title\"";
}
@@ -1057,13 +1057,14 @@ class MarkdownExtra extends \Michelf\Markdown {
protected function _doImages_inline_callback($matches) {
$alt_text = $matches[2];
$url = $matches[3] === '' ? $matches[4] : $matches[3];
+ $title_quote =& $matches[6];
$title =& $matches[7];
$attr = $this->doExtraAttributes("img", $dummy =& $matches[8]);
$alt_text = $this->encodeAttribute($alt_text);
$url = $this->encodeURLAttribute($url);
$result = " encodeAttribute($title);
$result .= " title=\"$title\""; // $title already quoted
}
@@ -1891,7 +1892,7 @@ class MarkdownExtra extends \Michelf\Markdown {
}
return $matches[0];
}
-
+
protected function doStrikethrough($text) {
#
# Strikethrough:
@@ -1918,5 +1919,5 @@ class MarkdownExtra extends \Michelf\Markdown {
return implode('', $parts);
}
-
+
}
diff --git a/system/vendor/michelf/php-markdown/Michelf/MarkdownInterface.php b/system/vendor/michelf/php-markdown/Michelf/MarkdownInterface.php
index 0064524..32069df 100644
--- a/system/vendor/michelf/php-markdown/Michelf/MarkdownInterface.php
+++ b/system/vendor/michelf/php-markdown/Michelf/MarkdownInterface.php
@@ -4,7 +4,7 @@
*
* @package php-markdown
* @author Michel Fortin
- * @copyright 2004-2019 Michel Fortin
+ * @copyright 2004-2021 Michel Fortin
* @copyright (Original Markdown) 2004-2006 John Gruber
*/
diff --git a/system/vendor/michelf/php-markdown/Readme.md b/system/vendor/michelf/php-markdown/Readme.md
index e1eb306..1a0ee06 100644
--- a/system/vendor/michelf/php-markdown/Readme.md
+++ b/system/vendor/michelf/php-markdown/Readme.md
@@ -1,7 +1,7 @@
PHP Markdown
============
-PHP Markdown Lib 1.9.0 - 1 Dec 2019
+PHP Markdown Lib 1.9.1 - 23 Nov 2021
by Michel Fortin
@@ -183,6 +183,17 @@ PHP Markdown, please visit [michelf.ca/donate].
Version History
---------------
+PHP Markdown Lib 1.9.1 (23 Nov 2021)
+
+* Now treating `` and `` as block level so they don't
+ get wrapped in ``.
+ (Thanks to Thomas Hochstein for the fix.)
+
+* Fix for unintended blank title attribute when adding supplementary attributes
+ to a link in Markdown Extra.
+ (Thanks to Richie Black for the fix.)
+
+
PHP Markdown Lib 1.9.0 (1 Dec 2019)
* Added `fn_backlink_label` configuration variable to put some text in the
@@ -399,7 +410,7 @@ Copyright and License
---------------------
PHP Markdown Lib
-Copyright (c) 2004-2019 Michel Fortin
+Copyright (c) 2004-2021 Michel Fortin
All rights reserved.
diff --git a/system/vendor/michelf/php-markdown/test/helpers/MarkdownTestHelper.php b/system/vendor/michelf/php-markdown/test/helpers/MarkdownTestHelper.php
index 545dabd..ffca0c9 100644
--- a/system/vendor/michelf/php-markdown/test/helpers/MarkdownTestHelper.php
+++ b/system/vendor/michelf/php-markdown/test/helpers/MarkdownTestHelper.php
@@ -20,7 +20,7 @@ class MarkdownTestHelper
RecursiveRegexIterator::GET_MATCH
);
- $dataValues = [];
+ $dataValues = array();
/** @var SplFileInfo $inputFile */
foreach ($regexIterator as $inputFiles) {
@@ -31,7 +31,7 @@ class MarkdownTestHelper
$expectedHtmlPath = substr($inputMarkdownPath, 0, -4) . 'html';
$xhtml = false;
}
- $dataValues[] = [$inputMarkdownPath, $expectedHtmlPath, $xhtml];
+ $dataValues[] = array($inputMarkdownPath, $expectedHtmlPath, $xhtml);
}
}
diff --git a/system/vendor/michelf/php-markdown/test/resources/php-markdown.mdtest/Inline HTML (Simple).html b/system/vendor/michelf/php-markdown/test/resources/php-markdown.mdtest/Inline HTML (Simple).html
index 1451d62..efb6763 100644
--- a/system/vendor/michelf/php-markdown/test/resources/php-markdown.mdtest/Inline HTML (Simple).html
+++ b/system/vendor/michelf/php-markdown/test/resources/php-markdown.mdtest/Inline HTML (Simple).html
@@ -14,6 +14,13 @@
+Details and Summary:
+
+
+ Some details
+ More info about the details.
+
+
Regression:
diff --git a/system/vendor/michelf/php-markdown/test/resources/php-markdown.mdtest/Inline HTML (Simple).text b/system/vendor/michelf/php-markdown/test/resources/php-markdown.mdtest/Inline HTML (Simple).text
index 359b622..7b67dde 100644
--- a/system/vendor/michelf/php-markdown/test/resources/php-markdown.mdtest/Inline HTML (Simple).text
+++ b/system/vendor/michelf/php-markdown/test/resources/php-markdown.mdtest/Inline HTML (Simple).text
@@ -14,6 +14,13 @@ Hr's:
+Details and Summary:
+
+
+ Some details
+ More info about the details.
+
+
Regression:
diff --git a/system/vendor/paragonie/constant_time_encoding/LICENSE.txt b/system/vendor/paragonie/constant_time_encoding/LICENSE.txt
new file mode 100644
index 0000000..91acaca
--- /dev/null
+++ b/system/vendor/paragonie/constant_time_encoding/LICENSE.txt
@@ -0,0 +1,48 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 - 2022 Paragon Initiative Enterprises
+
+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.
+
+------------------------------------------------------------------------------
+This library was based on the work of Steve "Sc00bz" Thomas.
+------------------------------------------------------------------------------
+
+The MIT License (MIT)
+
+Copyright (c) 2014 Steve Thomas
+
+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.
+
diff --git a/system/vendor/paragonie/constant_time_encoding/README.md b/system/vendor/paragonie/constant_time_encoding/README.md
new file mode 100644
index 0000000..d2572e9
--- /dev/null
+++ b/system/vendor/paragonie/constant_time_encoding/README.md
@@ -0,0 +1,84 @@
+# Constant-Time Encoding
+
+[](https://github.com/paragonie/constant_time_encoding/actions)
+[](https://packagist.org/packages/paragonie/constant_time_encoding)
+[](https://packagist.org/packages/paragonie/constant_time_encoding)
+[](https://packagist.org/packages/paragonie/constant_time_encoding)
+[](https://packagist.org/packages/paragonie/constant_time_encoding)
+
+Based on the [constant-time base64 implementation made by Steve "Sc00bz" Thomas](https://github.com/Sc00bz/ConstTimeEncoding),
+this library aims to offer character encoding functions that do not leak
+information about what you are encoding/decoding via processor cache
+misses. Further reading on [cache-timing attacks](http://blog.ircmaxell.com/2014/11/its-all-about-time.html).
+
+Our fork offers the following enhancements:
+
+* `mbstring.func_overload` resistance
+* Unit tests
+* Composer- and Packagist-ready
+* Base16 encoding
+* Base32 encoding
+* Uses `pack()` and `unpack()` instead of `chr()` and `ord()`
+
+## PHP Version Requirements
+
+Version 2 of this library should work on **PHP 7** or newer. For PHP 5
+support, see [the v1.x branch](https://github.com/paragonie/constant_time_encoding/tree/v1.x).
+
+If you are adding this as a dependency to a project intended to work on both PHP 5 and PHP 7, please set the required version to `^1|^2` instead of just `^1` or `^2`.
+
+## How to Install
+
+```sh
+composer require paragonie/constant_time_encoding
+```
+
+## How to Use
+
+```php
+use ParagonIE\ConstantTime\Encoding;
+
+// possibly (if applicable):
+// require 'vendor/autoload.php';
+
+$data = random_bytes(32);
+echo Encoding::base64Encode($data), "\n";
+echo Encoding::base32EncodeUpper($data), "\n";
+echo Encoding::base32Encode($data), "\n";
+echo Encoding::hexEncode($data), "\n";
+echo Encoding::hexEncodeUpper($data), "\n";
+```
+
+Example output:
+
+```
+1VilPkeVqirlPifk5scbzcTTbMT2clp+Zkyv9VFFasE=
+2VMKKPSHSWVCVZJ6E7SONRY3ZXCNG3GE6ZZFU7TGJSX7KUKFNLAQ====
+2vmkkpshswvcvzj6e7sonry3zxcng3ge6zzfu7tgjsx7kukfnlaq====
+d558a53e4795aa2ae53e27e4e6c71bcdc4d36cc4f6725a7e664caff551456ac1
+D558A53E4795AA2AE53E27E4E6C71BDCC4D36CC4F6725A7E664CAFF551456AC1
+```
+
+If you only need a particular variant, you can just reference the
+required class like so:
+
+```php
+use ParagonIE\ConstantTime\Base64;
+use ParagonIE\ConstantTime\Base32;
+
+$data = random_bytes(32);
+echo Base64::encode($data), "\n";
+echo Base32::encode($data), "\n";
+```
+
+Example output:
+
+```
+1VilPkeVqirlPifk5scbzcTTbMT2clp+Zkyv9VFFasE=
+2vmkkpshswvcvzj6e7sonry3zxcng3ge6zzfu7tgjsx7kukfnlaq====
+```
+
+## Support Contracts
+
+If your company uses this library in their products or services, you may be
+interested in [purchasing a support contract from Paragon Initiative Enterprises](https://paragonie.com/enterprise).
diff --git a/system/vendor/paragonie/constant_time_encoding/composer.json b/system/vendor/paragonie/constant_time_encoding/composer.json
new file mode 100644
index 0000000..2fe9717
--- /dev/null
+++ b/system/vendor/paragonie/constant_time_encoding/composer.json
@@ -0,0 +1,56 @@
+{
+ "name": "paragonie/constant_time_encoding",
+ "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
+ "keywords": [
+ "base64",
+ "encoding",
+ "rfc4648",
+ "base32",
+ "base16",
+ "hex",
+ "bin2hex",
+ "hex2bin",
+ "base64_encode",
+ "base64_decode",
+ "base32_encode",
+ "base32_decode"
+ ],
+ "license": "MIT",
+ "type": "library",
+ "authors": [
+ {
+ "name": "Paragon Initiative Enterprises",
+ "email": "security@paragonie.com",
+ "homepage": "https://paragonie.com",
+ "role": "Maintainer"
+ },
+ {
+ "name": "Steve 'Sc00bz' Thomas",
+ "email": "steve@tobtu.com",
+ "homepage": "https://www.tobtu.com",
+ "role": "Original Developer"
+ }
+ ],
+ "support": {
+ "issues": "https://github.com/paragonie/constant_time_encoding/issues",
+ "email": "info@paragonie.com",
+ "source": "https://github.com/paragonie/constant_time_encoding"
+ },
+ "require": {
+ "php": "^7|^8"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^6|^7|^8|^9",
+ "vimeo/psalm": "^1|^2|^3|^4"
+ },
+ "autoload": {
+ "psr-4": {
+ "ParagonIE\\ConstantTime\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "ParagonIE\\ConstantTime\\Tests\\": "tests/"
+ }
+ }
+}
diff --git a/system/vendor/paragonie/constant_time_encoding/src/Base32.php b/system/vendor/paragonie/constant_time_encoding/src/Base32.php
new file mode 100644
index 0000000..48d00b9
--- /dev/null
+++ b/system/vendor/paragonie/constant_time_encoding/src/Base32.php
@@ -0,0 +1,541 @@
+ 96 && $src < 123) $ret += $src - 97 + 1; // -64
+ $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 96);
+
+ // if ($src > 0x31 && $src < 0x38) $ret += $src - 24 + 1; // -23
+ $ret += (((0x31 - $src) & ($src - 0x38)) >> 8) & ($src - 23);
+
+ return $ret;
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 5-bit integers
+ * into 8-bit integers.
+ *
+ * Uppercase variant.
+ *
+ * @param int $src
+ * @return int
+ */
+ protected static function decode5BitsUpper(int $src): int
+ {
+ $ret = -1;
+
+ // if ($src > 64 && $src < 91) $ret += $src - 65 + 1; // -64
+ $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64);
+
+ // if ($src > 0x31 && $src < 0x38) $ret += $src - 24 + 1; // -23
+ $ret += (((0x31 - $src) & ($src - 0x38)) >> 8) & ($src - 23);
+
+ return $ret;
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+ * into 5-bit integers.
+ *
+ * @param int $src
+ * @return string
+ */
+ protected static function encode5Bits(int $src): string
+ {
+ $diff = 0x61;
+
+ // if ($src > 25) $ret -= 72;
+ $diff -= ((25 - $src) >> 8) & 73;
+
+ return \pack('C', $src + $diff);
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+ * into 5-bit integers.
+ *
+ * Uppercase variant.
+ *
+ * @param int $src
+ * @return string
+ */
+ protected static function encode5BitsUpper(int $src): string
+ {
+ $diff = 0x41;
+
+ // if ($src > 25) $ret -= 40;
+ $diff -= ((25 - $src) >> 8) & 41;
+
+ return \pack('C', $src + $diff);
+ }
+
+ /**
+ * @param string $encodedString
+ * @param bool $upper
+ * @return string
+ */
+ public static function decodeNoPadding(
+ #[\SensitiveParameter]
+ string $encodedString,
+ bool $upper = false
+ ): string {
+ $srcLen = Binary::safeStrlen($encodedString);
+ if ($srcLen === 0) {
+ return '';
+ }
+ if (($srcLen & 7) === 0) {
+ for ($j = 0; $j < 7 && $j < $srcLen; ++$j) {
+ if ($encodedString[$srcLen - $j - 1] === '=') {
+ throw new InvalidArgumentException(
+ "decodeNoPadding() doesn't tolerate padding"
+ );
+ }
+ }
+ }
+ return static::doDecode(
+ $encodedString,
+ $upper,
+ true
+ );
+ }
+
+ /**
+ * Base32 decoding
+ *
+ * @param string $src
+ * @param bool $upper
+ * @param bool $strictPadding
+ * @return string
+ *
+ * @throws TypeError
+ */
+ protected static function doDecode(
+ #[\SensitiveParameter]
+ string $src,
+ bool $upper = false,
+ bool $strictPadding = false
+ ): string {
+ // We do this to reduce code duplication:
+ $method = $upper
+ ? 'decode5BitsUpper'
+ : 'decode5Bits';
+
+ // Remove padding
+ $srcLen = Binary::safeStrlen($src);
+ if ($srcLen === 0) {
+ return '';
+ }
+ if ($strictPadding) {
+ if (($srcLen & 7) === 0) {
+ for ($j = 0; $j < 7; ++$j) {
+ if ($src[$srcLen - 1] === '=') {
+ $srcLen--;
+ } else {
+ break;
+ }
+ }
+ }
+ if (($srcLen & 7) === 1) {
+ throw new RangeException(
+ 'Incorrect padding'
+ );
+ }
+ } else {
+ $src = \rtrim($src, '=');
+ $srcLen = Binary::safeStrlen($src);
+ }
+
+ $err = 0;
+ $dest = '';
+ // Main loop (no padding):
+ for ($i = 0; $i + 8 <= $srcLen; $i += 8) {
+ /** @var array $chunk */
+ $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 8));
+ /** @var int $c0 */
+ $c0 = static::$method($chunk[1]);
+ /** @var int $c1 */
+ $c1 = static::$method($chunk[2]);
+ /** @var int $c2 */
+ $c2 = static::$method($chunk[3]);
+ /** @var int $c3 */
+ $c3 = static::$method($chunk[4]);
+ /** @var int $c4 */
+ $c4 = static::$method($chunk[5]);
+ /** @var int $c5 */
+ $c5 = static::$method($chunk[6]);
+ /** @var int $c6 */
+ $c6 = static::$method($chunk[7]);
+ /** @var int $c7 */
+ $c7 = static::$method($chunk[8]);
+
+ $dest .= \pack(
+ 'CCCCC',
+ (($c0 << 3) | ($c1 >> 2) ) & 0xff,
+ (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff,
+ (($c3 << 4) | ($c4 >> 1) ) & 0xff,
+ (($c4 << 7) | ($c5 << 2) | ($c6 >> 3)) & 0xff,
+ (($c6 << 5) | ($c7 ) ) & 0xff
+ );
+ $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5 | $c6 | $c7) >> 8;
+ }
+ // The last chunk, which may have padding:
+ if ($i < $srcLen) {
+ /** @var array $chunk */
+ $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i));
+ /** @var int $c0 */
+ $c0 = static::$method($chunk[1]);
+
+ if ($i + 6 < $srcLen) {
+ /** @var int $c1 */
+ $c1 = static::$method($chunk[2]);
+ /** @var int $c2 */
+ $c2 = static::$method($chunk[3]);
+ /** @var int $c3 */
+ $c3 = static::$method($chunk[4]);
+ /** @var int $c4 */
+ $c4 = static::$method($chunk[5]);
+ /** @var int $c5 */
+ $c5 = static::$method($chunk[6]);
+ /** @var int $c6 */
+ $c6 = static::$method($chunk[7]);
+
+ $dest .= \pack(
+ 'CCCC',
+ (($c0 << 3) | ($c1 >> 2) ) & 0xff,
+ (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff,
+ (($c3 << 4) | ($c4 >> 1) ) & 0xff,
+ (($c4 << 7) | ($c5 << 2) | ($c6 >> 3)) & 0xff
+ );
+ $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5 | $c6) >> 8;
+ if ($strictPadding) {
+ $err |= ($c6 << 5) & 0xff;
+ }
+ } elseif ($i + 5 < $srcLen) {
+ /** @var int $c1 */
+ $c1 = static::$method($chunk[2]);
+ /** @var int $c2 */
+ $c2 = static::$method($chunk[3]);
+ /** @var int $c3 */
+ $c3 = static::$method($chunk[4]);
+ /** @var int $c4 */
+ $c4 = static::$method($chunk[5]);
+ /** @var int $c5 */
+ $c5 = static::$method($chunk[6]);
+
+ $dest .= \pack(
+ 'CCCC',
+ (($c0 << 3) | ($c1 >> 2) ) & 0xff,
+ (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff,
+ (($c3 << 4) | ($c4 >> 1) ) & 0xff,
+ (($c4 << 7) | ($c5 << 2) ) & 0xff
+ );
+ $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5) >> 8;
+ } elseif ($i + 4 < $srcLen) {
+ /** @var int $c1 */
+ $c1 = static::$method($chunk[2]);
+ /** @var int $c2 */
+ $c2 = static::$method($chunk[3]);
+ /** @var int $c3 */
+ $c3 = static::$method($chunk[4]);
+ /** @var int $c4 */
+ $c4 = static::$method($chunk[5]);
+
+ $dest .= \pack(
+ 'CCC',
+ (($c0 << 3) | ($c1 >> 2) ) & 0xff,
+ (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff,
+ (($c3 << 4) | ($c4 >> 1) ) & 0xff
+ );
+ $err |= ($c0 | $c1 | $c2 | $c3 | $c4) >> 8;
+ if ($strictPadding) {
+ $err |= ($c4 << 7) & 0xff;
+ }
+ } elseif ($i + 3 < $srcLen) {
+ /** @var int $c1 */
+ $c1 = static::$method($chunk[2]);
+ /** @var int $c2 */
+ $c2 = static::$method($chunk[3]);
+ /** @var int $c3 */
+ $c3 = static::$method($chunk[4]);
+
+ $dest .= \pack(
+ 'CC',
+ (($c0 << 3) | ($c1 >> 2) ) & 0xff,
+ (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff
+ );
+ $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
+ if ($strictPadding) {
+ $err |= ($c3 << 4) & 0xff;
+ }
+ } elseif ($i + 2 < $srcLen) {
+ /** @var int $c1 */
+ $c1 = static::$method($chunk[2]);
+ /** @var int $c2 */
+ $c2 = static::$method($chunk[3]);
+
+ $dest .= \pack(
+ 'CC',
+ (($c0 << 3) | ($c1 >> 2) ) & 0xff,
+ (($c1 << 6) | ($c2 << 1) ) & 0xff
+ );
+ $err |= ($c0 | $c1 | $c2) >> 8;
+ if ($strictPadding) {
+ $err |= ($c2 << 6) & 0xff;
+ }
+ } elseif ($i + 1 < $srcLen) {
+ /** @var int $c1 */
+ $c1 = static::$method($chunk[2]);
+
+ $dest .= \pack(
+ 'C',
+ (($c0 << 3) | ($c1 >> 2) ) & 0xff
+ );
+ $err |= ($c0 | $c1) >> 8;
+ if ($strictPadding) {
+ $err |= ($c1 << 6) & 0xff;
+ }
+ } else {
+ $dest .= \pack(
+ 'C',
+ (($c0 << 3) ) & 0xff
+ );
+ $err |= ($c0) >> 8;
+ }
+ }
+ $check = ($err === 0);
+ if (!$check) {
+ throw new RangeException(
+ 'Base32::doDecode() only expects characters in the correct base32 alphabet'
+ );
+ }
+ return $dest;
+ }
+
+ /**
+ * Base32 Encoding
+ *
+ * @param string $src
+ * @param bool $upper
+ * @param bool $pad
+ * @return string
+ * @throws TypeError
+ */
+ protected static function doEncode(
+ #[\SensitiveParameter]
+ string $src,
+ bool $upper = false,
+ $pad = true
+ ): string {
+ // We do this to reduce code duplication:
+ $method = $upper
+ ? 'encode5BitsUpper'
+ : 'encode5Bits';
+
+ $dest = '';
+ $srcLen = Binary::safeStrlen($src);
+
+ // Main loop (no padding):
+ for ($i = 0; $i + 5 <= $srcLen; $i += 5) {
+ /** @var array $chunk */
+ $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 5));
+ $b0 = $chunk[1];
+ $b1 = $chunk[2];
+ $b2 = $chunk[3];
+ $b3 = $chunk[4];
+ $b4 = $chunk[5];
+ $dest .=
+ static::$method( ($b0 >> 3) & 31) .
+ static::$method((($b0 << 2) | ($b1 >> 6)) & 31) .
+ static::$method((($b1 >> 1) ) & 31) .
+ static::$method((($b1 << 4) | ($b2 >> 4)) & 31) .
+ static::$method((($b2 << 1) | ($b3 >> 7)) & 31) .
+ static::$method((($b3 >> 2) ) & 31) .
+ static::$method((($b3 << 3) | ($b4 >> 5)) & 31) .
+ static::$method( $b4 & 31);
+ }
+ // The last chunk, which may have padding:
+ if ($i < $srcLen) {
+ /** @var array $chunk */
+ $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i));
+ $b0 = $chunk[1];
+ if ($i + 3 < $srcLen) {
+ $b1 = $chunk[2];
+ $b2 = $chunk[3];
+ $b3 = $chunk[4];
+ $dest .=
+ static::$method( ($b0 >> 3) & 31) .
+ static::$method((($b0 << 2) | ($b1 >> 6)) & 31) .
+ static::$method((($b1 >> 1) ) & 31) .
+ static::$method((($b1 << 4) | ($b2 >> 4)) & 31) .
+ static::$method((($b2 << 1) | ($b3 >> 7)) & 31) .
+ static::$method((($b3 >> 2) ) & 31) .
+ static::$method((($b3 << 3) ) & 31);
+ if ($pad) {
+ $dest .= '=';
+ }
+ } elseif ($i + 2 < $srcLen) {
+ $b1 = $chunk[2];
+ $b2 = $chunk[3];
+ $dest .=
+ static::$method( ($b0 >> 3) & 31) .
+ static::$method((($b0 << 2) | ($b1 >> 6)) & 31) .
+ static::$method((($b1 >> 1) ) & 31) .
+ static::$method((($b1 << 4) | ($b2 >> 4)) & 31) .
+ static::$method((($b2 << 1) ) & 31);
+ if ($pad) {
+ $dest .= '===';
+ }
+ } elseif ($i + 1 < $srcLen) {
+ $b1 = $chunk[2];
+ $dest .=
+ static::$method( ($b0 >> 3) & 31) .
+ static::$method((($b0 << 2) | ($b1 >> 6)) & 31) .
+ static::$method((($b1 >> 1) ) & 31) .
+ static::$method((($b1 << 4) ) & 31);
+ if ($pad) {
+ $dest .= '====';
+ }
+ } else {
+ $dest .=
+ static::$method( ($b0 >> 3) & 31) .
+ static::$method( ($b0 << 2) & 31);
+ if ($pad) {
+ $dest .= '======';
+ }
+ }
+ }
+ return $dest;
+ }
+}
diff --git a/system/vendor/paragonie/constant_time_encoding/src/Base32Hex.php b/system/vendor/paragonie/constant_time_encoding/src/Base32Hex.php
new file mode 100644
index 0000000..b868dd0
--- /dev/null
+++ b/system/vendor/paragonie/constant_time_encoding/src/Base32Hex.php
@@ -0,0 +1,111 @@
+ 0x30 && $src < 0x3a) ret += $src - 0x2e + 1; // -47
+ $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src - 47);
+
+ // if ($src > 0x60 && $src < 0x77) ret += $src - 0x61 + 10 + 1; // -86
+ $ret += (((0x60 - $src) & ($src - 0x77)) >> 8) & ($src - 86);
+
+ return $ret;
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 5-bit integers
+ * into 8-bit integers.
+ *
+ * @param int $src
+ * @return int
+ */
+ protected static function decode5BitsUpper(int $src): int
+ {
+ $ret = -1;
+
+ // if ($src > 0x30 && $src < 0x3a) ret += $src - 0x2e + 1; // -47
+ $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src - 47);
+
+ // if ($src > 0x40 && $src < 0x57) ret += $src - 0x41 + 10 + 1; // -54
+ $ret += (((0x40 - $src) & ($src - 0x57)) >> 8) & ($src - 54);
+
+ return $ret;
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+ * into 5-bit integers.
+ *
+ * @param int $src
+ * @return string
+ */
+ protected static function encode5Bits(int $src): string
+ {
+ $src += 0x30;
+
+ // if ($src > 0x39) $src += 0x61 - 0x3a; // 39
+ $src += ((0x39 - $src) >> 8) & 39;
+
+ return \pack('C', $src);
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+ * into 5-bit integers.
+ *
+ * Uppercase variant.
+ *
+ * @param int $src
+ * @return string
+ */
+ protected static function encode5BitsUpper(int $src): string
+ {
+ $src += 0x30;
+
+ // if ($src > 0x39) $src += 0x41 - 0x3a; // 7
+ $src += ((0x39 - $src) >> 8) & 7;
+
+ return \pack('C', $src);
+ }
+}
\ No newline at end of file
diff --git a/system/vendor/paragonie/constant_time_encoding/src/Base64.php b/system/vendor/paragonie/constant_time_encoding/src/Base64.php
new file mode 100644
index 0000000..2e3ecc8
--- /dev/null
+++ b/system/vendor/paragonie/constant_time_encoding/src/Base64.php
@@ -0,0 +1,319 @@
+ $chunk */
+ $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 3));
+ $b0 = $chunk[1];
+ $b1 = $chunk[2];
+ $b2 = $chunk[3];
+
+ $dest .=
+ static::encode6Bits( $b0 >> 2 ) .
+ static::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
+ static::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) .
+ static::encode6Bits( $b2 & 63);
+ }
+ // The last chunk, which may have padding:
+ if ($i < $srcLen) {
+ /** @var array $chunk */
+ $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i));
+ $b0 = $chunk[1];
+ if ($i + 1 < $srcLen) {
+ $b1 = $chunk[2];
+ $dest .=
+ static::encode6Bits($b0 >> 2) .
+ static::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
+ static::encode6Bits(($b1 << 2) & 63);
+ if ($pad) {
+ $dest .= '=';
+ }
+ } else {
+ $dest .=
+ static::encode6Bits( $b0 >> 2) .
+ static::encode6Bits(($b0 << 4) & 63);
+ if ($pad) {
+ $dest .= '==';
+ }
+ }
+ }
+ return $dest;
+ }
+
+ /**
+ * decode from base64 into binary
+ *
+ * Base64 character set "./[A-Z][a-z][0-9]"
+ *
+ * @param string $encodedString
+ * @param bool $strictPadding
+ * @return string
+ *
+ * @throws RangeException
+ * @throws TypeError
+ */
+ public static function decode(
+ #[\SensitiveParameter]
+ string $encodedString,
+ bool $strictPadding = false
+ ): string {
+ // Remove padding
+ $srcLen = Binary::safeStrlen($encodedString);
+ if ($srcLen === 0) {
+ return '';
+ }
+
+ if ($strictPadding) {
+ if (($srcLen & 3) === 0) {
+ if ($encodedString[$srcLen - 1] === '=') {
+ $srcLen--;
+ if ($encodedString[$srcLen - 1] === '=') {
+ $srcLen--;
+ }
+ }
+ }
+ if (($srcLen & 3) === 1) {
+ throw new RangeException(
+ 'Incorrect padding'
+ );
+ }
+ if ($encodedString[$srcLen - 1] === '=') {
+ throw new RangeException(
+ 'Incorrect padding'
+ );
+ }
+ } else {
+ $encodedString = \rtrim($encodedString, '=');
+ $srcLen = Binary::safeStrlen($encodedString);
+ }
+
+ $err = 0;
+ $dest = '';
+ // Main loop (no padding):
+ for ($i = 0; $i + 4 <= $srcLen; $i += 4) {
+ /** @var array $chunk */
+ $chunk = \unpack('C*', Binary::safeSubstr($encodedString, $i, 4));
+ $c0 = static::decode6Bits($chunk[1]);
+ $c1 = static::decode6Bits($chunk[2]);
+ $c2 = static::decode6Bits($chunk[3]);
+ $c3 = static::decode6Bits($chunk[4]);
+
+ $dest .= \pack(
+ 'CCC',
+ ((($c0 << 2) | ($c1 >> 4)) & 0xff),
+ ((($c1 << 4) | ($c2 >> 2)) & 0xff),
+ ((($c2 << 6) | $c3 ) & 0xff)
+ );
+ $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
+ }
+ // The last chunk, which may have padding:
+ if ($i < $srcLen) {
+ /** @var array $chunk */
+ $chunk = \unpack('C*', Binary::safeSubstr($encodedString, $i, $srcLen - $i));
+ $c0 = static::decode6Bits($chunk[1]);
+
+ if ($i + 2 < $srcLen) {
+ $c1 = static::decode6Bits($chunk[2]);
+ $c2 = static::decode6Bits($chunk[3]);
+ $dest .= \pack(
+ 'CC',
+ ((($c0 << 2) | ($c1 >> 4)) & 0xff),
+ ((($c1 << 4) | ($c2 >> 2)) & 0xff)
+ );
+ $err |= ($c0 | $c1 | $c2) >> 8;
+ if ($strictPadding) {
+ $err |= ($c2 << 6) & 0xff;
+ }
+ } elseif ($i + 1 < $srcLen) {
+ $c1 = static::decode6Bits($chunk[2]);
+ $dest .= \pack(
+ 'C',
+ ((($c0 << 2) | ($c1 >> 4)) & 0xff)
+ );
+ $err |= ($c0 | $c1) >> 8;
+ if ($strictPadding) {
+ $err |= ($c1 << 4) & 0xff;
+ }
+ } elseif ($strictPadding) {
+ $err |= 1;
+ }
+ }
+ $check = ($err === 0);
+ if (!$check) {
+ throw new RangeException(
+ 'Base64::decode() only expects characters in the correct base64 alphabet'
+ );
+ }
+ return $dest;
+ }
+
+ /**
+ * @param string $encodedString
+ * @return string
+ */
+ public static function decodeNoPadding(
+ #[\SensitiveParameter]
+ string $encodedString
+ ): string {
+ $srcLen = Binary::safeStrlen($encodedString);
+ if ($srcLen === 0) {
+ return '';
+ }
+ if (($srcLen & 3) === 0) {
+ // If $strLen is not zero, and it is divisible by 4, then it's at least 4.
+ if ($encodedString[$srcLen - 1] === '=' || $encodedString[$srcLen - 2] === '=') {
+ throw new InvalidArgumentException(
+ "decodeNoPadding() doesn't tolerate padding"
+ );
+ }
+ }
+ return static::decode(
+ $encodedString,
+ true
+ );
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 6-bit integers
+ * into 8-bit integers.
+ *
+ * Base64 character set:
+ * [A-Z] [a-z] [0-9] + /
+ * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f
+ *
+ * @param int $src
+ * @return int
+ */
+ protected static function decode6Bits(int $src): int
+ {
+ $ret = -1;
+
+ // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64
+ $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64);
+
+ // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70
+ $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70);
+
+ // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5
+ $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5);
+
+ // if ($src == 0x2b) $ret += 62 + 1;
+ $ret += (((0x2a - $src) & ($src - 0x2c)) >> 8) & 63;
+
+ // if ($src == 0x2f) ret += 63 + 1;
+ $ret += (((0x2e - $src) & ($src - 0x30)) >> 8) & 64;
+
+ return $ret;
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+ * into 6-bit integers.
+ *
+ * @param int $src
+ * @return string
+ */
+ protected static function encode6Bits(int $src): string
+ {
+ $diff = 0x41;
+
+ // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
+ $diff += ((25 - $src) >> 8) & 6;
+
+ // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
+ $diff -= ((51 - $src) >> 8) & 75;
+
+ // if ($src > 61) $diff += 0x2b - 0x30 - 10; // -15
+ $diff -= ((61 - $src) >> 8) & 15;
+
+ // if ($src > 62) $diff += 0x2f - 0x2b - 1; // 3
+ $diff += ((62 - $src) >> 8) & 3;
+
+ return \pack('C', $src + $diff);
+ }
+}
diff --git a/system/vendor/paragonie/constant_time_encoding/src/Base64DotSlash.php b/system/vendor/paragonie/constant_time_encoding/src/Base64DotSlash.php
new file mode 100644
index 0000000..5e98a8f
--- /dev/null
+++ b/system/vendor/paragonie/constant_time_encoding/src/Base64DotSlash.php
@@ -0,0 +1,88 @@
+ 0x2d && $src < 0x30) ret += $src - 0x2e + 1; // -45
+ $ret += (((0x2d - $src) & ($src - 0x30)) >> 8) & ($src - 45);
+
+ // if ($src > 0x40 && $src < 0x5b) ret += $src - 0x41 + 2 + 1; // -62
+ $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 62);
+
+ // if ($src > 0x60 && $src < 0x7b) ret += $src - 0x61 + 28 + 1; // -68
+ $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 68);
+
+ // if ($src > 0x2f && $src < 0x3a) ret += $src - 0x30 + 54 + 1; // 7
+ $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 7);
+
+ return $ret;
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+ * into 6-bit integers.
+ *
+ * @param int $src
+ * @return string
+ */
+ protected static function encode6Bits(int $src): string
+ {
+ $src += 0x2e;
+
+ // if ($src > 0x2f) $src += 0x41 - 0x30; // 17
+ $src += ((0x2f - $src) >> 8) & 17;
+
+ // if ($src > 0x5a) $src += 0x61 - 0x5b; // 6
+ $src += ((0x5a - $src) >> 8) & 6;
+
+ // if ($src > 0x7a) $src += 0x30 - 0x7b; // -75
+ $src -= ((0x7a - $src) >> 8) & 75;
+
+ return \pack('C', $src);
+ }
+}
diff --git a/system/vendor/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php b/system/vendor/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php
new file mode 100644
index 0000000..9780b14
--- /dev/null
+++ b/system/vendor/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php
@@ -0,0 +1,82 @@
+ 0x2d && $src < 0x3a) ret += $src - 0x2e + 1; // -45
+ $ret += (((0x2d - $src) & ($src - 0x3a)) >> 8) & ($src - 45);
+
+ // if ($src > 0x40 && $src < 0x5b) ret += $src - 0x41 + 12 + 1; // -52
+ $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 52);
+
+ // if ($src > 0x60 && $src < 0x7b) ret += $src - 0x61 + 38 + 1; // -58
+ $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 58);
+
+ return $ret;
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+ * into 6-bit integers.
+ *
+ * @param int $src
+ * @return string
+ */
+ protected static function encode6Bits(int $src): string
+ {
+ $src += 0x2e;
+
+ // if ($src > 0x39) $src += 0x41 - 0x3a; // 7
+ $src += ((0x39 - $src) >> 8) & 7;
+
+ // if ($src > 0x5a) $src += 0x61 - 0x5b; // 6
+ $src += ((0x5a - $src) >> 8) & 6;
+
+ return \pack('C', $src);
+ }
+}
diff --git a/system/vendor/paragonie/constant_time_encoding/src/Base64UrlSafe.php b/system/vendor/paragonie/constant_time_encoding/src/Base64UrlSafe.php
new file mode 100644
index 0000000..8192c63
--- /dev/null
+++ b/system/vendor/paragonie/constant_time_encoding/src/Base64UrlSafe.php
@@ -0,0 +1,95 @@
+ 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64
+ $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64);
+
+ // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70
+ $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70);
+
+ // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5
+ $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5);
+
+ // if ($src == 0x2c) $ret += 62 + 1;
+ $ret += (((0x2c - $src) & ($src - 0x2e)) >> 8) & 63;
+
+ // if ($src == 0x5f) ret += 63 + 1;
+ $ret += (((0x5e - $src) & ($src - 0x60)) >> 8) & 64;
+
+ return $ret;
+ }
+
+ /**
+ * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+ * into 6-bit integers.
+ *
+ * @param int $src
+ * @return string
+ */
+ protected static function encode6Bits(int $src): string
+ {
+ $diff = 0x41;
+
+ // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
+ $diff += ((25 - $src) >> 8) & 6;
+
+ // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
+ $diff -= ((51 - $src) >> 8) & 75;
+
+ // if ($src > 61) $diff += 0x2d - 0x30 - 10; // -13
+ $diff -= ((61 - $src) >> 8) & 13;
+
+ // if ($src > 62) $diff += 0x5f - 0x2b - 1; // 3
+ $diff += ((62 - $src) >> 8) & 49;
+
+ return \pack('C', $src + $diff);
+ }
+}
diff --git a/system/vendor/paragonie/constant_time_encoding/src/Binary.php b/system/vendor/paragonie/constant_time_encoding/src/Binary.php
new file mode 100644
index 0000000..5368e4b
--- /dev/null
+++ b/system/vendor/paragonie/constant_time_encoding/src/Binary.php
@@ -0,0 +1,93 @@
+ $chunk */
+ $chunk = \unpack('C', $binString[$i]);
+ $c = $chunk[1] & 0xf;
+ $b = $chunk[1] >> 4;
+
+ $hex .= \pack(
+ 'CC',
+ (87 + $b + ((($b - 10) >> 8) & ~38)),
+ (87 + $c + ((($c - 10) >> 8) & ~38))
+ );
+ }
+ return $hex;
+ }
+
+ /**
+ * Convert a binary string into a hexadecimal string without cache-timing
+ * leaks, returning uppercase letters (as per RFC 4648)
+ *
+ * @param string $binString (raw binary)
+ * @return string
+ * @throws TypeError
+ */
+ public static function encodeUpper(
+ #[\SensitiveParameter]
+ string $binString
+ ): string {
+ $hex = '';
+ $len = Binary::safeStrlen($binString);
+
+ for ($i = 0; $i < $len; ++$i) {
+ /** @var array $chunk */
+ $chunk = \unpack('C', $binString[$i]);
+ $c = $chunk[1] & 0xf;
+ $b = $chunk[1] >> 4;
+
+ $hex .= \pack(
+ 'CC',
+ (55 + $b + ((($b - 10) >> 8) & ~6)),
+ (55 + $c + ((($c - 10) >> 8) & ~6))
+ );
+ }
+ return $hex;
+ }
+
+ /**
+ * Convert a hexadecimal string into a binary string without cache-timing
+ * leaks
+ *
+ * @param string $encodedString
+ * @param bool $strictPadding
+ * @return string (raw binary)
+ * @throws RangeException
+ */
+ public static function decode(
+ #[\SensitiveParameter]
+ string $encodedString,
+ bool $strictPadding = false
+ ): string {
+ $hex_pos = 0;
+ $bin = '';
+ $c_acc = 0;
+ $hex_len = Binary::safeStrlen($encodedString);
+ $state = 0;
+ if (($hex_len & 1) !== 0) {
+ if ($strictPadding) {
+ throw new RangeException(
+ 'Expected an even number of hexadecimal characters'
+ );
+ } else {
+ $encodedString = '0' . $encodedString;
+ ++$hex_len;
+ }
+ }
+
+ /** @var array $chunk */
+ $chunk = \unpack('C*', $encodedString);
+ while ($hex_pos < $hex_len) {
+ ++$hex_pos;
+ $c = $chunk[$hex_pos];
+ $c_num = $c ^ 48;
+ $c_num0 = ($c_num - 10) >> 8;
+ $c_alpha = ($c & ~32) - 55;
+ $c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8;
+
+ if (($c_num0 | $c_alpha0) === 0) {
+ throw new RangeException(
+ 'Expected hexadecimal character'
+ );
+ }
+ $c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0);
+ if ($state === 0) {
+ $c_acc = $c_val * 16;
+ } else {
+ $bin .= \pack('C', $c_acc | $c_val);
+ }
+ $state ^= 1;
+ }
+ return $bin;
+ }
+}
diff --git a/system/vendor/paragonie/constant_time_encoding/src/RFC4648.php b/system/vendor/paragonie/constant_time_encoding/src/RFC4648.php
new file mode 100644
index 0000000..7cd2e99
--- /dev/null
+++ b/system/vendor/paragonie/constant_time_encoding/src/RFC4648.php
@@ -0,0 +1,206 @@
+ "Zm9v"
+ *
+ * @param string $str
+ * @return string
+ *
+ * @throws TypeError
+ */
+ public static function base64Encode(
+ #[\SensitiveParameter]
+ string $str
+ ): string {
+ return Base64::encode($str);
+ }
+
+ /**
+ * RFC 4648 Base64 decoding
+ *
+ * "Zm9v" -> "foo"
+ *
+ * @param string $str
+ * @return string
+ *
+ * @throws TypeError
+ */
+ public static function base64Decode(
+ #[\SensitiveParameter]
+ string $str
+ ): string {
+ return Base64::decode($str, true);
+ }
+
+ /**
+ * RFC 4648 Base64 (URL Safe) encoding
+ *
+ * "foo" -> "Zm9v"
+ *
+ * @param string $str
+ * @return string
+ *
+ * @throws TypeError
+ */
+ public static function base64UrlSafeEncode(
+ #[\SensitiveParameter]
+ string $str
+ ): string {
+ return Base64UrlSafe::encode($str);
+ }
+
+ /**
+ * RFC 4648 Base64 (URL Safe) decoding
+ *
+ * "Zm9v" -> "foo"
+ *
+ * @param string $str
+ * @return string
+ *
+ * @throws TypeError
+ */
+ public static function base64UrlSafeDecode(
+ #[\SensitiveParameter]
+ string $str
+ ): string {
+ return Base64UrlSafe::decode($str, true);
+ }
+
+ /**
+ * RFC 4648 Base32 encoding
+ *
+ * "foo" -> "MZXW6==="
+ *
+ * @param string $str
+ * @return string
+ *
+ * @throws TypeError
+ */
+ public static function base32Encode(
+ #[\SensitiveParameter]
+ string $str
+ ): string {
+ return Base32::encodeUpper($str);
+ }
+
+ /**
+ * RFC 4648 Base32 encoding
+ *
+ * "MZXW6===" -> "foo"
+ *
+ * @param string $str
+ * @return string
+ *
+ * @throws TypeError
+ */
+ public static function base32Decode(
+ #[\SensitiveParameter]
+ string $str
+ ): string {
+ return Base32::decodeUpper($str, true);
+ }
+
+ /**
+ * RFC 4648 Base32-Hex encoding
+ *
+ * "foo" -> "CPNMU==="
+ *
+ * @param string $str
+ * @return string
+ *
+ * @throws TypeError
+ */
+ public static function base32HexEncode(
+ #[\SensitiveParameter]
+ string $str
+ ): string {
+ return Base32::encodeUpper($str);
+ }
+
+ /**
+ * RFC 4648 Base32-Hex decoding
+ *
+ * "CPNMU===" -> "foo"
+ *
+ * @param string $str
+ * @return string
+ *
+ * @throws TypeError
+ */
+ public static function base32HexDecode(
+ #[\SensitiveParameter]
+ string $str
+ ): string {
+ return Base32::decodeUpper($str, true);
+ }
+
+ /**
+ * RFC 4648 Base16 decoding
+ *
+ * "foo" -> "666F6F"
+ *
+ * @param string $str
+ * @return string
+ *
+ * @throws TypeError
+ */
+ public static function base16Encode(
+ #[\SensitiveParameter]
+ string $str
+ ): string {
+ return Hex::encodeUpper($str);
+ }
+
+ /**
+ * RFC 4648 Base16 decoding
+ *
+ * "666F6F" -> "foo"
+ *
+ * @param string $str
+ * @return string
+ */
+ public static function base16Decode(
+ #[\SensitiveParameter]
+ string $str
+ ): string {
+ return Hex::decode($str, true);
+ }
+}
diff --git a/system/vendor/pragmarx/google2fa/CHANGELOG.md b/system/vendor/pragmarx/google2fa/CHANGELOG.md
new file mode 100644
index 0000000..f493f43
--- /dev/null
+++ b/system/vendor/pragmarx/google2fa/CHANGELOG.md
@@ -0,0 +1,111 @@
+## Change Log
+
+## [8.0.0] - 2020-05-05
+### Added
+- PHP 8 Support
+- Tests
+- Extract som test helpers
+- PHPStan checks
+### Changed
+- PHP required version bumped to >= 7.1
+- Exception interfaces extending Throwable
+
+## [7.0.0] - 2019-09-21
+### Added
+- PHPStan checks
+### Removed
+- Constants::ARGUMENT_NOT_SET - This is a BC break
+
+## [6.1.3] - 2019-09-21
+### Drafted
+- To fix inserted BC break
+
+## [6.1.2] - 2019-09-21
+### DELETED
+- To fix inserted BC break
+
+## [6.1.1] - 2019-09-21
+### DELETED
+- To fix inserted BC break
+
+## [6.0.0] - 2019-09-11
+### Added
+- Base exception class and interfaces
+### Removed
+- Support for PHP 5.4 to 7.0, will keep supporting PHP 7.1, 7.2, 7.3 & 7.4
+
+## [5.0.0] - 2019-05-19
+### Changed
+- Remove dead Google Charts API
+
+## [4.0.0] - 2018-10-06
+### Changed
+- Bacon QRCode package removed
+
+## [3.0.1] - 2018-03-15
+### Changed
+- Relicensed to MIT
+
+## [3.0.0] - 2018-03-07
+### Changed
+- It's now mandatory to enable Google Api secret key access by executing `setAllowInsecureCallToGoogleApis(true);`
+
+## [2.0.4] - 2017-06-22
+### Fixed
+- Fix Base32 to keep supporting PHP 5.4 && 5.5.
+
+## [2.0.3] - 2017-06-22
+## [2.0.2] - 2017-06-21
+## [2.0.1] - 2017-06-20
+### Fixed
+- Minor bugs
+
+## [2.0.0] - 2017-06-20
+### Changed
+- Drop the Laravel support in favor of a bridge package (https://github.com/antonioribeiro/google2fa-laravel).
+- Using a more secure Base 32 algorithm, to prevent cache-timing attacks.
+- Added verifyKeyNewer() method to prevent reuse of keys.
+- Refactored to remove complexity, by extracting support methods.
+- Created a package playground page (https://pragmarx.com/google2fa)
+
+## [2.0.0] - 2017-06-20
+### Changed
+- Drop the Laravel support in favor of a bridge package (https://github.com/antonioribeiro/google2fa-laravel).
+- Using a more secure Base 32 algorithm, to prevent cache-timing attacks.
+- Added verifyKeyNewer() method to prevent reuse of keys.
+- Refactored to remove complexity, by extracting support methods.
+- Created a package playground page (https://pragmarx.com/google2fa)
+
+## [1.0.1] - 2016-07-18
+### Changed
+- Drop support for PHP 5.3.7, require PHP 5.4+.
+- Coding style is now PSR-2 automatically enforced by StyleCI.
+
+## [1.0.0] - 2016-07-17
+### Changed
+- Package bacon/bacon-qr-code was moved to "suggest".
+
+## [0.8.1] - 2016-07-17
+### Fixed
+- Allow paragonie/random_compat ~1.4|~2.0.
+
+## [0.8.0] - 2016-07-17
+### Changed
+- Bumped christian-riesen/base32 to ~1.3
+- Use paragonie/random_compat to generate cryptographically secure random secret keys
+- Readme improvements
+- Drop simple-qrcode in favor of bacon/bacon-qr-code
+- Fix tavis setup for phpspec, PHP 7, hhvm and improve cache
+
+## [0.7.0] - 2015-11-07
+### Changed
+- Fixed URL generation for QRCodes
+- Avoid time attacks
+
+## [0.2.0] - 2015-02-19
+### Changed
+- Laravel 5 compatibility.
+
+## [0.1.0] - 2014-07-06
+### Added
+- First version.
diff --git a/system/vendor/pragmarx/google2fa/LICENSE.md b/system/vendor/pragmarx/google2fa/LICENSE.md
new file mode 100644
index 0000000..7300640
--- /dev/null
+++ b/system/vendor/pragmarx/google2fa/LICENSE.md
@@ -0,0 +1,7 @@
+Copyright 2014-2018 Phil, Antonio Carlos Ribeiro and All Contributors
+
+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.
diff --git a/system/vendor/pragmarx/google2fa/README.md b/system/vendor/pragmarx/google2fa/README.md
new file mode 100644
index 0000000..c7f9237
--- /dev/null
+++ b/system/vendor/pragmarx/google2fa/README.md
@@ -0,0 +1,415 @@
+# Google2FA
+## Google Two-Factor Authentication for PHP
+
+Google2FA is a PHP implementation of the Google Two-Factor Authentication Module, supporting the HMAC-Based One-time Password (HOTP) algorithm specified in [RFC 4226](https://tools.ietf.org/html/rfc4226) and the Time-based One-time Password (TOTP) algorithm specified in [RFC 6238](https://tools.ietf.org/html/rfc6238).
+
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+## Menu
+
+ - [Version Compatibility](#version-compatibility)
+ - [Google Two-Factor Authentication for PHP](#google-two-factor-authentication-for-php)
+ - [Laravel bridge](#laravel-bridge)
+ - [Demos, Example & Playground](#demos-example--playground)
+ - [Requirements](#requirements)
+ - [Installing](#installing)
+ - [Usage](#usage)
+ - [How To Generate And Use Two Factor Authentication](#how-to-generate-and-use-two-factor-authentication)
+ - [Generating QRCodes](#generating-qrcodes)
+ - [QR Code Packages](#qr-code-packages)
+ - [Examples of Usage](#examples-of-usage)
+ - [HMAC Algorithms](#hmac-algorithms)
+ - [Server Time](#server-time)
+ - [Validation Window](#validation-window)
+ - [Using a Bigger and Prefixing the Secret Key](#using-a-bigger-and-prefixing-the-secret-key)
+ - [Google Authenticator secret key compatibility](#google-authenticator-secret-key-compatibility)
+ - [Google Authenticator Apps](#google-authenticator-apps)
+ - [Deprecation Warning](#deprecation-warning)
+ - [Testing](#testing)
+ - [Authors](#authors)
+ - [License](#license)
+ - [Contributing](#contributing)
+
+## Version Compatibility
+
+ PHP | Google2FA
+:--------|:----------
+ 5.4 | 7.x LTS
+ 5.5 | 7.x LTS
+ 5.6 | 7.x LTS
+ 7.1 | 8.x
+ 7.2 | 8.x
+ 7.3 | 8.x
+ 7.4 | 8.x
+ 8.0 (β) | 8.x
+
+## Laravel bridge
+
+This package is agnostic, but there's a [Laravel bridge](https://github.com/antonioribeiro/google2fa-laravel).
+
+## About QRCode generation
+
+This package does not generate QRCodes for 2FA.
+
+If you are looking for Google Two-Factor Authentication, but also need to generate QRCode for it, you can use the [Google2FA QRCode package](https://github.com/antonioribeiro/google2fa-qrcode), which integrates this package and also generates QRCodes using the BaconQRCode library, or check options on how to do it yourself [here in the docs](#qr-code-packages).
+
+## Demos, Example & Playground
+
+Please check the [Google2FA Package Playground](http://pragmarx.com/playground/google2fa).
+
+
+
+Here's an demo app showing how to use Google2FA: [google2fa-example](https://github.com/antonioribeiro/google2fa-example).
+
+You can scan the QR code on [this (old) demo page](https://antoniocarlosribeiro.com/technology/google2fa) with a Google Authenticator app and view the code changing (almost) in real time.
+
+## Requirements
+
+- PHP 7.1 or greater
+
+## Installing
+
+Use Composer to install it:
+
+ composer require pragmarx/google2fa
+
+To generate inline QRCodes, you'll need to install a QR code generator, e.g. [BaconQrCode](https://github.com/Bacon/BaconQrCode):
+
+ composer require bacon/bacon-qr-code
+
+## Usage
+
+### Instantiate it directly
+
+```php
+use PragmaRX\Google2FA\Google2FA;
+
+$google2fa = new Google2FA();
+
+return $google2fa->generateSecretKey();
+```
+
+## How To Generate And Use Two Factor Authentication
+
+Generate a secret key for your user and save it:
+
+```php
+$user->google2fa_secret = $google2fa->generateSecretKey();
+```
+
+## Generating QRCodes
+
+The securer way of creating QRCode is to do it yourself or using a library. First you have to install a QR code generator e.g. BaconQrCode, as stated above, then you just have to generate the QR code url using:
+
+```php
+$qrCodeUrl = $google2fa->getQRCodeUrl(
+ $companyName,
+ $companyEmail,
+ $secretKey
+);
+```
+
+Once you have the QR code url, you can feed it to your preferred QR code generator.
+
+```php
+// Use your own QR Code generator to generate a data URL:
+$google2fa_url = custom_generate_qrcode_url($qrCodeUrl);
+
+/// and in your view:
+
+
+```
+
+And to verify, you just have to:
+
+```php
+$secret = $request->input('secret');
+
+$valid = $google2fa->verifyKey($user->google2fa_secret, $secret);
+```
+
+## QR Code Packages
+
+This package suggests the use of [Bacon/QRCode](https://github.com/Bacon/BaconQrCode) because
+it is known as a good QR Code package, but you can use it with any other package, for
+instance [Google2FA QRCode](https://github.com/antonioribeiro/google2fa-qrcode),
+[Simple QrCode](https://www.simplesoftware.io/docs/simple-qrcode)
+or [Endroid QR Code](https://github.com/endroid/qr-code), all of them use
+[Bacon/QRCode](https://github.com/Bacon/BaconQrCode) to produce QR Codes.
+
+Usually you'll need a 2FA URL, so you just have to use the URL generator:
+
+```php
+$google2fa->getQRCodeUrl($companyName, $companyEmail, $secretKey)
+```
+
+## Examples of Usage
+
+### [Google2FA QRCode](https://github.com/antonioribeiro/google2fa-qrcode)
+
+Get a QRCode to be used inline:
+
+```php
+$google2fa = (new \PragmaRX\Google2FAQRCode\Google2FA());
+
+$inlineUrl = $google2fa->getQRCodeInline(
+ 'Company Name',
+ 'company@email.com',
+ $google2fa->generateSecretKey()
+);
+```
+
+And use in your template:
+
+```php
+
+```
+
+### [Simple QrCode](https://www.simplesoftware.io/docs/simple-qrcode)
+
+```php
+
+ {!! QrCode::size(100)->generate($google2fa->getQRCodeUrl($companyName, $companyEmail, $secretKey)); !!}
+
Scan me to return to the original page.
+
+```
+
+### [Endroid QR Code Generator](https://github.com/endroid/qr-code)
+
+Generate the data URL
+
+```php
+
+$qrCode = new \Endroid\QrCode\QrCode($value);
+$qrCode->setSize(100);
+$google2fa_url = $qrCode->writeDataUri();
+```
+
+And in your view
+
+```php
+
+ {!! $google2fa_url !!}
+
Scan me to return to the original page.
+
+```
+
+### [Bacon/QRCode](https://github.com/Bacon/BaconQrCode)
+
+```php
+getQRCodeUrl(
+ 'pragmarx',
+ 'google2fa@pragmarx.com',
+ $google2fa->generateSecretKey()
+);
+
+$writer = new Writer(
+ new ImageRenderer(
+ new RendererStyle(400),
+ new ImagickImageBackEnd()
+ )
+);
+
+$qrcode_image = base64_encode($writer->writeString($g2faUrl));
+```
+
+And show it as an image:
+
+```php
+
+```
+
+## HMAC Algorithms
+
+To comply with [RFC6238](https://tools.ietf.org/html/rfc6238), this package supports SHA1, SHA256 and SHA512. It defaults to SHA1, so to use a different algorithm you just have to use the method `setAlgorith()`:
+
+``` php
+
+use PragmaRX\Google2FA\Support\Constants;
+
+$google2fa->setAlgorithm(Constants::SHA512);
+```
+
+## Server Time
+
+It's really important that you keep your server time in sync with some NTP server, on Ubuntu you can add this to the crontab:
+
+```bash
+sudo service ntp stop
+sudo ntpd -gq
+sudo service ntp start
+```
+
+## Validation Window
+
+To avoid problems with clocks that are slightly out of sync, we do not check against the current key only but also consider `$window` keys each from the past and future. You can pass `$window` as optional third parameter to `verifyKey`, it defaults to `4`. A new key is generated every 30 seconds, so this window includes keys from the previous two and next two minutes.
+
+```php
+$secret = $request->input('secret');
+
+$window = 8; // 8 keys (respectively 4 minutes) past and future
+
+$valid = $google2fa->verifyKey($user->google2fa_secret, $secret, $window);
+```
+
+An attacker might be able to watch the user entering his credentials and one time key.
+Without further precautions, the key remains valid until it is no longer within the window of the server time. In order to prevent usage of a one time key that has already been used, you can utilize the `verifyKeyNewer` function.
+
+```php
+$secret = $request->input('secret');
+
+$timestamp = $google2fa->verifyKeyNewer($user->google2fa_secret, $secret, $user->google2fa_ts);
+
+if ($timestamp !== false) {
+ $user->update(['google2fa_ts' => $timestamp]);
+ // successful
+} else {
+ // failed
+}
+```
+
+Note that `$timestamp` either `false` (if the key is invalid or has been used before) or the provided key's unix timestamp divided by the key regeneration period of 30 seconds.
+
+## Using a Bigger and Prefixing the Secret Key
+
+Although the probability of collision of a 16 bytes (128 bits) random string is very low, you can harden it by:
+
+#### Use a bigger key
+
+```php
+$secretKey = $google2fa->generateSecretKey(32); // defaults to 16 bytes
+```
+
+#### You can prefix your secret keys
+
+You may prefix your secret keys, but you have to understand that, as your secret key must have length in power of 2, your prefix will have to have a complementary size. So if your key is 16 bytes long, if you add a prefix it must be also 16 bytes long, but as your prefixes will be converted to base 32, the max length of your prefix is 10 bytes. So, those are the sizes you can use in your prefixes:
+
+```
+1, 2, 5, 10, 20, 40, 80...
+```
+
+And it can be used like so:
+
+```php
+$prefix = strpad($userId, 10, 'X');
+
+$secretKey = $google2fa->generateSecretKey(16, $prefix);
+```
+
+#### Window
+
+The Window property defines how long a OTP will work, or how many cycles it will last. A key has a 30 seconds cycle, setting the window to 0 will make the key lasts for those 30 seconds, setting it to 2 will make it last for 120 seconds. This is how you set the window:
+
+```php
+$secretKey = $google2fa->setWindow(4);
+```
+
+But you can also set the window while checking the key. If you need to set a window of 4 during key verification, this is how you do:
+
+```php
+$isValid = $google2fa->verifyKey($seed, $key, 4);
+```
+
+#### Key Regeneration Interval
+
+You can change key regeneration interval, which defaults to 30 seconds, but remember that this is a default value on most authentication apps, like Google Authenticator, which will, basically, make your app out of sync with them.
+
+```php
+$google2fa->setKeyRegeneration(40);
+```
+
+## Google Authenticator secret key compatibility
+
+To be compatible with Google Authenticator, your (converted to base 32) secret key length must be at least 8 chars and be a power of 2: 8, 16, 32, 64...
+
+So, to prevent errors, you can do something like this while generating it:
+
+```php
+$secretKey = '123456789';
+
+$secretKey = str_pad($secretKey, pow(2,ceil(log(strlen($secretKey),2))), 'X');
+```
+
+And it will generate
+
+```
+123456789XXXXXXX
+```
+
+By default, this package will enforce compatibility, but, if Google Authenticator is not a target, you can disable it by doing
+
+```php
+$google2fa->setEnforceGoogleAuthenticatorCompatibility(false);
+```
+
+## Google Authenticator Apps
+
+To use the two factor authentication, your user will have to install a Google Authenticator compatible app, those are some of the currently available:
+
+* [Authy for iOS, Android, Chrome, OS X](https://www.authy.com/)
+* [FreeOTP for iOS, Android and Pebble](https://apps.getpebble.com/en_US/application/52f1a4c3c4117252f9000bb8)
+* [Google Authenticator for iOS](https://itunes.apple.com/us/app/google-authenticator/id388497605?mt=8)
+* [Google Authenticator for Android](https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2)
+* [Google Authenticator (port) on Windows Store](https://www.microsoft.com/en-us/store/p/google-authenticator/9wzdncrdnkrf)
+* [Microsoft Authenticator for Windows Phone](https://www.microsoft.com/en-us/store/apps/authenticator/9wzdncrfj3rj)
+* [LastPass Authenticator for iOS, Android, OS X, Windows](https://lastpass.com/auth/)
+* [1Password for iOS, Android, OS X, Windows](https://1password.com)
+
+## Deprecation Warning
+
+Google API for QR generator is turned off. All version of that package prior to 5.0.0 are deprecated. Please upgrade and check documentation regarding [QRCode generation](https://github.com/antonioribeiro/google2fa#generating-qrcodes).
+
+## Testing
+
+The package tests were written with [PHPUnit](https://phpunit.de/). There are some Composer scripts to help you run tests and analysis:
+
+PHPUnit:
+
+````
+composer test
+````
+
+PHPStan analysis:
+
+````
+composer analyse
+````
+
+## Authors
+
+- [Antonio Carlos Ribeiro](http://twitter.com/iantonioribeiro)
+- [Phil (Orginal author of this class)](https://www.idontplaydarts.com/static/ga.php_.txt)
+- [All Contributors](https://github.com/antonioribeiro/google2fa/graphs/contributors)
+
+## License
+
+Google2FA is licensed under the MIT License - see the [LICENSE](LICENSE.md) file for details.
+
+## Contributing
+
+Pull requests and issues are more than welcome.
diff --git a/system/vendor/pragmarx/google2fa/composer.json b/system/vendor/pragmarx/google2fa/composer.json
new file mode 100644
index 0000000..2a1f9e6
--- /dev/null
+++ b/system/vendor/pragmarx/google2fa/composer.json
@@ -0,0 +1,43 @@
+{
+ "name": "pragmarx/google2fa",
+ "description": "A One Time Password Authentication package, compatible with Google Authenticator.",
+ "keywords": [
+ "authentication",
+ "two factor authentication",
+ "google2fa",
+ "2fa"
+ ],
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Antonio Carlos Ribeiro",
+ "email": "acr@antoniocarlosribeiro.com",
+ "role": "Creator & Designer"
+ }
+ ],
+ "require": {
+ "php": "^7.1|^8.0",
+ "paragonie/constant_time_encoding": "^1.0|^2.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.5.15|^8.5|^9.0",
+ "phpstan/phpstan": "^0.12.18"
+ },
+ "autoload": {
+ "psr-4": {
+ "PragmaRX\\Google2FA\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "PragmaRX\\Google2FA\\Tests\\": "tests/"
+ },
+ "files": ["tests/helpers.php"]
+ },
+ "scripts": {
+ "test": "bash ./tests/tools/test.sh",
+ "analyse": "bash ./tests/tools/analyse.sh"
+ },
+ "minimum-stability": "dev",
+ "prefer-stable": true
+}
diff --git a/system/vendor/pragmarx/google2fa/src/Exceptions/Contracts/Google2FA.php b/system/vendor/pragmarx/google2fa/src/Exceptions/Contracts/Google2FA.php
new file mode 100644
index 0000000..90848f9
--- /dev/null
+++ b/system/vendor/pragmarx/google2fa/src/Exceptions/Contracts/Google2FA.php
@@ -0,0 +1,9 @@
+getWindow($window);
+ $startingTimestamp++
+ ) {
+ if (
+ hash_equals($this->oathTotp($secret, $startingTimestamp), $key)
+ ) {
+ return is_null($oldTimestamp)
+ ? true
+ : $startingTimestamp;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Generate the HMAC OTP.
+ *
+ * @param string $secret
+ * @param int $counter
+ *
+ * @return string
+ */
+ protected function generateHotp($secret, $counter)
+ {
+ return hash_hmac(
+ $this->getAlgorithm(),
+ pack('N*', 0, $counter), // Counter must be 64-bit int
+ $secret,
+ true
+ );
+ }
+
+ /**
+ * Generate a digit secret key in base32 format.
+ *
+ * @param int $length
+ * @param string $prefix
+ *
+ * @throws \PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException
+ * @throws \PragmaRX\Google2FA\Exceptions\InvalidCharactersException
+ * @throws \PragmaRX\Google2FA\Exceptions\SecretKeyTooShortException
+ *
+ * @return string
+ */
+ public function generateSecretKey($length = 16, $prefix = '')
+ {
+ return $this->generateBase32RandomKey($length, $prefix);
+ }
+
+ /**
+ * Get the current one time password for a key.
+ *
+ * @param string $secret
+ *
+ * @throws \PragmaRX\Google2FA\Exceptions\SecretKeyTooShortException
+ * @throws \PragmaRX\Google2FA\Exceptions\InvalidCharactersException
+ * @throws \PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException
+ *
+ * @return string
+ */
+ public function getCurrentOtp($secret)
+ {
+ return $this->oathTotp($secret, $this->getTimestamp());
+ }
+
+ /**
+ * Get the HMAC algorithm.
+ *
+ * @return string
+ */
+ public function getAlgorithm()
+ {
+ return $this->algorithm;
+ }
+
+ /**
+ * Get key regeneration.
+ *
+ * @return int
+ */
+ public function getKeyRegeneration()
+ {
+ return $this->keyRegeneration;
+ }
+
+ /**
+ * Get OTP length.
+ *
+ * @return int
+ */
+ public function getOneTimePasswordLength()
+ {
+ return $this->oneTimePasswordLength;
+ }
+
+ /**
+ * Get secret.
+ *
+ * @param string|null $secret
+ *
+ * @return string
+ */
+ public function getSecret($secret = null)
+ {
+ return is_null($secret) ? $this->secret : $secret;
+ }
+
+ /**
+ * Returns the current Unix Timestamp divided by the $keyRegeneration
+ * period.
+ *
+ * @return int
+ **/
+ public function getTimestamp()
+ {
+ return (int) floor(microtime(true) / $this->keyRegeneration);
+ }
+
+ /**
+ * Get a list of valid HMAC algorithms.
+ *
+ * @return array
+ */
+ protected function getValidAlgorithms()
+ {
+ return [
+ Constants::SHA1,
+ Constants::SHA256,
+ Constants::SHA512,
+ ];
+ }
+
+ /**
+ * Get the OTP window.
+ *
+ * @param null|int $window
+ *
+ * @return int
+ */
+ public function getWindow($window = null)
+ {
+ return is_null($window) ? $this->window : $window;
+ }
+
+ /**
+ * Make a window based starting timestamp.
+ *
+ * @param int|null $window
+ * @param int $timestamp
+ * @param int|null $oldTimestamp
+ *
+ * @return mixed
+ */
+ private function makeStartingTimestamp($window, $timestamp, $oldTimestamp = null)
+ {
+ return is_null($oldTimestamp)
+ ? $timestamp - $this->getWindow($window)
+ : max($timestamp - $this->getWindow($window), $oldTimestamp + 1);
+ }
+
+ /**
+ * Get/use a starting timestamp for key verification.
+ *
+ * @param string|int|null $timestamp
+ *
+ * @return int
+ */
+ protected function makeTimestamp($timestamp = null)
+ {
+ if (is_null($timestamp)) {
+ return $this->getTimestamp();
+ }
+
+ return (int) $timestamp;
+ }
+
+ /**
+ * Takes the secret key and the timestamp and returns the one time
+ * password.
+ *
+ * @param string $secret Secret key in binary form.
+ * @param int $counter Timestamp as returned by getTimestamp.
+ *
+ * @throws \PragmaRX\Google2FA\Exceptions\SecretKeyTooShortException
+ * @throws \PragmaRX\Google2FA\Exceptions\InvalidCharactersException
+ * @throws Exceptions\IncompatibleWithGoogleAuthenticatorException
+ *
+ * @return string
+ */
+ public function oathTotp($secret, $counter)
+ {
+ if (strlen($secret) < 8) {
+ throw new SecretKeyTooShortException();
+ }
+
+ $secret = $this->base32Decode($this->getSecret($secret));
+
+ return str_pad(
+ $this->oathTruncate($this->generateHotp($secret, $counter)),
+ $this->getOneTimePasswordLength(),
+ '0',
+ STR_PAD_LEFT
+ );
+ }
+
+ /**
+ * Extracts the OTP from the SHA1 hash.
+ *
+ * @param string $hash
+ *
+ * @return string
+ **/
+ public function oathTruncate($hash)
+ {
+ $offset = ord($hash[strlen($hash) - 1]) & 0xF;
+
+ $temp = unpack('N', substr($hash, $offset, 4));
+
+ $temp = $temp[1] & 0x7FFFFFFF;
+
+ return substr(
+ (string) $temp,
+ -$this->getOneTimePasswordLength()
+ );
+ }
+
+ /**
+ * Remove invalid chars from a base 32 string.
+ *
+ * @param string $string
+ *
+ * @return string|null
+ */
+ public function removeInvalidChars($string)
+ {
+ return preg_replace(
+ '/[^'.Constants::VALID_FOR_B32.']/',
+ '',
+ $string
+ );
+ }
+
+ /**
+ * Setter for the enforce Google Authenticator compatibility property.
+ *
+ * @param mixed $enforceGoogleAuthenticatorCompatibility
+ *
+ * @return $this
+ */
+ public function setEnforceGoogleAuthenticatorCompatibility(
+ $enforceGoogleAuthenticatorCompatibility
+ ) {
+ $this->enforceGoogleAuthenticatorCompatibility = $enforceGoogleAuthenticatorCompatibility;
+
+ return $this;
+ }
+
+ /**
+ * Set the HMAC hashing algorithm.
+ *
+ * @param mixed $algorithm
+ *
+ * @throws \PragmaRX\Google2FA\Exceptions\InvalidAlgorithmException
+ *
+ * @return \PragmaRX\Google2FA\Google2FA
+ */
+ public function setAlgorithm($algorithm)
+ {
+ // Default to SHA1 HMAC algorithm
+ if (!in_array($algorithm, $this->getValidAlgorithms())) {
+ throw new InvalidAlgorithmException();
+ }
+
+ $this->algorithm = $algorithm;
+
+ return $this;
+ }
+
+ /**
+ * Set key regeneration.
+ *
+ * @param mixed $keyRegeneration
+ */
+ public function setKeyRegeneration($keyRegeneration)
+ {
+ $this->keyRegeneration = $keyRegeneration;
+ }
+
+ /**
+ * Set OTP length.
+ *
+ * @param mixed $oneTimePasswordLength
+ */
+ public function setOneTimePasswordLength($oneTimePasswordLength)
+ {
+ $this->oneTimePasswordLength = $oneTimePasswordLength;
+ }
+
+ /**
+ * Set secret.
+ *
+ * @param mixed $secret
+ */
+ public function setSecret($secret)
+ {
+ $this->secret = $secret;
+ }
+
+ /**
+ * Set the OTP window.
+ *
+ * @param mixed $window
+ */
+ public function setWindow($window)
+ {
+ $this->window = $window;
+ }
+
+ /**
+ * Verifies a user inputted key against the current timestamp. Checks $window
+ * keys either side of the timestamp.
+ *
+ * @param string $key User specified key
+ * @param string $secret
+ * @param null|int $window
+ * @param null|int $timestamp
+ * @param null|int $oldTimestamp
+ *
+ * @throws \PragmaRX\Google2FA\Exceptions\SecretKeyTooShortException
+ * @throws \PragmaRX\Google2FA\Exceptions\InvalidCharactersException
+ * @throws \PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException
+ *
+ * @return bool|int
+ */
+ public function verify(
+ $key,
+ $secret,
+ $window = null,
+ $timestamp = null,
+ $oldTimestamp = null
+ ) {
+ return $this->verifyKey(
+ $secret,
+ $key,
+ $window,
+ $timestamp,
+ $oldTimestamp
+ );
+ }
+
+ /**
+ * Verifies a user inputted key against the current timestamp. Checks $window
+ * keys either side of the timestamp.
+ *
+ * @param string $secret
+ * @param string $key User specified key
+ * @param int|null $window
+ * @param null|int $timestamp
+ * @param null|int $oldTimestamp
+ *
+ * @throws \PragmaRX\Google2FA\Exceptions\SecretKeyTooShortException
+ * @throws \PragmaRX\Google2FA\Exceptions\InvalidCharactersException
+ * @throws \PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException
+ *
+ * @return bool|int
+ */
+ public function verifyKey(
+ $secret,
+ $key,
+ $window = null,
+ $timestamp = null,
+ $oldTimestamp = null
+ ) {
+ $timestamp = $this->makeTimestamp($timestamp);
+
+ return $this->findValidOTP(
+ $secret,
+ $key,
+ $window,
+ $this->makeStartingTimestamp($window, $timestamp, $oldTimestamp),
+ $timestamp,
+ $oldTimestamp
+ );
+ }
+
+ /**
+ * Verifies a user inputted key against the current timestamp. Checks $window
+ * keys either side of the timestamp, but ensures that the given key is newer than
+ * the given oldTimestamp. Useful if you need to ensure that a single key cannot
+ * be used twice.
+ *
+ * @param string $secret
+ * @param string $key User specified key
+ * @param int|null $oldTimestamp The timestamp from the last verified key
+ * @param int|null $window
+ * @param int|null $timestamp
+ *
+ * @throws \PragmaRX\Google2FA\Exceptions\SecretKeyTooShortException
+ * @throws \PragmaRX\Google2FA\Exceptions\InvalidCharactersException
+ * @throws \PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException
+ *
+ * @return bool|int
+ */
+ public function verifyKeyNewer(
+ $secret,
+ $key,
+ $oldTimestamp,
+ $window = null,
+ $timestamp = null
+ ) {
+ return $this->verifyKey(
+ $secret,
+ $key,
+ $window,
+ $timestamp,
+ $oldTimestamp
+ );
+ }
+}
diff --git a/system/vendor/pragmarx/google2fa/src/Support/Base32.php b/system/vendor/pragmarx/google2fa/src/Support/Base32.php
new file mode 100644
index 0000000..83167ba
--- /dev/null
+++ b/system/vendor/pragmarx/google2fa/src/Support/Base32.php
@@ -0,0 +1,208 @@
+toBase32($prefix) : '';
+
+ $secret = $this->strPadBase32($secret, $length);
+
+ $this->validateSecret($secret);
+
+ return $secret;
+ }
+
+ /**
+ * Decodes a base32 string into a binary string.
+ *
+ * @param string $b32
+ *
+ * @throws \PragmaRX\Google2FA\Exceptions\InvalidCharactersException
+ * @throws \PragmaRX\Google2FA\Exceptions\SecretKeyTooShortException
+ * @throws \PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException
+ *
+ * @return string
+ */
+ public function base32Decode($b32)
+ {
+ $b32 = strtoupper($b32);
+
+ $this->validateSecret($b32);
+
+ return ParagonieBase32::decodeUpper($b32);
+ }
+
+ /**
+ * Check if the string length is power of two.
+ *
+ * @param string $b32
+ *
+ * @return bool
+ */
+ protected function isCharCountNotAPowerOfTwo($b32)
+ {
+ return (strlen($b32) & (strlen($b32) - 1)) !== 0;
+ }
+
+ /**
+ * Pad string with random base 32 chars.
+ *
+ * @param string $string
+ * @param int $length
+ *
+ * @throws \Exception
+ *
+ * @return string
+ */
+ private function strPadBase32($string, $length)
+ {
+ for ($i = 0; $i < $length; $i++) {
+ $string .= substr(
+ Constants::VALID_FOR_B32_SCRAMBLED,
+ $this->getRandomNumber(),
+ 1
+ );
+ }
+
+ return $string;
+ }
+
+ /**
+ * Encode a string to Base32.
+ *
+ * @param string $string
+ *
+ * @return string
+ */
+ public function toBase32($string)
+ {
+ $encoded = ParagonieBase32::encodeUpper($string);
+
+ return str_replace('=', '', $encoded);
+ }
+
+ /**
+ * Get a random number.
+ *
+ * @param int $from
+ * @param int $to
+ *
+ * @throws \Exception
+ *
+ * @return int
+ */
+ protected function getRandomNumber($from = 0, $to = 31)
+ {
+ return random_int($from, $to);
+ }
+
+ /**
+ * Validate the secret.
+ *
+ * @param string $b32
+ *
+ * @throws \PragmaRX\Google2FA\Exceptions\InvalidCharactersException
+ * @throws \PragmaRX\Google2FA\Exceptions\SecretKeyTooShortException
+ * @throws \PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException
+ */
+ protected function validateSecret($b32)
+ {
+ $this->checkForValidCharacters($b32);
+
+ $this->checkGoogleAuthenticatorCompatibility($b32);
+
+ $this->checkIsBigEnough($b32);
+ }
+
+ /**
+ * Check if the secret key is compatible with Google Authenticator.
+ *
+ * @param string $b32
+ *
+ * @throws IncompatibleWithGoogleAuthenticatorException
+ */
+ protected function checkGoogleAuthenticatorCompatibility($b32)
+ {
+ if (
+ $this->enforceGoogleAuthenticatorCompatibility &&
+ $this->isCharCountNotAPowerOfTwo($b32) // Google Authenticator requires it to be a power of 2 base32 length string
+ ) {
+ throw new IncompatibleWithGoogleAuthenticatorException();
+ }
+ }
+
+ /**
+ * Check if all secret key characters are valid.
+ *
+ * @param string $b32
+ *
+ * @throws \PragmaRX\Google2FA\Exceptions\InvalidCharactersException
+ */
+ protected function checkForValidCharacters($b32)
+ {
+ if (
+ preg_replace('/[^'.Constants::VALID_FOR_B32.']/', '', $b32) !==
+ $b32
+ ) {
+ throw new InvalidCharactersException();
+ }
+ }
+
+ /**
+ * Check if secret key length is big enough.
+ *
+ * @param string $b32
+ *
+ * @throws \PragmaRX\Google2FA\Exceptions\SecretKeyTooShortException
+ */
+ protected function checkIsBigEnough($b32)
+ {
+ // Minimum = 128 bits
+ // Recommended = 160 bits
+ // Compatible with Google Authenticator = 256 bits
+
+ if (
+ $this->charCountBits($b32) < 128
+ ) {
+ throw new SecretKeyTooShortException();
+ }
+ }
+}
diff --git a/system/vendor/pragmarx/google2fa/src/Support/Constants.php b/system/vendor/pragmarx/google2fa/src/Support/Constants.php
new file mode 100644
index 0000000..8fff653
--- /dev/null
+++ b/system/vendor/pragmarx/google2fa/src/Support/Constants.php
@@ -0,0 +1,31 @@
+getAlgorithm())).
+ '&digits='.
+ rawurlencode(strtoupper((string) $this->getOneTimePasswordLength())).
+ '&period='.
+ rawurlencode(strtoupper((string) $this->getKeyRegeneration())).
+ '';
+ }
+}
diff --git a/system/vendor/suin/php-rss-writer/.gitignore b/system/vendor/suin/php-rss-writer/.gitignore
index 78b6bc4..cbdab51 100644
--- a/system/vendor/suin/php-rss-writer/.gitignore
+++ b/system/vendor/suin/php-rss-writer/.gitignore
@@ -1,3 +1,4 @@
-.idea/
-.phpmake
-.DS_Store
+/.idea
+/vendor
+/composer.lock
+/tests/cover
diff --git a/system/vendor/suin/php-rss-writer/.travis.yml b/system/vendor/suin/php-rss-writer/.travis.yml
index eddea83..674a91e 100644
--- a/system/vendor/suin/php-rss-writer/.travis.yml
+++ b/system/vendor/suin/php-rss-writer/.travis.yml
@@ -1,19 +1,26 @@
sudo: false
+
language: php
+
php:
- - 5.3
- 5.4
- 5.5
- 5.6
+ - 7.0
+ - master
- hhvm
-before_script:
- - cd tests
- - composer install -n
+matrix:
+ fast_finish: true
+ allow_failures:
+ - php: master
-script: phpunit --coverage-text --configuration phpunit.xml.dist
+install:
+ - composer install --prefer-dist
+
+script:
+ - vendor/bin/phpunit --coverage-text
cache:
directories:
- - tests/vendor
- - $HOME/.composer/cache
\ No newline at end of file
+ - $HOME/.composer/cache
diff --git a/system/vendor/suin/php-rss-writer/Makefile b/system/vendor/suin/php-rss-writer/Makefile
new file mode 100644
index 0000000..52087c3
--- /dev/null
+++ b/system/vendor/suin/php-rss-writer/Makefile
@@ -0,0 +1,5 @@
+test:
+ docker-compose up php54
+ docker-compose up php55
+ docker-compose up php56
+ docker-compose up php70
diff --git a/system/vendor/suin/php-rss-writer/README.md b/system/vendor/suin/php-rss-writer/README.md
index 64d19a8..cabfb7f 100644
--- a/system/vendor/suin/php-rss-writer/README.md
+++ b/system/vendor/suin/php-rss-writer/README.md
@@ -1,59 +1,91 @@
# \Suin\RSSWriter
-`\Suin\RSSWriter` is yet another simple RSS writer library for PHP 5.3 or later. This component is Licensed under MIT license.
+`\Suin\RSSWriter` is yet another simple RSS writer library for PHP 5.4 or later. This component is Licensed under MIT license.
This library can also be used to publish Podcasts.
-The build status of the current master branch is tracked by Travis CI: [](http://travis-ci.org/suin/php-rss-writer)
+[](https://packagist.org/packages/suin/php-rss-writer)
+[](https://packagist.org/packages/suin/php-rss-writer)
+[](https://packagist.org/packages/suin/php-rss-writer)
+[](https://packagist.org/packages/suin/php-rss-writer)
+[](https://travis-ci.org/suin/php-rss-writer)
+[](https://www.codacy.com/app/suinyeze/php-rss-writer)
+## Quick demo
-Implementation:
```php
-title("Channel Title")
- ->description("Channel Description")
- ->url('http://blog.example.com')
- ->appendTo($feed);
+ ->title('Channel Title')
+ ->description('Channel Description')
+ ->url('http://blog.example.com')
+ ->feedUrl('http://blog.example.com/rss')
+ ->language('en-US')
+ ->copyright('Copyright 2012, Foo Bar')
+ ->pubDate(strtotime('Tue, 21 Aug 2012 19:50:37 +0900'))
+ ->lastBuildDate(strtotime('Tue, 21 Aug 2012 19:50:37 +0900'))
+ ->ttl(60)
+ ->pubsubhubbub('http://example.com/feed.xml', 'http://pubsubhubbub.appspot.com') // This is optional. Specify PubSubHubbub discovery if you want.
+ ->appendTo($feed);
-// RSS item
+// Blog item
$item = new Item();
$item
- ->title("Blog Entry Title")
- ->description("Blog body
")
- ->url('http://blog.example.com/2012/08/21/blog-entry/')
- ->appendTo($channel);
+ ->title('Blog Entry Title')
+ ->description('Blog body
')
+ ->contentEncoded('Blog body
')
+ ->url('http://blog.example.com/2012/08/21/blog-entry/')
+ ->author('John Smith')
+ ->pubDate(strtotime('Tue, 21 Aug 2012 19:50:37 +0900'))
+ ->guid('http://blog.example.com/2012/08/21/blog-entry/', true)
+ ->preferCdata(true) // By this, title and description become CDATA wrapped HTML.
+ ->appendTo($channel);
// Podcast item
$item = new Item();
$item
- ->title("Some Podcast Entry")
- ->description("Podcast body
")
- ->url('http://podcast.example.com/2012/08/21/podcast-entry/')
- ->enclosure('http://link-to-audio-file.com/2013/08/21/podcast.mp3', 4889, 'audio/mpeg')
- ->appendTo($channel);
+ ->title('Some Podcast Entry')
+ ->description('Podcast body
')
+ ->url('http://podcast.example.com/2012/08/21/podcast-entry/')
+ ->enclosure('http://podcast.example.com/2012/08/21/podcast.mp3', 4889, 'audio/mpeg')
+ ->appendTo($channel);
-
-echo $feed;
+echo $feed; // or echo $feed->render();
```
Output:
```xml
-
-
+
+
Channel Title
http://blog.example.com
Channel Description
+ en-US
+ Copyright 2012, Foo Bar
+ Tue, 21 Aug 2012 10:50:37 +0000
+ Tue, 21 Aug 2012 10:50:37 +0000
+ 60
+
+
-
-
Blog Entry Title
+
http://blog.example.com/2012/08/21/blog-entry/
- <div>Blog body</div>
+ Blog body]]>
+ Blog body]]>
+ http://blog.example.com/2012/08/21/blog-entry/
+ Tue, 21 Aug 2012 10:50:37 +0000
+ John Smith
+
+ -
+
Some Podcast Entry
+ http://podcast.example.com/2012/08/21/podcast-entry/
+ <div>Podcast body</div>
+
@@ -62,12 +94,15 @@ Output:
## Installation
### Easy installation
+
You can install directly via [Composer](https://getcomposer.org/):
+
```bash
$ composer require suin/php-rss-writer
```
### Manual installation
+
Add the following code to your `composer.json` file:
```json
@@ -79,13 +114,14 @@ Add the following code to your `composer.json` file:
```
...and run composer to install it:
+
```bash
$ composer install
```
Finally, include `vendor/autoload.php` in your product:
+
```php
-assertAttributeSame($ttl, 'ttl', $channel);
}
+ public function testPubsubhubbub()
+ {
+ $channel = new Channel();
+ $channel->pubsubhubbub('http://example.com/feed.xml', 'http://pubsubhubbub.appspot.com');
+ $xml = $channel->asXML()->asXML();
+ $this->assertContains(' ', $xml);
+ $this->assertContains(' ', $xml);
+ }
+
public function testAddItem()
{
$item = $this->getMock($this->itemInterface);
$channel = new Channel();
$this->assertSame($channel, $channel->addItem($item));
- $this->assertAttributeSame(array($item), 'items', $channel);
+ $this->assertAttributeSame([$item], 'items', $channel);
}
public function testAppendTo()
@@ -109,102 +118,102 @@ class ChannelTest extends \XoopsUnit\TestCase
$now = time();
$nowString = date(DATE_RSS, $now);
- return array(
- array(
+ return [
+ [
"
-
- GoUpstate.com News Headlines
- http://www.goupstate.com/
- The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.
-
- ",
- array(
- 'title' => "GoUpstate.com News Headlines",
- 'url' => 'http://www.goupstate.com/',
+
+ GoUpstate.com News Headlines
+ http://www.goupstate.com/
+ The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.
+
+ ",
+ [
+ 'title' => "GoUpstate.com News Headlines",
+ 'url' => 'http://www.goupstate.com/',
'description' => "The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.",
- )
- ),
- array(
+ ]
+ ],
+ [
"
-
- GoUpstate.com News Headlines
- http://www.goupstate.com/
- The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.
- en-us
-
- ",
- array(
- 'title' => "GoUpstate.com News Headlines",
- 'url' => 'http://www.goupstate.com/',
+
+ GoUpstate.com News Headlines
+ http://www.goupstate.com/
+ The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.
+ en-us
+
+ ",
+ [
+ 'title' => "GoUpstate.com News Headlines",
+ 'url' => 'http://www.goupstate.com/',
'description' => "The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.",
- 'language' => 'en-us',
- )
- ),
- array(
+ 'language' => 'en-us',
+ ]
+ ],
+ [
"
-
- GoUpstate.com News Headlines
- http://www.goupstate.com/
- The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.
- {$nowString}
-
- ",
- array(
- 'title' => "GoUpstate.com News Headlines",
- 'url' => 'http://www.goupstate.com/',
+
+ GoUpstate.com News Headlines
+ http://www.goupstate.com/
+ The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.
+ {$nowString}
+
+ ",
+ [
+ 'title' => "GoUpstate.com News Headlines",
+ 'url' => 'http://www.goupstate.com/',
'description' => "The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.",
- 'pubDate' => $now,
- )
- ),
- array(
+ 'pubDate' => $now,
+ ]
+ ],
+ [
"
-
- GoUpstate.com News Headlines
- http://www.goupstate.com/
- The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.
- {$nowString}
-
- ",
- array(
- 'title' => "GoUpstate.com News Headlines",
- 'url' => 'http://www.goupstate.com/',
- 'description' => "The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.",
+
+ GoUpstate.com News Headlines
+ http://www.goupstate.com/
+ The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.
+ {$nowString}
+
+ ",
+ [
+ 'title' => "GoUpstate.com News Headlines",
+ 'url' => 'http://www.goupstate.com/',
+ 'description' => "The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.",
'lastBuildDate' => $now,
- )
- ),
- array(
+ ]
+ ],
+ [
"
-
- GoUpstate.com News Headlines
- http://www.goupstate.com/
- The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.
- 60
-
- ",
- array(
- 'title' => "GoUpstate.com News Headlines",
- 'url' => 'http://www.goupstate.com/',
+
+ GoUpstate.com News Headlines
+ http://www.goupstate.com/
+ The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.
+ 60
+
+ ",
+ [
+ 'title' => "GoUpstate.com News Headlines",
+ 'url' => 'http://www.goupstate.com/',
'description' => "The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.",
- 'ttl' => 60,
- )
- ),
- array(
+ 'ttl' => 60,
+ ]
+ ],
+ [
"
-
- GoUpstate.com News Headlines
- http://www.goupstate.com/
- The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.
- Copyright 2002, Spartanburg Herald-Journal
-
- ",
- array(
- 'title' => "GoUpstate.com News Headlines",
- 'url' => 'http://www.goupstate.com/',
+
+ GoUpstate.com News Headlines
+ http://www.goupstate.com/
+ The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.
+ Copyright 2002, Spartanburg Herald-Journal
+
+ ",
+ [
+ 'title' => "GoUpstate.com News Headlines",
+ 'url' => 'http://www.goupstate.com/',
'description' => "The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.",
- 'copyright' => "Copyright 2002, Spartanburg Herald-Journal",
- )
- ),
- );
+ 'copyright' => "Copyright 2002, Spartanburg Herald-Journal",
+ ]
+ ],
+ ];
}
public function testAppendTo_with_items()
@@ -226,24 +235,24 @@ class ChannelTest extends \XoopsUnit\TestCase
->attr('title', "GoUpstate.com News Headlines")
->attr('url', 'http://www.goupstate.com/')
->attr('description', "The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.")
- ->attr('items', array($item1, $item2, $item3));
+ ->attr('items', [$item1, $item2, $item3]);
$expect = '
-
- GoUpstate.com News Headlines
- http://www.goupstate.com/
- The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.
- -
-
item1
-
- -
-
item2
-
- -
-
item3
-
-
- ';
+
+ GoUpstate.com News Headlines
+ http://www.goupstate.com/
+ The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.
+ -
+
item1
+
+ -
+
item2
+
+ -
+
item3
+
+
+ ';
$this->assertXmlStringEqualsXmlString($expect, $channel->asXML()->asXML());
}
diff --git a/system/vendor/suin/php-rss-writer/Tests/Suin/RSSWriter/FeedTest.php b/system/vendor/suin/php-rss-writer/Tests/Suin/RSSWriter/FeedTest.php
index a949584..97203f1 100644
--- a/system/vendor/suin/php-rss-writer/Tests/Suin/RSSWriter/FeedTest.php
+++ b/system/vendor/suin/php-rss-writer/Tests/Suin/RSSWriter/FeedTest.php
@@ -13,7 +13,7 @@ class FeedTest extends \XoopsUnit\TestCase
$channel = Mockery::mock($this->channelInterface);
$feed = new Feed();
$this->assertSame($feed, $feed->addChannel($channel));
- $this->assertAttributeSame(array($channel), 'channels', $feed);
+ $this->assertAttributeSame([$channel], 'channels', $feed);
}
public function testRender()
@@ -28,14 +28,14 @@ class FeedTest extends \XoopsUnit\TestCase
$channel2->expects($this->once())->method('asXML')->will($this->returnValue($xml2));
$channel3 = $this->getMock($this->channelInterface);
$channel3->expects($this->once())->method('asXML')->will($this->returnValue($xml3));
- $this->reveal($feed)->attr('channels', array($channel1, $channel2, $channel3));
+ $this->reveal($feed)->attr('channels', [$channel1, $channel2, $channel3]);
$expect = '
-
- channel1
- channel2
- channel3
-
- ';
+
+ channel1
+ channel2
+ channel3
+
+ ';
$this->assertXmlStringEqualsXmlString($expect, $feed->render());
}
@@ -51,10 +51,10 @@ class FeedTest extends \XoopsUnit\TestCase
$channel2->expects($this->once())->method('asXML')->will($this->returnValue($xml2));
$channel3 = $this->getMock($this->channelInterface);
$channel3->expects($this->once())->method('asXML')->will($this->returnValue($xml3));
- $this->reveal($feed)->attr('channels', array($channel1, $channel2, $channel3));
+ $this->reveal($feed)->attr('channels', [$channel1, $channel2, $channel3]);
$expect = <<< 'XML'
-
+
日本語1
@@ -83,14 +83,14 @@ XML;
$channel2->expects($this->once())->method('asXML')->will($this->returnValue($xml2));
$channel3 = $this->getMock($this->channelInterface);
$channel3->expects($this->once())->method('asXML')->will($this->returnValue($xml3));
- $this->reveal($feed)->attr('channels', array($channel1, $channel2, $channel3));
+ $this->reveal($feed)->attr('channels', [$channel1, $channel2, $channel3]);
$expect = '
-
- channel1
- channel2
- channel3
-
- ';
- $this->assertXmlStringEqualsXmlString($expect, $feed);
+
+ channel1
+ channel2
+ channel3
+
+ ';
+ $this->assertXmlStringEqualsXmlString($expect, strval($feed));
}
}
diff --git a/system/vendor/suin/php-rss-writer/Tests/Suin/RSSWriter/ItemTest.php b/system/vendor/suin/php-rss-writer/Tests/Suin/RSSWriter/ItemTest.php
index c8ccd18..e31978d 100644
--- a/system/vendor/suin/php-rss-writer/Tests/Suin/RSSWriter/ItemTest.php
+++ b/system/vendor/suin/php-rss-writer/Tests/Suin/RSSWriter/ItemTest.php
@@ -32,14 +32,42 @@ class ItemTest extends TestCase
$this->assertAttributeSame($description, 'description', $item);
}
+ public function testContentEncoded()
+ {
+ $item = new Item();
+ $this->assertSame($item, $item->contentEncoded('contents
'));
+ $this->assertAttributeSame('contents
', 'contentEncoded', $item);
+
+ $feed = new Feed();
+ $channel = new Channel();
+ $item->appendTo($channel);
+ $channel->appendTo($feed);
+
+ $expected = '
+
+
+
+
+
+ -
+
+
+
+ contents]]>
+
+
+ ';
+ $this->assertXmlStringEqualsXmlString($expected, $feed->render());
+ }
+
public function testCategory()
{
$category = uniqid();
$item = new Item();
$this->assertSame($item, $item->category($category));
- $this->assertAttributeSame(array(
- array($category, null),
- ), 'categories', $item);
+ $this->assertAttributeSame([
+ [$category, null],
+ ], 'categories', $item);
}
public function testCategory_with_domain()
@@ -48,9 +76,9 @@ class ItemTest extends TestCase
$domain = uniqid();
$item = new Item();
$this->assertSame($item, $item->category($category, $domain));
- $this->assertAttributeSame(array(
- array($category, $domain),
- ), 'categories', $item);
+ $this->assertAttributeSame([
+ [$category, $domain],
+ ], 'categories', $item);
}
public function testGuid()
@@ -93,7 +121,7 @@ class ItemTest extends TestCase
public function testEnclosure()
{
$url = uniqid();
- $enclosure = array('url' => $url, 'length' => 0, 'type' => 'audio/mpeg');
+ $enclosure = ['url' => $url, 'length' => 0, 'type' => 'audio/mpeg'];
$item = new Item();
$this->assertSame($item, $item->enclosure($url));
$this->assertAttributeSame($enclosure, 'enclosure', $item);
@@ -107,28 +135,57 @@ class ItemTest extends TestCase
$this->assertAttributeSame($author, 'author', $item);
}
+ public function testPreferCdata()
+ {
+ $item = new Item();
+ $item->title('title ');
+ $item->description('description
');
+
+ // By default, prefer no CDATA on title and description
+ $actualXml = $item->asXML()->asXML();
+ $this->assertContains('<h1>title</h1> ', $actualXml);
+ $this->assertContains('<p>description</p> ', $actualXml);
+
+ // Once prefer-cdata is enabled, title and description is wrapped by CDATA
+ $item->preferCdata(true);
+ $actualXml = $item->asXML()->asXML();
+ $this->assertContains('title]]> ', $actualXml);
+ $this->assertContains('description
]]>', $actualXml);
+
+ // Of course, prefer-cdata can be disabled again
+ $item->preferCdata(false);
+ $actualXml = $item->asXML()->asXML();
+ $this->assertContains('<h1>title</h1> ', $actualXml);
+ $this->assertContains('<p>description</p> ', $actualXml);
+
+ // And like other APIs `preferCdata` is also fluent interface
+ $obj = $item->preferCdata(true);
+ $this->assertSame($obj, $item);
+ }
+
public function testAsXML()
{
$now = time();
$nowString = date(DATE_RSS, $now);
- $data = array(
- 'title' => "Venice Film Festival Tries to Quit Sinking",
- 'url' => 'http://nytimes.com/2004/12/07FEST.html',
+ $data = [
+ 'title' => "Venice Film Festival Tries to Quit Sinking",
+ 'url' => 'http://nytimes.com/2004/12/07FEST.html',
'description' => "Some of the most heated chatter at the Venice Film Festival this week was about the way that the arrival of the stars at the Palazzo del Cinema was being staged.",
- 'categories' => array(
- array("Grateful Dead", null),
- array("MSFT", 'http://www.fool.com/cusips'),
- ),
- 'guid' => "http://inessential.com/2002/09/01.php#a2",
+ 'categories' => [
+ ["Grateful Dead", null],
+ ["MSFT", 'http://www.fool.com/cusips'],
+ ],
+ 'guid' => "http://inessential.com/2002/09/01.php#a2",
'isPermalink' => true,
- 'pubDate' => $now,
- 'enclosure' => array(
- 'url' => 'http://link-to-audio-file.com/test.mp3',
+ 'pubDate' => $now,
+ 'enclosure' => [
+ 'url' => 'http://link-to-audio-file.com/test.mp3',
'length' => 4992,
- 'type' => 'audio/mpeg'),
- 'author' => 'Hidehito Nozawa aka Suin'
- );
+ 'type' => 'audio/mpeg'
+ ],
+ 'author' => 'John Smith'
+ ];
$item = new Item();
@@ -137,18 +194,18 @@ class ItemTest extends TestCase
}
$expect = "
- -
-
{$data['title']}
- {$data['url']}
- {$data['description']}
- {$data['categories'][0][0]}
- {$data['categories'][1][0]}
- {$data['guid']}
- {$nowString}
-
- {$data['author']}
-
- ";
+ -
+
{$data['title']}
+ {$data['url']}
+ {$data['description']}
+ {$data['categories'][0][0]}
+ {$data['categories'][1][0]}
+ {$data['guid']}
+ {$nowString}
+
+ {$data['author']}
+
+ ";
$this->assertXmlStringEqualsXmlString($expect, $item->asXML()->asXML());
}
@@ -157,23 +214,24 @@ class ItemTest extends TestCase
$now = time();
$nowString = date(DATE_RSS, $now);
- $data = array(
- 'title' => "Venice Film Festival Tries to Quit Sinking",
- 'url' => 'http://nytimes.com/2004/12/07FEST.html',
+ $data = [
+ 'title' => "Venice Film Festival Tries to Quit Sinking",
+ 'url' => 'http://nytimes.com/2004/12/07FEST.html',
'description' => "Some of the most heated chatter at the Venice Film Festival this week was about the way that the arrival of the stars at the Palazzo del Cinema was being staged.",
- 'categories' => array(
- array("Grateful Dead", null),
- array("MSFT", 'http://www.fool.com/cusips'),
- ),
- 'guid' => "http://inessential.com/2002/09/01.php#a2",
+ 'categories' => [
+ ["Grateful Dead", null],
+ ["MSFT", 'http://www.fool.com/cusips'],
+ ],
+ 'guid' => "http://inessential.com/2002/09/01.php#a2",
'isPermalink' => false,
- 'pubDate' => $now,
- 'enclosure' => array(
- 'url' => 'http://link-to-audio-file.com/test.mp3',
+ 'pubDate' => $now,
+ 'enclosure' => [
+ 'url' => 'http://link-to-audio-file.com/test.mp3',
'length' => 4992,
- 'type' => 'audio/mpeg'),
- 'author' => 'Hidehito Nozawa aka Suin'
- );
+ 'type' => 'audio/mpeg'
+ ],
+ 'author' => 'John Smith'
+ ];
$item = new Item();
@@ -182,28 +240,28 @@ class ItemTest extends TestCase
}
$expect = "
- -
-
{$data['title']}
- {$data['url']}
- {$data['description']}
- {$data['categories'][0][0]}
- {$data['categories'][1][0]}
- {$data['guid']}
- {$nowString}
-
- {$data['author']}
-
- ";
+ -
+
{$data['title']}
+ {$data['url']}
+ {$data['description']}
+ {$data['categories'][0][0]}
+ {$data['categories'][1][0]}
+ {$data['guid']}
+ {$nowString}
+
+ {$data['author']}
+
+ ";
$this->assertXmlStringEqualsXmlString($expect, $item->asXML()->asXML());
}
public function testAsXML_test_Japanese()
{
- $data = array(
- 'title' => "Venice Film Festival",
- 'url' => 'http://nytimes.com/2004/12/07FEST.html',
+ $data = [
+ 'title' => "Venice Film Festival",
+ 'url' => 'http://nytimes.com/2004/12/07FEST.html',
'description' => "Some of the most heated chatter at the Venice Film Festival this week was about the way that the arrival of the stars at the Palazzo del Cinema was being staged.",
- );
+ ];
$item = new Item();
@@ -212,12 +270,12 @@ class ItemTest extends TestCase
}
$expect = "
- -
-
{$data['title']}
- {$data['url']}
- {$data['description']}
-
- ";
+ -
+
{$data['title']}
+ {$data['url']}
+ {$data['description']}
+
+ ";
$this->assertXmlStringEqualsXmlString($expect, $item->asXML()->asXML());
}
diff --git a/system/vendor/suin/php-rss-writer/composer.json b/system/vendor/suin/php-rss-writer/composer.json
index dcffdb7..29e6f3c 100644
--- a/system/vendor/suin/php-rss-writer/composer.json
+++ b/system/vendor/suin/php-rss-writer/composer.json
@@ -1,20 +1,33 @@
{
- "name": "suin/php-rss-writer",
- "type": "library",
- "description": "Yet another simple RSS writer library for PHP 5.3 or later.",
- "keywords": ["rss", "generator", "writer", "feed", "php"],
- "homepage": "https://github.com/suin/php-rss-writer",
- "license": "MIT",
- "authors": [
- {
- "name": "Hidehito Nozawa aka Suin",
- "email": "suinyeze@gmail.com"
- }
- ],
- "require": {
- "php": ">=5.3.0"
- },
- "autoload": {
- "psr-0": { "Suin\\RSSWriter": "src" }
- }
+ "name": "suin/php-rss-writer",
+ "type": "library",
+ "description": "Yet another simple RSS writer library for PHP 5.4 or later.",
+ "keywords": [
+ "rss",
+ "generator",
+ "writer",
+ "feed",
+ "php"
+ ],
+ "homepage": "https://github.com/suin/php-rss-writer",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "suin",
+ "email": "suinyeze@gmail.com"
+ }
+ ],
+ "require": {
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "EHER/PHPUnit": ">=1.6",
+ "mockery/mockery": ">=0.7.2",
+ "suin/xoopsunit": ">=1.2"
+ },
+ "autoload": {
+ "psr-0": {
+ "Suin\\RSSWriter": "src"
+ }
+ }
}
diff --git a/system/vendor/suin/php-rss-writer/docker-compose.development.yml b/system/vendor/suin/php-rss-writer/docker-compose.development.yml
new file mode 100644
index 0000000..412c257
--- /dev/null
+++ b/system/vendor/suin/php-rss-writer/docker-compose.development.yml
@@ -0,0 +1 @@
+docker-compose.yml
\ No newline at end of file
diff --git a/system/vendor/suin/php-rss-writer/docker-compose.yml b/system/vendor/suin/php-rss-writer/docker-compose.yml
new file mode 100644
index 0000000..08f157b
--- /dev/null
+++ b/system/vendor/suin/php-rss-writer/docker-compose.yml
@@ -0,0 +1,25 @@
+version: "2"
+services:
+ php70:
+ image: php:7.0-alpine
+ command: vendor/bin/phpunit
+ volumes: [".:/app"]
+ working_dir: /app
+
+ php56:
+ image: php:5.6-alpine
+ command: vendor/bin/phpunit
+ volumes: [".:/app"]
+ working_dir: /app
+
+ php55:
+ image: php:5.5-alpine
+ command: vendor/bin/phpunit
+ volumes: [".:/app"]
+ working_dir: /app
+
+ php54:
+ image: php:5.4-cli
+ command: vendor/bin/phpunit
+ volumes: [".:/app"]
+ working_dir: /app
diff --git a/system/vendor/suin/php-rss-writer/examples/simple-feed.php b/system/vendor/suin/php-rss-writer/examples/simple-feed.php
index 7e12210..a96d33d 100644
--- a/system/vendor/suin/php-rss-writer/examples/simple-feed.php
+++ b/system/vendor/suin/php-rss-writer/examples/simple-feed.php
@@ -1,37 +1,52 @@
title("Channel Title")
- ->description("Channel Description")
- ->url('http://blog.example.com')
- ->language('en-US')
- ->copyright('Copyright 2012, Foo Bar')
- ->pubDate(strtotime('Tue, 21 Aug 2012 19:50:37 +0900'))
- ->lastBuildDate(strtotime('Tue, 21 Aug 2012 19:50:37 +0900'))
- ->ttl(60)
- ->appendTo($feed);
+ ->title('Channel Title')
+ ->description('Channel Description')
+ ->url('http://blog.example.com')
+ ->feedUrl('http://blog.example.com/rss')
+ ->language('en-US')
+ ->copyright('Copyright 2012, Foo Bar')
+ ->pubDate(strtotime('Tue, 21 Aug 2012 19:50:37 +0900'))
+ ->lastBuildDate(strtotime('Tue, 21 Aug 2012 19:50:37 +0900'))
+ ->ttl(60)
+ ->pubsubhubbub('http://example.com/feed.xml', 'http://pubsubhubbub.appspot.com') // This is optional. Specify PubSubHubbub discovery if you want.
+ ->appendTo($feed);
+// Blog item
$item = new Item();
$item
- ->title("Blog Entry Title")
- ->description("Blog body
")
- ->url('http://blog.example.com/2012/08/21/blog-entry/')
- ->pubDate(strtotime('Tue, 21 Aug 2012 19:50:37 +0900'))
- ->guid('http://blog.example.com/2012/08/21/blog-entry/', true)
- ->appendTo($channel);
+ ->title('Blog Entry Title')
+ ->description('Blog body
')
+ ->contentEncoded('Blog body
')
+ ->url('http://blog.example.com/2012/08/21/blog-entry/')
+ ->author('john@smith.com')
+ ->creator('John Smith')
+ ->pubDate(strtotime('Tue, 21 Aug 2012 19:50:37 +0900'))
+ ->guid('http://blog.example.com/2012/08/21/blog-entry/', true)
+ ->preferCdata(true) // By this, title and description become CDATA wrapped HTML.
+ ->appendTo($channel);
+// Podcast item
+$item = new Item();
+$item
+ ->title('Some Podcast Entry')
+ ->description('Podcast body
')
+ ->url('http://podcast.example.com/2012/08/21/podcast-entry/')
+ ->enclosure('http://podcast.example.com/2012/08/21/podcast.mp3', 4889, 'audio/mpeg')
+ ->appendTo($channel);
-echo $feed; // or echo $feed->render();
\ No newline at end of file
+echo $feed; // or echo $feed->render();
diff --git a/system/vendor/suin/php-rss-writer/phpunit.xml.dist b/system/vendor/suin/php-rss-writer/phpunit.xml.dist
new file mode 100644
index 0000000..7df3144
--- /dev/null
+++ b/system/vendor/suin/php-rss-writer/phpunit.xml.dist
@@ -0,0 +1,40 @@
+
+
+
+
+ tests
+
+
+
+
+
+
+
+
+
+ src
+
+ src
+
+
+
+ vendor
+
+
+
+
+
+
diff --git a/system/vendor/suin/php-rss-writer/src/Suin/RSSWriter/Channel.php b/system/vendor/suin/php-rss-writer/src/Suin/RSSWriter/Channel.php
index 0c97f92..72adae7 100644
--- a/system/vendor/suin/php-rss-writer/src/Suin/RSSWriter/Channel.php
+++ b/system/vendor/suin/php-rss-writer/src/Suin/RSSWriter/Channel.php
@@ -14,6 +14,9 @@ class Channel implements ChannelInterface
/** @var string */
protected $url;
+ /** @var feedUrl */
+ protected $feedUrl;
+
/** @var string */
protected $description;
@@ -32,8 +35,11 @@ class Channel implements ChannelInterface
/** @var int */
protected $ttl;
+ /** @var string[] */
+ protected $pubsubhubbub;
+
/** @var ItemInterface[] */
- protected $items = array();
+ protected $items = [];
/**
* Set channel title
@@ -57,6 +63,17 @@ class Channel implements ChannelInterface
return $this;
}
+ /**
+ * Set URL of this feed
+ * @param string $url
+ * @return $this;
+ */
+ public function feedUrl($url)
+ {
+ $this->feedUrl = $url;
+ return $this;
+ }
+
/**
* Set channel description
* @param string $description
@@ -129,6 +146,21 @@ class Channel implements ChannelInterface
return $this;
}
+ /**
+ * Enable PubSubHubbub discovery
+ * @param string $feedUrl
+ * @param string $hubUrl
+ * @return $this
+ */
+ public function pubsubhubbub($feedUrl, $hubUrl)
+ {
+ $this->pubsubhubbub = [
+ 'feedUrl' => $feedUrl,
+ 'hubUrl' => $hubUrl,
+ ];
+ return $this;
+ }
+
/**
* Add item object
* @param ItemInterface $item
@@ -162,6 +194,13 @@ class Channel implements ChannelInterface
$xml->addChild('link', $this->url);
$xml->addChild('description', $this->description);
+ if($this->feedUrl !== null) {
+ $link = $xml->addChild('atom:link', '', "http://www.w3.org/2005/Atom");
+ $link->addAttribute('href',$this->feedUrl);
+ $link->addAttribute('type','application/rss+xml');
+ $link->addAttribute('rel','self');
+ }
+
if ($this->language !== null) {
$xml->addChild('language', $this->language);
}
@@ -182,6 +221,17 @@ class Channel implements ChannelInterface
$xml->addChild('ttl', $this->ttl);
}
+ if ($this->pubsubhubbub !== null) {
+ $feedUrl = $xml->addChild('xmlns:atom:link');
+ $feedUrl->addAttribute('rel', 'self');
+ $feedUrl->addAttribute('href', $this->pubsubhubbub['feedUrl']);
+ $feedUrl->addAttribute('type', 'application/rss+xml');
+
+ $hubUrl = $xml->addChild('xmlns:atom:link');
+ $hubUrl->addAttribute('rel', 'hub');
+ $hubUrl->addAttribute('href', $this->pubsubhubbub['hubUrl']);
+ }
+
foreach ($this->items as $item) {
$toDom = dom_import_simplexml($xml);
$fromDom = dom_import_simplexml($item->asXML());
diff --git a/system/vendor/suin/php-rss-writer/src/Suin/RSSWriter/Feed.php b/system/vendor/suin/php-rss-writer/src/Suin/RSSWriter/Feed.php
index 4a4fc2d..e805049 100644
--- a/system/vendor/suin/php-rss-writer/src/Suin/RSSWriter/Feed.php
+++ b/system/vendor/suin/php-rss-writer/src/Suin/RSSWriter/Feed.php
@@ -11,7 +11,7 @@ use DOMDocument;
class Feed implements FeedInterface
{
/** @var ChannelInterface[] */
- protected $channels = array();
+ protected $channels = [];
/**
* Add channel
@@ -30,7 +30,7 @@ class Feed implements FeedInterface
*/
public function render()
{
- $xml = new SimpleXMLElement(' ', LIBXML_NOERROR | LIBXML_ERR_NONE | LIBXML_ERR_FATAL);
+ $xml = new SimpleXMLElement(' ', LIBXML_NOERROR | LIBXML_ERR_NONE | LIBXML_ERR_FATAL);
foreach ($this->channels as $channel) {
$toDom = dom_import_simplexml($xml);
diff --git a/system/vendor/suin/php-rss-writer/src/Suin/RSSWriter/Item.php b/system/vendor/suin/php-rss-writer/src/Suin/RSSWriter/Item.php
index c392100..17cd8e4 100644
--- a/system/vendor/suin/php-rss-writer/src/Suin/RSSWriter/Item.php
+++ b/system/vendor/suin/php-rss-writer/src/Suin/RSSWriter/Item.php
@@ -17,8 +17,11 @@ class Item implements ItemInterface
/** @var string */
protected $description;
+ /** @var string */
+ protected $contentEncoded;
+
/** @var array */
- protected $categories = array();
+ protected $categories = [];
/** @var string */
protected $guid;
@@ -35,6 +38,11 @@ class Item implements ItemInterface
/** @var string */
protected $author;
+ /** @var string */
+ protected $creator;
+
+ protected $preferCdata = false;
+
public function title($title)
{
$this->title = $title;
@@ -53,9 +61,15 @@ class Item implements ItemInterface
return $this;
}
+ public function contentEncoded($content)
+ {
+ $this->contentEncoded = $content;
+ return $this;
+ }
+
public function category($name, $domain = null)
{
- $this->categories[] = array($name, $domain);
+ $this->categories[] = [$name, $domain];
return $this;
}
@@ -74,7 +88,7 @@ class Item implements ItemInterface
public function enclosure($url, $length = 0, $type = 'audio/mpeg')
{
- $this->enclosure = array('url' => $url, 'length' => $length, 'type' => $type);
+ $this->enclosure = ['url' => $url, 'length' => $length, 'type' => $type];
return $this;
}
@@ -84,6 +98,18 @@ class Item implements ItemInterface
return $this;
}
+ public function creator($creator)
+ {
+ $this->creator = $creator;
+ return $this;
+ }
+
+ public function preferCdata($preferCdata)
+ {
+ $this->preferCdata = (bool)$preferCdata;
+ return $this;
+ }
+
public function appendTo(ChannelInterface $channel)
{
$channel->addItem($this);
@@ -93,9 +119,24 @@ class Item implements ItemInterface
public function asXML()
{
$xml = new SimpleXMLElement(' ', LIBXML_NOERROR | LIBXML_ERR_NONE | LIBXML_ERR_FATAL);
- $xml->addChild('title', $this->title);
+
+ if ($this->preferCdata) {
+ $xml->addCdataChild('title', $this->title);
+ } else {
+ $xml->addChild('title', $this->title);
+ }
+
$xml->addChild('link', $this->url);
- $xml->addChild('description', $this->description);
+
+ if ($this->preferCdata) {
+ $xml->addCdataChild('description', $this->description);
+ } else {
+ $xml->addChild('description', $this->description);
+ }
+
+ if ($this->contentEncoded) {
+ $xml->addCdataChild('xmlns:content:encoded', $this->contentEncoded);
+ }
foreach ($this->categories as $category) {
$element = $xml->addChild('category', $category[0]);
@@ -131,6 +172,10 @@ class Item implements ItemInterface
$xml->addChild('author', $this->author);
}
+ if (!empty($this->creator)) {
+ $xml->addChild('dc:creator', $this->creator,"http://purl.org/dc/elements/1.1/");
+ }
+
return $xml;
}
}
diff --git a/system/vendor/suin/php-rss-writer/src/Suin/RSSWriter/ItemInterface.php b/system/vendor/suin/php-rss-writer/src/Suin/RSSWriter/ItemInterface.php
index 744ffa1..0bef322 100644
--- a/system/vendor/suin/php-rss-writer/src/Suin/RSSWriter/ItemInterface.php
+++ b/system/vendor/suin/php-rss-writer/src/Suin/RSSWriter/ItemInterface.php
@@ -29,6 +29,13 @@ interface ItemInterface
*/
public function description($description);
+ /**
+ * Set content:encoded
+ * @param string $content
+ * @return $this
+ */
+ public function contentEncoded($content);
+
/**
* Set item category
* @param string $name Category name
diff --git a/system/vendor/suin/php-rss-writer/src/Suin/RSSWriter/SimpleXMLElement.php b/system/vendor/suin/php-rss-writer/src/Suin/RSSWriter/SimpleXMLElement.php
index c734719..cbc49ff 100644
--- a/system/vendor/suin/php-rss-writer/src/Suin/RSSWriter/SimpleXMLElement.php
+++ b/system/vendor/suin/php-rss-writer/src/Suin/RSSWriter/SimpleXMLElement.php
@@ -9,6 +9,12 @@ namespace Suin\RSSWriter;
class SimpleXMLElement extends \SimpleXMLElement
{
#[\ReturnTypeWillChange]
+ /**
+ * @param string $name
+ * @param string $value
+ * @param string $namespace
+ * @return \SimpleXMLElement
+ */
public function addChild($name, $value = null, $namespace = null)
{
if ($value !== null and is_string($value) === true) {
@@ -17,4 +23,19 @@ class SimpleXMLElement extends \SimpleXMLElement
return parent::addChild($name, $value, $namespace);
}
+
+ /**
+ * @param string $name
+ * @param string $value
+ * @param string $namespace
+ * @return \SimpleXMLElement
+ */
+ public function addCdataChild($name, $value = null, $namespace = null)
+ {
+ $element = $this->addChild($name, null, $namespace);
+ $dom = dom_import_simplexml($element);
+ $elementOwner = $dom->ownerDocument;
+ $dom->appendChild($elementOwner->createCDATASection($value));
+ return $element;
+ }
}
diff --git a/system/vendor/voku/portable-ascii/CHANGELOG.md b/system/vendor/voku/portable-ascii/CHANGELOG.md
new file mode 100644
index 0000000..12fc393
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/CHANGELOG.md
@@ -0,0 +1,202 @@
+# Changelog
+
+### 2.0.1 (2022-03-08)
+
+- "To people of Russia": There is a war in Ukraine right now. The forces of the Russian Federation are attacking civilians.
+- optimize some phpdocs
+
+### 2.0.0 (2022-01-24)
+
+- prefer "Russian - Passport (2013), ICAO" instead of "Russian - GOST 7.79-2000(B)"
+- fix "Ukrainian" char-mapping (thanks to @Andr1yk0)
+- fix "Persian" char-mapping (thanks to @frost-cyber)
+
+### 1.6.1 (2022-01-24)
+
+- revert: prefer "Russian - Passport (2013), ICAO" instead of "Russian - GOST 7.79-2000(B)"
+- revert: fix "Ukrainian" char-mapping (thanks to @Andr1yk0)
+- revert: fix "Persian" char-mapping (thanks to @frost-cyber)
+
+### 1.6.0 (2022-01-24)
+
+- prefer "Russian - Passport (2013), ICAO" instead of "Russian - GOST 7.79-2000(B)"
+- fix "Ukrainian" char-mapping (thanks to @Andr1yk0)
+- fix "Persian" char-mapping (thanks to @frost-cyber)
+- fix "ASCII::normalize_whitespace()" -> "CARRIAGE RETURN" is more like " " and no "\n"
+- add "ASCII::to_ascii_remap()" -> this method will return broken characters and is only for special cases
+
+### 1.5.6 (2020-11-12)
+
+- "ASCII::normalize_whitespace()" -> can now also remove "control characters" if needed v2
+
+### 1.5.5 (2020-11-12)
+
+- fix "Greeklish" char-mapping (thanks @sebdesign)
+- "ASCII::normalize_whitespace()" -> can now also remove "control characters" if needed
+
+### 1.5.4 (2020-11-08)
+
+- add some missing replacements in U+23xx page (thanks @marcoffee)
+- fix "Russian" char-mapping (thanks @ilyahoilik)
+- running test with PHP 8.0 rc3
+
+### 1.5.3 (2020-07-23)
+
+- fix "Georgian" char-mapping (thanks @waska14)
+
+### 1.5.2 (2020-06-16)
+
+- add "Bengali" (bn) language support (thanks @eliyas5044)
+- fix "Portuguese" char-mapping
+- reduce the file size (removed extra comments from "avian2/unidecode")
+
+### 1.5.1 (2020-05-26)
+
+- fix merge ASCII transliterations from "avian2/unidecode" (python)
+ -> https://github.com/avian2/unidecode/
+
+### 1.5.0 (2020-05-24)
+
+- merge ASCII transliterations from "avian2/unidecode" (python)
+ -> https://github.com/avian2/unidecode/
+
+### 1.4.11 (2020-05-23)
+
+- "composer.json" -> remove "autoload-dev" stuff from "autoload"
+- "voku/php-readme-helper" -> auto-generate the API documentation in the README
+
+### 1.4.10 (2020-03-13)
+
+- ASCII::to_ascii() -> fix extra symbol handling in the regex
+- ASCII::to_ascii() -> fix for languages with multi-length-special-char (e.g. Greek -> 'ει' => 'i')
+
+### 1.4.9 (2020-03-06)
+
+- ASCII::to_slugify() -> fix php warning from empty "separator"
+
+### 1.4.8 (2020-02-06)
+
+- small optimization for "ASCII::to_ascii()" performance
+
+### 1.4.7 (2020-01-27)
+
+- fix possible wrong type from "getDataIfExists()" -> e.g. a bug reported where "/data/" was modified
+- inline variables
+- do not use "=== true" for "bool"-types
+
+### 1.4.6 (2019-12-23)
+
+- optimize "ASCII::to_ascii()" performance
+- add "armenian" chars
+- add "ASCII:getAllLanguages()"
+
+### 1.4.5 (2019-12-19)
+
+- use "@psalm-pure" v2
+
+### 1.4.4 (2019-12-19)
+
+- use "@psalm-pure"
+
+### 1.4.3 (2019-12-19)
+
+- use "@psalm-immutable"
+
+### 1.4.2 (2019-12-13)
+
+- optimize the performance v2
+- more fixes for non-ascii regex
+
+### 1.4.1 (2019-12-13)
+
+- fix regex for non-ascii
+
+### 1.4.0 (2019-12-13)
+
+- optimize the performance, via single char replacements
+
+### 1.3.6 (2019-12-13)
+
+- "ascii_extras" -> convert the static content into ascii
+ -> e.g.: instead of replacing "+" with "più" we use "piu" (Italian), because we want to use ascii anyway
+
+### 1.3.5 (2019-11-11)
+
+- fix "ASCII::remove_invisible_characters()" -> do not remove invisible encoded url strings by default
+
+### 1.3.4 (2019-10-14)
+
+- fix static cache for "ASCII::charsArrayWithOneLanguage"
+
+### 1.3.3 (2019-10-14)
+
+- fix "Turkish" mapping -> 'ä' -> 'a'
+
+### 1.3.2 (2019-10-14)
+
+- fix language parameter usage with e.g. "de_DE"
+- re-add missing "extra"-mapping chars
+
+### 1.3.1 (2019-10-13)
+
+- fix "ASCII::to_slugify" -> remove unicode chars
+- add more test for ascii chars in the mapping
+- fix non ascii chars in the mapping
+
+### 1.3.0 (2019-10-12)
+
+- add transliteration "fr" (was supported before, but with chars from other languages)
+- add transliteration "ru" - Passport (2013), ICAO
+- add transliteration "ru" - GOST 7.79-2000(B)
+- add transliteration "el" - greeklish
+- add transliteration "zh"
+- add transliteration "nl"
+- add transliteration "it"
+- add transliteration "mk"
+- add transliteration "pt"
+- add constants -> ASCII::*LANGUAGE_CODES
+- add more special latin chars / (currency) symbols
+- add simple tests for all supported languages
+- optimize "Russian" to ASCII (via "translit.ru")
+- optimize performance of string replacement
+- optimize performance of array merging
+- optimize phpdoc comments
+- "ASCII::to_transliterate" -> use "transliterator_create" + static cache
+- "ASCII::to_ascii" -> fix "remove unsupported chars"
+- "ASCII::to_ascii" -> add some more special chars
+- run/fix static analyse via "pslam" + "phpstan"
+- auto fix code style via "php-cs-fixer"
+- fix transliteration for "german"
+- fix transliteration for "persian" (thanks @mardep)
+- fix transliteration for "polish" (thanks @dariusz.drobisz)
+- fix transliteration for "bulgarian" (thanks @mkosturkov)
+- fix transliteration for "croatian" (thanks @ludifonovac)
+- fix transliteration for "serbian" (thanks @ludifonovac)
+- fix transliteration for "swedish" (thanks @nicholasruunu)
+- fix transliteration for "france" (thanks @sharptsa)
+- fix transliteration for "serbian" (thanks @nikolaposa)
+- fix transliteration for "czech" (thanks @slepic)
+
+### 1.2.3 (2019-09-10)
+
+- fix language depending ASCII chars (the order matters)
+
+### 1.2.2 (2019-09-10)
+
+- fix bulgarian ASCII chars | thanks @bgphp
+
+### 1.2.1 (2019-09-07)
+
+- "charsArray()" -> add access to "ASCII::$ASCII_MAPS*""
+
+### 1.2.0 (2019-09-07)
+
+- "to_slugify()" -> use the extra ascii array
+
+### 1.1.0 (2019-09-07)
+
+- add + split extra ascii replacements
+
+### 1.0.0 (2019-09-05)
+
+- initial commit
\ No newline at end of file
diff --git a/system/vendor/voku/portable-ascii/LICENSE.txt b/system/vendor/voku/portable-ascii/LICENSE.txt
new file mode 100644
index 0000000..b6ba47e
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/LICENSE.txt
@@ -0,0 +1,19 @@
+Copyright (C) 2019 Lars Moelleken
+
+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.
diff --git a/system/vendor/voku/portable-ascii/README.md b/system/vendor/voku/portable-ascii/README.md
new file mode 100644
index 0000000..3ce36d6
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/README.md
@@ -0,0 +1,451 @@
+[//]: # (AUTO-GENERATED BY "PHP README Helper": base file -> docs/base.md)
+[](https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md)
+
+[](https://github.com/voku/portable-ascii/actions)
+[](https://ci.appveyor.com/project/voku/portable-ascii/branch/master)
+[](https://codecov.io/github/voku/portable-ascii?branch=master)
+[](https://www.codacy.com/app/voku/portable-ascii)
+[](https://packagist.org/packages/voku/portable-ascii)
+[](https://packagist.org/packages/voku/portable-ascii)
+[](https://packagist.org/packages/voku/portable-ascii)
+[](https://www.paypal.me/moelleken)
+[](https://www.patreon.com/voku)
+
+# 🔡 Portable ASCII
+
+## Description
+
+It is written in PHP (PHP 7+) and can work without "mbstring", "iconv" or any other extra encoding php-extension on your server.
+
+The benefit of Portable ASCII is that it is easy to use, easy to bundle.
+
+The project based on ...
++ Sean M. Burke's work (https://metacpan.org/pod/Text::Unidecode)
++ Tomaz Solc's work (https://pypi.org/project/Unidecode/)
++ Portable UTF-8 work (https://github.com/voku/portable-utf8)
++ Daniel St. Jules's work (https://github.com/danielstjules/Stringy)
++ Johnny Broadway's work (https://github.com/jbroadway/urlify)
++ and many cherry-picks from "github"-gists and "Stack Overflow"-snippets ...
+
+## Index
+
+* [Alternative](#alternative)
+* [Install](#install-portable-ascii-via-composer-require)
+* [Why Portable ASCII?](#why-portable-ascii)
+* [Requirements and Recommendations](#requirements-and-recommendations)
+* [Usage](#usage)
+* [Class methods](#class-methods)
+* [Unit Test](#unit-test)
+* [License and Copyright](#license-and-copyright)
+
+## Alternative
+
+If you like a more Object Oriented Way to edit strings, then you can take a look at [voku/Stringy](https://github.com/voku/Stringy), it's a fork of "danielstjules/Stringy" but it used the "Portable ASCII"-Class and some extra methods.
+
+```php
+// Portable ASCII
+use voku\helper\ASCII;
+ASCII::to_transliterate('déjà σσς iıii'); // 'deja sss iiii'
+
+// voku/Stringy
+use Stringy\Stringy as S;
+$stringy = S::create('déjà σσς iıii');
+$stringy->toTransliterate(); // 'deja sss iiii'
+```
+
+## Install "Portable ASCII" via "composer require"
+```shell
+composer require voku/portable-ascii
+```
+
+## Why Portable ASCII?[]()
+I need ASCII char handling in different classes and before I added this functions into "Portable UTF-8",
+but this repo is more modular and portable, because it has no dependencies.
+
+## Requirements and Recommendations
+
+* No extensions are required to run this library. Portable ASCII only needs PCRE library that is available by default since PHP 4.2.0 and cannot be disabled since PHP 5.3.0. "\u" modifier support in PCRE for ASCII handling is not a must.
+* PHP 7.0 is the minimum requirement
+* PHP 8.0 is also supported
+
+## Usage
+
+Example: ASCII::to_ascii()
+```php
+ echo ASCII::to_ascii('�Düsseldorf�', 'de');
+
+ // will output
+ // Duesseldorf
+
+ echo ASCII::to_ascii('�Düsseldorf�', 'en');
+
+ // will output
+ // Dusseldorf
+```
+
+# Portable ASCII | API
+
+The API from the "ASCII"-Class is written as small static methods.
+
+
+## Class methods
+
+
+
+#### charsArray(bool $replace_extra_symbols): array
+↑
+Returns an replacement array for ASCII methods.
+
+EXAMPLE:
+$array = ASCII::charsArray();
+var_dump($array['ru']['б']); // 'b'
+
+
+**Parameters:**
+- `bool $replace_extra_symbols [optional] Add some more replacements e.g. "£" with " pound ".
`
+
+**Return:**
+- `array`
+
+--------
+
+#### charsArrayWithMultiLanguageValues(bool $replace_extra_symbols): array
+↑
+Returns an replacement array for ASCII methods with a mix of multiple languages.
+
+EXAMPLE:
+$array = ASCII::charsArrayWithMultiLanguageValues();
+var_dump($array['b']); // ['β', 'б', 'ဗ', 'ბ', 'ب']
+
+
+**Parameters:**
+- `bool $replace_extra_symbols [optional] Add some more replacements e.g. "£" with " pound ".
`
+
+**Return:**
+- `array An array of replacements.
`
+
+--------
+
+#### charsArrayWithOneLanguage(string $language, bool $replace_extra_symbols, bool $asOrigReplaceArray): array
+↑
+Returns an replacement array for ASCII methods with one language.
+
+For example, German will map 'ä' to 'ae', while other languages
+will simply return e.g. 'a'.
+
+EXAMPLE:
+$array = ASCII::charsArrayWithOneLanguage('ru');
+$tmpKey = \array_search('yo', $array['replace']);
+echo $array['orig'][$tmpKey]; // 'ё'
+
+
+**Parameters:**
+- `ASCII::* $language [optional] Language of the source string e.g.: en, de_at, or de-ch.
+(default is 'en') | ASCII::*_LANGUAGE_CODE
`
+- `bool $replace_extra_symbols [optional] Add some more replacements e.g. "£" with " pound ".
`
+- `bool $asOrigReplaceArray [optional] TRUE === return {orig: string[], replace: string[]}
+array
`
+
+**Return:**
+- `array An array of replacements.
`
+
+--------
+
+#### charsArrayWithSingleLanguageValues(bool $replace_extra_symbols, bool $asOrigReplaceArray): array
+↑
+Returns an replacement array for ASCII methods with multiple languages.
+
+EXAMPLE:
+$array = ASCII::charsArrayWithSingleLanguageValues();
+$tmpKey = \array_search('hnaik', $array['replace']);
+echo $array['orig'][$tmpKey]; // '၌'
+
+
+**Parameters:**
+- `bool $replace_extra_symbols [optional] Add some more replacements e.g. "£" with " pound ".
`
+- `bool $asOrigReplaceArray [optional] TRUE === return {orig: string[], replace: string[]}
+array
`
+
+**Return:**
+- `array An array of replacements.
`
+
+--------
+
+#### clean(string $str, bool $normalize_whitespace, bool $keep_non_breaking_space, bool $normalize_msword, bool $remove_invisible_characters): string
+↑
+Accepts a string and removes all non-UTF-8 characters from it + extras if needed.
+
+**Parameters:**
+- `string $str The string to be sanitized.
`
+- `bool $normalize_whitespace [optional] Set to true, if you need to normalize the
+whitespace.
`
+- `bool $keep_non_breaking_space [optional] Set to true, to keep non-breaking-spaces, in
+combination with
+$normalize_whitespace
`
+- `bool $normalize_msword [optional] Set to true, if you need to normalize MS Word chars
+e.g.: "…"
+=> "..."
`
+- `bool $remove_invisible_characters [optional] Set to false, if you not want to remove invisible
+characters e.g.: "\0"
`
+
+**Return:**
+- `string A clean UTF-8 string.
`
+
+--------
+
+#### getAllLanguages(): string[]
+↑
+Get all languages from the constants "ASCII::.*LANGUAGE_CODE".
+
+**Parameters:**
+__nothing__
+
+**Return:**
+- `string[]`
+
+--------
+
+#### is_ascii(string $str): bool
+↑
+Checks if a string is 7 bit ASCII.
+
+EXAMPLE:
+ASCII::is_ascii('白'); // false
+
+
+**Parameters:**
+- `string $str The string to check.
`
+
+**Return:**
+- `bool
+true if it is ASCII
+false otherwise
+
`
+
+--------
+
+#### normalize_msword(string $str): string
+↑
+Returns a string with smart quotes, ellipsis characters, and dashes from
+Windows-1252 (commonly used in Word documents) replaced by their ASCII
+equivalents.
+
+EXAMPLE:
+ASCII::normalize_msword('„Abcdef…”'); // '"Abcdef..."'
+
+
+**Parameters:**
+- `string $str The string to be normalized.
`
+
+**Return:**
+- `string A string with normalized characters for commonly used chars in Word documents.
`
+
+--------
+
+#### normalize_whitespace(string $str, bool $keepNonBreakingSpace, bool $keepBidiUnicodeControls, bool $normalize_control_characters): string
+↑
+Normalize the whitespace.
+
+EXAMPLE:
+ASCII::normalize_whitespace("abc-\xc2\xa0-öäü-\xe2\x80\xaf-\xE2\x80\xAC", true); // "abc-\xc2\xa0-öäü- -"
+
+
+**Parameters:**
+- `string $str The string to be normalized.
`
+- `bool $keepNonBreakingSpace [optional] Set to true, to keep non-breaking-spaces.
`
+- `bool $keepBidiUnicodeControls [optional] Set to true, to keep non-printable (for the web)
+bidirectional text chars.
`
+- `bool $normalize_control_characters [optional] Set to true, to convert e.g. LINE-, PARAGRAPH-SEPARATOR with "\n" and LINE TABULATION with "\t".
`
+
+**Return:**
+- `string A string with normalized whitespace.
`
+
+--------
+
+#### remove_invisible_characters(string $str, bool $url_encoded, string $replacement, bool $keep_basic_control_characters): string
+↑
+Remove invisible characters from a string.
+
+e.g.: This prevents sandwiching null characters between ascii characters, like Java\0script.
+
+copy&past from https://github.com/bcit-ci/CodeIgniter/blob/develop/system/core/Common.php
+
+**Parameters:**
+- `string $str`
+- `bool $url_encoded`
+- `string $replacement`
+- `bool $keep_basic_control_characters`
+
+**Return:**
+- `string`
+
+--------
+
+#### to_ascii(string $str, string $language, bool $remove_unsupported_chars, bool $replace_extra_symbols, bool $use_transliterate, bool|null $replace_single_chars_only): string
+↑
+Returns an ASCII version of the string. A set of non-ASCII characters are
+replaced with their closest ASCII counterparts, and the rest are removed
+by default. The language or locale of the source string can be supplied
+for language-specific transliteration in any of the following formats:
+en, en_GB, or en-GB. For example, passing "de" results in "äöü" mapping
+to "aeoeue" rather than "aou" as in other languages.
+
+EXAMPLE:
+ASCII::to_ascii('�Düsseldorf�', 'en'); // Dusseldorf
+
+
+**Parameters:**
+- `string $str The input string.
`
+- `ASCII::* $language [optional] Language of the source string.
+(default is 'en') | ASCII::*_LANGUAGE_CODE
`
+- `bool $remove_unsupported_chars [optional] Whether or not to remove the
+unsupported characters.
`
+- `bool $replace_extra_symbols [optional] Add some more replacements e.g. "£" with " pound
+".
`
+- `bool $use_transliterate [optional] Use ASCII::to_transliterate() for unknown chars.
`
+- `bool|null $replace_single_chars_only [optional] Single char replacement is better for the
+performance, but some languages need to replace more then one char
+at the same time. | NULL === auto-setting, depended on the
+language
`
+
+**Return:**
+- `string A string that contains only ASCII characters.
`
+
+--------
+
+#### to_ascii_remap(string $str1, string $str2): string[]
+↑
+WARNING: This method will return broken characters and is only for special cases.
+
+Convert two UTF-8 encoded string to a single-byte strings suitable for
+functions that need the same string length after the conversion.
+
+The function simply uses (and updates) a tailored dynamic encoding
+(in/out map parameter) where non-ascii characters are remapped to
+the range [128-255] in order of appearance.
+
+**Parameters:**
+- `string $str1`
+- `string $str2`
+
+**Return:**
+- `string[]`
+
+--------
+
+#### to_filename(string $str, bool $use_transliterate, string $fallback_char): string
+↑
+Convert given string to safe filename (and keep string case).
+
+EXAMPLE:
+ASCII::to_filename('שדגשדג.png', true)); // 'shdgshdg.png'
+
+
+**Parameters:**
+- `string $str`
+- `bool $use_transliterate ASCII::to_transliterate() is used by default - unsafe characters are
+simply replaced with hyphen otherwise.
`
+- `string $fallback_char`
+
+**Return:**
+- `string A string that contains only safe characters for a filename.
`
+
+--------
+
+#### to_slugify(string $str, string $separator, string $language, string[] $replacements, bool $replace_extra_symbols, bool $use_str_to_lower, bool $use_transliterate): string
+↑
+Converts the string into an URL slug. This includes replacing non-ASCII
+characters with their closest ASCII equivalents, removing remaining
+non-ASCII and non-alphanumeric characters, and replacing whitespace with
+$separator. The separator defaults to a single dash, and the string
+is also converted to lowercase. The language of the source string can
+also be supplied for language-specific transliteration.
+
+**Parameters:**
+- `string $str`
+- `string $separator [optional] The string used to replace whitespace.
`
+- `ASCII::* $language [optional] Language of the source string.
+(default is 'en') | ASCII::*_LANGUAGE_CODE
`
+- `array $replacements [optional] A map of replaceable strings.
`
+- `bool $replace_extra_symbols [optional] Add some more replacements e.g. "£" with "
+pound ".
`
+- `bool $use_str_to_lower [optional] Use "string to lower" for the input.
`
+- `bool $use_transliterate [optional] Use ASCII::to_transliterate() for unknown
+chars.
`
+
+**Return:**
+- `string A string that has been converted to an URL slug.
`
+
+--------
+
+#### to_transliterate(string $str, string|null $unknown, bool $strict): string
+↑
+Returns an ASCII version of the string. A set of non-ASCII characters are
+replaced with their closest ASCII counterparts, and the rest are removed
+unless instructed otherwise.
+
+EXAMPLE:
+ASCII::to_transliterate('déjà σσς iıii'); // 'deja sss iiii'
+
+
+**Parameters:**
+- `string $str The input string.
`
+- `string|null $unknown [optional] Character use if character unknown. (default is '?')
+But you can also use NULL to keep the unknown chars.
`
+- `bool $strict [optional] Use "transliterator_transliterate()" from PHP-Intl`
+
+**Return:**
+- `string
A String that contains only ASCII characters.
`
+
+--------
+
+
+
+## Unit Test
+
+1) [Composer](https://getcomposer.org) is a prerequisite for running the tests.
+
+```
+composer install
+```
+
+2) The tests can be executed by running this command from the root directory:
+
+```bash
+./vendor/bin/phpunit
+```
+
+### Support
+
+For support and donations please visit [Github](https://github.com/voku/portable-ascii/) | [Issues](https://github.com/voku/portable-ascii/issues) | [PayPal](https://paypal.me/moelleken) | [Patreon](https://www.patreon.com/voku).
+
+For status updates and release announcements please visit [Releases](https://github.com/voku/portable-ascii/releases) | [Twitter](https://twitter.com/suckup_de) | [Patreon](https://www.patreon.com/voku/posts).
+
+For professional support please contact [me](https://about.me/voku).
+
+### Thanks
+
+- Thanks to [GitHub](https://github.com) (Microsoft) for hosting the code and a good infrastructure including Issues-Managment, etc.
+- Thanks to [IntelliJ](https://www.jetbrains.com) as they make the best IDEs for PHP and they gave me an open source license for PhpStorm!
+- Thanks to [Travis CI](https://travis-ci.com/) for being the most awesome, easiest continous integration tool out there!
+- Thanks to [StyleCI](https://styleci.io/) for the simple but powerful code style check.
+- Thanks to [PHPStan](https://github.com/phpstan/phpstan) && [Psalm](https://github.com/vimeo/psalm) for really great Static analysis tools and for discover bugs in the code!
+
+### License and Copyright
+
+Released under the MIT License - see `LICENSE.txt` for details.
diff --git a/system/vendor/voku/portable-ascii/composer.json b/system/vendor/voku/portable-ascii/composer.json
new file mode 100644
index 0000000..99dee4f
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/composer.json
@@ -0,0 +1,37 @@
+{
+ "name": "voku/portable-ascii",
+ "description": "Portable ASCII library - performance optimized (ascii) string functions for php.",
+ "type": "library",
+ "keywords": [
+ "clean",
+ "php",
+ "ascii"
+ ],
+ "homepage": "https://github.com/voku/portable-ascii",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Lars Moelleken",
+ "homepage": "http://www.moelleken.org/"
+ }
+ ],
+ "require": {
+ "php": ">=7.0.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0"
+ },
+ "suggest": {
+ "ext-intl": "Use Intl for transliterator_transliterate() support"
+ },
+ "autoload": {
+ "psr-4": {
+ "voku\\": "src/voku/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "voku\\tests\\": "tests/"
+ }
+ }
+}
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/ASCII.php b/system/vendor/voku/portable-ascii/src/voku/helper/ASCII.php
new file mode 100644
index 0000000..7d8b66d
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/ASCII.php
@@ -0,0 +1,1501 @@
+>|null
+ */
+ private static $ASCII_MAPS;
+
+ /**
+ * @var array>|null
+ */
+ private static $ASCII_MAPS_AND_EXTRAS;
+
+ /**
+ * @var array>|null
+ */
+ private static $ASCII_EXTRAS;
+
+ /**
+ * @var array|null
+ */
+ private static $ORD;
+
+ /**
+ * @var array|null
+ */
+ private static $LANGUAGE_MAX_KEY;
+
+ /**
+ * url: https://en.wikipedia.org/wiki/Wikipedia:ASCII#ASCII_printable_characters
+ *
+ * @var string
+ */
+ private static $REGEX_ASCII = "[^\x09\x10\x13\x0A\x0D\x20-\x7E]";
+
+ /**
+ * bidirectional text chars
+ *
+ * url: https://www.w3.org/International/questions/qa-bidi-unicode-controls
+ *
+ * @var array
+ */
+ private static $BIDI_UNI_CODE_CONTROLS_TABLE = [
+ // LEFT-TO-RIGHT EMBEDDING (use -> dir = "ltr")
+ 8234 => "\xE2\x80\xAA",
+ // RIGHT-TO-LEFT EMBEDDING (use -> dir = "rtl")
+ 8235 => "\xE2\x80\xAB",
+ // POP DIRECTIONAL FORMATTING // (use -> )
+ 8236 => "\xE2\x80\xAC",
+ // LEFT-TO-RIGHT OVERRIDE // (use -> )
+ 8237 => "\xE2\x80\xAD",
+ // RIGHT-TO-LEFT OVERRIDE // (use -> )
+ 8238 => "\xE2\x80\xAE",
+ // LEFT-TO-RIGHT ISOLATE // (use -> dir = "ltr")
+ 8294 => "\xE2\x81\xA6",
+ // RIGHT-TO-LEFT ISOLATE // (use -> dir = "rtl")
+ 8295 => "\xE2\x81\xA7",
+ // FIRST STRONG ISOLATE // (use -> dir = "auto")
+ 8296 => "\xE2\x81\xA8",
+ // POP DIRECTIONAL ISOLATE
+ 8297 => "\xE2\x81\xA9",
+ ];
+
+ /**
+ * Get all languages from the constants "ASCII::.*LANGUAGE_CODE".
+ *
+ * @return string[]
+ *
+ * @phpstan-return array
+ */
+ public static function getAllLanguages(): array
+ {
+ // init
+ static $LANGUAGES = [];
+
+ if ($LANGUAGES !== []) {
+ return $LANGUAGES;
+ }
+
+ foreach ((new \ReflectionClass(__CLASS__))->getConstants() as $constant => $lang) {
+ if (\strpos($constant, 'EXTRA') !== false) {
+ $LANGUAGES[\strtolower($constant)] = $lang;
+ } else {
+ $LANGUAGES[\strtolower(\str_replace('_LANGUAGE_CODE', '', $constant))] = $lang;
+ }
+ }
+
+ return $LANGUAGES;
+ }
+
+ /**
+ * Returns an replacement array for ASCII methods.
+ *
+ * EXAMPLE:
+ * $array = ASCII::charsArray();
+ * var_dump($array['ru']['б']); // 'b'
+ *
+ *
+ * @psalm-suppress InvalidNullableReturnType - we use the prepare* methods here, so we don't get NULL here
+ *
+ * @param bool $replace_extra_symbols [optional] Add some more replacements e.g. "£" with " pound ".
+ *
+ * @psalm-pure
+ *
+ * @return array
+ *
+ * @phpstan-return array>
+ */
+ public static function charsArray(bool $replace_extra_symbols = false): array
+ {
+ if ($replace_extra_symbols) {
+ self::prepareAsciiAndExtrasMaps();
+
+ return self::$ASCII_MAPS_AND_EXTRAS ?? [];
+ }
+
+ self::prepareAsciiMaps();
+
+ return self::$ASCII_MAPS ?? [];
+ }
+
+ /**
+ * Returns an replacement array for ASCII methods with a mix of multiple languages.
+ *
+ * EXAMPLE:
+ * $array = ASCII::charsArrayWithMultiLanguageValues();
+ * var_dump($array['b']); // ['β', 'б', 'ဗ', 'ბ', 'ب']
+ *
+ *
+ * @param bool $replace_extra_symbols [optional] Add some more replacements e.g. "£" with " pound ".
+ *
+ * @psalm-pure
+ *
+ * @return array
+ * An array of replacements.
+ *
+ * @phpstan-return array>
+ */
+ public static function charsArrayWithMultiLanguageValues(bool $replace_extra_symbols = false): array
+ {
+ /** @var array>> */
+ static $CHARS_ARRAY = [];
+ $cacheKey = '' . $replace_extra_symbols;
+
+ if (isset($CHARS_ARRAY[$cacheKey])) {
+ return $CHARS_ARRAY[$cacheKey];
+ }
+
+ // init
+ $return = [];
+ $language_all_chars = self::charsArrayWithSingleLanguageValues(
+ $replace_extra_symbols,
+ false
+ );
+
+ /** @noinspection PhpSillyAssignmentInspection - hack for phpstan */
+ /** @var array $language_all_chars */
+ $language_all_chars = $language_all_chars;
+
+ /** @noinspection AlterInForeachInspection */
+ foreach ($language_all_chars as $key => &$value) {
+ $return[$value][] = $key;
+ }
+
+ $CHARS_ARRAY[$cacheKey] = $return;
+
+ /** @var array> $return - hack for phpstan */
+ return $return;
+ }
+
+ /**
+ * Returns an replacement array for ASCII methods with one language.
+ *
+ * For example, German will map 'ä' to 'ae', while other languages
+ * will simply return e.g. 'a'.
+ *
+ * EXAMPLE:
+ * $array = ASCII::charsArrayWithOneLanguage('ru');
+ * $tmpKey = \array_search('yo', $array['replace']);
+ * echo $array['orig'][$tmpKey]; // 'ё'
+ *
+ *
+ * @psalm-suppress InvalidNullableReturnType - we use the prepare* methods here, so we don't get NULL here
+ *
+ * @param string $language [optional] Language of the source string e.g.: en, de_at, or de-ch.
+ * (default is 'en') | ASCII::*_LANGUAGE_CODE
+ * @param bool $replace_extra_symbols [optional] Add some more replacements e.g. "£" with " pound ".
+ * @param bool $asOrigReplaceArray [optional] TRUE === return {orig: string[], replace: string[]}
+ * array
+ *
+ * @psalm-pure
+ *
+ * @return array
+ * An array of replacements.
+ *
+ * @phpstan-param ASCII::*_LANGUAGE_CODE $language
+ * @phpstan-return array{orig: string[], replace: string[]}|array
+ */
+ public static function charsArrayWithOneLanguage(
+ string $language = self::ENGLISH_LANGUAGE_CODE,
+ bool $replace_extra_symbols = false,
+ bool $asOrigReplaceArray = true
+ ): array {
+ $language = self::get_language($language);
+
+ // init
+ /** @var array|array{orig: string[], replace: string[]}>> */
+ static $CHARS_ARRAY = [];
+ $cacheKey = '' . $replace_extra_symbols . '-' . $asOrigReplaceArray;
+
+ // check static cache
+ if (isset($CHARS_ARRAY[$cacheKey][$language])) {
+ return $CHARS_ARRAY[$cacheKey][$language];
+ }
+
+ if ($replace_extra_symbols) {
+ self::prepareAsciiAndExtrasMaps();
+
+ /** @noinspection DuplicatedCode */
+ if (isset(self::$ASCII_MAPS_AND_EXTRAS[$language])) {
+ $tmpArray = self::$ASCII_MAPS_AND_EXTRAS[$language];
+
+ if ($asOrigReplaceArray) {
+ $CHARS_ARRAY[$cacheKey][$language] = [
+ 'orig' => \array_keys($tmpArray),
+ 'replace' => \array_values($tmpArray),
+ ];
+ } else {
+ $CHARS_ARRAY[$cacheKey][$language] = $tmpArray;
+ }
+ } else {
+ /** @noinspection NestedPositiveIfStatementsInspection */
+ if ($asOrigReplaceArray) {
+ $CHARS_ARRAY[$cacheKey][$language] = [
+ 'orig' => [],
+ 'replace' => [],
+ ];
+ } else {
+ $CHARS_ARRAY[$cacheKey][$language] = [];
+ }
+ }
+ } else {
+ self::prepareAsciiMaps();
+
+ /** @noinspection DuplicatedCode */
+ if (isset(self::$ASCII_MAPS[$language])) {
+ $tmpArray = self::$ASCII_MAPS[$language];
+
+ if ($asOrigReplaceArray) {
+ $CHARS_ARRAY[$cacheKey][$language] = [
+ 'orig' => \array_keys($tmpArray),
+ 'replace' => \array_values($tmpArray),
+ ];
+ } else {
+ $CHARS_ARRAY[$cacheKey][$language] = $tmpArray;
+ }
+ } else {
+ /** @noinspection NestedPositiveIfStatementsInspection */
+ if ($asOrigReplaceArray) {
+ $CHARS_ARRAY[$cacheKey][$language] = [
+ 'orig' => [],
+ 'replace' => [],
+ ];
+ } else {
+ $CHARS_ARRAY[$cacheKey][$language] = [];
+ }
+ }
+ }
+
+ return $CHARS_ARRAY[$cacheKey][$language] ?? ['orig' => [], 'replace' => []];
+ }
+
+ /**
+ * Returns an replacement array for ASCII methods with multiple languages.
+ *
+ * EXAMPLE:
+ * $array = ASCII::charsArrayWithSingleLanguageValues();
+ * $tmpKey = \array_search('hnaik', $array['replace']);
+ * echo $array['orig'][$tmpKey]; // '၌'
+ *
+ *
+ * @param bool $replace_extra_symbols [optional] Add some more replacements e.g. "£" with " pound ".
+ * @param bool $asOrigReplaceArray [optional] TRUE === return {orig: string[], replace: string[]}
+ * array
+ *
+ * @psalm-pure
+ *
+ * @return array
+ * An array of replacements.
+ *
+ * @phpstan-return array{orig: string[], replace: string[]}|array
+ */
+ public static function charsArrayWithSingleLanguageValues(
+ bool $replace_extra_symbols = false,
+ bool $asOrigReplaceArray = true
+ ): array {
+ // init
+ /** @var array|array{orig: string[], replace: string[]}> */
+ static $CHARS_ARRAY = [];
+ $cacheKey = '' . $replace_extra_symbols . '-' . $asOrigReplaceArray;
+
+ if (isset($CHARS_ARRAY[$cacheKey])) {
+ return $CHARS_ARRAY[$cacheKey];
+ }
+
+ if ($replace_extra_symbols) {
+ self::prepareAsciiAndExtrasMaps();
+
+ /** @noinspection AlterInForeachInspection */
+ /** @psalm-suppress PossiblyNullIterator - we use the prepare* methods here, so we don't get NULL here */
+ foreach (self::$ASCII_MAPS_AND_EXTRAS ?? [] as &$map) {
+ $CHARS_ARRAY[$cacheKey][] = $map;
+ }
+ } else {
+ self::prepareAsciiMaps();
+
+ /** @noinspection AlterInForeachInspection */
+ /** @psalm-suppress PossiblyNullIterator - we use the prepare* methods here, so we don't get NULL here */
+ foreach (self::$ASCII_MAPS ?? [] as &$map) {
+ $CHARS_ARRAY[$cacheKey][] = $map;
+ }
+ }
+
+ /** @phpstan-ignore-next-line - ... error? */
+ $CHARS_ARRAY[$cacheKey] = \array_merge([], ...$CHARS_ARRAY[$cacheKey]);
+
+ if ($asOrigReplaceArray) {
+ $CHARS_ARRAY[$cacheKey] = [
+ 'orig' => \array_keys($CHARS_ARRAY[$cacheKey]),
+ 'replace' => \array_values($CHARS_ARRAY[$cacheKey]),
+ ];
+ }
+
+ return $CHARS_ARRAY[$cacheKey];
+ }
+
+ /**
+ * Accepts a string and removes all non-UTF-8 characters from it + extras if needed.
+ *
+ * @param string $str The string to be sanitized.
+ * @param bool $normalize_whitespace [optional] Set to true, if you need to normalize the
+ * whitespace.
+ * @param bool $normalize_msword [optional] Set to true, if you need to normalize MS Word chars
+ * e.g.: "…"
+ * => "..."
+ * @param bool $keep_non_breaking_space [optional] Set to true, to keep non-breaking-spaces, in
+ * combination with
+ * $normalize_whitespace
+ * @param bool $remove_invisible_characters [optional] Set to false, if you not want to remove invisible
+ * characters e.g.: "\0"
+ *
+ * @psalm-pure
+ *
+ * @return string
+ * A clean UTF-8 string.
+ */
+ public static function clean(
+ string $str,
+ bool $normalize_whitespace = true,
+ bool $keep_non_breaking_space = false,
+ bool $normalize_msword = true,
+ bool $remove_invisible_characters = true
+ ): string {
+ // http://stackoverflow.com/questions/1401317/remove-non-utf8-characters-from-string
+ // caused connection reset problem on larger strings
+
+ $regex = '/
+ (
+ (?: [\x00-\x7F] # single-byte sequences 0xxxxxxx
+ | [\xC0-\xDF][\x80-\xBF] # double-byte sequences 110xxxxx 10xxxxxx
+ | [\xE0-\xEF][\x80-\xBF]{2} # triple-byte sequences 1110xxxx 10xxxxxx * 2
+ | [\xF0-\xF7][\x80-\xBF]{3} # quadruple-byte sequence 11110xxx 10xxxxxx * 3
+ ){1,100} # ...one or more times
+ )
+ | ( [\x80-\xBF] ) # invalid byte in range 10000000 - 10111111
+ | ( [\xC0-\xFF] ) # invalid byte in range 11000000 - 11111111
+ /x';
+ $str = (string) \preg_replace($regex, '$1', $str);
+
+ if ($normalize_whitespace) {
+ $str = self::normalize_whitespace($str, $keep_non_breaking_space);
+ }
+
+ if ($normalize_msword) {
+ $str = self::normalize_msword($str);
+ }
+
+ if ($remove_invisible_characters) {
+ $str = self::remove_invisible_characters($str);
+ }
+
+ return $str;
+ }
+
+ /**
+ * Checks if a string is 7 bit ASCII.
+ *
+ * EXAMPLE:
+ * ASCII::is_ascii('白'); // false
+ *
+ *
+ * @param string $str The string to check.
+ *
+ * @psalm-pure
+ *
+ * @return bool
+ *
+ * true if it is ASCII
+ * false otherwise
+ *
+ */
+ public static function is_ascii(string $str): bool
+ {
+ if ($str === '') {
+ return true;
+ }
+
+ return !\preg_match('/' . self::$REGEX_ASCII . '/', $str);
+ }
+
+ /**
+ * Returns a string with smart quotes, ellipsis characters, and dashes from
+ * Windows-1252 (commonly used in Word documents) replaced by their ASCII
+ * equivalents.
+ *
+ * EXAMPLE:
+ * ASCII::normalize_msword('„Abcdef…”'); // '"Abcdef..."'
+ *
+ *
+ * @param string $str The string to be normalized.
+ *
+ * @psalm-pure
+ *
+ * @return string
+ * A string with normalized characters for commonly used chars in Word documents.
+ */
+ public static function normalize_msword(string $str): string
+ {
+ if ($str === '') {
+ return '';
+ }
+
+ /** @var array{orig: string[], replace: string[]} */
+ static $MSWORD_CACHE = ['orig' => [], 'replace' => []];
+
+ if (empty($MSWORD_CACHE['orig'])) {
+ self::prepareAsciiMaps();
+
+ /** @var array */
+ $map = self::$ASCII_MAPS[self::EXTRA_MSWORD_CHARS_LANGUAGE_CODE] ?? [];
+
+ $MSWORD_CACHE = [
+ 'orig' => \array_keys($map),
+ 'replace' => \array_values($map),
+ ];
+ }
+
+ return \str_replace($MSWORD_CACHE['orig'], $MSWORD_CACHE['replace'], $str);
+ }
+
+ /**
+ * Normalize the whitespace.
+ *
+ * EXAMPLE:
+ * ASCII::normalize_whitespace("abc-\xc2\xa0-öäü-\xe2\x80\xaf-\xE2\x80\xAC", true); // "abc-\xc2\xa0-öäü- -"
+ *
+ *
+ * @param string $str The string to be normalized.
+ * @param bool $keepNonBreakingSpace [optional] Set to true, to keep non-breaking-spaces.
+ * @param bool $keepBidiUnicodeControls [optional] Set to true, to keep non-printable (for the web)
+ * bidirectional text chars.
+ * @param bool $normalize_control_characters [optional] Set to true, to convert e.g. LINE-, PARAGRAPH-SEPARATOR with "\n" and LINE TABULATION with "\t".
+ *
+ * @psalm-pure
+ *
+ * @return string
+ * A string with normalized whitespace.
+ */
+ public static function normalize_whitespace(
+ string $str,
+ bool $keepNonBreakingSpace = false,
+ bool $keepBidiUnicodeControls = false,
+ bool $normalize_control_characters = false
+ ): string {
+ if ($str === '') {
+ return '';
+ }
+
+ /** @var array> */
+ static $WHITESPACE_CACHE = [];
+ $cacheKey = (int) $keepNonBreakingSpace;
+
+ if ($normalize_control_characters) {
+ $str = \str_replace(
+ [
+ "\x0d\x0c", // 'END OF LINE'
+ "\xe2\x80\xa8", // 'LINE SEPARATOR'
+ "\xe2\x80\xa9", // 'PARAGRAPH SEPARATOR'
+ "\x0c", // 'FORM FEED' // "\f"
+ "\x0b", // 'VERTICAL TAB' // "\v"
+ ],
+ [
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\t",
+ ],
+ $str
+ );
+ }
+
+ if (!isset($WHITESPACE_CACHE[$cacheKey])) {
+ self::prepareAsciiMaps();
+
+ $WHITESPACE_CACHE[$cacheKey] = self::$ASCII_MAPS[self::EXTRA_WHITESPACE_CHARS_LANGUAGE_CODE] ?? [];
+
+ if ($keepNonBreakingSpace) {
+ unset($WHITESPACE_CACHE[$cacheKey]["\xc2\xa0"]);
+ }
+
+ $WHITESPACE_CACHE[$cacheKey] = array_keys($WHITESPACE_CACHE[$cacheKey]);
+ }
+
+ if (!$keepBidiUnicodeControls) {
+ /** @var array|null */
+ static $BIDI_UNICODE_CONTROLS_CACHE = null;
+
+ if ($BIDI_UNICODE_CONTROLS_CACHE === null) {
+ $BIDI_UNICODE_CONTROLS_CACHE = self::$BIDI_UNI_CODE_CONTROLS_TABLE;
+ }
+
+ $str = \str_replace($BIDI_UNICODE_CONTROLS_CACHE, '', $str);
+ }
+
+ return \str_replace($WHITESPACE_CACHE[$cacheKey], ' ', $str);
+ }
+
+ /**
+ * Remove invisible characters from a string.
+ *
+ * e.g.: This prevents sandwiching null characters between ascii characters, like Java\0script.
+ *
+ * copy&past from https://github.com/bcit-ci/CodeIgniter/blob/develop/system/core/Common.php
+ *
+ * @param string $str
+ * @param bool $url_encoded
+ * @param string $replacement
+ * @param bool $keep_basic_control_characters
+ *
+ * @psalm-pure
+ *
+ * @return string
+ */
+ public static function remove_invisible_characters(
+ string $str,
+ bool $url_encoded = false,
+ string $replacement = '',
+ bool $keep_basic_control_characters = true
+ ): string {
+ // init
+ $non_displayables = [];
+
+ // every control character except:
+ // - newline (dec 10),
+ // - carriage return (dec 13),
+ // - horizontal tab (dec 09)
+ if ($url_encoded) {
+ $non_displayables[] = '/%0[0-8bcefBCEF]/'; // url encoded 00-08, 11, 12, 14, 15
+ $non_displayables[] = '/%1[0-9a-fA-F]/'; // url encoded 16-31
+ }
+
+ if ($keep_basic_control_characters) {
+ $non_displayables[] = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S'; // 00-08, 11, 12, 14-31, 127
+ } else {
+ $str = self::normalize_whitespace($str, false, false, true);
+ $non_displayables[] = '/[^\P{C}\s]/u';
+ }
+
+ do {
+ $str = (string) \preg_replace($non_displayables, $replacement, $str, -1, $count);
+ } while ($count !== 0);
+
+ return $str;
+ }
+
+ /**
+ * WARNING: This method will return broken characters and is only for special cases.
+ *
+ * Convert two UTF-8 encoded string to a single-byte strings suitable for
+ * functions that need the same string length after the conversion.
+ *
+ * The function simply uses (and updates) a tailored dynamic encoding
+ * (in/out map parameter) where non-ascii characters are remapped to
+ * the range [128-255] in order of appearance.
+ *
+ * @param string $str1
+ * @param string $str2
+ *
+ * @return string[]
+ *
+ * @phpstan-return array{0: string, 1: string}
+ */
+ public static function to_ascii_remap(string $str1, string $str2): array
+ {
+ $charMap = [];
+ $str1 = self::to_ascii_remap_intern($str1, $charMap);
+ $str2 = self::to_ascii_remap_intern($str2, $charMap);
+
+ return [$str1, $str2];
+ }
+
+ /**
+ * Returns an ASCII version of the string. A set of non-ASCII characters are
+ * replaced with their closest ASCII counterparts, and the rest are removed
+ * by default. The language or locale of the source string can be supplied
+ * for language-specific transliteration in any of the following formats:
+ * en, en_GB, or en-GB. For example, passing "de" results in "äöü" mapping
+ * to "aeoeue" rather than "aou" as in other languages.
+ *
+ * EXAMPLE:
+ * ASCII::to_ascii('�Düsseldorf�', 'en'); // Dusseldorf
+ *
+ *
+ * @param string $str The input string.
+ * @param string $language [optional] Language of the source string.
+ * (default is 'en') | ASCII::*_LANGUAGE_CODE
+ * @param bool $remove_unsupported_chars [optional] Whether or not to remove the
+ * unsupported characters.
+ * @param bool $replace_extra_symbols [optional] Add some more replacements e.g. "£" with " pound
+ * ".
+ * @param bool $use_transliterate [optional] Use ASCII::to_transliterate() for unknown chars.
+ * @param bool|null $replace_single_chars_only [optional] Single char replacement is better for the
+ * performance, but some languages need to replace more then one char
+ * at the same time. | NULL === auto-setting, depended on the
+ * language
+ *
+ * @psalm-pure
+ *
+ * @return string
+ * A string that contains only ASCII characters.
+ *
+ * @phpstan-param ASCII::*_LANGUAGE_CODE $language
+ */
+ public static function to_ascii(
+ string $str,
+ string $language = self::ENGLISH_LANGUAGE_CODE,
+ bool $remove_unsupported_chars = true,
+ bool $replace_extra_symbols = false,
+ bool $use_transliterate = false,
+ bool $replace_single_chars_only = null
+ ): string {
+ if ($str === '') {
+ return '';
+ }
+
+ /** @phpstan-var ASCII::*_LANGUAGE_CODE - hack for phpstan */
+ $language = self::get_language($language);
+
+ static $EXTRA_SYMBOLS_CACHE = null;
+
+ /** @var array> */
+ static $REPLACE_HELPER_CACHE = [];
+ $cacheKey = $language . '-' . $replace_extra_symbols;
+
+ if (!isset($REPLACE_HELPER_CACHE[$cacheKey])) {
+ $langAll = self::charsArrayWithSingleLanguageValues($replace_extra_symbols, false);
+
+ $langSpecific = self::charsArrayWithOneLanguage($language, $replace_extra_symbols, false);
+
+ if ($langSpecific === []) {
+ $REPLACE_HELPER_CACHE[$cacheKey] = $langAll;
+ } else {
+ $REPLACE_HELPER_CACHE[$cacheKey] = \array_merge([], $langAll, $langSpecific);
+ }
+ }
+
+ if (
+ $replace_extra_symbols
+ &&
+ $EXTRA_SYMBOLS_CACHE === null
+ ) {
+ $EXTRA_SYMBOLS_CACHE = [];
+ foreach (self::$ASCII_EXTRAS ?? [] as $extrasDataTmp) {
+ foreach ($extrasDataTmp as $extrasDataKeyTmp => $extrasDataValueTmp) {
+ $EXTRA_SYMBOLS_CACHE[$extrasDataKeyTmp] = $extrasDataKeyTmp;
+ }
+ }
+ $EXTRA_SYMBOLS_CACHE = \implode('', $EXTRA_SYMBOLS_CACHE);
+ }
+
+ $charDone = [];
+ if (\preg_match_all('/' . self::$REGEX_ASCII . ($replace_extra_symbols ? '|[' . $EXTRA_SYMBOLS_CACHE . ']' : '') . '/u', $str, $matches)) {
+ if (!$replace_single_chars_only) {
+ if (self::$LANGUAGE_MAX_KEY === null) {
+ self::$LANGUAGE_MAX_KEY = self::getData('ascii_language_max_key');
+ }
+
+ $maxKeyLength = self::$LANGUAGE_MAX_KEY[$language] ?? 0;
+
+ if ($maxKeyLength >= 5) {
+ foreach ($matches[0] as $keyTmp => $char) {
+ if (isset($matches[0][$keyTmp + 4])) {
+ $fiveChars = $matches[0][$keyTmp + 0] . $matches[0][$keyTmp + 1] . $matches[0][$keyTmp + 2] . $matches[0][$keyTmp + 3] . $matches[0][$keyTmp + 4];
+ } else {
+ $fiveChars = null;
+ }
+ if (
+ $fiveChars
+ &&
+ !isset($charDone[$fiveChars])
+ &&
+ isset($REPLACE_HELPER_CACHE[$cacheKey][$fiveChars])
+ &&
+ \strpos($str, $fiveChars) !== false
+ ) {
+ // DEBUG
+ //\var_dump($str, $fiveChars, $REPLACE_HELPER_CACHE[$cacheKey][$fiveChars]);
+
+ $charDone[$fiveChars] = true;
+ $str = \str_replace($fiveChars, $REPLACE_HELPER_CACHE[$cacheKey][$fiveChars], $str);
+
+ // DEBUG
+ //\var_dump($str, "\n");
+ }
+ }
+ }
+
+ if ($maxKeyLength >= 4) {
+ foreach ($matches[0] as $keyTmp => $char) {
+ if (isset($matches[0][$keyTmp + 3])) {
+ $fourChars = $matches[0][$keyTmp + 0] . $matches[0][$keyTmp + 1] . $matches[0][$keyTmp + 2] . $matches[0][$keyTmp + 3];
+ } else {
+ $fourChars = null;
+ }
+ if (
+ $fourChars
+ &&
+ !isset($charDone[$fourChars])
+ &&
+ isset($REPLACE_HELPER_CACHE[$cacheKey][$fourChars])
+ &&
+ \strpos($str, $fourChars) !== false
+ ) {
+ // DEBUG
+ //\var_dump($str, $fourChars, $REPLACE_HELPER_CACHE[$cacheKey][$fourChars]);
+
+ $charDone[$fourChars] = true;
+ $str = \str_replace($fourChars, $REPLACE_HELPER_CACHE[$cacheKey][$fourChars], $str);
+
+ // DEBUG
+ //\var_dump($str, "\n");
+ }
+ }
+ }
+
+ foreach ($matches[0] as $keyTmp => $char) {
+ if (isset($matches[0][$keyTmp + 2])) {
+ $threeChars = $matches[0][$keyTmp + 0] . $matches[0][$keyTmp + 1] . $matches[0][$keyTmp + 2];
+ } else {
+ $threeChars = null;
+ }
+ if (
+ $threeChars
+ &&
+ !isset($charDone[$threeChars])
+ &&
+ isset($REPLACE_HELPER_CACHE[$cacheKey][$threeChars])
+ &&
+ \strpos($str, $threeChars) !== false
+ ) {
+ // DEBUG
+ //\var_dump($str, $threeChars, $REPLACE_HELPER_CACHE[$cacheKey][$threeChars]);
+
+ $charDone[$threeChars] = true;
+ $str = \str_replace($threeChars, $REPLACE_HELPER_CACHE[$cacheKey][$threeChars], $str);
+
+ // DEBUG
+ //\var_dump($str, "\n");
+ }
+ }
+
+ foreach ($matches[0] as $keyTmp => $char) {
+ if (isset($matches[0][$keyTmp + 1])) {
+ $twoChars = $matches[0][$keyTmp + 0] . $matches[0][$keyTmp + 1];
+ } else {
+ $twoChars = null;
+ }
+ if (
+ $twoChars
+ &&
+ !isset($charDone[$twoChars])
+ &&
+ isset($REPLACE_HELPER_CACHE[$cacheKey][$twoChars])
+ &&
+ \strpos($str, $twoChars) !== false
+ ) {
+ // DEBUG
+ //\var_dump($str, $twoChars, $REPLACE_HELPER_CACHE[$cacheKey][$twoChars]);
+
+ $charDone[$twoChars] = true;
+ $str = \str_replace($twoChars, $REPLACE_HELPER_CACHE[$cacheKey][$twoChars], $str);
+
+ // DEBUG
+ //\var_dump($str, "\n");
+ }
+ }
+ }
+
+ foreach ($matches[0] as $char) {
+ if (
+ !isset($charDone[$char])
+ &&
+ isset($REPLACE_HELPER_CACHE[$cacheKey][$char])
+ &&
+ \strpos($str, $char) !== false
+ ) {
+ // DEBUG
+ //\var_dump($str, $char, $REPLACE_HELPER_CACHE[$cacheKey][$char]);
+
+ $charDone[$char] = true;
+ $str = \str_replace($char, $REPLACE_HELPER_CACHE[$cacheKey][$char], $str);
+
+ // DEBUG
+ //\var_dump($str, "\n");
+ }
+ }
+ }
+
+ /** @psalm-suppress PossiblyNullOperand - we use the prepare* methods here, so we don't get NULL here */
+ if (!isset(self::$ASCII_MAPS[$language])) {
+ $use_transliterate = true;
+ }
+
+ if ($use_transliterate) {
+ $str = self::to_transliterate($str, null, false);
+ }
+
+ if ($remove_unsupported_chars) {
+ $str = (string) \str_replace(["\n\r", "\n", "\r", "\t"], ' ', $str);
+ $str = (string) \preg_replace('/' . self::$REGEX_ASCII . '/', '', $str);
+ }
+
+ return $str;
+ }
+
+ /**
+ * Convert given string to safe filename (and keep string case).
+ *
+ * EXAMPLE:
+ * ASCII::to_filename('שדגשדג.png', true)); // 'shdgshdg.png'
+ *
+ *
+ * @param string $str
+ * @param bool $use_transliterate ASCII::to_transliterate() is used by default - unsafe characters are
+ * simply replaced with hyphen otherwise.
+ * @param string $fallback_char
+ *
+ * @psalm-pure
+ *
+ * @return string
+ * A string that contains only safe characters for a filename.
+ */
+ public static function to_filename(
+ string $str,
+ bool $use_transliterate = true,
+ string $fallback_char = '-'
+ ): string {
+ if ($use_transliterate) {
+ $str = self::to_transliterate($str, $fallback_char);
+ }
+
+ $fallback_char_escaped = \preg_quote($fallback_char, '/');
+
+ $str = (string) \preg_replace(
+ [
+ '/[^' . $fallback_char_escaped . '.\\-a-zA-Z\d\\s]/', // 1) remove un-needed chars
+ '/\s+/u', // 2) convert spaces to $fallback_char
+ '/[' . $fallback_char_escaped . ']+/u', // 3) remove double $fallback_char's
+ ],
+ [
+ '',
+ $fallback_char,
+ $fallback_char,
+ ],
+ $str
+ );
+
+ return \trim($str, $fallback_char);
+ }
+
+ /**
+ * Converts the string into an URL slug. This includes replacing non-ASCII
+ * characters with their closest ASCII equivalents, removing remaining
+ * non-ASCII and non-alphanumeric characters, and replacing whitespace with
+ * $separator. The separator defaults to a single dash, and the string
+ * is also converted to lowercase. The language of the source string can
+ * also be supplied for language-specific transliteration.
+ *
+ * @param string $str
+ * @param string $separator [optional] The string used to replace whitespace.
+ * @param string $language [optional] Language of the source string.
+ * (default is 'en') | ASCII::*_LANGUAGE_CODE
+ * @param array $replacements [optional] A map of replaceable strings.
+ * @param bool $replace_extra_symbols [optional] Add some more replacements e.g. "£" with "
+ * pound ".
+ * @param bool $use_str_to_lower [optional] Use "string to lower" for the input.
+ * @param bool $use_transliterate [optional] Use ASCII::to_transliterate() for unknown
+ * chars.
+ * @psalm-pure
+ *
+ * @return string
+ * A string that has been converted to an URL slug.
+ *
+ * @phpstan-param ASCII::*_LANGUAGE_CODE $language
+ */
+ public static function to_slugify(
+ string $str,
+ string $separator = '-',
+ string $language = self::ENGLISH_LANGUAGE_CODE,
+ array $replacements = [],
+ bool $replace_extra_symbols = false,
+ bool $use_str_to_lower = true,
+ bool $use_transliterate = false
+ ): string {
+ if ($str === '') {
+ return '';
+ }
+
+ foreach ($replacements as $from => $to) {
+ $str = \str_replace($from, $to, $str);
+ }
+
+ $str = self::to_ascii(
+ $str,
+ $language,
+ false,
+ $replace_extra_symbols,
+ $use_transliterate
+ );
+
+ $str = \str_replace('@', $separator, $str);
+
+ $str = (string) \preg_replace(
+ '/[^a-zA-Z\\d\\s\\-_' . \preg_quote($separator, '/') . ']/',
+ '',
+ $str
+ );
+
+ if ($use_str_to_lower) {
+ $str = \strtolower($str);
+ }
+
+ $str = (string) \preg_replace('/^[\'\\s]+|[\'\\s]+$/', '', $str);
+ $str = (string) \preg_replace('/\\B([A-Z])/', '-\1', $str);
+ $str = (string) \preg_replace('/[\\-_\\s]+/', $separator, $str);
+
+ $l = \strlen($separator);
+ if ($l && \strpos($str, $separator) === 0) {
+ $str = (string) \substr($str, $l);
+ }
+
+ if (\substr($str, -$l) === $separator) {
+ $str = (string) \substr($str, 0, \strlen($str) - $l);
+ }
+
+ return $str;
+ }
+
+ /**
+ * Returns an ASCII version of the string. A set of non-ASCII characters are
+ * replaced with their closest ASCII counterparts, and the rest are removed
+ * unless instructed otherwise.
+ *
+ * EXAMPLE:
+ * ASCII::to_transliterate('déjà σσς iıii'); // 'deja sss iiii'
+ *
+ *
+ * @param string $str The input string.
+ * @param string|null $unknown [optional] Character use if character unknown. (default is '?')
+ * But you can also use NULL to keep the unknown chars.
+ * @param bool $strict [optional] Use "transliterator_transliterate()" from PHP-Intl
+ *
+ * @psalm-pure
+ *
+ * @return string
+ *
A String that contains only ASCII characters.
+ *
+ * @noinspection ParameterDefaultValueIsNotNullInspection
+ */
+ public static function to_transliterate(
+ string $str,
+ $unknown = '?',
+ bool $strict = false
+ ): string {
+ /** @var array|null */
+ static $UTF8_TO_TRANSLIT = null;
+
+ /** null|\Transliterator */
+ static $TRANSLITERATOR = null;
+
+ /** @var bool|null */
+ static $SUPPORT_INTL = null;
+
+ if ($str === '') {
+ return '';
+ }
+
+ if ($SUPPORT_INTL === null) {
+ $SUPPORT_INTL = \extension_loaded('intl');
+ }
+
+ // check if we only have ASCII, first (better performance)
+ $str_tmp = $str;
+ if (self::is_ascii($str)) {
+ return $str;
+ }
+
+ $str = self::clean($str);
+
+ // check again, if we only have ASCII, now ...
+ if (
+ $str_tmp !== $str
+ &&
+ self::is_ascii($str)
+ ) {
+ return $str;
+ }
+
+ if (
+ $strict
+ &&
+ $SUPPORT_INTL === true
+ ) {
+ if (!isset($TRANSLITERATOR)) {
+ // INFO: see "*-Latin" rules via "transliterator_list_ids()"
+ /** @var \Transliterator */
+ $TRANSLITERATOR = \transliterator_create('NFKC; [:Nonspacing Mark:] Remove; NFKC; Any-Latin; Latin-ASCII;');
+ }
+
+ // INFO: https://unicode.org/cldr/utility/character.jsp
+ $str_tmp = \transliterator_transliterate($TRANSLITERATOR, $str);
+
+ if ($str_tmp !== false) {
+
+ // check again, if we only have ASCII, now ...
+ if (
+ $str_tmp !== $str
+ &&
+ self::is_ascii($str_tmp)
+ ) {
+ return $str_tmp;
+ }
+
+ $str = $str_tmp;
+ }
+ }
+
+ if (self::$ORD === null) {
+ self::$ORD = self::getData('ascii_ord');
+ }
+
+ \preg_match_all('/.|[^\x00]$/us', $str, $array_tmp);
+ $chars = $array_tmp[0];
+ $ord = null;
+ $str_tmp = '';
+ foreach ($chars as &$c) {
+ $ordC0 = self::$ORD[$c[0]];
+
+ if ($ordC0 >= 0 && $ordC0 <= 127) {
+ $str_tmp .= $c;
+
+ continue;
+ }
+
+ $ordC1 = self::$ORD[$c[1]];
+
+ // ASCII - next please
+ if ($ordC0 >= 192 && $ordC0 <= 223) {
+ $ord = ($ordC0 - 192) * 64 + ($ordC1 - 128);
+ }
+
+ if ($ordC0 >= 224) {
+ $ordC2 = self::$ORD[$c[2]];
+
+ if ($ordC0 <= 239) {
+ $ord = ($ordC0 - 224) * 4096 + ($ordC1 - 128) * 64 + ($ordC2 - 128);
+ }
+
+ if ($ordC0 >= 240) {
+ $ordC3 = self::$ORD[$c[3]];
+
+ if ($ordC0 <= 247) {
+ $ord = ($ordC0 - 240) * 262144 + ($ordC1 - 128) * 4096 + ($ordC2 - 128) * 64 + ($ordC3 - 128);
+ }
+
+ // We only process valid UTF-8 chars (<= 4 byte), so we don't need this code here ...
+ /*
+ if ($ordC0 >= 248) {
+ $ordC4 = self::$ORD[$c[4]];
+
+ if ($ordC0 <= 251) {
+ $ord = ($ordC0 - 248) * 16777216 + ($ordC1 - 128) * 262144 + ($ordC2 - 128) * 4096 + ($ordC3 - 128) * 64 + ($ordC4 - 128);
+ }
+
+ if ($ordC0 >= 252) {
+ $ordC5 = self::$ORD[$c[5]];
+
+ if ($ordC0 <= 253) {
+ $ord = ($ordC0 - 252) * 1073741824 + ($ordC1 - 128) * 16777216 + ($ordC2 - 128) * 262144 + ($ordC3 - 128) * 4096 + ($ordC4 - 128) * 64 + ($ordC5 - 128);
+ }
+ }
+ }
+ */
+ }
+ }
+
+ if (
+ $ordC0 === 254
+ ||
+ $ordC0 === 255
+ ||
+ $ord === null
+ ) {
+ $str_tmp .= $unknown ?? $c;
+
+ continue;
+ }
+
+ $bank = $ord >> 8;
+ if (!isset($UTF8_TO_TRANSLIT[$bank])) {
+ $UTF8_TO_TRANSLIT[$bank] = self::getDataIfExists(\sprintf('x%03x', $bank));
+ }
+
+ $new_char = $ord & 255;
+
+ if (isset($UTF8_TO_TRANSLIT[$bank][$new_char])) {
+
+ // keep for debugging
+ /*
+ echo "file: " . sprintf('x%02x', $bank) . "\n";
+ echo "char: " . $c . "\n";
+ echo "ord: " . $ord . "\n";
+ echo "new_char: " . $new_char . "\n";
+ echo "new_char: " . mb_chr($new_char) . "\n";
+ echo "ascii: " . $UTF8_TO_TRANSLIT[$bank][$new_char] . "\n";
+ echo "bank:" . $bank . "\n\n";
+ */
+
+ $new_char = $UTF8_TO_TRANSLIT[$bank][$new_char];
+
+ /** @noinspection MissingOrEmptyGroupStatementInspection */
+ /** @noinspection PhpStatementHasEmptyBodyInspection */
+ if ($unknown === null && $new_char === '') {
+ // nothing
+ } elseif (
+ $new_char === '[?]'
+ ||
+ $new_char === '[?] '
+ ) {
+ $c = $unknown ?? $c;
+ } else {
+ $c = $new_char;
+ }
+ } else {
+
+ // keep for debugging missing chars
+ /*
+ echo "file: " . sprintf('x%02x', $bank) . "\n";
+ echo "char: " . $c . "\n";
+ echo "ord: " . $ord . "\n";
+ echo "new_char: " . $new_char . "\n";
+ echo "new_char: " . mb_chr($new_char) . "\n";
+ echo "bank:" . $bank . "\n\n";
+ */
+
+ $c = $unknown ?? $c;
+ }
+
+ $str_tmp .= $c;
+ }
+
+ return $str_tmp;
+ }
+
+ /**
+ * WARNING: This method will return broken characters and is only for special cases.
+ *
+ * Convert a UTF-8 encoded string to a single-byte string suitable for
+ * functions that need the same string length after the conversion.
+ *
+ * The function simply uses (and updates) a tailored dynamic encoding
+ * (in/out map parameter) where non-ascii characters are remapped to
+ * the range [128-255] in order of appearance.
+ *
+ * Thus, it supports up to 128 different multibyte code points max over
+ * the whole set of strings sharing this encoding.
+ *
+ * Source: https://github.com/KEINOS/mb_levenshtein
+ *
+ * @param string $str UTF-8 string to be converted to extended ASCII.
+ * @param array $map Internal-Map of code points to ASCII characters.
+ *
+ * @return string
+ * Mapped borken string.
+ *
+ * @phpstan-param array $map
+ */
+ private static function to_ascii_remap_intern(string $str, array &$map): string
+ {
+ // find all utf-8 characters
+ $matches = [];
+ if (!\preg_match_all('/[\xC0-\xF7][\x80-\xBF]+/', $str, $matches)) {
+ return $str; // plain ascii string
+ }
+
+ // update the encoding map with the characters not already met
+ $mapCount = \count($map);
+ foreach ($matches[0] as $mbc) {
+ if (!isset($map[$mbc])) {
+ $map[$mbc] = \chr(128 + $mapCount);
+ ++$mapCount;
+ }
+ }
+
+ // finally, remap non-ascii characters
+ return \strtr($str, $map);
+ }
+
+ /**
+ * Get the language from a string.
+ *
+ * e.g.: de_at -> de_at
+ * de_DE -> de
+ * DE_DE -> de
+ * de-de -> de
+ *
+ * @noinspection ReturnTypeCanBeDeclaredInspection
+ *
+ * @param string $language
+ *
+ * @psalm-pure
+ *
+ * @return string
+ */
+ private static function get_language(string $language)
+ {
+ if ($language === '') {
+ return '';
+ }
+
+ if (
+ \strpos($language, '_') === false
+ &&
+ \strpos($language, '-') === false
+ ) {
+ return \strtolower($language);
+ }
+
+ $language = \str_replace('-', '_', \strtolower($language));
+
+ $regex = '/(?[a-z]+)_\g{first}/';
+
+ return (string) \preg_replace($regex, '$1', $language);
+ }
+
+ /**
+ * Get data from "/data/*.php".
+ *
+ * @noinspection ReturnTypeCanBeDeclaredInspection
+ *
+ * @param string $file
+ *
+ * @psalm-pure
+ *
+ * @return array
+ */
+ private static function getData(string $file)
+ {
+ /** @noinspection PhpIncludeInspection */
+ /** @noinspection UsingInclusionReturnValueInspection */
+ /** @psalm-suppress UnresolvableInclude */
+ return include __DIR__ . '/data/' . $file . '.php';
+ }
+
+ /**
+ * Get data from "/data/*.php".
+ *
+ * @param string $file
+ *
+ * @psalm-pure
+ *
+ * @return array
+ */
+ private static function getDataIfExists(string $file): array
+ {
+ $file = __DIR__ . '/data/' . $file . '.php';
+ /** @psalm-suppress ImpureFunctionCall */
+ if (\is_file($file)) {
+ /** @noinspection PhpIncludeInspection */
+ /** @noinspection UsingInclusionReturnValueInspection */
+ /** @psalm-suppress UnresolvableInclude */
+ return include $file;
+ }
+
+ return [];
+ }
+
+ /**
+ * @psalm-pure
+ *
+ * @return void
+ */
+ private static function prepareAsciiAndExtrasMaps()
+ {
+ if (self::$ASCII_MAPS_AND_EXTRAS === null) {
+ self::prepareAsciiMaps();
+ self::prepareAsciiExtras();
+
+ /** @psalm-suppress PossiblyNullArgument - we use the prepare* methods here, so we don't get NULL here */
+ self::$ASCII_MAPS_AND_EXTRAS = \array_merge_recursive(
+ self::$ASCII_MAPS ?? [],
+ self::$ASCII_EXTRAS ?? []
+ );
+ }
+ }
+
+ /**
+ * @psalm-pure
+ *
+ * @return void
+ */
+ private static function prepareAsciiMaps()
+ {
+ if (self::$ASCII_MAPS === null) {
+ self::$ASCII_MAPS = self::getData('ascii_by_languages');
+ }
+ }
+
+ /**
+ * @psalm-pure
+ *
+ * @return void
+ */
+ private static function prepareAsciiExtras()
+ {
+ if (self::$ASCII_EXTRAS === null) {
+ self::$ASCII_EXTRAS = self::getData('ascii_extras_by_languages');
+ }
+ }
+}
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/data/ascii_by_languages.php b/system/vendor/voku/portable-ascii/src/voku/helper/data/ascii_by_languages.php
new file mode 100644
index 0000000..68c3f9d
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/data/ascii_by_languages.php
@@ -0,0 +1,2950 @@
+ [
+ 'Á' => 'A',
+ 'á' => 'a',
+ 'Ä' => 'A',
+ 'ä' => 'a',
+ 'À' => 'A',
+ 'à' => 'a',
+ 'Â' => 'A',
+ 'â' => 'a',
+ 'É' => 'E',
+ 'é' => 'e',
+ 'Ë' => 'E',
+ 'ë' => 'e',
+ 'È' => 'E',
+ 'è' => 'e',
+ 'Ê' => 'E',
+ 'ê' => 'e',
+ 'Í' => 'I',
+ 'í' => 'i',
+ 'Ï' => 'I',
+ 'ï' => 'i',
+ 'Ì' => 'I',
+ 'ì' => 'i',
+ 'Î' => 'I',
+ 'î' => 'i',
+ 'Ó' => 'O',
+ 'ó' => 'o',
+ 'Ö' => 'O',
+ 'ö' => 'o',
+ 'Ò' => 'O',
+ 'ò' => 'o',
+ 'Ô' => 'O',
+ 'ô' => 'o',
+ 'Ú' => 'U',
+ 'ú' => 'u',
+ 'Ü' => 'U',
+ 'ü' => 'u',
+ 'Ù' => 'U',
+ 'ù' => 'u',
+ 'Û' => 'U',
+ 'û' => 'u',
+ 'Ý' => 'Y',
+ 'ý' => 'y',
+ 'Ÿ' => 'Y',
+ ],
+ // Italian
+ 'it' => [
+ 'à' => 'a',
+ 'À' => 'A',
+ 'é' => 'e',
+ 'É' => 'E',
+ 'è' => 'e',
+ 'È' => 'E',
+ 'ì' => 'i',
+ 'Ì' => 'I',
+ 'Ò' => 'O',
+ 'ò' => 'o',
+ 'ù' => 'u',
+ 'Ù' => 'U',
+ ],
+ // Macedonian
+ 'mk' => [
+ 'А' => 'A',
+ 'Б' => 'B',
+ 'В' => 'V',
+ 'Г' => 'G',
+ 'Д' => 'D',
+ 'Ѓ' => 'Gj',
+ 'Е' => 'E',
+ 'Ж' => 'Zh',
+ 'З' => 'Z',
+ 'Ѕ' => 'Dz',
+ 'И' => 'I',
+ 'Ј' => 'J',
+ 'К' => 'K',
+ 'Л' => 'L',
+ 'Љ' => 'Lj',
+ 'М' => 'M',
+ 'Н' => 'N',
+ 'Њ' => 'Nj',
+ 'О' => 'O',
+ 'П' => 'P',
+ 'Р' => 'R',
+ 'С' => 'S',
+ 'Т' => 'T',
+ 'Ќ' => 'Kj',
+ 'У' => 'U',
+ 'Ф' => 'F',
+ 'Х' => 'H',
+ 'Ц' => 'C',
+ 'Ч' => 'Ch',
+ 'Џ' => 'Dj',
+ 'Ш' => 'Sh',
+ 'а' => 'a',
+ 'б' => 'b',
+ 'в' => 'v',
+ 'г' => 'g',
+ 'д' => 'd',
+ 'ѓ' => 'gj',
+ 'е' => 'e',
+ 'ж' => 'zh',
+ 'з' => 'z',
+ 'ѕ' => 'dz',
+ 'и' => 'i',
+ 'ј' => 'j',
+ 'к' => 'k',
+ 'л' => 'l',
+ 'љ' => 'lj',
+ 'м' => 'm',
+ 'н' => 'n',
+ 'њ' => 'nj',
+ 'о' => 'o',
+ 'п' => 'p',
+ 'р' => 'r',
+ 'с' => 's',
+ 'т' => 't',
+ 'ќ' => 'kj',
+ 'у' => 'u',
+ 'ф' => 'f',
+ 'х' => 'h',
+ 'ц' => 'c',
+ 'ч' => 'ch',
+ 'џ' => 'dj',
+ 'ш' => 'sh',
+ ],
+ // Portuguese (Brazil)
+ 'pt' => [
+ 'æ' => 'ae',
+ 'ǽ' => 'ae',
+ 'À' => 'A',
+ 'Á' => 'A',
+ 'Â' => 'A',
+ 'Ã' => 'A',
+ 'Å' => 'AA',
+ 'Ǻ' => 'A',
+ 'Ă' => 'A',
+ 'Ǎ' => 'A',
+ 'Æ' => 'AE',
+ 'Ǽ' => 'AE',
+ 'à' => 'a',
+ 'á' => 'a',
+ 'â' => 'a',
+ 'ã' => 'a',
+ 'å' => 'aa',
+ 'ǻ' => 'a',
+ 'ă' => 'a',
+ 'ǎ' => 'a',
+ 'ª' => 'a',
+ 'Ĉ' => 'C',
+ 'Ċ' => 'C',
+ 'Ç' => 'C',
+ 'ç' => 'c',
+ 'ĉ' => 'c',
+ 'ċ' => 'c',
+ 'Ð' => 'Dj',
+ 'Đ' => 'D',
+ 'ð' => 'dj',
+ 'đ' => 'd',
+ 'È' => 'E',
+ 'É' => 'E',
+ 'Ê' => 'E',
+ 'Ë' => 'E',
+ 'Ĕ' => 'E',
+ 'Ė' => 'E',
+ 'è' => 'e',
+ 'é' => 'e',
+ 'ê' => 'e',
+ 'ë' => 'e',
+ 'ĕ' => 'e',
+ 'ė' => 'e',
+ 'ƒ' => 'f',
+ 'Ĝ' => 'G',
+ 'Ġ' => 'G',
+ 'ĝ' => 'g',
+ 'ġ' => 'g',
+ 'Ĥ' => 'H',
+ 'Ħ' => 'H',
+ 'ĥ' => 'h',
+ 'ħ' => 'h',
+ 'Ì' => 'I',
+ 'Í' => 'I',
+ 'Î' => 'I',
+ 'Ï' => 'I',
+ 'Ĩ' => 'I',
+ 'Ĭ' => 'I',
+ 'Ǐ' => 'I',
+ 'Į' => 'I',
+ 'IJ' => 'IJ',
+ 'ì' => 'i',
+ 'í' => 'i',
+ 'î' => 'i',
+ 'ï' => 'i',
+ 'ĩ' => 'i',
+ 'ĭ' => 'i',
+ 'ǐ' => 'i',
+ 'į' => 'i',
+ 'ij' => 'ij',
+ 'Ĵ' => 'J',
+ 'ĵ' => 'j',
+ 'Ĺ' => 'L',
+ 'Ľ' => 'L',
+ 'Ŀ' => 'L',
+ 'ĺ' => 'l',
+ 'ľ' => 'l',
+ 'ŀ' => 'l',
+ 'Ñ' => 'N',
+ 'ñ' => 'n',
+ 'ʼn' => 'n',
+ 'Ò' => 'O',
+ 'Ó' => 'O',
+ 'Ô' => 'O',
+ 'Õ' => 'O',
+ 'Ō' => 'O',
+ 'Ŏ' => 'O',
+ 'Ǒ' => 'O',
+ 'Ő' => 'O',
+ 'Ơ' => 'O',
+ 'Ø' => 'OE',
+ 'Ǿ' => 'O',
+ 'Œ' => 'OE',
+ 'ò' => 'o',
+ 'ó' => 'o',
+ 'ô' => 'o',
+ 'õ' => 'o',
+ 'ō' => 'o',
+ 'ŏ' => 'o',
+ 'ǒ' => 'o',
+ 'ő' => 'o',
+ 'ơ' => 'o',
+ 'ø' => 'oe',
+ 'ǿ' => 'o',
+ 'º' => 'o',
+ 'œ' => 'oe',
+ 'Ŕ' => 'R',
+ 'Ŗ' => 'R',
+ 'ŕ' => 'r',
+ 'ŗ' => 'r',
+ 'Ŝ' => 'S',
+ 'Ș' => 'S',
+ 'ŝ' => 's',
+ 'ș' => 's',
+ 'ſ' => 's',
+ 'Ţ' => 'T',
+ 'Ț' => 'T',
+ 'Ŧ' => 'T',
+ 'Þ' => 'TH',
+ 'ţ' => 't',
+ 'ț' => 't',
+ 'ŧ' => 't',
+ 'þ' => 'th',
+ 'Ù' => 'U',
+ 'Ú' => 'U',
+ 'Û' => 'U',
+ 'Ü' => 'U',
+ 'Ũ' => 'U',
+ 'Ŭ' => 'U',
+ 'Ű' => 'U',
+ 'Ų' => 'U',
+ 'Ư' => 'U',
+ 'Ǔ' => 'U',
+ 'Ǖ' => 'U',
+ 'Ǘ' => 'U',
+ 'Ǚ' => 'U',
+ 'Ǜ' => 'U',
+ 'ù' => 'u',
+ 'ú' => 'u',
+ 'û' => 'u',
+ 'ü' => 'u',
+ 'ũ' => 'u',
+ 'ŭ' => 'u',
+ 'ű' => 'u',
+ 'ų' => 'u',
+ 'ư' => 'u',
+ 'ǔ' => 'u',
+ 'ǖ' => 'u',
+ 'ǘ' => 'u',
+ 'ǚ' => 'u',
+ 'ǜ' => 'u',
+ 'Ŵ' => 'W',
+ 'ŵ' => 'w',
+ 'Ý' => 'Y',
+ 'Ÿ' => 'Y',
+ 'Ŷ' => 'Y',
+ 'ý' => 'y',
+ 'ÿ' => 'y',
+ 'ŷ' => 'y',
+ ],
+ // Greek(lish) (Elláda)
+ 'el__greeklish' => [
+ 'ΑΥ' => 'AU',
+ 'ΑΎ' => 'AU',
+ 'Αυ' => 'Au',
+ 'Αύ' => 'Au',
+ 'ΕΊ' => 'EI',
+ 'ΕΙ' => 'EI',
+ 'Ει' => 'EI',
+ 'ΕΥ' => 'EU',
+ 'ΕΎ' => 'EU',
+ 'Εί' => 'Ei',
+ 'Ευ' => 'Eu',
+ 'Εύ' => 'Eu',
+ 'ΟΙ' => 'OI',
+ 'ΟΊ' => 'OI',
+ 'ΟΥ' => 'OU',
+ 'ΟΎ' => 'OU',
+ 'Οι' => 'Oi',
+ 'Οί' => 'Oi',
+ 'Ου' => 'Ou',
+ 'Ού' => 'Ou',
+ 'ΥΙ' => 'YI',
+ 'ΎΙ' => 'YI',
+ 'Υι' => 'Yi',
+ 'Ύι' => 'Yi',
+ 'ΥΊ' => 'Yi',
+ 'Υί' => 'Yi',
+ 'αυ' => 'au',
+ 'αύ' => 'au',
+ 'εί' => 'ei',
+ 'ει' => 'ei',
+ 'ευ' => 'eu',
+ 'εύ' => 'eu',
+ 'οι' => 'oi',
+ 'οί' => 'oi',
+ 'ου' => 'ou',
+ 'ού' => 'ou',
+ 'υι' => 'yi',
+ 'ύι' => 'yi',
+ 'υί' => 'yi',
+ 'Α' => 'A',
+ 'Ά' => 'A',
+ 'Β' => 'B',
+ 'Δ' => 'D',
+ 'Ε' => 'E',
+ 'Έ' => 'E',
+ 'Φ' => 'F',
+ 'Γ' => 'G',
+ 'Η' => 'H',
+ 'Ή' => 'H',
+ 'Ι' => 'I',
+ 'Ί' => 'I',
+ 'Ϊ' => 'I',
+ 'Κ' => 'K',
+ 'Ξ' => 'Ks',
+ 'Λ' => 'L',
+ 'Μ' => 'M',
+ 'Ν' => 'N',
+ 'Π' => 'N',
+ 'Ο' => 'O',
+ 'Ό' => 'O',
+ 'Ψ' => 'Ps',
+ 'Ρ' => 'R',
+ 'Σ' => 'S',
+ 'Τ' => 'T',
+ 'Θ' => 'Th',
+ 'Ω' => 'W',
+ 'Ώ' => 'W',
+ 'Χ' => 'X',
+ 'ϒ' => 'Y',
+ 'Υ' => 'Y',
+ 'Ύ' => 'Y',
+ 'Ϋ' => 'Y',
+ 'Ζ' => 'Z',
+ 'α' => 'a',
+ 'ά' => 'a',
+ 'β' => 'b',
+ 'δ' => 'd',
+ 'ε' => 'e',
+ 'έ' => 'e',
+ 'φ' => 'f',
+ 'γ' => 'g',
+ 'η' => 'h',
+ 'ή' => 'h',
+ 'ι' => 'i',
+ 'ί' => 'i',
+ 'ϊ' => 'i',
+ 'ΐ' => 'i',
+ 'κ' => 'k',
+ 'ξ' => 'ks',
+ 'λ' => 'l',
+ 'μ' => 'm',
+ 'ν' => 'n',
+ 'ο' => 'o',
+ 'ό' => 'o',
+ 'π' => 'p',
+ 'ψ' => 'ps',
+ 'ρ' => 'r',
+ 'σ' => 's',
+ 'ς' => 's',
+ 'τ' => 't',
+ 'ϑ' => 'th',
+ 'θ' => 'th',
+ 'ϐ' => 'v',
+ 'ω' => 'w',
+ 'ώ' => 'w',
+ 'χ' => 'x',
+ 'υ' => 'y',
+ 'ύ' => 'y',
+ 'ΰ' => 'y',
+ 'ϋ' => 'y',
+ 'ζ' => 'z',
+ ],
+ // Greek (Elláda)
+ 'el' => [
+ 'ΑΥ' => 'AU',
+ 'Αυ' => 'Au',
+ 'ΟΥ' => 'U',
+ 'Ου' => 'u',
+ 'ΕΥ' => 'EF',
+ 'Ευ' => 'Ef',
+ 'ΕΙ' => 'I',
+ 'Ει' => 'I',
+ 'ΟΙ' => 'I',
+ 'Οι' => 'I',
+ 'ΥΙ' => 'I',
+ 'Υι' => 'I',
+ 'ΑΎ' => 'AU',
+ 'Αύ' => 'Au',
+ 'ΟΎ' => 'OU',
+ 'Ού' => 'Ou',
+ 'ΕΎ' => 'EU',
+ 'Εύ' => 'Eu',
+ 'ΕΊ' => 'I',
+ 'Εί' => 'I',
+ 'ΟΊ' => 'I',
+ 'Οί' => 'I',
+ 'ΎΙ' => 'I',
+ 'Ύι' => 'I',
+ 'ΥΊ' => 'I',
+ 'Υί' => 'I',
+ 'αυ' => 'au',
+ 'ου' => 'u',
+ 'ευ' => 'ef',
+ 'ει' => 'i',
+ 'οι' => 'i',
+ 'υι' => 'i',
+ 'αύ' => 'au',
+ 'ού' => 'ou',
+ 'εύ' => 'eu',
+ 'εί' => 'i',
+ 'οί' => 'i',
+ 'ύι' => 'i',
+ 'υί' => 'i',
+ 'α' => 'a',
+ 'β' => 'v',
+ 'γ' => 'gh',
+ 'δ' => 'd',
+ 'ε' => 'e',
+ 'ζ' => 'z',
+ 'η' => 'i',
+ 'θ' => 'th',
+ 'ι' => 'i',
+ 'κ' => 'k',
+ 'λ' => 'l',
+ 'μ' => 'm',
+ 'ν' => 'n',
+ 'ξ' => 'ks',
+ 'ο' => 'o',
+ 'π' => 'p',
+ 'ρ' => 'r',
+ 'σ' => 's',
+ 'τ' => 't',
+ 'υ' => 'i',
+ 'φ' => 'f',
+ 'χ' => 'kh',
+ 'ψ' => 'ps',
+ 'ω' => 'o',
+ 'ά' => 'a',
+ 'έ' => 'e',
+ 'ί' => 'i',
+ 'ό' => 'o',
+ 'ϒ' => 'Y',
+ 'ύ' => 'y',
+ 'ή' => 'i',
+ 'ώ' => 'w',
+ 'ς' => 's',
+ 'ϊ' => 'i',
+ 'ΰ' => 'y',
+ 'ϋ' => 'y',
+ 'ΐ' => 'i',
+ 'Α' => 'A',
+ 'Β' => 'B',
+ 'Γ' => 'G',
+ 'Δ' => 'D',
+ 'Ε' => 'E',
+ 'Ζ' => 'Z',
+ 'Η' => 'H',
+ 'Θ' => 'Th',
+ 'Ι' => 'I',
+ 'Κ' => 'K',
+ 'Λ' => 'L',
+ 'Μ' => 'M',
+ 'Ν' => 'N',
+ 'Ξ' => 'Ks',
+ 'Ο' => 'O',
+ 'Π' => 'P',
+ 'Ρ' => 'R',
+ 'Σ' => 'S',
+ 'Τ' => 'T',
+ 'Υ' => 'Y',
+ 'Φ' => 'F',
+ 'Χ' => 'X',
+ 'Ψ' => 'Ps',
+ 'Ω' => 'O',
+ 'Ά' => 'A',
+ 'Έ' => 'E',
+ 'Ί' => 'I',
+ 'Ό' => 'O',
+ 'Ύ' => 'Y',
+ 'Ή' => 'I',
+ 'Ώ' => 'W',
+ 'Ϊ' => 'I',
+ 'Ϋ' => 'Y',
+ 'ϐ' => 'v',
+ 'ϑ' => 'th',
+ ],
+ // Hindi
+ 'hi' => [
+ 'अ' => 'a',
+ 'आ' => 'aa',
+ 'ए' => 'e',
+ 'ई' => 'ii',
+ 'ऍ' => 'ei',
+ 'ऎ' => 'ae',
+ 'ऐ' => 'ai',
+ 'इ' => 'i',
+ 'ओ' => 'o',
+ 'ऑ' => 'oi',
+ 'ऒ' => 'oii',
+ 'ऊ' => 'uu',
+ 'औ' => 'ou',
+ 'उ' => 'u',
+ 'ब' => 'B',
+ 'भ' => 'Bha',
+ 'च' => 'Ca',
+ 'छ' => 'Chha',
+ 'ड' => 'Da',
+ 'ढ' => 'Dha',
+ 'फ' => 'Fa',
+ 'फ़' => 'Fi',
+ 'ग' => 'Ga',
+ 'घ' => 'Gha',
+ 'ग़' => 'Ghi',
+ 'ह' => 'Ha',
+ 'ज' => 'Ja',
+ 'झ' => 'Jha',
+ 'क' => 'Ka',
+ 'ख' => 'Kha',
+ 'ख़' => 'Khi',
+ 'ल' => 'L',
+ 'ळ' => 'Li',
+ 'ऌ' => 'Li',
+ 'ऴ' => 'Lii',
+ 'ॡ' => 'Lii',
+ 'म' => 'Ma',
+ 'न' => 'Na',
+ 'ङ' => 'Na',
+ 'ञ' => 'Nia',
+ 'ण' => 'Nae',
+ 'ऩ' => 'Ni',
+ 'ॐ' => 'oms',
+ 'प' => 'Pa',
+ 'क़' => 'Qi',
+ 'र' => 'Ra',
+ 'ऋ' => 'Ri',
+ 'ॠ' => 'Ri',
+ 'ऱ' => 'Ri',
+ 'स' => 'Sa',
+ 'श' => 'Sha',
+ 'ष' => 'Shha',
+ 'ट' => 'Ta',
+ 'त' => 'Ta',
+ 'ठ' => 'Tha',
+ 'द' => 'Tha',
+ 'थ' => 'Tha',
+ 'ध' => 'Thha',
+ 'ड़' => 'ugDha',
+ 'ढ़' => 'ugDhha',
+ 'व' => 'Va',
+ 'य' => 'Ya',
+ 'य़' => 'Yi',
+ 'ज़' => 'Za',
+ ],
+ // Armenian
+ 'hy' => [
+ 'Ա' => 'A',
+ 'Բ' => 'B',
+ 'Գ' => 'G',
+ 'Դ' => 'D',
+ 'Ե' => 'E',
+ 'Զ' => 'Z',
+ 'Է' => 'E',
+ 'Ը' => 'Y',
+ 'Թ' => 'Th',
+ 'Ժ' => 'Zh',
+ 'Ի' => 'I',
+ 'Լ' => 'L',
+ 'Խ' => 'Kh',
+ 'Ծ' => 'Ts',
+ 'Կ' => 'K',
+ 'Հ' => 'H',
+ 'Ձ' => 'Dz',
+ 'Ղ' => 'Gh',
+ 'Ճ' => 'Tch',
+ 'Մ' => 'M',
+ 'Յ' => 'Y',
+ 'Ն' => 'N',
+ 'Շ' => 'Sh',
+ 'Ո' => 'Vo',
+ 'Չ' => 'Ch',
+ 'Պ' => 'P',
+ 'Ջ' => 'J',
+ 'Ռ' => 'R',
+ 'Ս' => 'S',
+ 'Վ' => 'V',
+ 'Տ' => 'T',
+ 'Ր' => 'R',
+ 'Ց' => 'C',
+ 'Ւ' => 'u',
+ 'Փ' => 'Ph',
+ 'Ք' => 'Q',
+ 'և' => 'ev',
+ 'Օ' => 'O',
+ 'Ֆ' => 'F',
+ 'ա' => 'a',
+ 'բ' => 'b',
+ 'գ' => 'g',
+ 'դ' => 'd',
+ 'ե' => 'e',
+ 'զ' => 'z',
+ 'է' => 'e',
+ 'ը' => 'y',
+ 'թ' => 'th',
+ 'ժ' => 'zh',
+ 'ի' => 'i',
+ 'լ' => 'l',
+ 'խ' => 'kh',
+ 'ծ' => 'ts',
+ 'կ' => 'k',
+ 'հ' => 'h',
+ 'ձ' => 'dz',
+ 'ղ' => 'gh',
+ 'ճ' => 'tch',
+ 'մ' => 'm',
+ 'յ' => 'y',
+ 'ն' => 'n',
+ 'շ' => 'sh',
+ 'ո' => 'vo',
+ 'չ' => 'ch',
+ 'պ' => 'p',
+ 'ջ' => 'j',
+ 'ռ' => 'r',
+ 'ս' => 's',
+ 'վ' => 'v',
+ 'տ' => 't',
+ 'ր' => 'r',
+ 'ց' => 'c',
+ 'ւ' => 'u',
+ 'փ' => 'ph',
+ 'ք' => 'q',
+ 'օ' => 'o',
+ 'ֆ' => 'f',
+ ],
+ // Swedish
+ 'sv' => [
+ 'Ä' => 'A',
+ 'ä' => 'a',
+ 'Å' => 'A',
+ 'å' => 'a',
+ 'Ö' => 'O',
+ 'ö' => 'o',
+ ],
+ // Turkmen
+ 'tk' => [
+ 'Ç' => 'C',
+ 'Ä' => 'A',
+ 'Ž' => 'Z',
+ 'Ň' => 'N',
+ 'Ö' => 'O',
+ 'Ş' => 'S',
+ 'Ü' => 'U',
+ 'Ý' => 'Y',
+ 'ç' => 'c',
+ 'ä' => 'a',
+ 'ž' => 'z',
+ 'ň' => 'n',
+ 'ö' => 'o',
+ 'ş' => 's',
+ 'ü' => 'u',
+ 'ý' => 'y',
+ ],
+ // Turkish
+ 'tr' => [
+ 'ň' => 'n',
+ 'Ň' => 'N',
+ 'ş' => 's',
+ 'Ş' => 'S',
+ 'ı' => 'i',
+ 'İ' => 'I',
+ 'ç' => 'c',
+ 'Ç' => 'C',
+ 'ä' => 'a',
+ 'Ä' => 'A',
+ 'ü' => 'u',
+ 'Ü' => 'U',
+ 'ö' => 'o',
+ 'Ö' => 'O',
+ 'ğ' => 'g',
+ 'Ğ' => 'G',
+ 'ý' => 'y',
+ 'Ý' => 'Y',
+ 'ž' => 'z',
+ 'Ž' => 'Z',
+ ],
+ // Bulgarian
+ 'bg' => [
+ 'ьо' => 'yo',
+ 'А' => 'A',
+ 'Б' => 'B',
+ 'В' => 'V',
+ 'Г' => 'G',
+ 'Д' => 'D',
+ 'Е' => 'E',
+ 'Ж' => 'Zh',
+ 'З' => 'Z',
+ 'И' => 'I',
+ 'Й' => 'Y',
+ 'К' => 'K',
+ 'Л' => 'L',
+ 'М' => 'M',
+ 'Н' => 'N',
+ 'О' => 'O',
+ 'П' => 'P',
+ 'Р' => 'R',
+ 'С' => 'S',
+ 'Т' => 'T',
+ 'У' => 'U',
+ 'Ф' => 'F',
+ 'Х' => 'H',
+ 'Ц' => 'C',
+ 'Ч' => 'Ch',
+ 'Ш' => 'Sh',
+ 'Щ' => 'Sht',
+ 'Ъ' => 'A',
+ 'Ь' => '',
+ 'Ю' => 'Yu',
+ 'Я' => 'Ya',
+ 'а' => 'a',
+ 'б' => 'b',
+ 'в' => 'v',
+ 'г' => 'g',
+ 'д' => 'd',
+ 'е' => 'e',
+ 'ж' => 'zh',
+ 'з' => 'z',
+ 'и' => 'i',
+ 'й' => 'y',
+ 'к' => 'k',
+ 'л' => 'l',
+ 'м' => 'm',
+ 'н' => 'n',
+ 'о' => 'o',
+ 'п' => 'p',
+ 'р' => 'r',
+ 'с' => 's',
+ 'т' => 't',
+ 'у' => 'u',
+ 'ф' => 'f',
+ 'х' => 'h',
+ 'ц' => 'c',
+ 'ч' => 'ch',
+ 'ш' => 'sh',
+ 'щ' => 'sht',
+ 'ъ' => 'a',
+ 'ь' => '',
+ 'ю' => 'yu',
+ 'я' => 'ya',
+ ],
+ // Hungarian
+ 'hu' => [
+ 'Á' => 'A',
+ 'Ē' => 'E',
+ 'É' => 'E',
+ 'Í' => 'I',
+ 'Ó' => 'O',
+ 'Ö' => 'O',
+ 'Ő' => 'O',
+ 'Ú' => 'U',
+ 'Ü' => 'U',
+ 'Ű' => 'U',
+ 'á' => 'a',
+ 'ē' => 'e',
+ 'é' => 'e',
+ 'í' => 'i',
+ 'ó' => 'o',
+ 'ö' => 'o',
+ 'ő' => 'o',
+ 'ú' => 'u',
+ 'ü' => 'u',
+ 'ű' => 'u',
+ ],
+ // Myanmar (Burmese)
+ 'my' => [
+ 'န်ုပ်' => 'nub',
+ 'ောင်' => 'aung',
+ 'ိုက်' => 'aik',
+ 'ိုဒ်' => 'ok',
+ 'ိုင်' => 'aing',
+ 'ိုလ်' => 'ol',
+ 'ေါင်' => 'aung',
+ 'သြော' => 'aw',
+ 'ောက်' => 'auk',
+ 'ိတ်' => 'eik',
+ 'ုတ်' => 'ok',
+ 'ုန်' => 'on',
+ 'ေတ်' => 'it',
+ 'ုဒ်' => 'ait',
+ 'ာန်' => 'an',
+ 'ိန်' => 'ein',
+ 'ွတ်' => 'ut',
+ 'ေါ်' => 'aw',
+ 'ွန်' => 'un',
+ 'ိပ်' => 'eik',
+ 'ုပ်' => 'ok',
+ 'ွပ်' => 'ut',
+ 'ိမ်' => 'ein',
+ 'ုမ်' => 'on',
+ 'ော်' => 'aw',
+ 'ွမ်' => 'un',
+ 'က်' => 'et',
+ 'ေါ' => 'aw',
+ 'ော' => 'aw',
+ 'ျွ' => 'ywa',
+ 'ြွ' => 'yw',
+ 'ို' => 'o',
+ 'ုံ' => 'on',
+ 'တ်' => 'at',
+ 'င်' => 'in',
+ 'ည်' => 'i',
+ 'ဒ်' => 'd',
+ 'န်' => 'an',
+ 'ပ်' => 'at',
+ 'မ်' => 'an',
+ 'စျ' => 'za',
+ 'ယ်' => 'e',
+ 'ဉ်' => 'in',
+ 'စ်' => 'it',
+ 'ိံ' => 'ein',
+ 'ဲ' => 'e',
+ 'း' => '',
+ 'ာ' => 'a',
+ 'ါ' => 'a',
+ 'ေ' => 'e',
+ 'ံ' => 'an',
+ 'ိ' => 'i',
+ 'ီ' => 'i',
+ 'ု' => 'u',
+ 'ူ' => 'u',
+ '်' => 'at',
+ '္' => '',
+ '့' => '',
+ 'က' => 'k',
+ '၉' => '9',
+ 'တ' => 't',
+ 'ရ' => 'ya',
+ 'ယ' => 'y',
+ 'မ' => 'm',
+ 'ဘ' => 'ba',
+ 'ဗ' => 'b',
+ 'ဖ' => 'pa',
+ 'ပ' => 'p',
+ 'န' => 'n',
+ 'ဓ' => 'da',
+ 'ဒ' => 'd',
+ 'ထ' => 'ta',
+ 'ဏ' => 'na',
+ 'ဝ' => 'w',
+ 'ဎ' => 'da',
+ 'ဍ' => 'd',
+ 'ဌ' => 'ta',
+ 'ဋ' => 't',
+ 'ည' => 'ny',
+ 'ဇ' => 'z',
+ 'ဆ' => 'sa',
+ 'စ' => 's',
+ 'င' => 'ng',
+ 'ဃ' => 'ga',
+ 'ဂ' => 'g',
+ 'လ' => 'l',
+ 'သ' => 'th',
+ '၈' => '8',
+ 'ဩ' => 'aw',
+ 'ခ' => 'kh',
+ '၆' => '6',
+ '၅' => '5',
+ '၄' => '4',
+ '၃' => '3',
+ '၂' => '2',
+ '၁' => '1',
+ '၀' => '0',
+ '၌' => 'hnaik',
+ '၍' => 'ywae',
+ 'ဪ' => 'aw',
+ 'ဦ' => '-u',
+ 'ဟ' => 'h',
+ 'ဉ' => 'u',
+ 'ဤ' => '-i',
+ 'ဣ' => 'i',
+ '၏' => '-e',
+ 'ဧ' => 'e',
+ 'ှ' => 'h',
+ 'ွ' => 'w',
+ 'ျ' => 'ya',
+ 'ြ' => 'y',
+ 'အ' => 'a',
+ 'ဠ' => 'la',
+ '၇' => '7',
+ ],
+ // Croatian (Hrvatska)
+ 'hr' => [
+ 'DŽ' => 'DZ',
+ 'Dž' => 'Dz',
+ 'dž' => 'dz',
+ 'DZ' => 'DZ',
+ 'Dz' => 'Dz',
+ 'dz' => 'dz',
+ 'IJ' => 'IJ',
+ 'ij' => 'ij',
+ 'LJ' => 'LJ',
+ 'Lj' => 'Lj',
+ 'lj' => 'lj',
+ 'NJ' => 'NJ',
+ 'Nj' => 'Nj',
+ 'nj' => 'nj',
+ 'ž' => 'z',
+ 'Ž' => 'Z',
+ 'đ' => 'dj',
+ 'Đ' => 'Dj',
+ 'č' => 'c',
+ 'Č' => 'C',
+ 'ć' => 'c',
+ 'Ć' => 'C',
+ 'š' => 's',
+ 'Š' => 'S',
+ ],
+ // Finnish
+ 'fi' => [
+ 'Ä' => 'A',
+ 'Ö' => 'O',
+ 'ä' => 'a',
+ 'ö' => 'o',
+ ],
+ // Georgian (Kartvelian)
+ 'ka' => [
+ 'ა' => 'a',
+ 'ბ' => 'b',
+ 'გ' => 'g',
+ 'დ' => 'd',
+ 'ე' => 'e',
+ 'ვ' => 'v',
+ 'ზ' => 'z',
+ 'თ' => 't',
+ 'ი' => 'i',
+ 'კ' => 'k',
+ 'ლ' => 'l',
+ 'მ' => 'm',
+ 'ნ' => 'n',
+ 'ო' => 'o',
+ 'პ' => 'p',
+ 'ჟ' => 'zh',
+ 'რ' => 'r',
+ 'ს' => 's',
+ 'ტ' => 't',
+ 'უ' => 'u',
+ 'ფ' => 'f',
+ 'ქ' => 'q',
+ 'ღ' => 'gh',
+ 'ყ' => 'y',
+ 'შ' => 'sh',
+ 'ჩ' => 'ch',
+ 'ც' => 'ts',
+ 'ძ' => 'dz',
+ 'წ' => 'ts',
+ 'ჭ' => 'ch',
+ 'ხ' => 'kh',
+ 'ჯ' => 'j',
+ 'ჰ' => 'h',
+ ],
+ // Russian
+ 'ru' => [
+ 'А' => 'A',
+ 'а' => 'a',
+ 'Б' => 'B',
+ 'б' => 'b',
+ 'В' => 'V',
+ 'в' => 'v',
+ 'Г' => 'G',
+ 'г' => 'g',
+ 'Д' => 'D',
+ 'д' => 'd',
+ 'Е' => 'E',
+ 'е' => 'e',
+ 'Ё' => 'Yo',
+ 'ё' => 'yo',
+ 'Ж' => 'Zh',
+ 'ж' => 'zh',
+ 'З' => 'Z',
+ 'з' => 'z',
+ 'И' => 'I',
+ 'и' => 'i',
+ 'Й' => 'Y',
+ 'й' => 'y',
+ 'К' => 'K',
+ 'к' => 'k',
+ 'Л' => 'L',
+ 'л' => 'l',
+ 'М' => 'M',
+ 'м' => 'm',
+ 'Н' => 'N',
+ 'н' => 'n',
+ 'О' => 'O',
+ 'о' => 'o',
+ 'П' => 'P',
+ 'п' => 'p',
+ 'Р' => 'R',
+ 'р' => 'r',
+ 'С' => 'S',
+ 'с' => 's',
+ 'Т' => 'T',
+ 'т' => 't',
+ 'У' => 'U',
+ 'у' => 'u',
+ 'Ф' => 'F',
+ 'ф' => 'f',
+ 'Х' => 'H',
+ 'х' => 'h',
+ 'Ц' => 'Ts',
+ 'ц' => 'ts',
+ 'Ч' => 'Ch',
+ 'ч' => 'ch',
+ 'ш' => 'sh',
+ 'Ш' => 'Sh',
+ 'Щ' => 'Sch',
+ 'щ' => 'sch',
+ 'Ъ' => '',
+ 'ъ' => '',
+ 'Ы' => 'Y',
+ 'ы' => 'y',
+ 'Ь' => '',
+ 'ь' => '',
+ 'Э' => 'E',
+ 'э' => 'e',
+ 'Ю' => 'Yu',
+ 'ю' => 'yu',
+ 'Я' => 'Ya',
+ 'я' => 'ya',
+ ],
+ // Russian - GOST 7.79-2000(B)
+ // -> https://en.m.wikipedia.org/wiki/Romanization_of_Russian#content-collapsible-block-1
+ 'ru__gost_2000_b' => [
+ 'А' => 'A',
+ 'а' => 'a',
+ 'Б' => 'B',
+ 'б' => 'b',
+ 'В' => 'V',
+ 'в' => 'v',
+ 'Г' => 'G',
+ 'г' => 'g',
+ 'Д' => 'D',
+ 'д' => 'd',
+ 'Е' => 'E',
+ 'е' => 'e',
+ 'Ё' => 'Yo',
+ 'ё' => 'yo',
+ 'Ж' => 'Zh',
+ 'ж' => 'zh',
+ 'З' => 'Z',
+ 'з' => 'z',
+ 'И' => 'i',
+ 'и' => 'i',
+ 'Й' => 'i',
+ 'й' => 'i',
+ 'К' => 'K',
+ 'к' => 'k',
+ 'Л' => 'L',
+ 'л' => 'l',
+ 'М' => 'M',
+ 'м' => 'm',
+ 'Н' => 'N',
+ 'н' => 'n',
+ 'О' => 'O',
+ 'о' => 'o',
+ 'П' => 'P',
+ 'п' => 'p',
+ 'Р' => 'R',
+ 'р' => 'r',
+ 'С' => 'S',
+ 'с' => 's',
+ 'Т' => 'T',
+ 'т' => 't',
+ 'У' => 'U',
+ 'у' => 'u',
+ 'Ф' => 'F',
+ 'ф' => 'f',
+ 'Х' => 'X',
+ 'х' => 'x',
+ 'Ц' => 'Cz',
+ 'ц' => 'cz',
+ 'Ч' => 'Ch',
+ 'ч' => 'ch',
+ 'ш' => 'sh',
+ 'Ш' => 'Sh',
+ 'Щ' => 'Shh',
+ 'щ' => 'shh',
+ 'Ъ' => '',
+ 'ъ' => '',
+ 'Ы' => 'Y\'',
+ 'ы' => 'y\'',
+ 'Ь' => '',
+ 'ь' => '',
+ 'Э' => 'E\'',
+ 'э' => 'e\'',
+ 'Ю' => 'Yu',
+ 'ю' => 'yu',
+ 'Я' => 'Ya',
+ 'я' => 'ya',
+ 'І' => 'I',
+ 'і' => 'i',
+ 'Ѳ' => 'Fh',
+ 'ѳ' => 'fh',
+ 'Ѣ' => 'Ye',
+ 'ѣ' => 'ye',
+ 'Ѵ' => 'Yh',
+ 'ѵ' => 'yh',
+ 'Є' => '',
+ 'є' => '',
+ 'Ѥ' => '',
+ 'ѥ' => '',
+ 'Ѕ' => 'Js',
+ 'ѕ' => 'js',
+ 'Ꙋ' => '',
+ 'ꙋ' => '',
+ 'Ѡ' => '',
+ 'ѡ' => '',
+ 'Ѿ' => '',
+ 'ѿ' => '',
+ 'Ѫ' => '',
+ 'ѫ' => '',
+ 'Ѧ' => '',
+ 'ѧ' => '',
+ 'Ѭ' => '',
+ 'ѭ' => '',
+ 'Ѩ' => '',
+ 'ѩ' => '',
+ 'Ѯ' => '',
+ 'ѯ' => '',
+ 'Ѱ' => '',
+ 'ѱ' => '',
+ ],
+ // Russian - Passport (2013), ICAO
+ // -> https://en.m.wikipedia.org/wiki/Romanization_of_Russian#content-collapsible-block-1
+ 'ru__passport_2013' => [
+ 'А' => 'A',
+ 'а' => 'a',
+ 'Б' => 'B',
+ 'б' => 'b',
+ 'В' => 'V',
+ 'в' => 'v',
+ 'Г' => 'G',
+ 'г' => 'g',
+ 'Д' => 'D',
+ 'д' => 'd',
+ 'Е' => 'E',
+ 'е' => 'e',
+ 'Ё' => 'E',
+ 'ё' => 'e',
+ 'Ж' => 'Zh',
+ 'ж' => 'zh',
+ 'З' => 'Z',
+ 'з' => 'z',
+ 'И' => 'i',
+ 'и' => 'i',
+ 'Й' => 'i',
+ 'й' => 'i',
+ 'К' => 'K',
+ 'к' => 'k',
+ 'Л' => 'L',
+ 'л' => 'l',
+ 'М' => 'M',
+ 'м' => 'm',
+ 'Н' => 'N',
+ 'н' => 'n',
+ 'О' => 'O',
+ 'о' => 'o',
+ 'П' => 'P',
+ 'п' => 'p',
+ 'Р' => 'R',
+ 'р' => 'r',
+ 'С' => 'S',
+ 'с' => 's',
+ 'Т' => 'T',
+ 'т' => 't',
+ 'У' => 'U',
+ 'у' => 'u',
+ 'Ф' => 'F',
+ 'ф' => 'f',
+ 'Х' => 'Kh',
+ 'х' => 'kh',
+ 'Ц' => 'Ts',
+ 'ц' => 'ts',
+ 'Ч' => 'Ch',
+ 'ч' => 'ch',
+ 'ш' => 'sh',
+ 'Ш' => 'Sh',
+ 'Щ' => 'Shch',
+ 'щ' => 'shch',
+ 'Ъ' => 'Ie',
+ 'ъ' => 'ie',
+ 'Ы' => 'Y',
+ 'ы' => 'y',
+ 'Ь' => '',
+ 'ь' => '',
+ 'Э' => 'E',
+ 'э' => 'e',
+ 'Ю' => 'Iu',
+ 'ю' => 'iu',
+ 'Я' => 'Ia',
+ 'я' => 'ia',
+ 'І' => '',
+ 'і' => '',
+ 'Ѳ' => '',
+ 'ѳ' => '',
+ 'Ѣ' => '',
+ 'ѣ' => '',
+ 'Ѵ' => '',
+ 'ѵ' => '',
+ 'Є' => '',
+ 'є' => '',
+ 'Ѥ' => '',
+ 'ѥ' => '',
+ 'Ѕ' => '',
+ 'ѕ' => '',
+ 'Ꙋ' => '',
+ 'ꙋ' => '',
+ 'Ѡ' => '',
+ 'ѡ' => '',
+ 'Ѿ' => '',
+ 'ѿ' => '',
+ 'Ѫ' => '',
+ 'ѫ' => '',
+ 'Ѧ' => '',
+ 'ѧ' => '',
+ 'Ѭ' => '',
+ 'ѭ' => '',
+ 'Ѩ' => '',
+ 'ѩ' => '',
+ 'Ѯ' => '',
+ 'ѯ' => '',
+ 'Ѱ' => '',
+ 'ѱ' => '',
+ ],
+ // Ukrainian
+ // -> https://zakon.rada.gov.ua/laws/show/55-2010-%D0%BF?lang=en
+ 'uk' => [
+ 'Г' => 'H',
+ 'г' => 'h',
+ 'Ґ' => 'G',
+ 'ґ' => 'g',
+ 'Є' => 'Ye',
+ 'є' => 'ye',
+ 'И' => 'Y',
+ 'и' => 'y',
+ 'І' => 'I',
+ 'і' => 'i',
+ 'Ї' => 'Yi',
+ 'ї' => 'yi',
+ 'Й' => 'Y',
+ 'й' => 'y',
+ 'Х' => 'Kh',
+ 'х' => 'kh',
+ 'Ц' => 'Ts',
+ 'ц' => 'ts',
+ 'Ч' => 'Ch',
+ 'ч' => 'ch',
+ 'Ш' => 'Sh',
+ 'ш' => 'sh',
+ 'Щ' => 'Shch',
+ 'щ' => 'shch',
+ ],
+ // Kazakh
+ 'kk' => [
+ 'Ә' => 'A',
+ 'Ғ' => 'G',
+ 'Қ' => 'Q',
+ 'Ң' => 'N',
+ 'Ө' => 'O',
+ 'Ұ' => 'U',
+ 'Ү' => 'U',
+ 'Һ' => 'H',
+ 'ә' => 'a',
+ 'ғ' => 'g',
+ 'қ' => 'q',
+ 'ң' => 'n',
+ 'ө' => 'o',
+ 'ұ' => 'u',
+ 'ү' => 'u',
+ 'һ' => 'h',
+ ],
+ // Czech
+ 'cs' => [
+ 'á' => 'a',
+ 'Á' => 'A',
+ 'č' => 'c',
+ 'Č' => 'C',
+ 'ď' => 'd',
+ 'Ď' => 'D',
+ 'é' => 'e',
+ 'É' => 'E',
+ 'ě' => 'e',
+ 'Ě' => 'E',
+ 'í' => 'i',
+ 'Í' => 'I',
+ 'ň' => 'n',
+ 'Ň' => 'N',
+ 'ó' => 'o',
+ 'Ó' => 'O',
+ 'ř' => 'r',
+ 'Ř' => 'R',
+ 'š' => 's',
+ 'Š' => 'S',
+ 'ť' => 't',
+ 'Ť' => 'T',
+ 'ú' => 'u',
+ 'Ú' => 'U',
+ 'ů' => 'u',
+ 'Ů' => 'U',
+ 'ý' => 'y',
+ 'Ý' => 'Y',
+ 'ž' => 'z',
+ 'Ž' => 'Z',
+ ],
+ // Danish
+ 'da' => [
+ 'Æ' => 'Ae',
+ 'æ' => 'ae',
+ 'Ø' => 'Oe',
+ 'ø' => 'oe',
+ 'Å' => 'Aa',
+ 'å' => 'aa',
+ 'É' => 'E',
+ 'é' => 'e',
+ ],
+ // Polish
+ 'pl' => [
+ 'ą' => 'a',
+ 'ć' => 'c',
+ 'ę' => 'e',
+ 'ł' => 'l',
+ 'ń' => 'n',
+ 'ó' => 'o',
+ 'ś' => 's',
+ 'ź' => 'z',
+ 'ż' => 'z',
+ 'Ą' => 'A',
+ 'Ć' => 'C',
+ 'Ę' => 'E',
+ 'Ł' => 'L',
+ 'Ń' => 'N',
+ 'Ó' => 'O',
+ 'Ś' => 'S',
+ 'Ź' => 'Z',
+ 'Ż' => 'Z',
+ ],
+ // Romanian
+ 'ro' => [
+ 'ă' => 'a',
+ 'â' => 'a',
+ 'Ă' => 'A',
+ 'Â' => 'A',
+ 'î' => 'i',
+ 'Î' => 'I',
+ 'ș' => 's',
+ 'ş' => 's',
+ 'Ş' => 'S',
+ 'Ș' => 'S',
+ 'ț' => 't',
+ 'ţ' => 't',
+ 'Ţ' => 'T',
+ 'Ț' => 'T',
+ ],
+ // Esperanto
+ 'eo' => [
+ 'ĉ' => 'cx',
+ 'ĝ' => 'gx',
+ 'ĥ' => 'hx',
+ 'ĵ' => 'jx',
+ 'ŝ' => 'sx',
+ 'ŭ' => 'ux',
+ 'Ĉ' => 'CX',
+ 'Ĝ' => 'GX',
+ 'Ĥ' => 'HX',
+ 'Ĵ' => 'JX',
+ 'Ŝ' => 'SX',
+ 'Ŭ' => 'UX',
+ ],
+ // Estonian
+ 'et' => [
+ 'Š' => 'S',
+ 'Ž' => 'Z',
+ 'Õ' => 'O',
+ 'Ä' => 'A',
+ 'Ö' => 'O',
+ 'Ü' => 'U',
+ 'š' => 's',
+ 'ž' => 'z',
+ 'õ' => 'o',
+ 'ä' => 'a',
+ 'ö' => 'o',
+ 'ü' => 'u',
+ ],
+ // Latvian
+ 'lv' => [
+ 'ā' => 'a',
+ 'č' => 'c',
+ 'ē' => 'e',
+ 'ģ' => 'g',
+ 'ī' => 'i',
+ 'ķ' => 'k',
+ 'ļ' => 'l',
+ 'ņ' => 'n',
+ 'š' => 's',
+ 'ū' => 'u',
+ 'ž' => 'z',
+ 'Ā' => 'A',
+ 'Č' => 'C',
+ 'Ē' => 'E',
+ 'Ģ' => 'G',
+ 'Ī' => 'i',
+ 'Ķ' => 'k',
+ 'Ļ' => 'L',
+ 'Ņ' => 'N',
+ 'Š' => 'S',
+ 'Ū' => 'u',
+ 'Ž' => 'Z',
+ ],
+ // Lithuanian
+ 'lt' => [
+ 'ą' => 'a',
+ 'č' => 'c',
+ 'ę' => 'e',
+ 'ė' => 'e',
+ 'į' => 'i',
+ 'š' => 's',
+ 'ų' => 'u',
+ 'ū' => 'u',
+ 'ž' => 'z',
+ 'Ą' => 'A',
+ 'Č' => 'C',
+ 'Ę' => 'E',
+ 'Ė' => 'E',
+ 'Į' => 'I',
+ 'Š' => 'S',
+ 'Ų' => 'U',
+ 'Ū' => 'U',
+ 'Ž' => 'Z',
+ ],
+ // Norwegian
+ 'no' => [
+ 'Æ' => 'AE',
+ 'æ' => 'ae',
+ 'Ø' => 'OE',
+ 'ø' => 'oe',
+ 'Å' => 'AA',
+ 'å' => 'aa',
+ ],
+ // Vietnamese
+ 'vi' => [
+ 'Á' => 'A',
+ 'À' => 'A',
+ 'Ả' => 'A',
+ 'Ã' => 'A',
+ 'Ạ' => 'A',
+ 'Ă' => 'A',
+ 'Ắ' => 'A',
+ 'Ằ' => 'A',
+ 'Ẳ' => 'A',
+ 'Ẵ' => 'A',
+ 'Ặ' => 'A',
+ 'Â' => 'A',
+ 'Ấ' => 'A',
+ 'Ầ' => 'A',
+ 'Ẩ' => 'A',
+ 'Ẫ' => 'A',
+ 'Ậ' => 'A',
+ 'á' => 'a',
+ 'à' => 'a',
+ 'ả' => 'a',
+ 'ã' => 'a',
+ 'ạ' => 'a',
+ 'ă' => 'a',
+ 'ắ' => 'a',
+ 'ằ' => 'a',
+ 'ẳ' => 'a',
+ 'ẵ' => 'a',
+ 'ặ' => 'a',
+ 'â' => 'a',
+ 'ấ' => 'a',
+ 'ầ' => 'a',
+ 'ẩ' => 'a',
+ 'ẫ' => 'a',
+ 'ậ' => 'a',
+ 'É' => 'E',
+ 'È' => 'E',
+ 'Ẻ' => 'E',
+ 'Ẽ' => 'E',
+ 'Ẹ' => 'E',
+ 'Ê' => 'E',
+ 'Ế' => 'E',
+ 'Ề' => 'E',
+ 'Ể' => 'E',
+ 'Ễ' => 'E',
+ 'Ệ' => 'E',
+ 'é' => 'e',
+ 'è' => 'e',
+ 'ẻ' => 'e',
+ 'ẽ' => 'e',
+ 'ẹ' => 'e',
+ 'ê' => 'e',
+ 'ế' => 'e',
+ 'ề' => 'e',
+ 'ể' => 'e',
+ 'ễ' => 'e',
+ 'ệ' => 'e',
+ 'Í' => 'I',
+ 'Ì' => 'I',
+ 'Ỉ' => 'I',
+ 'Ĩ' => 'I',
+ 'Ị' => 'I',
+ 'í' => 'i',
+ 'ì' => 'i',
+ 'ỉ' => 'i',
+ 'ĩ' => 'i',
+ 'ị' => 'i',
+ 'Ó' => 'O',
+ 'Ò' => 'O',
+ 'Ỏ' => 'O',
+ 'Õ' => 'O',
+ 'Ọ' => 'O',
+ 'Ô' => 'O',
+ 'Ố' => 'O',
+ 'Ồ' => 'O',
+ 'Ổ' => 'O',
+ 'Ỗ' => 'O',
+ 'Ộ' => 'O',
+ 'Ơ' => 'O',
+ 'Ớ' => 'O',
+ 'Ờ' => 'O',
+ 'Ở' => 'O',
+ 'Ỡ' => 'O',
+ 'Ợ' => 'O',
+ 'ó' => 'o',
+ 'ò' => 'o',
+ 'ỏ' => 'o',
+ 'õ' => 'o',
+ 'ọ' => 'o',
+ 'ô' => 'o',
+ 'ố' => 'o',
+ 'ồ' => 'o',
+ 'ổ' => 'o',
+ 'ỗ' => 'o',
+ 'ộ' => 'o',
+ 'ơ' => 'o',
+ 'ớ' => 'o',
+ 'ờ' => 'o',
+ 'ở' => 'o',
+ 'ỡ' => 'o',
+ 'ợ' => 'o',
+ 'Ú' => 'U',
+ 'Ù' => 'U',
+ 'Ủ' => 'U',
+ 'Ũ' => 'U',
+ 'Ụ' => 'U',
+ 'Ư' => 'U',
+ 'Ứ' => 'U',
+ 'Ừ' => 'U',
+ 'Ử' => 'U',
+ 'Ữ' => 'U',
+ 'Ự' => 'U',
+ 'ú' => 'u',
+ 'ù' => 'u',
+ 'ủ' => 'u',
+ 'ũ' => 'u',
+ 'ụ' => 'u',
+ 'ư' => 'u',
+ 'ứ' => 'u',
+ 'ừ' => 'u',
+ 'ử' => 'u',
+ 'ữ' => 'u',
+ 'ự' => 'u',
+ 'Ý' => 'Y',
+ 'Ỳ' => 'Y',
+ 'Ỷ' => 'Y',
+ 'Ỹ' => 'Y',
+ 'Ỵ' => 'Y',
+ 'ý' => 'y',
+ 'ỳ' => 'y',
+ 'ỷ' => 'y',
+ 'ỹ' => 'y',
+ 'ỵ' => 'y',
+ 'Đ' => 'D',
+ 'đ' => 'd',
+ ],
+ // Persian (Farsi)
+ 'fa' => [
+ 'ا' => 'a',
+ 'ب' => 'b',
+ 'پ' => 'p',
+ 'ت' => 't',
+ 'ث' => 's',
+ 'ج' => 'j',
+ 'چ' => 'ch',
+ 'ح' => 'h',
+ 'خ' => 'kh',
+ 'د' => 'd',
+ 'ذ' => 'z',
+ 'ر' => 'r',
+ 'ز' => 'z',
+ 'س' => 's',
+ 'ش' => 'sh',
+ 'ص' => 's',
+ 'ض' => 'z',
+ 'ط' => 't',
+ 'ظ' => 'z',
+ 'ع' => 'a',
+ 'غ' => 'gh',
+ 'ف' => 'f',
+ 'ق' => 'gh',
+ 'ک' => 'k',
+ 'گ' => 'g',
+ 'ل' => 'l',
+ 'ژ' => 'zh',
+ 'ك' => 'k',
+ 'م' => 'm',
+ 'ن' => 'n',
+ 'ه' => 'h',
+ 'و' => 'o',
+ 'ی' => 'y',
+ 'آ' => 'a',
+ '٠' => '0',
+ '١' => '1',
+ '٢' => '2',
+ '٣' => '3',
+ '٤' => '4',
+ '٥' => '5',
+ '٦' => '6',
+ '٧' => '7',
+ '٨' => '8',
+ '٩' => '9',
+ ],
+ // Arabic
+ 'ar' => [
+ 'أ' => 'a',
+ 'ب' => 'b',
+ 'ت' => 't',
+ 'ث' => 'th',
+ 'ج' => 'g',
+ 'ح' => 'h',
+ 'خ' => 'kh',
+ 'د' => 'd',
+ 'ذ' => 'th',
+ 'ر' => 'r',
+ 'ز' => 'z',
+ 'س' => 's',
+ 'ش' => 'sh',
+ 'ص' => 's',
+ 'ض' => 'd',
+ 'ط' => 't',
+ 'ظ' => 'th',
+ 'ع' => 'aa',
+ 'غ' => 'gh',
+ 'ف' => 'f',
+ 'ق' => 'k',
+ 'ك' => 'k',
+ 'ل' => 'l',
+ 'م' => 'm',
+ 'ن' => 'n',
+ 'ه' => 'h',
+ 'و' => 'o',
+ 'ي' => 'y',
+ 'ا' => 'a',
+ 'إ' => 'a',
+ 'آ' => 'a',
+ 'ؤ' => 'o',
+ 'ئ' => 'y',
+ 'ء' => 'aa',
+ '٠' => '0',
+ '١' => '1',
+ '٢' => '2',
+ '٣' => '3',
+ '٤' => '4',
+ '٥' => '5',
+ '٦' => '6',
+ '٧' => '7',
+ '٨' => '8',
+ '٩' => '9',
+ ],
+ // Serbian
+ 'sr' => [
+ 'đ' => 'dj',
+ 'ž' => 'z',
+ 'ć' => 'c',
+ 'č' => 'c',
+ 'š' => 's',
+ 'Đ' => 'Dj',
+ 'Ž' => 'Z',
+ 'Ć' => 'C',
+ 'Č' => 'C',
+ 'Š' => 'S',
+ 'а' => 'a',
+ 'б' => 'b',
+ 'в' => 'v',
+ 'г' => 'g',
+ 'д' => 'd',
+ 'ђ' => 'dj',
+ 'е' => 'e',
+ 'ж' => 'z',
+ 'з' => 'z',
+ 'и' => 'i',
+ 'ј' => 'j',
+ 'к' => 'k',
+ 'л' => 'l',
+ 'љ' => 'lj',
+ 'м' => 'm',
+ 'н' => 'n',
+ 'њ' => 'nj',
+ 'о' => 'o',
+ 'п' => 'p',
+ 'р' => 'r',
+ 'с' => 's',
+ 'т' => 't',
+ 'ћ' => 'c',
+ 'у' => 'u',
+ 'ф' => 'f',
+ 'х' => 'h',
+ 'ц' => 'c',
+ 'ч' => 'c',
+ 'џ' => 'dz',
+ 'ш' => 's',
+ 'А' => 'A',
+ 'Б' => 'B',
+ 'В' => 'V',
+ 'Г' => 'G',
+ 'Д' => 'D',
+ 'Ђ' => 'Dj',
+ 'Е' => 'E',
+ 'Ж' => 'Z',
+ 'З' => 'Z',
+ 'И' => 'I',
+ 'Ј' => 'j',
+ 'К' => 'K',
+ 'Л' => 'L',
+ 'Љ' => 'Lj',
+ 'М' => 'M',
+ 'Н' => 'N',
+ 'Њ' => 'Nj',
+ 'О' => 'O',
+ 'П' => 'P',
+ 'Р' => 'R',
+ 'С' => 'S',
+ 'Т' => 'T',
+ 'Ћ' => 'C',
+ 'У' => 'U',
+ 'Ф' => 'F',
+ 'Х' => 'H',
+ 'Ц' => 'C',
+ 'Ч' => 'C',
+ 'Џ' => 'Dz',
+ 'Ш' => 'S',
+ ],
+ // Serbian - Cyrillic
+ 'sr__cyr' => [
+ 'а' => 'a',
+ 'б' => 'b',
+ 'в' => 'v',
+ 'г' => 'g',
+ 'д' => 'd',
+ 'ђ' => 'dj',
+ 'е' => 'e',
+ 'ж' => 'z',
+ 'з' => 'z',
+ 'и' => 'i',
+ 'ј' => 'j',
+ 'к' => 'k',
+ 'л' => 'l',
+ 'љ' => 'lj',
+ 'м' => 'm',
+ 'н' => 'n',
+ 'њ' => 'nj',
+ 'о' => 'o',
+ 'п' => 'p',
+ 'р' => 'r',
+ 'с' => 's',
+ 'т' => 't',
+ 'ћ' => 'c',
+ 'у' => 'u',
+ 'ф' => 'f',
+ 'х' => 'h',
+ 'ц' => 'c',
+ 'ч' => 'c',
+ 'џ' => 'dz',
+ 'ш' => 's',
+ 'А' => 'A',
+ 'Б' => 'B',
+ 'В' => 'V',
+ 'Г' => 'G',
+ 'Д' => 'D',
+ 'Ђ' => 'Dj',
+ 'Е' => 'E',
+ 'Ж' => 'Z',
+ 'З' => 'Z',
+ 'И' => 'I',
+ 'Ј' => 'j',
+ 'К' => 'K',
+ 'Л' => 'L',
+ 'Љ' => 'Lj',
+ 'М' => 'M',
+ 'Н' => 'N',
+ 'Њ' => 'Nj',
+ 'О' => 'O',
+ 'П' => 'P',
+ 'Р' => 'R',
+ 'С' => 'S',
+ 'Т' => 'T',
+ 'Ћ' => 'C',
+ 'У' => 'U',
+ 'Ф' => 'F',
+ 'Х' => 'H',
+ 'Ц' => 'C',
+ 'Ч' => 'C',
+ 'Џ' => 'Dz',
+ 'Ш' => 'S',
+ ],
+ // Serbian - Latin
+ 'sr__lat' => [
+ 'đ' => 'dj',
+ 'ž' => 'z',
+ 'ć' => 'c',
+ 'č' => 'c',
+ 'š' => 's',
+ 'Đ' => 'Dj',
+ 'Ž' => 'Z',
+ 'Ć' => 'C',
+ 'Č' => 'C',
+ 'Š' => 'S',
+ ],
+ // Azerbaijani
+ 'az' => [
+ 'ç' => 'c',
+ 'ə' => 'e',
+ 'ğ' => 'g',
+ 'ı' => 'i',
+ 'ö' => 'o',
+ 'ş' => 's',
+ 'ü' => 'u',
+ 'Ç' => 'C',
+ 'Ə' => 'E',
+ 'Ğ' => 'G',
+ 'İ' => 'I',
+ 'Ö' => 'O',
+ 'Ş' => 'S',
+ 'Ü' => 'U',
+ ],
+ // Slovak
+ 'sk' => [
+ 'á' => 'a',
+ 'ä' => 'a',
+ 'č' => 'c',
+ 'ď' => 'd',
+ 'é' => 'e',
+ 'í' => 'i',
+ 'ľ' => 'l',
+ 'ĺ' => 'l',
+ 'ň' => 'n',
+ 'ó' => 'o',
+ 'ô' => 'o',
+ 'ŕ' => 'r',
+ 'š' => 's',
+ 'ť' => 't',
+ 'ú' => 'u',
+ 'ý' => 'y',
+ 'ž' => 'z',
+ 'Á' => 'A',
+ 'Ä' => 'A',
+ 'Č' => 'C',
+ 'Ď' => 'D',
+ 'É' => 'E',
+ 'Í' => 'I',
+ 'Ľ' => 'L',
+ 'Ĺ' => 'L',
+ 'Ň' => 'N',
+ 'Ó' => 'O',
+ 'Ô' => 'O',
+ 'Ŕ' => 'R',
+ 'Š' => 'S',
+ 'Ť' => 'T',
+ 'Ú' => 'U',
+ 'Ý' => 'Y',
+ 'Ž' => 'Z',
+ ],
+ // French
+ 'fr' => [
+ 'Æ' => 'AE',
+ 'æ' => 'ae',
+ 'Œ' => 'OE',
+ 'œ' => 'oe',
+ 'â' => 'a',
+ 'Â' => 'A',
+ 'à' => 'a',
+ 'À' => 'A',
+ 'ä' => 'a',
+ 'Ä' => 'A',
+ 'ç' => 'c',
+ 'Ç' => 'C',
+ 'é' => 'e',
+ 'É' => 'E',
+ 'ê' => 'e',
+ 'Ê' => 'E',
+ 'ë' => 'e',
+ 'Ë' => 'E',
+ 'è' => 'e',
+ 'È' => 'E',
+ 'ï' => 'i',
+ 'î' => 'i',
+ 'Ï' => 'I',
+ 'Î' => 'I',
+ 'ÿ' => 'y',
+ 'Ÿ' => 'Y',
+ 'ô' => 'o',
+ 'Ô' => 'O',
+ 'ö' => 'o',
+ 'Ö' => 'O',
+ 'û' => 'u',
+ 'Û' => 'U',
+ 'ù' => 'u',
+ 'Ù' => 'U',
+ 'ü' => 'u',
+ 'Ü' => 'U',
+ ],
+ // Austrian (French)
+ 'fr_at' => [
+ 'ß' => 'sz',
+ 'ẞ' => 'SZ',
+ 'Æ' => 'AE',
+ 'æ' => 'ae',
+ 'Œ' => 'OE',
+ 'œ' => 'oe',
+ 'â' => 'a',
+ 'Â' => 'A',
+ 'à' => 'a',
+ 'À' => 'A',
+ 'ä' => 'a',
+ 'Ä' => 'A',
+ 'ç' => 'c',
+ 'Ç' => 'C',
+ 'é' => 'e',
+ 'É' => 'E',
+ 'ê' => 'e',
+ 'Ê' => 'E',
+ 'ë' => 'e',
+ 'Ë' => 'E',
+ 'è' => 'e',
+ 'È' => 'E',
+ 'ï' => 'i',
+ 'î' => 'i',
+ 'Ï' => 'I',
+ 'Î' => 'I',
+ 'ÿ' => 'y',
+ 'Ÿ' => 'Y',
+ 'ô' => 'o',
+ 'Ô' => 'O',
+ 'ö' => 'o',
+ 'Ö' => 'O',
+ 'û' => 'u',
+ 'Û' => 'U',
+ 'ù' => 'u',
+ 'Ù' => 'U',
+ 'ü' => 'u',
+ 'Ü' => 'U',
+ ],
+ // Switzerland (French)
+ 'fr_ch' => [
+ 'ß' => 'ss',
+ 'ẞ' => 'SS',
+ 'Æ' => 'AE',
+ 'æ' => 'ae',
+ 'Œ' => 'OE',
+ 'œ' => 'oe',
+ 'â' => 'a',
+ 'Â' => 'A',
+ 'à' => 'a',
+ 'À' => 'A',
+ 'ä' => 'a',
+ 'Ä' => 'A',
+ 'ç' => 'c',
+ 'Ç' => 'C',
+ 'é' => 'e',
+ 'É' => 'E',
+ 'ê' => 'e',
+ 'Ê' => 'E',
+ 'ë' => 'e',
+ 'Ë' => 'E',
+ 'è' => 'e',
+ 'È' => 'E',
+ 'ï' => 'i',
+ 'î' => 'i',
+ 'Ï' => 'I',
+ 'Î' => 'I',
+ 'ÿ' => 'y',
+ 'Ÿ' => 'Y',
+ 'ô' => 'o',
+ 'Ô' => 'O',
+ 'ö' => 'o',
+ 'Ö' => 'O',
+ 'û' => 'u',
+ 'Û' => 'U',
+ 'ù' => 'u',
+ 'Ù' => 'U',
+ 'ü' => 'u',
+ 'Ü' => 'U',
+ ],
+ // German
+ 'de' => [
+ 'Ä' => 'Ae',
+ 'Ö' => 'Oe',
+ 'Ü' => 'Ue',
+ 'ä' => 'ae',
+ 'ö' => 'oe',
+ 'ü' => 'ue',
+ 'ß' => 'ss',
+ 'ẞ' => 'SS',
+ ],
+ // Austrian (German)
+ 'de_at' => [
+ 'Ä' => 'Ae',
+ 'Ö' => 'Oe',
+ 'Ü' => 'Ue',
+ 'ä' => 'ae',
+ 'ö' => 'oe',
+ 'ü' => 'ue',
+ 'ß' => 'sz',
+ 'ẞ' => 'SZ',
+ ],
+ // Switzerland (German)
+ 'de_ch' => [
+ 'Ä' => 'Ae',
+ 'Ö' => 'Oe',
+ 'Ü' => 'Ue',
+ 'ä' => 'ae',
+ 'ö' => 'oe',
+ 'ü' => 'ue',
+ 'ß' => 'ss',
+ 'ẞ' => 'SS',
+ ],
+ // Bengali (Bangla)
+ 'bn' => [
+ 'ভ্ল' => 'vl',
+ 'পশ' => 'psh',
+ 'ব্ধ' => 'bdh',
+ 'ব্জ' => 'bj',
+ 'ব্দ' => 'bd',
+ 'ব্ব' => 'bb',
+ 'ব্ল' => 'bl',
+ 'ভ' => 'v',
+ 'ব' => 'b',
+ 'চ্ঞ' => 'cNG',
+ 'চ্ছ' => 'cch',
+ 'চ্চ' => 'cc',
+ 'ছ' => 'ch',
+ 'চ' => 'c',
+ 'ধ্ন' => 'dhn',
+ 'ধ্ম' => 'dhm',
+ 'দ্ঘ' => 'dgh',
+ 'দ্ধ' => 'ddh',
+ 'দ্ভ' => 'dv',
+ 'দ্ম' => 'dm',
+ 'ড্ড' => 'DD',
+ 'ঢ' => 'Dh',
+ 'ধ' => 'dh',
+ 'দ্গ' => 'dg',
+ 'দ্দ' => 'dd',
+ 'ড' => 'D',
+ 'দ' => 'd',
+ '।' => '.',
+ 'ঘ্ন' => 'Ghn',
+ 'গ্ধ' => 'Gdh',
+ 'গ্ণ' => 'GN',
+ 'গ্ন' => 'Gn',
+ 'গ্ম' => 'Gm',
+ 'গ্ল' => 'Gl',
+ 'জ্ঞ' => 'jNG',
+ 'ঘ' => 'Gh',
+ 'গ' => 'g',
+ 'হ্ণ' => 'hN',
+ 'হ্ন' => 'hn',
+ 'হ্ম' => 'hm',
+ 'হ্ল' => 'hl',
+ 'হ' => 'h',
+ 'জ্ঝ' => 'jjh',
+ 'ঝ' => 'jh',
+ 'জ্জ' => 'jj',
+ 'জ' => 'j',
+ 'ক্ষ্ণ' => 'kxN',
+ 'ক্ষ্ম' => 'kxm',
+ 'ক্ষ' => 'ksh',
+ 'কশ' => 'ksh',
+ 'ক্ক' => 'kk',
+ 'ক্ট' => 'kT',
+ 'ক্ত' => 'kt',
+ 'ক্ল' => 'kl',
+ 'ক্স' => 'ks',
+ 'খ' => 'kh',
+ 'ক' => 'k',
+ 'ল্ভ' => 'lv',
+ 'ল্ধ' => 'ldh',
+ 'লখ' => 'lkh',
+ 'লঘ' => 'lgh',
+ 'লফ' => 'lph',
+ 'ল্ক' => 'lk',
+ 'ল্গ' => 'lg',
+ 'ল্ট' => 'lT',
+ 'ল্ড' => 'lD',
+ 'ল্প' => 'lp',
+ 'ল্ম' => 'lm',
+ 'ল্ল' => 'll',
+ 'ল্ব' => 'lb',
+ 'ল' => 'l',
+ 'ম্থ' => 'mth',
+ 'ম্ফ' => 'mf',
+ 'ম্ভ' => 'mv',
+ 'মপ্ল' => 'mpl',
+ 'ম্ন' => 'mn',
+ 'ম্প' => 'mp',
+ 'ম্ম' => 'mm',
+ 'ম্ল' => 'ml',
+ 'ম্ব' => 'mb',
+ 'ম' => 'm',
+ '০' => '0',
+ '১' => '1',
+ '২' => '2',
+ '৩' => '3',
+ '৪' => '4',
+ '৫' => '5',
+ '৬' => '6',
+ '৭' => '7',
+ '৮' => '8',
+ '৯' => '9',
+ 'ঙ্ক্ষ' => 'Ngkx',
+ 'ঞ্ছ' => 'nch',
+ 'ঙ্ঘ' => 'ngh',
+ 'ঙ্খ' => 'nkh',
+ 'ঞ্ঝ' => 'njh',
+ 'ঙ্গৌ' => 'ngOU',
+ 'ঙ্গৈ' => 'ngOI',
+ 'ঞ্চ' => 'nc',
+ 'ঙ্ক' => 'nk',
+ 'ঙ্ষ' => 'Ngx',
+ 'ঙ্গ' => 'ngo',
+ 'ঙ্ম' => 'Ngm',
+ 'ঞ্জ' => 'nj',
+ 'ন্ধ' => 'ndh',
+ 'ন্ঠ' => 'nTh',
+ 'ণ্ঠ' => 'NTh',
+ 'ন্থ' => 'nth',
+ 'ঙ্গা' => 'nga',
+ 'ঙ্গি' => 'ngi',
+ 'ঙ্গী' => 'ngI',
+ 'ঙ্গু' => 'ngu',
+ 'ঙ্গূ' => 'ngU',
+ 'ঙ্গে' => 'nge',
+ 'ঙ্গো' => 'ngO',
+ 'ণ্ঢ' => 'NDh',
+ 'নশ' => 'nsh',
+ 'ঙর' => 'Ngr',
+ 'ঞর' => 'NGr',
+ 'ংর' => 'ngr',
+ 'ঙ' => 'Ng',
+ 'ঞ' => 'NG',
+ 'ং' => 'ng',
+ 'ন্ন' => 'nn',
+ 'ণ্ণ' => 'NN',
+ 'ণ্ন' => 'Nn',
+ 'ন্ম' => 'nm',
+ 'ণ্ম' => 'Nm',
+ 'ন্দ' => 'nd',
+ 'ন্ট' => 'nT',
+ 'ণ্ট' => 'NT',
+ 'ন্ড' => 'nD',
+ 'ণ্ড' => 'ND',
+ 'ন্ত' => 'nt',
+ 'ন্স' => 'ns',
+ 'ন' => 'n',
+ 'ণ' => 'N',
+ 'ৈ' => 'OI',
+ 'ৌ' => 'OU',
+ 'ো' => 'O',
+ 'ঐ' => 'OI',
+ 'ঔ' => 'OU',
+ 'অ' => 'o',
+ 'ও' => 'oo',
+ 'ফ্ল' => 'fl',
+ 'প্ট' => 'pT',
+ 'প্ত' => 'pt',
+ 'প্ন' => 'pn',
+ 'প্প' => 'pp',
+ 'প্ল' => 'pl',
+ 'প্স' => 'ps',
+ 'ফ' => 'f',
+ 'প' => 'p',
+ 'ৃ' => 'rri',
+ 'ঋ' => 'rri',
+ 'রর্য' => 'rry',
+ '্র্য' => 'ry',
+ '্রর' => 'rr',
+ 'ড়্গ' => 'Rg',
+ 'ঢ়' => 'Rh',
+ 'ড়' => 'R',
+ 'র' => 'r',
+ '্র' => 'r',
+ 'শ্ছ' => 'Sch',
+ 'ষ্ঠ' => 'ShTh',
+ 'ষ্ফ' => 'Shf',
+ 'স্ক্ল' => 'skl',
+ 'স্খ' => 'skh',
+ 'স্থ' => 'sth',
+ 'স্ফ' => 'sf',
+ 'শ্চ' => 'Sc',
+ 'শ্ত' => 'St',
+ 'শ্ন' => 'Sn',
+ 'শ্ম' => 'Sm',
+ 'শ্ল' => 'Sl',
+ 'ষ্ক' => 'Shk',
+ 'ষ্ট' => 'ShT',
+ 'ষ্ণ' => 'ShN',
+ 'ষ্প' => 'Shp',
+ 'ষ্ম' => 'Shm',
+ 'স্প্ল' => 'spl',
+ 'স্ক' => 'sk',
+ 'স্ট' => 'sT',
+ 'স্ত' => 'st',
+ 'স্ন' => 'sn',
+ 'স্প' => 'sp',
+ 'স্ম' => 'sm',
+ 'স্ল' => 'sl',
+ 'শ' => 'S',
+ 'ষ' => 'Sh',
+ 'স' => 's',
+ 'ু' => 'u',
+ 'উ' => 'u',
+ 'অ্য' => 'oZ',
+ 'ত্থ' => 'tth',
+ 'ৎ' => 'tt',
+ 'ট্ট' => 'TT',
+ 'ট্ম' => 'Tm',
+ 'ঠ' => 'Th',
+ 'ত্ন' => 'tn',
+ 'ত্ম' => 'tm',
+ 'থ' => 'th',
+ 'ত্ত' => 'tt',
+ 'ট' => 'T',
+ 'ত' => 't',
+ 'অ্যা' => 'AZ',
+ 'া' => 'a',
+ 'আ' => 'a',
+ 'য়া' => 'ya',
+ 'য়' => 'y',
+ 'ি' => 'i',
+ 'ই' => 'i',
+ 'ী' => 'ee',
+ 'ঈ' => 'ee',
+ 'ূ' => 'uu',
+ 'ঊ' => 'uu',
+ 'ে' => 'e',
+ 'এ' => 'e',
+ 'য' => 'z',
+ '্য' => 'Z',
+ 'ইয়' => 'y',
+ 'ওয়' => 'w',
+ '্ব' => 'w',
+ 'এক্স' => 'x',
+ 'ঃ' => ':',
+ 'ঁ' => 'nn',
+ '্' => '',
+ ],
+ // English
+ 'en' => [
+ ],
+ // Latin (+ Cyrillic ?) chars
+ //
+ // -> Mix of languages, but we need to keep this here, so that different languages can handle there own behavior.
+ 'latin' => [
+ '˚' => '0',
+ '¹' => '1',
+ '²' => '2',
+ '³' => '3',
+ '⁴' => '4',
+ '⁵' => '5',
+ '⁶' => '6',
+ '⁷' => '7',
+ '⁸' => '8',
+ '⁹' => '9',
+ '₀' => '0',
+ '₁' => '1',
+ '₂' => '2',
+ '₃' => '3',
+ '₄' => '4',
+ '₅' => '5',
+ '₆' => '6',
+ '₇' => '7',
+ '₈' => '8',
+ '₉' => '9',
+ '௦' => '0',
+ '௧' => '1',
+ '௨' => '2',
+ '௩' => '3',
+ '௪' => '4',
+ '௫' => '5',
+ '௬' => '6',
+ '௭' => '7',
+ '௮' => '8',
+ '௯' => '9',
+ '௰' => '10',
+ '௱' => '100',
+ '௲' => '1000',
+ 'Ꜳ' => 'AA',
+ 'ꜳ' => 'aa',
+ 'Æ' => 'AE',
+ 'æ' => 'ae',
+ 'Ǽ' => 'AE',
+ 'ǽ' => 'ae',
+ 'Ꜵ' => 'AO',
+ 'ꜵ' => 'ao',
+ 'Ꜷ' => 'AU',
+ 'ꜷ' => 'au',
+ 'Ꜹ' => 'AV',
+ 'ꜹ' => 'av',
+ 'Ꜻ' => 'av',
+ 'ꜻ' => 'av',
+ 'Ꜽ' => 'AY',
+ 'ꜽ' => 'ay',
+ 'ȸ' => 'db',
+ 'ʣ' => 'dz',
+ 'ʥ' => 'dz',
+ 'ʤ' => 'dezh',
+ '🙰' => 'et',
+ 'ff' => 'ff',
+ 'ffi' => 'ffi',
+ 'ffl' => 'ffl',
+ 'fi' => 'fi',
+ 'fl' => 'fl',
+ 'ʩ' => 'feng',
+ 'IJ' => 'IJ',
+ 'ij' => 'ij',
+ 'ʪ' => 'ls',
+ 'ʫ' => 'lz',
+ 'ɮ' => 'lezh',
+ 'ȹ' => 'qp',
+ 'ʨ' => 'tc',
+ 'ʦ' => 'ts',
+ 'ʧ' => 'tesh',
+ 'Œ' => 'OE',
+ 'œ' => 'oe',
+ 'Ꝏ' => 'OO',
+ 'ꝏ' => 'oo',
+ 'ẞ' => 'SS',
+ 'ß' => 'ss',
+ 'st' => 'st',
+ 'ſt' => 'st',
+ 'Ꜩ' => 'TZ',
+ 'ꜩ' => 'tz',
+ 'ᵫ' => 'ue',
+ 'Aι' => 'Ai',
+ 'αι' => 'ai',
+ 'Ει' => 'Ei',
+ 'ει' => 'ei',
+ 'Οι' => 'Oi',
+ 'οι' => 'oi',
+ 'Ου' => 'Oy',
+ 'ου' => 'oy',
+ 'Υι' => 'Yi',
+ 'υι' => 'yi',
+ 'ἀ' => 'a',
+ 'ἁ' => 'a',
+ 'ἂ' => 'a',
+ 'ἃ' => 'a',
+ 'ἄ' => 'a',
+ 'ἅ' => 'a',
+ 'ἆ' => 'a',
+ 'ἇ' => 'a',
+ 'Ἀ' => 'A',
+ 'Ἁ' => 'A',
+ 'Ἂ' => 'A',
+ 'Ἃ' => 'A',
+ 'Ἄ' => 'A',
+ 'Ἅ' => 'A',
+ 'Ἆ' => 'A',
+ 'Ἇ' => 'A',
+ 'ᾰ' => 'a',
+ 'ᾱ' => 'a',
+ 'ᾲ' => 'a',
+ 'ᾳ' => 'a',
+ 'ᾴ' => 'a',
+ 'ᾶ' => 'a',
+ 'ᾷ' => 'a',
+ 'Ᾰ' => 'A',
+ 'Ᾱ' => 'A',
+ 'Ὰ' => 'A',
+ 'Ά' => 'A',
+ 'ᾼ' => 'A',
+ 'Ä' => 'A',
+ 'ä' => 'a',
+ 'À' => 'A',
+ 'à' => 'a',
+ 'Á' => 'A',
+ 'á' => 'a',
+ 'Â' => 'A',
+ 'â' => 'a',
+ 'Ã' => 'A',
+ 'ã' => 'a',
+ 'A̧' => 'A',
+ 'a̧' => 'a',
+ 'Ą' => 'A',
+ 'ą' => 'a',
+ 'Ⱥ' => 'A',
+ 'ⱥ' => 'a',
+ 'Å' => 'A',
+ 'å' => 'a',
+ 'Ǻ' => 'A',
+ 'ǻ' => 'a',
+ 'Ă' => 'A',
+ 'ă' => 'a',
+ 'Ǎ' => 'A',
+ 'ǎ' => 'a',
+ 'Ȧ' => 'A',
+ 'ȧ' => 'a',
+ 'Ạ' => 'A',
+ 'ạ' => 'a',
+ 'Ā' => 'A',
+ 'ā' => 'a',
+ 'ª' => 'a',
+ 'Ɓ' => 'B',
+ 'Ѣ' => 'E',
+ 'ѣ' => 'e',
+ 'Ç' => 'C',
+ 'ç' => 'c',
+ 'Ĉ' => 'C',
+ 'ĉ' => 'c',
+ 'C̈' => 'C',
+ 'c̈' => 'c',
+ 'C̨' => 'C',
+ 'c̨' => 'c',
+ 'Ȼ' => 'C',
+ 'ȼ' => 'c',
+ 'Č' => 'C',
+ 'č' => 'c',
+ 'Ć' => 'C',
+ 'ć' => 'c',
+ 'C̀' => 'C',
+ 'c̀' => 'c',
+ 'Ċ' => 'C',
+ 'ċ' => 'c',
+ 'C̣' => 'C',
+ 'c̣' => 'c',
+ 'C̄' => 'C',
+ 'c̄' => 'c',
+ 'C̃' => 'C',
+ 'c̃' => 'c',
+ 'Ð' => 'D',
+ 'Đ' => 'D',
+ 'ð' => 'd',
+ 'đ' => 'd',
+ 'È' => 'E',
+ 'É' => 'E',
+ 'Ê' => 'E',
+ 'Ë' => 'E',
+ 'Ĕ' => 'E',
+ 'Ė' => 'E',
+ 'Ȩ' => 'E',
+ 'ȩ' => 'e',
+ 'Ę' => 'E',
+ 'ę' => 'e',
+ 'Ɇ' => 'E',
+ 'ɇ' => 'e',
+ 'Ě' => 'E',
+ 'ě' => 'e',
+ 'Ẹ' => 'E',
+ 'ẹ' => 'e',
+ 'Ē' => 'E',
+ 'ē' => 'e',
+ 'Ẽ' => 'E',
+ 'ẽ' => 'e',
+ 'è' => 'e',
+ 'é' => 'e',
+ 'ê' => 'e',
+ 'ë' => 'e',
+ 'ĕ' => 'e',
+ 'ė' => 'e',
+ 'ƒ' => 'f',
+ 'Ѳ' => 'F',
+ 'ѳ' => 'f',
+ 'Ĝ' => 'G',
+ 'Ġ' => 'G',
+ 'ĝ' => 'g',
+ 'ġ' => 'g',
+ 'Ĥ' => 'H',
+ 'Ħ' => 'H',
+ 'ĥ' => 'h',
+ 'ħ' => 'h',
+ 'Ì' => 'I',
+ 'Í' => 'I',
+ 'Î' => 'I',
+ 'Ï' => 'I',
+ 'Ĩ' => 'I',
+ 'Ĭ' => 'I',
+ 'Ǐ' => 'I',
+ 'Į' => 'I',
+ 'ì' => 'i',
+ 'í' => 'i',
+ 'î' => 'i',
+ 'ï' => 'i',
+ 'ĩ' => 'i',
+ 'ĭ' => 'i',
+ 'ǐ' => 'i',
+ 'į' => 'i',
+ 'І' => 'I',
+ 'і' => 'i',
+ 'I̧' => 'I',
+ 'i̧' => 'i',
+ 'Ɨ' => 'I',
+ 'ɨ' => 'i',
+ 'İ' => 'I',
+ 'i' => 'i',
+ 'Ị' => 'I',
+ 'ị' => 'i',
+ 'Ī' => 'I',
+ 'ī' => 'i',
+ 'Ĵ' => 'J',
+ 'ĵ' => 'j',
+ 'J́́' => 'J',
+ 'j́' => 'j',
+ 'J̀̀' => 'J',
+ 'j̀' => 'j',
+ 'J̈' => 'J',
+ 'j̈' => 'j',
+ 'J̧' => 'J',
+ 'j̧' => 'j',
+ 'J̨' => 'J',
+ 'j̨' => 'j',
+ 'Ɉ' => 'J',
+ 'ɉ' => 'j',
+ 'J̌' => 'J',
+ 'ǰ' => 'j',
+ 'J̇' => 'J',
+ 'j' => 'j',
+ 'J̣' => 'J',
+ 'j̣' => 'j',
+ 'J̄' => 'J',
+ 'j̄' => 'j',
+ 'J̃' => 'J',
+ 'j̃' => 'j',
+ 'Й' => 'i',
+ 'й' => 'i',
+ 'ĸ' => 'k',
+ 'Ĺ' => 'L',
+ 'Ľ' => 'L',
+ 'Ŀ' => 'L',
+ 'ĺ' => 'l',
+ 'ľ' => 'l',
+ 'ŀ' => 'l',
+ 'L̀' => 'L',
+ 'l̀' => 'l',
+ 'L̂' => 'L',
+ 'l̂' => 'l',
+ 'L̈' => 'L',
+ 'l̈' => 'l',
+ 'Ļ' => 'L',
+ 'ļ' => 'l',
+ 'L̨' => 'L',
+ 'l̨' => 'l',
+ 'Ł' => 'L',
+ 'ł' => 'l',
+ 'Ƚ' => 'L',
+ 'ƚ' => 'l',
+ 'L̇' => 'L',
+ 'l̇' => 'l',
+ 'Ḷ' => 'L',
+ 'ḷ' => 'l',
+ 'L̄' => 'L',
+ 'l̄' => 'l',
+ 'L̃' => 'L',
+ 'l̃' => 'l',
+ 'Ñ' => 'N',
+ 'ñ' => 'n',
+ 'Ŋ' => 'N',
+ 'ŋ' => 'n',
+ 'ʼn' => 'n',
+ 'Ń' => 'N',
+ 'ń' => 'n',
+ 'Ǹ' => 'N',
+ 'ǹ' => 'n',
+ 'N̂' => 'N',
+ 'n̂' => 'n',
+ 'N̈' => 'N',
+ 'n̈' => 'n',
+ 'Ņ' => 'N',
+ 'ņ' => 'n',
+ 'N̨' => 'N',
+ 'n̨' => 'n',
+ 'Ꞥ' => 'N',
+ 'ꞥ' => 'n',
+ 'Ň' => 'N',
+ 'ň' => 'n',
+ 'Ṅ' => 'N',
+ 'ṅ' => 'n',
+ 'Ṇ' => 'N',
+ 'ṇ' => 'n',
+ 'N̄' => 'N',
+ 'n̄' => 'n',
+ 'Ö' => 'O',
+ 'Ò' => 'O',
+ 'Ó' => 'O',
+ 'Ô' => 'O',
+ 'Õ' => 'O',
+ 'Ō' => 'O',
+ 'Ŏ' => 'O',
+ 'Ǒ' => 'O',
+ 'Ő' => 'O',
+ 'Ơ' => 'O',
+ 'Ø' => 'O',
+ 'Ǿ' => 'O',
+ 'ö' => 'o',
+ 'ò' => 'o',
+ 'ó' => 'o',
+ 'ô' => 'o',
+ 'õ' => 'o',
+ 'ō' => 'o',
+ 'ŏ' => 'o',
+ 'ǒ' => 'o',
+ 'ő' => 'o',
+ 'ơ' => 'o',
+ 'ø' => 'o',
+ 'ǿ' => 'o',
+ 'º' => 'o',
+ 'O̧' => 'O',
+ 'o̧' => 'o',
+ 'Ǫ' => 'O',
+ 'ǫ' => 'o',
+ 'Ɵ' => 'O',
+ 'ɵ' => 'o',
+ 'Ȯ' => 'O',
+ 'ȯ' => 'o',
+ 'Ọ' => 'O',
+ 'ọ' => 'o',
+ 'Ŕ' => 'R',
+ 'Ŗ' => 'R',
+ 'ŕ' => 'r',
+ 'ŗ' => 'r',
+ 'Ŝ' => 'S',
+ 'Ș' => 'S',
+ 'ș' => 's',
+ 'Ś' => 'S',
+ 'ś' => 's',
+ 'S̀' => 'S',
+ 's̀' => 's',
+ 'Ŝ̀' => 'S',
+ 'ŝ' => 's',
+ 'S̈' => 'S',
+ 's̈' => 's',
+ 'Ş' => 'S',
+ 'ş' => 's',
+ 'S̨' => 'S',
+ 's̨' => 's',
+ 'Ꞩ' => 'S',
+ 'ꞩ' => 's',
+ 'Š' => 'S',
+ 'š' => 's',
+ 'Ṡ' => 'S',
+ 'ṡ' => 's',
+ 'Ṣ' => 'S',
+ 'ṣ' => 's',
+ 'S̄' => 'S',
+ 's̄' => 's',
+ 'S̃' => 'S',
+ 's̃' => 's',
+ 'ſ' => 's',
+ 'Ţ' => 'T',
+ 'Ț' => 'T',
+ 'Ŧ' => 'T',
+ 'Þ' => 'TH',
+ 'ţ' => 't',
+ 'ț' => 't',
+ 'ŧ' => 't',
+ 'þ' => 'th',
+ 'T́' => 'T',
+ 't́' => 't',
+ 'T̀' => 'T',
+ 't̀' => 't',
+ 'T̂' => 'T',
+ 't̂' => 't',
+ 'T̈' => 'T',
+ 'ẗ' => 't',
+ 'T̨' => 'T',
+ 't̨' => 't',
+ 'Ⱦ' => 'T',
+ 'ⱦ' => 't',
+ 'Ť' => 'T',
+ 'ť' => 't',
+ 'Ṫ' => 'T',
+ 'ṫ' => 't',
+ 'Ṭ' => 'T',
+ 'ṭ' => 't',
+ 'T̄' => 'T',
+ 't̄' => 't',
+ 'T̃' => 'T',
+ 't̃' => 't',
+ 'Ü' => 'U',
+ 'Ù' => 'U',
+ 'Ú' => 'U',
+ 'Û' => 'U',
+ 'Ũ' => 'U',
+ 'Ŭ' => 'U',
+ 'Ű' => 'U',
+ 'Ų' => 'U',
+ 'Ư' => 'U',
+ 'Ǔ' => 'U',
+ 'Ǖ' => 'U',
+ 'Ǘ' => 'U',
+ 'Ǚ' => 'U',
+ 'Ǜ' => 'U',
+ 'ü' => 'u',
+ 'ù' => 'u',
+ 'ú' => 'u',
+ 'û' => 'u',
+ 'ũ' => 'u',
+ 'ŭ' => 'u',
+ 'ű' => 'u',
+ 'ų' => 'u',
+ 'ư' => 'u',
+ 'ǔ' => 'u',
+ 'ǖ' => 'u',
+ 'ǘ' => 'u',
+ 'ǚ' => 'u',
+ 'ǜ' => 'u',
+ 'U̧' => 'U',
+ 'u̧' => 'u',
+ 'Ʉ' => 'U',
+ 'ʉ' => 'u',
+ 'U̇' => 'U',
+ 'u̇' => 'u',
+ 'Ụ' => 'U',
+ 'ụ' => 'u',
+ 'Ū' => 'U',
+ 'ū' => 'u',
+ 'Ʊ' => 'U',
+ 'ʊ' => 'u',
+ 'Ŵ' => 'W',
+ 'ŵ' => 'w',
+ 'Ẁ' => 'W',
+ 'ẁ' => 'w',
+ 'Ẃ' => 'W',
+ 'ẃ' => 'w',
+ 'Ẅ' => 'W',
+ 'ẅ' => 'w',
+ 'Ѵ' => 'I',
+ 'ѵ' => 'i',
+ 'Ꙗ' => 'Ja',
+ 'ꙗ' => 'ja',
+ 'Є' => 'Je',
+ 'є' => 'je',
+ 'Ѥ' => 'Je',
+ 'ѥ' => 'je',
+ 'Ѕ' => 'Dz',
+ 'ѕ' => 'dz',
+ 'Ꙋ' => 'U',
+ 'ꙋ' => 'u',
+ 'Ѡ' => 'O',
+ 'ѡ' => 'o',
+ 'Ѿ' => 'Ot',
+ 'ѿ' => 'ot',
+ 'Ѫ' => 'U',
+ 'ѫ' => 'u',
+ 'Ѧ' => 'Ja',
+ 'ѧ' => 'ja',
+ 'Ѭ' => 'Ju',
+ 'ѭ' => 'ju',
+ 'Ѩ' => 'Ja',
+ 'ѩ' => 'Ja',
+ 'Ѯ' => 'Ks',
+ 'ѯ' => 'ks',
+ 'Ѱ' => 'Ps',
+ 'ѱ' => 'ps',
+ 'Х' => 'X',
+ 'х' => 'x',
+ 'Ý' => 'Y',
+ 'Ÿ' => 'Y',
+ 'Ŷ' => 'Y',
+ 'ý' => 'y',
+ 'ÿ' => 'y',
+ 'ŷ' => 'y',
+ 'Ỳ' => 'Y',
+ 'ỳ' => 'y',
+ 'Y̧' => 'Y',
+ 'y̧' => 'y',
+ 'Y̨' => 'Y',
+ 'y̨' => 'y',
+ 'Ɏ' => 'Y',
+ 'ɏ' => 'y',
+ 'Y̌' => 'Y',
+ 'y̌' => 'y',
+ 'Ẏ' => 'Y',
+ 'ẏ' => 'y',
+ 'Ỵ' => 'Y',
+ 'ỵ' => 'y',
+ 'Ȳ' => 'Y',
+ 'ȳ' => 'y',
+ 'Ỹ' => 'Y',
+ 'ỹ' => 'y',
+ 'Щ' => 'Shh',
+ 'щ' => 'shh',
+ 'Ź' => 'Z',
+ 'ź' => 'z',
+ 'Z̀' => 'Z',
+ 'z̀' => 'z',
+ 'Ẑ' => 'Z',
+ 'ẑ' => 'z',
+ 'Z̈' => 'Z',
+ 'z̈' => 'z',
+ 'Z̧' => 'Z',
+ 'z̧' => 'z',
+ 'Z̨' => 'Z',
+ 'z̨' => 'z',
+ 'Ƶ' => 'Z',
+ 'ƶ' => 'z',
+ 'Ž' => 'Z',
+ 'ž' => 'z',
+ 'Ż' => 'Z',
+ 'ż' => 'z',
+ 'Ẓ' => 'Z',
+ 'ẓ' => 'z',
+ 'Z̄' => 'Z',
+ 'z̄' => 'z',
+ 'Z̃' => 'Z',
+ 'z̃' => 'z',
+ ],
+ // whitespace chars
+ ' ' => [
+ "\xc2\xa0" => ' ', // 'NO-BREAK SPACE'
+ "\xe1\x9a\x80" => ' ', // 'OGHAM SPACE MARK'
+ "\xe2\x80\x80" => ' ', // 'EN QUAD'
+ "\xe2\x80\x81" => ' ', // 'EM QUAD'
+ "\xe2\x80\x82" => ' ', // 'EN SPACE'
+ "\xe2\x80\x83" => ' ', // 'EM SPACE'
+ "\xe2\x80\x84" => ' ', // 'THREE-PER-EM SPACE'
+ "\xe2\x80\x85" => ' ', // 'FOUR-PER-EM SPACE'
+ "\xe2\x80\x86" => ' ', // 'SIX-PER-EM SPACE'
+ "\xe2\x80\x87" => ' ', // 'FIGURE SPACE'
+ "\xe2\x80\x88" => ' ', // 'PUNCTUATION SPACE'
+ "\xe2\x80\x89" => ' ', // 'THIN SPACE'
+ "\xe2\x80\x8a" => ' ', // 'HAIR SPACE'
+ "\xe2\x80\xa8" => ' ', // 'LINE SEPARATOR'
+ "\xe2\x80\xa9" => ' ', // 'PARAGRAPH SEPARATOR'
+ "\xe2\x80\x8b" => ' ', // 'ZERO WIDTH SPACE'
+ "\xe2\x80\xaf" => ' ', // 'NARROW NO-BREAK SPACE'
+ "\xe2\x81\x9f" => ' ', // 'MEDIUM MATHEMATICAL SPACE'
+ "\xe3\x80\x80" => ' ', // 'IDEOGRAPHIC SPACE'
+ "\xef\xbe\xa0" => ' ', // 'HALFWIDTH HANGUL FILLER'
+ ],
+ // commonly used in Word documents
+ 'msword' => [
+ "\xc2\xab" => '<<', // « (U+00AB) in UTF-8
+ "\xc2\xbb" => '>>', // » (U+00BB) in UTF-8
+ "\xe2\x80\x98" => "'", // ‘ (U+2018) in UTF-8
+ "\xe2\x80\x99" => "'", // ’ (U+2019) in UTF-8
+ "\xe2\x80\x9a" => "'", // ‚ (U+201A) in UTF-8
+ "\xe2\x80\x9b" => "'", // ‛ (U+201B) in UTF-8
+ "\xe2\x80\x9c" => '"', // “ (U+201C) in UTF-8
+ "\xe2\x80\x9d" => '"', // ” (U+201D) in UTF-8
+ "\xe2\x80\x9e" => '"', // „ (U+201E) in UTF-8
+ "\xe2\x80\x9f" => '"', // ‟ (U+201F) in UTF-8
+ "\xe2\x80\xb9" => "'", // ‹ (U+2039) in UTF-8
+ "\xe2\x80\xba" => "'", // › (U+203A) in UTF-8
+ "\xe2\x80\x93" => '-', // – (U+2013) in UTF-8
+ "\xe2\x80\x94" => '-', // — (U+2014) in UTF-8
+ "\xe2\x80\xa6" => '...', // … (U+2026) in UTF-8
+ ],
+ // Currency
+ //
+ // url => https://en.wikipedia.org/wiki/Currency_symbol
+ 'currency_short' => [
+ '€' => 'EUR',
+ '$' => '$',
+ '₢' => 'Cr',
+ '₣' => 'Fr.',
+ '£' => 'PS',
+ '₤' => 'L.',
+ 'ℳ' => 'M',
+ '₥' => 'mil',
+ '₦' => 'N',
+ '₧' => 'Pts',
+ '₨' => 'Rs',
+ 'රු' => 'LKR',
+ 'ரூ' => 'LKR',
+ '௹' => 'Rs',
+ 'रू' => 'NPR',
+ '₹' => 'Rs',
+ '૱' => 'Rs',
+ '₩' => 'W',
+ '₪' => 'NS',
+ '₸' => 'KZT',
+ '₫' => 'D',
+ '֏' => 'AMD',
+ '₭' => 'K',
+ '₺' => 'TL',
+ '₼' => 'AZN',
+ '₮' => 'T',
+ '₯' => 'Dr',
+ '₲' => 'PYG',
+ '₾' => 'GEL',
+ '₳' => 'ARA',
+ '₴' => 'UAH',
+ '₽' => 'RUB',
+ '₵' => 'GHS',
+ '₡' => 'CL',
+ '¢' => 'c',
+ '¥' => 'YEN',
+ '円' => 'JPY',
+ '৳' => 'BDT',
+ '元' => 'CNY',
+ '﷼' => 'SAR',
+ '៛' => 'KR',
+ '₠' => 'ECU',
+ '¤' => '$?',
+ '฿' => 'THB',
+ '؋' => 'AFN',
+ ],
+];
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/data/ascii_extras_by_languages.php b/system/vendor/voku/portable-ascii/src/voku/helper/data/ascii_extras_by_languages.php
new file mode 100644
index 0000000..afe31ae
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/data/ascii_extras_by_languages.php
@@ -0,0 +1,759 @@
+ [
+ '=' => ' gelijk ',
+ '%' => ' procent ',
+ '∑' => ' som ',
+ '∆' => ' delta ',
+ '∞' => ' oneindig ',
+ '♥' => ' love ',
+ '&' => ' en ',
+ '+' => ' plus ',
+ ],
+ // Italian
+ 'it' => [
+ '=' => ' uguale ',
+ '%' => ' percent ',
+ '∑' => ' somma ',
+ '∆' => ' delta ',
+ '∞' => ' infinito ',
+ '♥' => ' amore ',
+ '&' => ' e ',
+ '+' => ' piu ',
+ ],
+ // Macedonian
+ 'mk' => [
+ '=' => ' ednakva ',
+ '%' => ' procenti ',
+ '∑' => ' zbir ',
+ '∆' => ' delta ',
+ '∞' => ' beskonecnost ',
+ '♥' => ' loveubov ',
+ '&' => ' i ',
+ '+' => ' plus ',
+ ],
+ // Portuguese (Brazil)
+ 'pt' => [
+ '=' => ' igual ',
+ '%' => ' por cento ',
+ '∑' => ' soma ',
+ '∆' => ' delta ',
+ '∞' => ' infinito ',
+ '♥' => ' amor ',
+ '&' => ' e ',
+ '+' => ' mais ',
+ ],
+ // Greek(lish) (Elláda)
+ 'el__greeklish' => [
+ '=' => ' isos ',
+ '%' => ' tois ekato ',
+ '∑' => ' athroisma ',
+ '∆' => ' delta ',
+ '∞' => ' apeiro ',
+ '♥' => ' agape ',
+ '&' => ' kai ',
+ '+' => ' syn ',
+ ],
+ // Greek (Elláda)
+ 'el' => [
+ '=' => ' isos ',
+ '%' => ' tois ekato ',
+ '∑' => ' athroisma ',
+ '∆' => ' delta ',
+ '∞' => ' apeiro ',
+ '♥' => ' agape ',
+ '&' => ' kai ',
+ '+' => ' syn ',
+ ],
+ // Hindi
+ 'hi' => [
+ '=' => ' samana ',
+ '%' => ' paratisata ',
+ '∑' => ' yoga ',
+ '∆' => ' dalata ',
+ '∞' => ' anata ',
+ '♥' => ' payara ',
+ '&' => ' aura ',
+ '+' => ' palasa ',
+ ],
+ // Armenian
+ 'hy' => [
+ '=' => ' havasar ',
+ '%' => ' tvokvos ',
+ '∑' => ' gvoumar ',
+ '∆' => ' delta ',
+ '∞' => ' ansahmanvouthyvoun ',
+ '♥' => ' ser ',
+ '&' => ' ev ',
+ '+' => ' gvoumarats ',
+ ],
+ // Swedish
+ 'sv' => [
+ '=' => ' lika ',
+ '%' => ' procent ',
+ '∑' => ' summa ',
+ '∆' => ' delta ',
+ '∞' => ' oandlighet ',
+ '♥' => ' alskar ',
+ '&' => ' och ',
+ '+' => ' plus ',
+ ],
+ // Turkmen
+ 'tk' => [
+ '=' => ' den ',
+ '%' => ' yuzde ',
+ '∑' => ' jem ',
+ '∆' => ' delta ',
+ '∞' => ' mudimilik ',
+ '♥' => ' soygi ',
+ '&' => ' we ',
+ '+' => ' yzy ',
+ ],
+ // Turkish
+ 'tr' => [
+ '=' => ' esit ',
+ '%' => ' yuzde ',
+ '∑' => ' Toplam ',
+ '∆' => ' delta ',
+ '∞' => ' sonsuzluk ',
+ '♥' => ' ask ',
+ '&' => ' ve ',
+ '+' => ' arti ',
+ ],
+ // Bulgarian
+ 'bg' => [
+ '=' => ' raven ',
+ '%' => ' na sto ',
+ '∑' => ' suma ',
+ '∆' => ' delta ',
+ '∞' => ' bezkrajnost ',
+ '♥' => ' obicam ',
+ '&' => ' i ',
+ '+' => ' plus ',
+ ],
+ // Hungarian
+ 'hu' => [
+ '=' => ' Egyenlo ',
+ '%' => ' Szazalek ',
+ '∑' => ' osszeg ',
+ '∆' => ' delta ',
+ '∞' => ' vegtelenitett ',
+ '♥' => ' love ',
+ '&' => ' Es ',
+ '+' => ' Plusz ',
+ ],
+ // Myanmar (Burmese)
+ 'my' => [
+ '=' => ' ttn:ttnnym? ',
+ '%' => ' raakhngnn:k ',
+ '∑' => ' ld ',
+ '∆' => ' m?cwk?n:pe? ',
+ '∞' => ' ach:m ',
+ '♥' => ' mettttaa ',
+ '&' => ' n ',
+ '+' => ' ape?ng: ',
+ ],
+ // Croatian (Hrvatska)
+ 'hr' => [
+ '=' => ' Jednaki ',
+ '%' => ' Posto ',
+ '∑' => ' zbroj ',
+ '∆' => ' Delta ',
+ '∞' => ' beskonacno ',
+ '♥' => ' ljubav ',
+ '&' => ' I ',
+ '+' => ' Plus ',
+ ],
+ // Finnish
+ 'fi' => [
+ '=' => ' Sama ',
+ '%' => ' Prosenttia ',
+ '∑' => ' sum ',
+ '∆' => ' delta ',
+ '∞' => ' aareton ',
+ '♥' => ' rakkautta ',
+ '&' => ' Ja ',
+ '+' => ' Plus ',
+ ],
+ // Georgian (Kartvelian)
+ 'ka' => [
+ '=' => ' tanasts\'ori ',
+ '%' => ' p\'rotsent\'i ',
+ '∑' => ' tankha ',
+ '∆' => ' delt\'a ',
+ '∞' => ' usasrulo ',
+ '♥' => ' siq\'varuli ',
+ '&' => ' da ',
+ '+' => ' p\'lus ',
+ ],
+ // Russian
+ 'ru' => [
+ '=' => ' ravnyj ',
+ '%' => ' procent ',
+ '∑' => ' summa ',
+ '∆' => ' del\'ta ',
+ '∞' => ' beskonecnost\' ',
+ '♥' => ' lublu ',
+ '&' => ' i ',
+ '+' => ' plus ',
+ ],
+ // Russian - GOST 7.79-2000(B)
+ 'ru__gost_2000_b' => [
+ '=' => ' ravnyj ',
+ '%' => ' procent ',
+ '∑' => ' summa ',
+ '∆' => ' del\'ta ',
+ '∞' => ' beskonecnost\' ',
+ '♥' => ' lublu ',
+ '&' => ' i ',
+ '+' => ' plus ',
+ ],
+ // Russian - Passport (2013), ICAO
+ 'ru__passport_2013' => [
+ '=' => ' ravnyj ',
+ '%' => ' procent ',
+ '∑' => ' summa ',
+ '∆' => ' del\'ta ',
+ '∞' => ' beskonecnost\' ',
+ '♥' => ' lublu ',
+ '&' => ' i ',
+ '+' => ' plus ',
+ ],
+ // Ukrainian
+ 'uk' => [
+ '=' => ' rivnij ',
+ '%' => ' vidsotkiv ',
+ '∑' => ' suma ',
+ '∆' => ' del\'ta ',
+ '∞' => ' neskincennist\' ',
+ '♥' => ' lubov ',
+ '&' => ' i ',
+ '+' => ' plus ',
+ ],
+ // Kazakh
+ 'kk' => [
+ '=' => ' ten\' ',
+ '%' => ' Pajyzdar ',
+ '∑' => ' zalpy ',
+ '∆' => ' ajyrmasylyk, ',
+ '∞' => ' seksiz ',
+ '♥' => ' mahabbat ',
+ '&' => ' z@ne ',
+ '+' => ' plus ',
+ ],
+ // Czech
+ 'cs' => [
+ '=' => ' rovnat se ',
+ '%' => ' procento ',
+ '∑' => ' soucet ',
+ '∆' => ' delta ',
+ '∞' => ' nekonecno ',
+ '♥' => ' laska ',
+ '&' => ' a ',
+ '+' => ' plus ',
+ ],
+ // Danish
+ 'da' => [
+ '=' => ' Lige ',
+ '%' => ' Prozent ',
+ '∑' => ' sum ',
+ '∆' => ' delta ',
+ '∞' => ' uendelig ',
+ '♥' => ' kaerlighed ',
+ '&' => ' Og ',
+ '+' => ' Plus ',
+ ],
+ // Polish
+ 'pl' => [
+ '=' => ' rowny ',
+ '%' => ' procent ',
+ '∑' => ' suma ',
+ '∆' => ' delta ',
+ '∞' => ' nieskonczonosc ',
+ '♥' => ' milosc ',
+ '&' => ' i ',
+ '+' => ' plus ',
+ ],
+ // Romanian
+ 'ro' => [
+ '=' => ' egal ',
+ '%' => ' la suta ',
+ '∑' => ' suma ',
+ '∆' => ' delta ',
+ '∞' => ' infinit ',
+ '♥' => ' dragoste ',
+ '&' => ' si ',
+ '+' => ' la care se adauga ',
+ ],
+ // Esperanto
+ 'eo' => [
+ '=' => ' Egalaj ',
+ '%' => ' Procento ',
+ '∑' => ' sumo ',
+ '∆' => ' delto ',
+ '∞' => ' senfina ',
+ '♥' => ' amo ',
+ '&' => ' Kaj ',
+ '+' => ' Pli ',
+ ],
+ // Estonian
+ 'et' => [
+ '=' => ' Vordsed ',
+ '%' => ' Protsenti ',
+ '∑' => ' summa ',
+ '∆' => ' o ',
+ '∞' => ' loputut ',
+ '♥' => ' armastus ',
+ '&' => ' Ja ',
+ '+' => ' Pluss ',
+ ],
+ // Latvian
+ 'lv' => [
+ '=' => ' vienads ',
+ '%' => ' procents ',
+ '∑' => ' summa ',
+ '∆' => ' delta ',
+ '∞' => ' bezgaliba ',
+ '♥' => ' milestiba ',
+ '&' => ' un ',
+ '+' => ' pluss ',
+ ],
+ // Lithuanian
+ 'lt' => [
+ '=' => ' lygus ',
+ '%' => ' procentu ',
+ '∑' => ' suma ',
+ '∆' => ' delta ',
+ '∞' => ' begalybe ',
+ '♥' => ' meile ',
+ '&' => ' ir ',
+ '+' => ' plius ',
+ ],
+ // Norwegian
+ 'no' => [
+ '=' => ' Lik ',
+ '%' => ' Prosent ',
+ '∑' => ' sum ',
+ '∆' => ' delta ',
+ '∞' => ' uendelig ',
+ '♥' => ' kjaerlighet ',
+ '&' => ' Og ',
+ '+' => ' Pluss ',
+ ],
+ // Vietnamese
+ 'vi' => [
+ '=' => ' cong bang ',
+ '%' => ' phan tram ',
+ '∑' => ' tong so ',
+ '∆' => ' dong bang ',
+ '∞' => ' vo cuc ',
+ '♥' => ' Yeu ',
+ '&' => ' va ',
+ '+' => ' them ',
+ ],
+ // Arabic
+ 'ar' => [
+ '=' => ' mtsawy ',
+ '%' => ' nsbh mywyh ',
+ '∑' => ' mjmw\' ',
+ '∆' => ' dlta ',
+ '∞' => ' ma la nhayt ',
+ '♥' => ' hb ',
+ '&' => ' w ',
+ '+' => ' zayd ',
+ ],
+ // Persian (Farsi)
+ 'fa' => [
+ '=' => ' brabr ',
+ '%' => ' dr sd ',
+ '∑' => ' mjmw\' ',
+ '∆' => ' dlta ',
+ '∞' => ' by nhayt ',
+ '♥' => ' \'shq ',
+ '&' => ' w ',
+ '+' => ' bh \'lawh ',
+ ],
+ // Serbian
+ 'sr' => [
+ '=' => ' jednak ',
+ '%' => ' procenat ',
+ '∑' => ' zbir ',
+ '∆' => ' delta ',
+ '∞' => ' beskraj ',
+ '♥' => ' lubav ',
+ '&' => ' i ',
+ '+' => ' vise ',
+ ],
+ // Serbian - Cyrillic
+ 'sr__cyr' => [
+ '=' => ' jednak ',
+ '%' => ' procenat ',
+ '∑' => ' zbir ',
+ '∆' => ' delta ',
+ '∞' => ' beskraj ',
+ '♥' => ' lubav ',
+ '&' => ' i ',
+ '+' => ' vise ',
+ ],
+ // Serbian - Latin
+ 'sr__lat' => [
+ '=' => ' jednak ',
+ '%' => ' procenat ',
+ '∑' => ' zbir ',
+ '∆' => ' delta ',
+ '∞' => ' beskraj ',
+ '♥' => ' lubav ',
+ '&' => ' i ',
+ '+' => ' vise ',
+ ],
+ // Azerbaijani
+ 'az' => [
+ '=' => ' b@rab@r ',
+ '%' => ' faiz ',
+ '∑' => ' m@bl@g ',
+ '∆' => ' delta ',
+ '∞' => ' sonsuzluq ',
+ '♥' => ' sevgi ',
+ '&' => ' v@ ',
+ '+' => ' plus ',
+ ],
+ // Slovak
+ 'sk' => [
+ '=' => ' rovny ',
+ '%' => ' percento ',
+ '∑' => ' sucet ',
+ '∆' => ' delta ',
+ '∞' => ' infinity ',
+ '♥' => ' milovat ',
+ '&' => ' a ',
+ '+' => ' viac ',
+ ],
+ // French
+ 'fr' => [
+ '=' => ' Egal ',
+ '%' => ' Pourcentage ',
+ '∑' => ' somme ',
+ '∆' => ' delta ',
+ '∞' => ' infini ',
+ '♥' => ' amour ',
+ '&' => ' Et ',
+ '+' => ' Plus ',
+ ],
+ // Austrian (French)
+ 'fr_at' => [
+ '=' => ' Egal ',
+ '%' => ' Pourcentage ',
+ '∑' => ' somme ',
+ '∆' => ' delta ',
+ '∞' => ' infini ',
+ '♥' => ' amour ',
+ '&' => ' Et ',
+ '+' => ' Plus ',
+ ],
+ // Switzerland (French)
+ 'fr_ch' => [
+ '=' => ' Egal ',
+ '%' => ' Pourcentage ',
+ '∑' => ' somme ',
+ '∆' => ' delta ',
+ '∞' => ' infini ',
+ '♥' => ' amour ',
+ '&' => ' Et ',
+ '+' => ' Plus ',
+ ],
+ // German
+ 'de' => [
+ '=' => ' gleich ',
+ '%' => ' Prozent ',
+ '∑' => ' gesamt ',
+ '∆' => ' Unterschied ',
+ '∞' => ' undendlich ',
+ '♥' => ' liebe ',
+ '&' => ' und ',
+ '+' => ' plus ',
+ ],
+ // Austrian (German)
+ 'de_at' => [
+ '=' => ' gleich ',
+ '%' => ' Prozent ',
+ '∑' => ' gesamt ',
+ '∆' => ' Unterschied ',
+ '∞' => ' undendlich ',
+ '♥' => ' liebe ',
+ '&' => ' und ',
+ '+' => ' plus ',
+ ],
+ // Switzerland (German)
+ 'de_ch' => [
+ '=' => ' gleich ',
+ '%' => ' Prozent ',
+ '∑' => ' gesamt ',
+ '∆' => ' Unterschied ',
+ '∞' => ' undendlich ',
+ '♥' => ' liebe ',
+ '&' => ' und ',
+ '+' => ' plus ',
+ ],
+ // Bengali (Bangla)
+ 'bn' => [
+ '=' => ' Saman ',
+ '%' => ' Satakora ',
+ '∑' => ' Samasti ',
+ '∆' => ' Badhip ',
+ '∞' => ' Ananta ',
+ '♥' => ' Valobasa ',
+ '&' => ' Abong ',
+ '+' => ' Songzojon ',
+ ],
+ // English
+ 'en' => [
+ '=' => ' equal ',
+ '%' => ' percent ',
+ '∑' => ' sum ',
+ '∆' => ' delta ',
+ '∞' => ' infinity ',
+ '♥' => ' love ',
+ '&' => ' and ',
+ '+' => ' plus ',
+ ],
+ // Currency
+ //
+ // url: https://en.wikipedia.org/wiki/Currency_symbol
+ 'currency' => [
+ '€' => ' Euro ',
+ '$' => ' Dollar ',
+ '₢' => ' cruzeiro ',
+ '₣' => ' French franc ',
+ '£' => ' pound ',
+ '₤' => ' lira ', // Italian
+ '₶' => ' livre tournois ',
+ 'ℳ' => ' mark ',
+ '₥' => ' mill ',
+ '₦' => ' naira ',
+ '₧' => ' peseta ',
+ '₨' => ' rupee ',
+ 'රු' => ' rupee ', // Sri Lankan
+ 'ரூ' => ' rupee ', // Sri Lankan
+ '௹' => ' rupee ', // Tamil
+ 'रू' => ' rupee ', // Nepalese
+ '₹' => ' rupee ', // Indian
+ '૱' => ' rupee ', // Gujarat
+ '₩' => ' won ',
+ '₪' => ' new shequel ',
+ '₸' => ' tenge ',
+ '₫' => ' dong ',
+ '֏' => ' dram ',
+ '₭' => ' kip ',
+ '₺' => ' lira ', // Turkish
+ '₼' => ' manat ',
+ '₮' => ' tugrik ',
+ '₯' => ' drachma ',
+ '₰' => ' pfennig ',
+ '₷' => ' spesmilo ',
+ '₱' => ' peso ', // Philippine
+ '﷼' => ' riyal ',
+ '₲' => ' guarani ',
+ '₾' => ' lari ',
+ '₳' => ' austral ',
+ '₴' => ' hryvnia ',
+ '₽' => ' ruble ',
+ '₵' => ' cedi ',
+ '₡' => ' colon ',
+ '¢' => ' cent ',
+ '¥' => ' yen ',
+ '円' => ' yen ',
+ '৳' => ' taka ',
+ '元' => ' yuan ',
+ '﷼' => ' riyal ',
+ '៛' => ' riel ',
+ '₠' => ' European Currency ',
+ '¤' => ' currency ',
+ '฿' => ' baht ',
+ '؋' => ' afghani ',
+ ],
+ // Temperature
+ //
+ // url: https://en.wikipedia.org/wiki/Conversion_of_units_of_temperature
+ 'temperature' => [
+ '°De' => ' Delisle ',
+ '°Re' => ' Reaumur ', // Réaumur
+ '°Ro' => ' Romer ', // Rømer
+ '°R' => ' Rankine ',
+ '°C' => ' Celsius ',
+ '°F' => ' Fahrenheit ',
+ '°N' => ' Newton ',
+ ],
+ 'latin_symbols' => [
+ '=' => '=',
+ '%' => '%',
+ '∑' => '∑',
+ '∆' => '∆',
+ '∞' => '∞',
+ '♥' => '♥',
+ '&' => '&',
+ '+' => '+',
+ // ---
+ '©' => ' (c) ',
+ '®' => ' (r) ',
+ '@' => ' (at) ',
+ '№' => ' No. ',
+ '℞' => ' Rx ',
+ '[' => '[',
+ '\' => '\\',
+ ']' => ']',
+ '^' => '^',
+ '_' => '_',
+ '`' => '`',
+ '‐' => '-',
+ '‑' => '-',
+ '‒' => '-',
+ '–' => '-',
+ '−' => '-',
+ '—' => '-',
+ '―' => '-',
+ '﹘' => '-',
+ '│' => '|',
+ '∖' => '\\',
+ '∕' => '/',
+ '⁄' => '/',
+ '←' => '<-',
+ '→' => '->',
+ '↑' => '|',
+ '↓' => '|',
+ '⁅' => '[',
+ '⁆' => ']',
+ '⁎' => '*',
+ '、' => ',',
+ '。' => '.',
+ '〈' => '<',
+ '〉' => '>',
+ '《' => '<<',
+ '》' => '>>',
+ '〔' => '[',
+ '〕' => ']',
+ '〘' => '[',
+ '〙' => ']',
+ '〚' => '[',
+ '〛' => ']',
+ '﹝' => '[',
+ '﹞' => ']',
+ '︹' => '[',
+ '︺' => ']',
+ '﹇' => '[',
+ '﹈' => ']',
+ '︐' => ',',
+ '︑' => ',',
+ '︒' => '.',
+ '︓' => ':',
+ '︔' => ';',
+ '︕' => '!',
+ '︖' => '?',
+ '︙' => '...',
+ '︰' => '..',
+ '︵' => '(',
+ '︶' => ')',
+ '﹙' => '(',
+ '﹚' => ')',
+ '︷' => '{',
+ '︸' => '}',
+ '﹛' => '{',
+ '﹜' => '}',
+ '︽' => '<<',
+ '︾' => '>>',
+ '︿' => '<',
+ '﹀' => '>',
+ '×' => '*',
+ '÷' => '/',
+ '≪' => '<<',
+ '≫' => '>>',
+ '⦅' => '((',
+ '⦆' => '))',
+ '〇' => '0',
+ '′' => '\'',
+ '〝' => '"',
+ '〞' => '"',
+ '«' => '<<',
+ '»' => '>>',
+ '‘' => "'",
+ '’' => "'",
+ '‚' => ',',
+ '‛' => "'",
+ '“' => '"',
+ '”' => '"',
+ '„' => '"',
+ '‟' => '"',
+ '‹' => '<',
+ '›' => '>',
+ '․' => '.',
+ '‥' => '..',
+ '…' => '...',
+ '″' => '"',
+ '‴' => '\'\'\'',
+ '‶' => '``',
+ '‷' => '```',
+ '‼' => '!!',
+ '⁇' => '??',
+ '⁈' => '?!',
+ '⁉' => '!?',
+ '⁗' => '````',
+ '⩴' => '::=',
+ '⩵' => '==',
+ '⩶' => '===',
+ '﹔' => ';',
+ '﹕' => ':',
+ '﹖' => '?',
+ '﹗' => '!',
+ '﹍' => '_',
+ '﹎' => '_',
+ '﹏' => '_',
+ '﹐' => ',',
+ '﹑' => ',',
+ '﹒' => '.',
+ '﹟' => '#',
+ '﹠' => '&',
+ '﹡' => '*',
+ '﹢' => '+',
+ '﹣' => '-',
+ '﹤' => '<',
+ '﹥' => '>',
+ '﹦' => '=',
+ '﹨' => '\\',
+ '﹩' => '$',
+ '﹪' => '%',
+ '﹫' => '@',
+ '!' => '!',
+ '"' => '"',
+ '#' => '#',
+ '$' => '$',
+ '%' => '%',
+ '&' => '&',
+ ''' => '\'',
+ '(' => '(',
+ ')' => ')',
+ '*' => '*',
+ '+' => '+',
+ ',' => ',',
+ '-' => '-',
+ '.' => '.',
+ '/' => '/',
+ ':' => ':',
+ ';' => ';',
+ '<' => '<',
+ '=' => '=',
+ '>' => '>',
+ '?' => '?',
+ '@' => '@',
+ '{' => '{',
+ '|' => '|',
+ '}' => '}',
+ '~' => '~',
+ '⦅' => '((',
+ '⦆' => '))',
+ '¬' => '!',
+ ' ̄' => '-',
+ '¦' => '|',
+ '■' => '#',
+ ],
+];
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/data/ascii_language_max_key.php b/system/vendor/voku/portable-ascii/src/voku/helper/data/ascii_language_max_key.php
new file mode 100644
index 0000000..da81ae2
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/data/ascii_language_max_key.php
@@ -0,0 +1,65 @@
+ 0,
+ 'tk' => 1,
+ 'th' => 0,
+ 'ps' => 0,
+ 'or' => 0,
+ 'mn' => 0,
+ 'ko' => 0,
+ 'ky' => 0,
+ 'hy' => 1,
+ 'bn' => 5,
+ 'be' => 0,
+ 'am' => 0,
+ 'ja' => 0,
+ 'zh' => 0,
+ 'nl' => 1,
+ 'it' => 1,
+ 'mk' => 1,
+ 'pt' => 1,
+ 'el__greeklish' => 2,
+ 'el' => 2,
+ 'hi' => 2,
+ 'sv' => 1,
+ 'tr' => 1,
+ 'bg' => 2,
+ 'hu' => 1,
+ 'my' => 5,
+ 'hr' => 2,
+ 'fi' => 1,
+ 'ka' => 1,
+ 'ru' => 1,
+ 'ru__gost_2000_b' => 1,
+ 'ru__passport_2013' => 1,
+ 'uk' => 1,
+ 'kk' => 1,
+ 'cs' => 1,
+ 'da' => 1,
+ 'pl' => 1,
+ 'ro' => 1,
+ 'eo' => 1,
+ 'et' => 1,
+ 'lv' => 1,
+ 'lt' => 1,
+ 'no' => 1,
+ 'vi' => 1,
+ 'ar' => 1,
+ 'fa' => 1,
+ 'sr' => 1,
+ 'sr__cyr' => 1,
+ 'sr__lat' => 1,
+ 'az' => 1,
+ 'sk' => 1,
+ 'fr' => 1,
+ 'fr_at' => 1,
+ 'fr_ch' => 1,
+ 'de' => 1,
+ 'de_at' => 1,
+ 'de_ch' => 1,
+ 'en' => 0,
+ 'latin' => 3,
+ ' ' => 1,
+ 'msword' => 1,
+];
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/data/ascii_ord.php b/system/vendor/voku/portable-ascii/src/voku/helper/data/ascii_ord.php
new file mode 100644
index 0000000..142318c
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/data/ascii_ord.php
@@ -0,0 +1 @@
+ 0, "\x00" => 0, "\x01" => 1, "\x02" => 2, "\x03" => 3, "\x04" => 4, "\x05" => 5, "\x06" => 6, "\x07" => 7, "\x08" => 8, "\x09" => 9, "\x0A" => 10, "\x0B" => 11, "\x0C" => 12, "\x0D" => 13, "\x0E" => 14, "\x0F" => 15, "\x10" => 16, "\x11" => 17, "\x12" => 18, "\x13" => 19, "\x14" => 20, "\x15" => 21, "\x16" => 22, "\x17" => 23, "\x18" => 24, "\x19" => 25, "\x1A" => 26, "\x1B" => 27, "\x1C" => 28, "\x1D" => 29, "\x1E" => 30, "\x1F" => 31, "\x20" => 32, "\x21" => 33, "\x22" => 34, "\x23" => 35, "\x24" => 36, "\x25" => 37, "\x26" => 38, "\x27" => 39, "\x28" => 40, "\x29" => 41, "\x2A" => 42, "\x2B" => 43, "\x2C" => 44, "\x2D" => 45, "\x2E" => 46, "\x2F" => 47, "\x30" => 48, "\x31" => 49, "\x32" => 50, "\x33" => 51, "\x34" => 52, "\x35" => 53, "\x36" => 54, "\x37" => 55, "\x38" => 56, "\x39" => 57, "\x3A" => 58, "\x3B" => 59, "\x3C" => 60, "\x3D" => 61, "\x3E" => 62, "\x3F" => 63, "\x40" => 64, "\x41" => 65, "\x42" => 66, "\x43" => 67, "\x44" => 68, "\x45" => 69, "\x46" => 70, "\x47" => 71, "\x48" => 72, "\x49" => 73, "\x4A" => 74, "\x4B" => 75, "\x4C" => 76, "\x4D" => 77, "\x4E" => 78, "\x4F" => 79, "\x50" => 80, "\x51" => 81, "\x52" => 82, "\x53" => 83, "\x54" => 84, "\x55" => 85, "\x56" => 86, "\x57" => 87, "\x58" => 88, "\x59" => 89, "\x5A" => 90, "\x5B" => 91, "\x5C" => 92, "\x5D" => 93, "\x5E" => 94, "\x5F" => 95, "\x60" => 96, "\x61" => 97, "\x62" => 98, "\x63" => 99, "\x64" => 100, "\x65" => 101, "\x66" => 102, "\x67" => 103, "\x68" => 104, "\x69" => 105, "\x6A" => 106, "\x6B" => 107, "\x6C" => 108, "\x6D" => 109, "\x6E" => 110, "\x6F" => 111, "\x70" => 112, "\x71" => 113, "\x72" => 114, "\x73" => 115, "\x74" => 116, "\x75" => 117, "\x76" => 118, "\x77" => 119, "\x78" => 120, "\x79" => 121, "\x7A" => 122, "\x7B" => 123, "\x7C" => 124, "\x7D" => 125, "\x7E" => 126, "\x7F" => 127, "\x80" => 128, "\x81" => 129, "\x82" => 130, "\x83" => 131, "\x84" => 132, "\x85" => 133, "\x86" => 134, "\x87" => 135, "\x88" => 136, "\x89" => 137, "\x8A" => 138, "\x8B" => 139, "\x8C" => 140, "\x8D" => 141, "\x8E" => 142, "\x8F" => 143, "\x90" => 144, "\x91" => 145, "\x92" => 146, "\x93" => 147, "\x94" => 148, "\x95" => 149, "\x96" => 150, "\x97" => 151, "\x98" => 152, "\x99" => 153, "\x9A" => 154, "\x9B" => 155, "\x9C" => 156, "\x9D" => 157, "\x9E" => 158, "\x9F" => 159, "\xA0" => 160, "\xA1" => 161, "\xA2" => 162, "\xA3" => 163, "\xA4" => 164, "\xA5" => 165, "\xA6" => 166, "\xA7" => 167, "\xA8" => 168, "\xA9" => 169, "\xAA" => 170, "\xAB" => 171, "\xAC" => 172, "\xAD" => 173, "\xAE" => 174, "\xAF" => 175, "\xB0" => 176, "\xB1" => 177, "\xB2" => 178, "\xB3" => 179, "\xB4" => 180, "\xB5" => 181, "\xB6" => 182, "\xB7" => 183, "\xB8" => 184, "\xB9" => 185, "\xBA" => 186, "\xBB" => 187, "\xBC" => 188, "\xBD" => 189, "\xBE" => 190, "\xBF" => 191, "\xC0" => 192, "\xC1" => 193, "\xC2" => 194, "\xC3" => 195, "\xC4" => 196, "\xC5" => 197, "\xC6" => 198, "\xC7" => 199, "\xC8" => 200, "\xC9" => 201, "\xCA" => 202, "\xCB" => 203, "\xCC" => 204, "\xCD" => 205, "\xCE" => 206, "\xCF" => 207, "\xD0" => 208, "\xD1" => 209, "\xD2" => 210, "\xD3" => 211, "\xD4" => 212, "\xD5" => 213, "\xD6" => 214, "\xD7" => 215, "\xD8" => 216, "\xD9" => 217, "\xDA" => 218, "\xDB" => 219, "\xDC" => 220, "\xDD" => 221, "\xDE" => 222, "\xDF" => 223, "\xE0" => 224, "\xE1" => 225, "\xE2" => 226, "\xE3" => 227, "\xE4" => 228, "\xE5" => 229, "\xE6" => 230, "\xE7" => 231, "\xE8" => 232, "\xE9" => 233, "\xEA" => 234, "\xEB" => 235, "\xEC" => 236, "\xED" => 237, "\xEE" => 238, "\xEF" => 239, "\xF0" => 240, "\xF1" => 241, "\xF2" => 242, "\xF3" => 243, "\xF4" => 244, "\xF5" => 245, "\xF6" => 246, "\xF7" => 247, "\xF8" => 248, "\xF9" => 249, "\xFA" => 250, "\xFB" => 251, "\xFC" => 252, "\xFD" => 253, "\xFE" => 254, "\xFF" => 255];
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/data/x000.php b/system/vendor/voku/portable-ascii/src/voku/helper/data/x000.php
new file mode 100644
index 0000000..6c9d81f
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/data/x000.php
@@ -0,0 +1,16 @@
+', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '', 'EUR', // "\xc2\x80" => "\xe2\x82\xac" => EURO SIGN
+ '', ',', 'f', ',,', // "\xc2\x84" => "\xe2\x80\x9e" => DOUBLE LOW-9 QUOTATION MARK
+ '...', // "\xc2\x85" => "\xe2\x80\xa6" => HORIZONTAL ELLIPSIS
+ '+', '++', // "\xc2\x87" => "\xe2\x80\xa1" => DOUBLE DAGGER
+ '^', '%0', // "\xc2\x89" => "\xe2\x80\xb0" => PER MILLE SIGN
+ 'S', '<', 'OE', // "\xc2\x8c" => "\xc5\x92" => LATIN CAPITAL LIGATURE OE
+ '', 'Z', '', '', '\'', // "\xc2\x91" => "\xe2\x80\x98" => LEFT SINGLE QUOTATION MARK
+ '\'', // "\xc2\x92" => "\xe2\x80\x99" => RIGHT SINGLE QUOTATION MARK
+ '"', '"', '*', '-', '--', // "\xc2\x97" => "\xe2\x80\x94" => EM DASH
+ '~', 'tm', 's', '>', 'oe', '', 'z', 'Y', ' ', '!', 'C/', 'PS', '$?', 'Y=', '|', 'SS', '"', '(c)', 'a', '<<', '!', '', '(r)', '-', 'deg', '+-', '2', '3', '\'', 'u', 'P', '*', ',', '1', 'o', '>>', '1/4', '1/2', '3/4', '?', 'A', 'A', 'A', 'A', // Not "AE" - used in languages other than German
+ 'A', 'A', 'AE', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', 'D', 'N', 'O', 'O', 'O', 'O', // Not "OE" - used in languages other than German
+ 'O', 'x', 'O', 'U', 'U', 'U', // Not "UE" - used in languages other than German
+ 'U', 'Y', 'Th', 'ss', 'a', 'a', 'a', 'a', // Not "ae" - used in languages other than German
+ 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'd', 'n', 'o', 'o', 'o', 'o', // Not "oe" - used in languages other than German
+ 'o', '/', 'o', 'u', 'u', 'u', // Not "ue" - used in languages other than German
+ 'u', 'y', 'th', 'y', ];
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/data/x001.php b/system/vendor/voku/portable-ascii/src/voku/helper/data/x001.php
new file mode 100644
index 0000000..87fb12f
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/data/x001.php
@@ -0,0 +1 @@
+', '^', 'V', '^', 'V', '\'', '-', '/', '\\', ',', '_', '\\', '/', ':', '.', '`', '\'', '^', 'V', '+', '-', 'V', '.', '@', ',', '~', '"', 'R', 'X', 'G', 'l', 's', 'x', '?', '', '', '', '', '', '', '', 'V', '=', '"', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/data/x003.php b/system/vendor/voku/portable-ascii/src/voku/helper/data/x003.php
new file mode 100644
index 0000000..3d02b86
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/data/x003.php
@@ -0,0 +1 @@
+', '[?]', '[?]', '[?]', 'f', 'v', 'u', 'yr', 'y', 'w', 'th', 'th', 'a', 'o', 'ac', 'ae', 'o', 'o', 'o', 'oe', 'on', 'r', 'k', 'c', 'k', 'g', 'ng', 'g', 'g', 'w', 'h', 'h', 'h', 'h', 'n', 'n', 'n', 'i', 'e', 'j', 'g', 'ae', 'a', 'eo', 'p', 'z', 's', 's', 's', 'c', 'z', 't', 't', 'd', 'b', 'b', 'p', 'p', 'e', 'm', 'm', 'm', 'l', 'l', 'ng', 'ng', 'd', 'o', 'ear', 'ior', 'qu', 'qu', 'qu', 's', 'yr', 'yr', 'yr', 'q', 'x', '.', ':', '+', '17', '18', '19', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/data/x017.php b/system/vendor/voku/portable-ascii/src/voku/helper/data/x017.php
new file mode 100644
index 0000000..8f2a7ca
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/data/x017.php
@@ -0,0 +1 @@
+', '.', '..', '...', '.', "\n",
+ "\n\n",
+ '', '', '', '', '', ' ', '%0', '%00', '\'', '\'\'', '\'\'\'', '`', '``', '```', '^', '<', '>', '*', '!!', '!?', '-', '_', '-', '^', '***', '--', '/', '-[', ']-', '??', '?!', '!?', '7', 'PP', '(]', '[)', '*', '[?]', '[?]', '[?]', '%', '~', '[?]', '[?]', '[?]', "''''", // 0x57
+ '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', ' ', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '', '', '', '', '', '', '0', 'i', '', '', '4', '5', '6', '7', '8', '9', '+', '-', '=', '(', ')', 'n', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '-', '=', '(', ')', '[?]', 'a', 'e', 'o', 'x', '[?]', 'h', 'k', 'l', 'm', 'n', 'p', 's', 't', '[?]', '[?]', '[?]', 'ECU', 'CL', 'Cr', 'Fr.', 'L.', 'mil', 'N', 'Pts', 'Rs', 'W', 'NS', 'D', 'EUR', 'K', 'T', 'Dr', 'Pf', 'P', 'G', 'A', 'UAH', 'C|', 'L', 'Sm', 'T', 'Rs', 'L', 'M', 'm', 'R', 'l', 'BTC', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '[?]', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', ];
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/data/x021.php b/system/vendor/voku/portable-ascii/src/voku/helper/data/x021.php
new file mode 100644
index 0000000..1643d67
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/data/x021.php
@@ -0,0 +1 @@
+=', '<=', '>=', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/data/x023.php b/system/vendor/voku/portable-ascii/src/voku/helper/data/x023.php
new file mode 100644
index 0000000..b8f4ca0
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/data/x023.php
@@ -0,0 +1 @@
+ ', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/data/x024.php b/system/vendor/voku/portable-ascii/src/voku/helper/data/x024.php
new file mode 100644
index 0000000..26abcc6
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/data/x024.php
@@ -0,0 +1 @@
+', '>', '>', '>', '>', '>', 'V', 'V', 'V', 'V', '<', '<', '<', '<', '<', '<', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '#', '#', '#', '#', '#', '^', '^', '^', 'O', '#', '#', '#', '#', 'O', 'O', 'O', 'O', '/', '\\\\', '\\\\', '#', '#', '#', '#', '/'];
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/data/x026.php b/system/vendor/voku/portable-ascii/src/voku/helper/data/x026.php
new file mode 100644
index 0000000..0c97de3
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/data/x026.php
@@ -0,0 +1 @@
+ ', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/data/x028.php b/system/vendor/voku/portable-ascii/src/voku/helper/data/x028.php
new file mode 100644
index 0000000..9585d91
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/data/x028.php
@@ -0,0 +1 @@
+', 'n', 't', 'q', ',', '*', '5', '<', '-', 'u', '8', 'v', '.', '%', '[', '$', '+', 'x', '!', '&', ';', ':', '4', '\\', '0', 'z', '7', '(', '_', '?', 'w', ']', '#', 'y', ')', '=', '[d7]', '[d17]', '[d27]', '[d127]', '[d37]', '[d137]', '[d237]', '[d1237]', '[d47]', '[d147]', '[d247]', '[d1247]', '[d347]', '[d1347]', '[d2347]', '[d12347]', '[d57]', '[d157]', '[d257]', '[d1257]', '[d357]', '[d1357]', '[d2357]', '[d12357]', '[d457]', '[d1457]', '[d2457]', '[d12457]', '[d3457]', '[d13457]', '[d23457]', '[d123457]', '[d67]', '[d167]', '[d267]', '[d1267]', '[d367]', '[d1367]', '[d2367]', '[d12367]', '[d467]', '[d1467]', '[d2467]', '[d12467]', '[d3467]', '[d13467]', '[d23467]', '[d123467]', '[d567]', '[d1567]', '[d2567]', '[d12567]', '[d3567]', '[d13567]', '[d23567]', '[d123567]', '[d4567]', '[d14567]', '[d24567]', '[d124567]', '[d34567]', '[d134567]', '[d234567]', '[d1234567]', '[d8]', '[d18]', '[d28]', '[d128]', '[d38]', '[d138]', '[d238]', '[d1238]', '[d48]', '[d148]', '[d248]', '[d1248]', '[d348]', '[d1348]', '[d2348]', '[d12348]', '[d58]', '[d158]', '[d258]', '[d1258]', '[d358]', '[d1358]', '[d2358]', '[d12358]', '[d458]', '[d1458]', '[d2458]', '[d12458]', '[d3458]', '[d13458]', '[d23458]', '[d123458]', '[d68]', '[d168]', '[d268]', '[d1268]', '[d368]', '[d1368]', '[d2368]', '[d12368]', '[d468]', '[d1468]', '[d2468]', '[d12468]', '[d3468]', '[d13468]', '[d23468]', '[d123468]', '[d568]', '[d1568]', '[d2568]', '[d12568]', '[d3568]', '[d13568]', '[d23568]', '[d123568]', '[d4568]', '[d14568]', '[d24568]', '[d124568]', '[d34568]', '[d134568]', '[d234568]', '[d1234568]', '[d78]', '[d178]', '[d278]', '[d1278]', '[d378]', '[d1378]', '[d2378]', '[d12378]', '[d478]', '[d1478]', '[d2478]', '[d12478]', '[d3478]', '[d13478]', '[d23478]', '[d123478]', '[d578]', '[d1578]', '[d2578]', '[d12578]', '[d3578]', '[d13578]', '[d23578]', '[d123578]', '[d4578]', '[d14578]', '[d24578]', '[d124578]', '[d34578]', '[d134578]', '[d234578]', '[d1234578]', '[d678]', '[d1678]', '[d2678]', '[d12678]', '[d3678]', '[d13678]', '[d23678]', '[d123678]', '[d4678]', '[d14678]', '[d24678]', '[d124678]', '[d34678]', '[d134678]', '[d234678]', '[d1234678]', '[d5678]', '[d15678]', '[d25678]', '[d125678]', '[d35678]', '[d135678]', '[d235678]', '[d1235678]', '[d45678]', '[d145678]', '[d245678]', '[d1245678]', '[d345678]', '[d1345678]', '[d2345678]', '[d12345678]'];
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/data/x029.php b/system/vendor/voku/portable-ascii/src/voku/helper/data/x029.php
new file mode 100644
index 0000000..5162de3
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/data/x029.php
@@ -0,0 +1 @@
+', '%', '[?]', '[?]', '>', '=', '[?]', '/', '-', '~', '\\', '/', '~', '~', '|-', '-|', '[?]', '[?]', '[?]', '[?]', '<=', '=>', '((', '))', '[?]', '[?]', '::', '[?]', '?', '\'', 'o', '.', ',', '.', ',', ';', '[?]', '[?]', '[?]', '[?]', '----', '------', 'x', '|', '[?]', '[?]', '=', ',', '"', '`--', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?]', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/data/x02f.php b/system/vendor/voku/portable-ascii/src/voku/helper/data/x02f.php
new file mode 100644
index 0000000..5147b57
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/data/x02f.php
@@ -0,0 +1 @@
+ ', '<<', '>> ', '[', '] ', '{', '} ', '[(', ')] ', '@', 'X ', '[', '] ', '[[', ']] ', '((', ')) ', '[[', ']] ', '~ ', '``', '\'\'', ',,', '@', '1', '2', '3', '4', '5', '6', '7', '8', '9', '', '', '', '', '', '', '~', '+', '+', '+', '+', '', '@', ' // ', '+10+', '+20+', '+30+', '[?]', '[?]', '[?]', '', '', '[?]', 'a', 'a', 'i', 'i', 'u', 'u', 'e', 'e', 'o', 'o', 'ka', 'ga', 'ki', 'gi', 'ku', 'gu', 'ke', 'ge', 'ko', 'go', 'sa', 'za', 'shi', // 0x57
+ 'zi', 'su', 'zu', 'se', 'ze', 'so', 'zo', 'ta', 'da', 'chi', // 0x61
+ 'di', 'tsu', // 0x63
+ 'tsu', // 0x64
+ 'du', 'te', 'de', 'to', 'do', 'na', 'ni', 'nu', 'ne', 'no', 'ha', 'ba', 'pa', 'hi', 'bi', 'pi', 'hu', 'bu', 'pu', 'he', 'be', 'pe', 'ho', 'bo', 'po', 'ma', 'mi', 'mu', 'me', 'mo', 'ya', 'ya', 'yu', 'yu', 'yo', 'yo', 'ra', 'ri', 'ru', 're', 'ro', 'wa', 'wa', 'wi', 'we', 'wo', 'n', 'vu', '[?]', '[?]', '[?]', '[?]', '', '', '', '', '"', '"', '[?]', '[?]', 'a', 'a', 'i', 'i', 'u', 'u', 'e', 'e', 'o', 'o', 'ka', 'ga', 'ki', 'gi', 'ku', 'gu', 'ke', 'ge', 'ko', 'go', 'sa', 'za', 'shi', // 0xb7
+ 'zi', 'su', 'zu', 'se', 'ze', 'so', 'zo', 'ta', 'da', 'chi', // 0xc1
+ 'di', 'tsu', // 0xc3
+ 'tsu', // 0xc4
+ 'du', 'te', 'de', 'to', 'do', 'na', 'ni', 'nu', 'ne', 'no', 'ha', 'ba', 'pa', 'hi', 'bi', 'pi', 'hu', 'bu', 'pu', 'he', 'be', 'pe', 'ho', 'bo', 'po', 'ma', 'mi', 'mu', 'me', 'mo', 'ya', 'ya', 'yu', 'yu', 'yo', 'yo', 'ra', 'ri', 'ru', 're', 'ro', 'wa', 'wa', 'wi', 'we', 'wo', 'n', 'vu', 'ka', 'ke', 'va', 'vi', 've', 'vo', '', '', '"', '"', ];
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/data/x031.php b/system/vendor/voku/portable-ascii/src/voku/helper/data/x031.php
new file mode 100644
index 0000000..72c0260
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/data/x031.php
@@ -0,0 +1 @@
+>', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '(g)', '(n)', '(d)', '(r)', '(m)', '(b)', '(s)', '()', '(j)', '(c)', '(k)', '(t)', '(p)', '(h)', '(ga)', '(na)', '(da)', '(ra)', '(ma)', '(ba)', '(sa)', '(a)', '(ja)', '(ca)', '(ka)', '(ta)', '(pa)', '(ha)', '[?]', '[?]', '[?]', 'KIS ', '(1) ', '(2) ', '(3) ', '(4) ', '(5) ', '(6) ', '(7) ', '(8) ', '(9) ', '(10) ', '(Yue) ', '(Huo) ', '(Shui) ', '(Mu) ', '(Jin) ', '(Tu) ', '(Ri) ', '(Zhu) ', '(You) ', '(She) ', '(Ming) ', '(Te) ', '(Cai) ', '(Zhu) ', '(Lao) ', '(Mi) ', '(Nan) ', '(Nu) ', '(Shi) ', '(You) ', '(Yin) ', '(Zhu) ', '(Xiang) ', '(Xiu) ', '(Xie) ', '(Zheng) ', '(Shang) ', '(Zhong) ', '(Xia) ', '(Zuo) ', '(You) ', '(Yi) ', '(Zong) ', '(Xue) ', '(Jian) ', '(Qi) ', '(Zi) ', '(Xie) ', '(Ye) ', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '1M', '2M', '3M', '4M', '5M', '6M', '7M', '8M', '9M', '10M', '11M', '12M', 'Hg', 'erg', 'eV', 'LTD', 'a', 'i', 'u', 'u', 'o', 'ka', 'ki', 'ku', 'ke', 'ko', 'sa', 'si', 'su', 'se', 'so', 'ta', 'ti', 'tu', 'te', 'to', 'na', 'ni', 'nu', 'ne', 'no', 'ha', 'hi', 'hu', 'he', 'ho', 'ma', 'mi', 'mu', 'me', 'mo', 'ya', 'yu', 'yo', 'ra', 'ri', 'ru', 're', 'ro', 'wa', 'wi', 'we', 'wo'];
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/data/x033.php b/system/vendor/voku/portable-ascii/src/voku/helper/data/x033.php
new file mode 100644
index 0000000..8505337
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/data/x033.php
@@ -0,0 +1 @@
+> ', '<', '> ', '[', '] ', '{', '}', '[?]', '[?]', '[?]', '[?]', '', '', '', '', '', '', '', ',', ',', '.', '', ';', ':', '?', '!', '-', '(', ')', '{', '}', '{', '}', '#', '&', '*', '+', '-', '<', '>', '=', '', '\\', '$', '%', '@', '[?]', '[?]', '[?]', '[?]', '', '', '', '[?]', '', '[?]', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '[?]', '[?]', ''];
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/data/x0ff.php b/system/vendor/voku/portable-ascii/src/voku/helper/data/x0ff.php
new file mode 100644
index 0000000..b3a1539
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/data/x0ff.php
@@ -0,0 +1 @@
+', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '[?]', '[?]', '.', '[', ']', ',', '*', 'wo', 'a', 'i', 'u', 'e', 'o', 'ya', 'yu', 'yo', 'tu', '+', 'a', 'i', 'u', 'e', 'o', 'ka', 'ki', 'ku', 'ke', 'ko', 'sa', 'si', 'su', 'se', 'so', 'ta', 'ti', 'tu', 'te', 'to', 'na', 'ni', 'nu', 'ne', 'no', 'ha', 'hi', 'hu', 'he', 'ho', 'ma', 'mi', 'mu', 'me', 'mo', 'ya', 'yu', 'yo', 'ra', 'ri', 'ru', 're', 'ro', 'wa', 'n', ':', ';', '', 'g', 'gg', 'gs', 'n', 'nj', 'nh', 'd', 'dd', 'r', 'lg', 'lm', 'lb', 'ls', 'lt', 'lp', 'rh', 'm', 'b', 'bb', 'bs', 's', 'ss', '', 'j', 'jj', 'c', 'k', 't', 'p', 'h', '[?]', '[?]', '[?]', 'a', 'ae', 'ya', 'yae', 'eo', 'e', '[?]', '[?]', 'yeo', 'ye', 'o', 'wa', 'wae', 'oe', '[?]', '[?]', 'yo', 'u', 'weo', 'we', 'wi', 'yu', '[?]', '[?]', 'eu', 'yi', 'i', '[?]', '[?]', '[?]', '/C', 'PS', '!', '-', '|', 'Y=', 'W=', '[?]', '|', '-', '|', '-', '|', '#', 'O', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '{', '|', '}', '', '', '', ''];
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/data/x1d4.php b/system/vendor/voku/portable-ascii/src/voku/helper/data/x1d4.php
new file mode 100644
index 0000000..ad8d3b2
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/data/x1d4.php
@@ -0,0 +1 @@
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 52 => 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 78 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 104 => 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 130 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 156 => 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 181 => 'Z', 182 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 208 => 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 234 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/data/x1d5.php b/system/vendor/voku/portable-ascii/src/voku/helper/data/x1d5.php
new file mode 100644
index 0000000..a2a9b90
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/data/x1d5.php
@@ -0,0 +1,4 @@
+ 'w', 'x', 'y', 'z', 4 => 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 30 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 56 => 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 82 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 108 => 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 134 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 160 => 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 186 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 212 => 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 238 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', ];
diff --git a/system/vendor/voku/portable-ascii/src/voku/helper/data/x1d6.php b/system/vendor/voku/portable-ascii/src/voku/helper/data/x1d6.php
new file mode 100644
index 0000000..315ef5e
--- /dev/null
+++ b/system/vendor/voku/portable-ascii/src/voku/helper/data/x1d6.php
@@ -0,0 +1 @@
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 80 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 112 => 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 230 => 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ];
diff --git a/system/vendor/voku/stop-words/CHANGELOG.md b/system/vendor/voku/stop-words/CHANGELOG.md
new file mode 100644
index 0000000..12d4a27
--- /dev/null
+++ b/system/vendor/voku/stop-words/CHANGELOG.md
@@ -0,0 +1,25 @@
+# Change log
+All notable changes to this project will be documented in this file.
+This project adheres to [Semantic Versioning](http://semver.org/).
+
+## [Unreleased]
+
+## [2.0.1] - 2018-11-23
+### Fix
+- switch czech and catalan stopwords | thx@retep007
+
+## [2.0.0] - 2017-11-26
+### Changed
+- "php": ">=7.0"
+
+## [1.2.0] - 2017-05-22
+### Changed
+- add more languages
+
+## [1.1.0] - 2017-05-12
+### Changed
+- add more languages
+
+## [1.0.0] - 2017-05-05
+### Changed
+- init
diff --git a/system/vendor/voku/stop-words/LICENSE b/system/vendor/voku/stop-words/LICENSE
new file mode 100644
index 0000000..8fba26e
--- /dev/null
+++ b/system/vendor/voku/stop-words/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Lars Moelleken
+
+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.
+
diff --git a/system/vendor/voku/stop-words/README.md b/system/vendor/voku/stop-words/README.md
new file mode 100644
index 0000000..66a3bd3
--- /dev/null
+++ b/system/vendor/voku/stop-words/README.md
@@ -0,0 +1,73 @@
+[](https://travis-ci.org/voku/stop-words)
+[](https://coveralls.io/github/voku/stop-words?branch=master)
+[](https://scrutinizer-ci.com/g/voku/stop-words/?branch=master)
+[](https://www.codacy.com/app/voku/stop-words?utm_source=github.com&utm_medium=referral&utm_content=voku/stop-words&utm_campaign=Badge_Grade)
+[](https://insight.sensiolabs.com/projects/316837f1-afb0-4ea5-938e-340527eeb4e6)
+[](https://packagist.org/packages/voku/stop-words)
+[](https://packagist.org/packages/voku/stop-words)
+[](https://packagist.org/packages/voku/stop-words)
+[](https://packagist.org/packages/voku/stop-words)
+
+# Stop-Words
+
+## Description
+
+A collection of stop words stop words in various languages for e.g. search-functions.
+
+* [Installation](#installation)
+* [Usage](#usage)
+* [History](#history)
+
+## Installation
+
+1. Install and use [composer](https://getcomposer.org/doc/00-intro.md) in your project.
+2. Require this package via composer:
+
+```sh
+composer require voku/stop-words
+```
+
+## Usage
+
+```php
+$stopWords = new StopWords();
+$stopWords->getStopWordsFromLanguage('de');
+```
+
+Available languages
+-------------------
+* Arabic (ar)
+* Bulgarian (bg)
+* Catalan (ca)
+* Croatian (hr)
+* Czech (cz)
+* Danish (da)
+* Dutch (nl)
+* English (en)
+* Esperanto (eo)
+* Estonian (et)
+* Finnish (fi)
+* French (fr)
+* Georgian (ka)
+* German (de)
+* Greek (el)
+* Hindi (hi)
+* Hungarian (hu)
+* Indonesian (id)
+* Italian (it)
+* Latvian (lv)
+* Lithuanian (lt)
+* Norwegian (no)
+* Polish (pl)
+* Portuguese (pt)
+* Romanian (ro)
+* Russian (ru)
+* Slovak (sk)
+* Spanish (es)
+* Swedish (sv)
+* Turkish (tr)
+* Ukrainian (uk)
+* Vietnamese (vi)
+
+## History
+See [CHANGELOG](CHANGELOG.md) for the full history of changes.
diff --git a/system/vendor/voku/stop-words/composer.json b/system/vendor/voku/stop-words/composer.json
new file mode 100644
index 0000000..e62caa5
--- /dev/null
+++ b/system/vendor/voku/stop-words/composer.json
@@ -0,0 +1,27 @@
+{
+ "name": "voku/stop-words",
+ "description": "Stop-Words via PHP",
+ "keywords": [
+ "stop-words",
+ "stop words"
+ ],
+ "type": "library",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Lars Moelleken",
+ "homepage": "http://www.moelleken.org/"
+ }
+ ],
+ "autoload": {
+ "psr-4": {
+ "voku\\": "src/voku/"
+ }
+ },
+ "require": {
+ "php": ">=7.0.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~6.0"
+ }
+}
diff --git a/system/vendor/voku/stop-words/src/voku/helper/StopWords.php b/system/vendor/voku/stop-words/src/voku/helper/StopWords.php
new file mode 100644
index 0000000..8450d9c
--- /dev/null
+++ b/system/vendor/voku/stop-words/src/voku/helper/StopWords.php
@@ -0,0 +1,143 @@
+stopWords[$language] = $this->getData($language);
+ }
+
+ /**
+ * Get data from "/data/*.php".
+ *
+ * @param string $file
+ *
+ * @return array Will return an empty array on error.
+ */
+ private function getData(string $file): array
+ {
+ static $RESULT_STOP_WORDS_CACHE = array();
+
+ if (isset($RESULT_STOP_WORDS_CACHE[$file])) {
+ return $RESULT_STOP_WORDS_CACHE[$file];
+ }
+
+ $file = __DIR__ . '/stopwords/' . $file . '.php';
+ if (file_exists($file)) {
+ /** @noinspection PhpIncludeInspection */
+ $RESULT_STOP_WORDS_CACHE[$file] = require $file;
+ } else {
+ $RESULT_STOP_WORDS_CACHE[$file] = array();
+ }
+
+ return $RESULT_STOP_WORDS_CACHE[$file];
+ }
+
+ /**
+ * Get the stop-words from one language.
+ *
+ * @param string $language
+ *
+ * @return array
+ *
+ * @throws StopWordsLanguageNotExists
+ */
+ public function getStopWordsFromLanguage(string $language = 'de'): array
+ {
+ if (\in_array($language, self::$availableLanguages, true) === false) {
+ throw new StopWordsLanguageNotExists('language not supported: ' . $language);
+ }
+
+ if (!isset($this->stopWords[$language])) {
+ $this->loadLanguageData($language);
+ }
+
+ return $this->stopWords[$language];
+ }
+
+ private function loadLanguageDataAll()
+ {
+ foreach (self::$availableLanguages as $language) {
+ if (!isset($this->stopWords[$language])) {
+ $this->loadLanguageData($language);
+ }
+ }
+ }
+
+ /**
+ * Get all stop-words from all languages.
+ *
+ * @return array
+ *
+ * @throws StopWordsLanguageNotExists
+ */
+ public function getStopWordsAll(): array
+ {
+ $this->loadLanguageDataAll();
+
+ return $this->stopWords;
+ }
+}
diff --git a/system/vendor/voku/stop-words/src/voku/helper/StopWordsLanguageNotExists.php b/system/vendor/voku/stop-words/src/voku/helper/StopWordsLanguageNotExists.php
new file mode 100644
index 0000000..7c9a6dc
--- /dev/null
+++ b/system/vendor/voku/stop-words/src/voku/helper/StopWordsLanguageNotExists.php
@@ -0,0 +1,14 @@
+