From 1fc1a1b93989648d02aa1db02bbaa1aea03262b0 Mon Sep 17 00:00:00 2001 From: Matthias Kappenberg Date: Thu, 2 Feb 2023 18:24:47 +0100 Subject: [PATCH] initial commit --- Classes/Hooks/GetOembedDataHook.php | 406 + Classes/Middleware/Api.php | 211 + .../ViewHelpers/JsonToObjectViewHelper.php | 52 + Configuration/RequestMiddlewares.php | 15 + .../TCA/Overrides/sys_file_reference.php | 6 + Configuration/TCA/Overrides/sys_template.php | 8 + Configuration/TCA/Overrides/tt_content.php | 135 + Configuration/TsConfig/All.tsconfig | 2 + .../ContentElements/RsmoembedDefault.tsconfig | 23 + .../RsmoembedDefault.typoscript | 25 + Configuration/TypoScript/constants.typoscript | 10 + Configuration/TypoScript/setup.typoscript | 3 + Resources/Private/.htaccess | 11 + Resources/Private/Api/Content.html | 25 + .../RsmoembedDefault/de.locallang_db.xlf | 18 + .../RsmoembedDefault/locallang_db.xlf | 18 + Resources/Private/Language/locallang.xlf | 24 + .../Language/locallang_csh_tt_content.xlf | 23 + Resources/Private/Language/locallang_db.xlf | 30 + Resources/Private/PHP/embed/composer.json | 5 + Resources/Private/PHP/embed/composer.lock | 501 ++ .../Private/PHP/embed/vendor/autoload.php | 25 + .../PHP/embed/vendor/composer/ClassLoader.php | 572 ++ .../vendor/composer/InstalledVersions.php | 352 + .../Private/PHP/embed/vendor/composer/LICENSE | 21 + .../vendor/composer/autoload_classmap.php | 10 + .../embed/vendor/composer/autoload_files.php | 10 + .../vendor/composer/autoload_namespaces.php | 10 + .../embed/vendor/composer/autoload_psr4.php | 15 + .../embed/vendor/composer/autoload_real.php | 57 + .../embed/vendor/composer/autoload_static.php | 89 + .../embed/vendor/composer/ca-bundle/LICENSE | 19 + .../embed/vendor/composer/ca-bundle/README.md | 85 + .../vendor/composer/ca-bundle/composer.json | 54 + .../vendor/composer/ca-bundle/res/cacert.pem | 3372 +++++++ .../composer/ca-bundle/src/CaBundle.php | 431 + .../PHP/embed/vendor/composer/installed.json | 512 ++ .../PHP/embed/vendor/composer/installed.php | 95 + .../embed/vendor/composer/platform_check.php | 26 + .../PHP/embed/vendor/embed/embed/CHANGELOG.md | 239 + .../PHP/embed/vendor/embed/embed/LICENSE | 21 + .../PHP/embed/vendor/embed/embed/README.md | 360 + .../embed/vendor/embed/embed/composer.json | 72 + .../embed/embed/src/Adapters/Archive/Api.php | 18 + .../Adapters/Archive/Detectors/AuthorName.php | 17 + .../src/Adapters/Archive/Detectors/Code.php | 37 + .../Archive/Detectors/Description.php | 17 + .../Archive/Detectors/ProviderName.php | 14 + .../Archive/Detectors/PublishedTime.php | 20 + .../src/Adapters/Archive/Detectors/Title.php | 17 + .../embed/src/Adapters/Archive/Extractor.php | 30 + .../Bandcamp/Detectors/ProviderName.php | 14 + .../embed/src/Adapters/Bandcamp/Extractor.php | 16 + .../src/Adapters/CadenaSer/Detectors/Code.php | 41 + .../src/Adapters/CadenaSer/Extractor.php | 16 + .../src/Adapters/Facebook/Detectors/Title.php | 21 + .../embed/src/Adapters/Facebook/Extractor.php | 18 + .../embed/src/Adapters/Facebook/OEmbed.php | 80 + .../src/Adapters/Flickr/Detectors/Code.php | 44 + .../embed/src/Adapters/Flickr/Extractor.php | 16 + .../embed/embed/src/Adapters/Gist/Api.php | 19 + .../Adapters/Gist/Detectors/AuthorName.php | 17 + .../src/Adapters/Gist/Detectors/AuthorUrl.php | 22 + .../src/Adapters/Gist/Detectors/Code.php | 31 + .../Adapters/Gist/Detectors/PublishedTime.php | 18 + .../embed/src/Adapters/Gist/Extractor.php | 28 + .../src/Adapters/Github/Detectors/Code.php | 47 + .../embed/src/Adapters/Github/Extractor.php | 16 + .../src/Adapters/Ideone/Detectors/Code.php | 31 + .../embed/src/Adapters/Ideone/Extractor.php | 16 + .../embed/src/Adapters/ImageShack/Api.php | 36 + .../ImageShack/Detectors/AuthorName.php | 17 + .../ImageShack/Detectors/AuthorUrl.php | 22 + .../ImageShack/Detectors/Description.php | 17 + .../Adapters/ImageShack/Detectors/Image.php | 18 + .../ImageShack/Detectors/ProviderName.php | 14 + .../ImageShack/Detectors/PublishedTime.php | 18 + .../Adapters/ImageShack/Detectors/Title.php | 17 + .../src/Adapters/ImageShack/Extractor.php | 31 + .../src/Adapters/Instagram/Extractor.php | 20 + .../embed/src/Adapters/Instagram/OEmbed.php | 33 + .../src/Adapters/Pinterest/Detectors/Code.php | 41 + .../src/Adapters/Pinterest/Extractor.php | 16 + .../Adapters/Sassmeister/Detectors/Code.php | 45 + .../src/Adapters/Sassmeister/Extractor.php | 16 + .../src/Adapters/Slides/Detectors/Code.php | 39 + .../embed/src/Adapters/Slides/Extractor.php | 16 + .../src/Adapters/Snipplr/Detectors/Code.php | 46 + .../embed/src/Adapters/Snipplr/Extractor.php | 16 + .../src/Adapters/Twitch/Detectors/Code.php | 82 + .../embed/src/Adapters/Twitch/Extractor.php | 16 + .../embed/embed/src/Adapters/Twitter/Api.php | 34 + .../Adapters/Twitter/Detectors/AuthorName.php | 17 + .../Adapters/Twitter/Detectors/AuthorUrl.php | 22 + .../Twitter/Detectors/Description.php | 17 + .../src/Adapters/Twitter/Detectors/Image.php | 28 + .../Twitter/Detectors/ProviderName.php | 14 + .../Twitter/Detectors/PublishedTime.php | 18 + .../src/Adapters/Twitter/Detectors/Title.php | 21 + .../embed/src/Adapters/Twitter/Extractor.php | 31 + .../embed/src/Adapters/Wikipedia/Api.php | 40 + .../Wikipedia/Detectors/Description.php | 17 + .../Adapters/Wikipedia/Detectors/Title.php | 17 + .../src/Adapters/Wikipedia/Extractor.php | 26 + .../src/Adapters/Youtube/Detectors/Feeds.php | 35 + .../embed/src/Adapters/Youtube/Extractor.php | 16 + .../embed/vendor/embed/embed/src/ApiTrait.php | 107 + .../embed/embed/src/Detectors/AuthorName.php | 24 + .../embed/embed/src/Detectors/AuthorUrl.php | 29 + .../vendor/embed/embed/src/Detectors/Cms.php | 68 + .../vendor/embed/embed/src/Detectors/Code.php | 142 + .../embed/embed/src/Detectors/Description.php | 28 + .../embed/embed/src/Detectors/Detector.php | 31 + .../embed/embed/src/Detectors/Favicon.php | 18 + .../embed/embed/src/Detectors/Feeds.php | 35 + .../vendor/embed/embed/src/Detectors/Icon.php | 20 + .../embed/embed/src/Detectors/Image.php | 38 + .../embed/embed/src/Detectors/Keywords.php | 63 + .../embed/embed/src/Detectors/Language.php | 20 + .../embed/embed/src/Detectors/Languages.php | 31 + .../embed/embed/src/Detectors/License.php | 16 + .../embed/src/Detectors/ProviderName.php | 56 + .../embed/embed/src/Detectors/ProviderUrl.php | 24 + .../embed/src/Detectors/PublishedTime.php | 60 + .../embed/embed/src/Detectors/Redirect.php | 26 + .../embed/embed/src/Detectors/Title.php | 27 + .../vendor/embed/embed/src/Detectors/Url.php | 18 + .../embed/vendor/embed/embed/src/Document.php | 124 + .../embed/vendor/embed/embed/src/Embed.php | 89 + .../vendor/embed/embed/src/EmbedCode.php | 42 + .../vendor/embed/embed/src/Extractor.php | 222 + .../embed/embed/src/ExtractorFactory.php | 93 + .../vendor/embed/embed/src/Http/Crawler.php | 77 + .../embed/embed/src/Http/CurlClient.php | 40 + .../embed/embed/src/Http/CurlDispatcher.php | 207 + .../embed/embed/src/Http/FactoryDiscovery.php | 72 + .../embed/embed/src/Http/NetworkException.php | 24 + .../embed/embed/src/Http/RequestException.php | 23 + .../vendor/embed/embed/src/HttpApiTrait.php | 32 + .../vendor/embed/embed/src/LinkedData.php | 111 + .../embed/vendor/embed/embed/src/Metas.php | 43 + .../embed/vendor/embed/embed/src/OEmbed.php | 173 + .../vendor/embed/embed/src/QueryResult.php | 112 + .../vendor/embed/embed/src/functions.php | 156 + .../embed/embed/src/resources/oembed.php | 1134 +++ .../embed/embed/src/resources/suffix.php | 8002 +++++++++++++++++ .../PHP/embed/vendor/ml/iri/ML/IRI/.gitignore | 3 + .../embed/vendor/ml/iri/ML/IRI/.travis.yml | 7 + .../PHP/embed/vendor/ml/iri/ML/IRI/IRI.php | 601 ++ .../PHP/embed/vendor/ml/iri/ML/IRI/LICENSE | 19 + .../PHP/embed/vendor/ml/iri/ML/IRI/README.md | 47 + .../vendor/ml/iri/ML/IRI/Test/IriTest.php | 1078 +++ .../vendor/ml/iri/ML/IRI/Test/bootstrap.php | 12 + .../embed/vendor/ml/iri/ML/IRI/composer.json | 24 + .../vendor/ml/iri/ML/IRI/phpunit.xml.dist | 32 + .../ml/json-ld/.devcontainer/Dockerfile | 16 + .../json-ld/.devcontainer/devcontainer.json | 46 + .../ml/json-ld/.github/workflows/ci.yaml | 43 + .../PHP/embed/vendor/ml/json-ld/.gitignore | 4 + .../vendor/ml/json-ld/.vscode/launch.json | 29 + .../ml/json-ld/DefaultDocumentFactory.php | 28 + .../PHP/embed/vendor/ml/json-ld/Document.php | 206 + .../ml/json-ld/DocumentFactoryInterface.php | 29 + .../vendor/ml/json-ld/DocumentInterface.php | 89 + .../ml/json-ld/DocumentLoaderInterface.php | 31 + .../Exception/InvalidQuadException.php | 61 + .../ml/json-ld/Exception/JsonLdException.php | 307 + .../ml/json-ld/FileGetContentsLoader.php | 197 + .../PHP/embed/vendor/ml/json-ld/Graph.php | 273 + .../vendor/ml/json-ld/GraphInterface.php | 117 + .../PHP/embed/vendor/ml/json-ld/JsonLD.php | 692 ++ .../vendor/ml/json-ld/JsonLdSerializable.php | 38 + .../PHP/embed/vendor/ml/json-ld/LICENSE | 19 + .../ml/json-ld/LanguageTaggedString.php | 95 + .../PHP/embed/vendor/ml/json-ld/NQuads.php | 176 + .../PHP/embed/vendor/ml/json-ld/Node.php | 509 ++ .../embed/vendor/ml/json-ld/NodeInterface.php | 218 + .../PHP/embed/vendor/ml/json-ld/Processor.php | 2973 ++++++ .../PHP/embed/vendor/ml/json-ld/Quad.php | 152 + .../vendor/ml/json-ld/QuadParserInterface.php | 27 + .../ml/json-ld/QuadSerializerInterface.php | 27 + .../PHP/embed/vendor/ml/json-ld/README.md | 104 + .../embed/vendor/ml/json-ld/RdfConstants.php | 28 + .../vendor/ml/json-ld/RemoteDocument.php | 57 + .../vendor/ml/json-ld/Test/DocumentTest.php | 100 + .../ml/json-ld/Test/EarlReportGenerator.php | 273 + .../Test/FileGetContentsLoaderTest.php | 99 + .../ml/json-ld/Test/Fixtures/dataset.jsonld | 36 + .../Test/Fixtures/sample-compacted.jsonld | 24 + .../Test/Fixtures/sample-context.jsonld | 11 + .../Test/Fixtures/sample-expanded.jsonld | 20 + .../Test/Fixtures/sample-flattened.jsonld | 34 + .../ml/json-ld/Test/Fixtures/sample-in.jsonld | 22 + .../sample-serialized-document.jsonld | 23 + .../vendor/ml/json-ld/Test/GraphTest.php | 915 ++ .../vendor/ml/json-ld/Test/JsonLDApiTest.php | 132 + .../vendor/ml/json-ld/Test/JsonTestCase.php | 64 + .../vendor/ml/json-ld/Test/NQuadsTest.php | 106 + .../ml/json-ld/Test/TestManifestIterator.php | 120 + .../vendor/ml/json-ld/Test/ValueTest.php | 138 + .../ml/json-ld/Test/W3CTestSuiteTest.php | 368 + .../vendor/ml/json-ld/Test/bootstrap.php | 19 + .../embed/vendor/ml/json-ld/TypedValue.php | 139 + .../PHP/embed/vendor/ml/json-ld/Value.php | 123 + .../PHP/embed/vendor/ml/json-ld/composer.json | 30 + .../embed/vendor/ml/json-ld/phpunit.xml.dist | 74 + .../html-parser/.github/workflows/test.yml | 44 + .../oscarotero/html-parser/CHANGELOG.md | 54 + .../vendor/oscarotero/html-parser/LICENSE | 21 + .../vendor/oscarotero/html-parser/README.md | 25 + .../oscarotero/html-parser/composer.json | 41 + .../oscarotero/html-parser/src/Parser.php | 95 + .../embed/vendor/psr/http-client/CHANGELOG.md | 23 + .../PHP/embed/vendor/psr/http-client/LICENSE | 19 + .../embed/vendor/psr/http-client/README.md | 12 + .../vendor/psr/http-client/composer.json | 27 + .../src/ClientExceptionInterface.php | 10 + .../psr/http-client/src/ClientInterface.php | 20 + .../src/NetworkExceptionInterface.php | 24 + .../src/RequestExceptionInterface.php | 24 + .../embed/vendor/psr/http-factory/.gitignore | 2 + .../vendor/psr/http-factory/.pullapprove.yml | 7 + .../PHP/embed/vendor/psr/http-factory/LICENSE | 21 + .../embed/vendor/psr/http-factory/README.md | 10 + .../vendor/psr/http-factory/composer.json | 35 + .../src/RequestFactoryInterface.php | 18 + .../src/ResponseFactoryInterface.php | 18 + .../src/ServerRequestFactoryInterface.php | 24 + .../src/StreamFactoryInterface.php | 45 + .../src/UploadedFileFactoryInterface.php | 34 + .../http-factory/src/UriFactoryInterface.php | 17 + .../vendor/psr/http-message/CHANGELOG.md | 36 + .../PHP/embed/vendor/psr/http-message/LICENSE | 19 + .../embed/vendor/psr/http-message/README.md | 13 + .../vendor/psr/http-message/composer.json | 26 + .../psr/http-message/src/MessageInterface.php | 187 + .../psr/http-message/src/RequestInterface.php | 129 + .../http-message/src/ResponseInterface.php | 68 + .../src/ServerRequestInterface.php | 261 + .../psr/http-message/src/StreamInterface.php | 158 + .../src/UploadedFileInterface.php | 123 + .../psr/http-message/src/UriInterface.php | 323 + .../Private/Templates/RsmoembedDefault.html | 33 + Resources/Public/Css/styles.css | 19 + Resources/Public/Css/styles.css.map | 7 + Resources/Public/Css/styles.scss | 27 + .../Icons/Backend/rsmoembed_default.svg | 7 + Resources/Public/Icons/Extension.svg | 7 + Resources/Public/JavaScript/main.js | 26 + composer.json | 49 + ext_emconf.php | 19 + ext_localconf.php | 31 + ext_tables.php | 24 + ext_tables.sql | 7 + 254 files changed, 34818 insertions(+) create mode 100644 Classes/Hooks/GetOembedDataHook.php create mode 100644 Classes/Middleware/Api.php create mode 100644 Classes/ViewHelpers/JsonToObjectViewHelper.php create mode 100644 Configuration/RequestMiddlewares.php create mode 100644 Configuration/TCA/Overrides/sys_file_reference.php create mode 100644 Configuration/TCA/Overrides/sys_template.php create mode 100644 Configuration/TCA/Overrides/tt_content.php create mode 100644 Configuration/TsConfig/All.tsconfig create mode 100644 Configuration/TsConfig/ContentElements/RsmoembedDefault.tsconfig create mode 100644 Configuration/TypoScript/ContentElements/RsmoembedDefault.typoscript create mode 100644 Configuration/TypoScript/constants.typoscript create mode 100644 Configuration/TypoScript/setup.typoscript create mode 100644 Resources/Private/.htaccess create mode 100644 Resources/Private/Api/Content.html create mode 100644 Resources/Private/Language/RsmoembedDefault/de.locallang_db.xlf create mode 100644 Resources/Private/Language/RsmoembedDefault/locallang_db.xlf create mode 100644 Resources/Private/Language/locallang.xlf create mode 100644 Resources/Private/Language/locallang_csh_tt_content.xlf create mode 100644 Resources/Private/Language/locallang_db.xlf create mode 100644 Resources/Private/PHP/embed/composer.json create mode 100644 Resources/Private/PHP/embed/composer.lock create mode 100644 Resources/Private/PHP/embed/vendor/autoload.php create mode 100644 Resources/Private/PHP/embed/vendor/composer/ClassLoader.php create mode 100644 Resources/Private/PHP/embed/vendor/composer/InstalledVersions.php create mode 100644 Resources/Private/PHP/embed/vendor/composer/LICENSE create mode 100644 Resources/Private/PHP/embed/vendor/composer/autoload_classmap.php create mode 100644 Resources/Private/PHP/embed/vendor/composer/autoload_files.php create mode 100644 Resources/Private/PHP/embed/vendor/composer/autoload_namespaces.php create mode 100644 Resources/Private/PHP/embed/vendor/composer/autoload_psr4.php create mode 100644 Resources/Private/PHP/embed/vendor/composer/autoload_real.php create mode 100644 Resources/Private/PHP/embed/vendor/composer/autoload_static.php create mode 100644 Resources/Private/PHP/embed/vendor/composer/ca-bundle/LICENSE create mode 100644 Resources/Private/PHP/embed/vendor/composer/ca-bundle/README.md create mode 100644 Resources/Private/PHP/embed/vendor/composer/ca-bundle/composer.json create mode 100644 Resources/Private/PHP/embed/vendor/composer/ca-bundle/res/cacert.pem create mode 100644 Resources/Private/PHP/embed/vendor/composer/ca-bundle/src/CaBundle.php create mode 100644 Resources/Private/PHP/embed/vendor/composer/installed.json create mode 100644 Resources/Private/PHP/embed/vendor/composer/installed.php create mode 100644 Resources/Private/PHP/embed/vendor/composer/platform_check.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/CHANGELOG.md create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/LICENSE create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/README.md create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/composer.json create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Api.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Detectors/AuthorName.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Detectors/Code.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Detectors/Description.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Detectors/ProviderName.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Detectors/PublishedTime.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Detectors/Title.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Extractor.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Bandcamp/Detectors/ProviderName.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Bandcamp/Extractor.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/CadenaSer/Detectors/Code.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/CadenaSer/Extractor.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Facebook/Detectors/Title.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Facebook/Extractor.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Facebook/OEmbed.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Flickr/Detectors/Code.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Flickr/Extractor.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Api.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Detectors/AuthorName.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Detectors/AuthorUrl.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Detectors/Code.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Detectors/PublishedTime.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Extractor.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Github/Detectors/Code.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Github/Extractor.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Ideone/Detectors/Code.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Ideone/Extractor.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Api.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/AuthorName.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/AuthorUrl.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/Description.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/Image.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/ProviderName.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/PublishedTime.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/Title.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Extractor.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Instagram/Extractor.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Instagram/OEmbed.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Pinterest/Detectors/Code.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Pinterest/Extractor.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Sassmeister/Detectors/Code.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Sassmeister/Extractor.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Slides/Detectors/Code.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Slides/Extractor.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Snipplr/Detectors/Code.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Snipplr/Extractor.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitch/Detectors/Code.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitch/Extractor.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Api.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/AuthorName.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/AuthorUrl.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/Description.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/Image.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/ProviderName.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/PublishedTime.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/Title.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Extractor.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Wikipedia/Api.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Wikipedia/Detectors/Description.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Wikipedia/Detectors/Title.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Wikipedia/Extractor.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Youtube/Detectors/Feeds.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Youtube/Extractor.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/ApiTrait.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/AuthorName.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/AuthorUrl.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Cms.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Code.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Description.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Detector.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Favicon.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Feeds.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Icon.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Image.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Keywords.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Language.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Languages.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/License.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/ProviderName.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/ProviderUrl.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/PublishedTime.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Redirect.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Title.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Url.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Document.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Embed.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/EmbedCode.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Extractor.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/ExtractorFactory.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Http/Crawler.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Http/CurlClient.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Http/CurlDispatcher.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Http/FactoryDiscovery.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Http/NetworkException.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Http/RequestException.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/HttpApiTrait.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/LinkedData.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/Metas.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/OEmbed.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/QueryResult.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/functions.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/resources/oembed.php create mode 100644 Resources/Private/PHP/embed/vendor/embed/embed/src/resources/suffix.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/.gitignore create mode 100644 Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/.travis.yml create mode 100644 Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/IRI.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/LICENSE create mode 100644 Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/README.md create mode 100644 Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/Test/IriTest.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/Test/bootstrap.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/composer.json create mode 100644 Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/phpunit.xml.dist create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/.devcontainer/Dockerfile create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/.devcontainer/devcontainer.json create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/.github/workflows/ci.yaml create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/.gitignore create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/.vscode/launch.json create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/DefaultDocumentFactory.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Document.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/DocumentFactoryInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/DocumentInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/DocumentLoaderInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Exception/InvalidQuadException.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Exception/JsonLdException.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/FileGetContentsLoader.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Graph.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/GraphInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/JsonLD.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/JsonLdSerializable.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/LICENSE create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/LanguageTaggedString.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/NQuads.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Node.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/NodeInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Processor.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Quad.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/QuadParserInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/QuadSerializerInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/README.md create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/RdfConstants.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/RemoteDocument.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Test/DocumentTest.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Test/EarlReportGenerator.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Test/FileGetContentsLoaderTest.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/dataset.jsonld create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-compacted.jsonld create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-context.jsonld create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-expanded.jsonld create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-flattened.jsonld create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-in.jsonld create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-serialized-document.jsonld create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Test/GraphTest.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Test/JsonLDApiTest.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Test/JsonTestCase.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Test/NQuadsTest.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Test/TestManifestIterator.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Test/ValueTest.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Test/W3CTestSuiteTest.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Test/bootstrap.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/TypedValue.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/Value.php create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/composer.json create mode 100644 Resources/Private/PHP/embed/vendor/ml/json-ld/phpunit.xml.dist create mode 100644 Resources/Private/PHP/embed/vendor/oscarotero/html-parser/.github/workflows/test.yml create mode 100644 Resources/Private/PHP/embed/vendor/oscarotero/html-parser/CHANGELOG.md create mode 100644 Resources/Private/PHP/embed/vendor/oscarotero/html-parser/LICENSE create mode 100644 Resources/Private/PHP/embed/vendor/oscarotero/html-parser/README.md create mode 100644 Resources/Private/PHP/embed/vendor/oscarotero/html-parser/composer.json create mode 100644 Resources/Private/PHP/embed/vendor/oscarotero/html-parser/src/Parser.php create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-client/CHANGELOG.md create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-client/LICENSE create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-client/README.md create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-client/composer.json create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-client/src/ClientExceptionInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-client/src/ClientInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-client/src/NetworkExceptionInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-client/src/RequestExceptionInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-factory/.gitignore create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-factory/.pullapprove.yml create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-factory/LICENSE create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-factory/README.md create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-factory/composer.json create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-factory/src/RequestFactoryInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-factory/src/ResponseFactoryInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-factory/src/ServerRequestFactoryInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-factory/src/StreamFactoryInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-factory/src/UriFactoryInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-message/CHANGELOG.md create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-message/LICENSE create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-message/README.md create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-message/composer.json create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-message/src/MessageInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-message/src/RequestInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-message/src/ResponseInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-message/src/ServerRequestInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-message/src/StreamInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-message/src/UploadedFileInterface.php create mode 100644 Resources/Private/PHP/embed/vendor/psr/http-message/src/UriInterface.php create mode 100644 Resources/Private/Templates/RsmoembedDefault.html create mode 100644 Resources/Public/Css/styles.css create mode 100644 Resources/Public/Css/styles.css.map create mode 100644 Resources/Public/Css/styles.scss create mode 100644 Resources/Public/Icons/Backend/rsmoembed_default.svg create mode 100644 Resources/Public/Icons/Extension.svg create mode 100644 Resources/Public/JavaScript/main.js create mode 100644 composer.json create mode 100644 ext_emconf.php create mode 100644 ext_localconf.php create mode 100644 ext_tables.php create mode 100644 ext_tables.sql diff --git a/Classes/Hooks/GetOembedDataHook.php b/Classes/Hooks/GetOembedDataHook.php new file mode 100644 index 0000000..90b1c66 --- /dev/null +++ b/Classes/Hooks/GetOembedDataHook.php @@ -0,0 +1,406 @@ +setSettings([ + //'oembed:query_parameters' => [], //Extra parameters send to oembed + //'twitch:parent' => 'example.com', //Required to embed twitch videos as iframe + //'facebook:token' => '1234|5678', //Required to embed content from Facebook + //'instagram:token' => '1234|5678', //Required to embed content from Instagram + //'twitter:token' => 'asdf', //Improve the data from twitter + ]); + //$info = $embed->get('https://www.instagram.com/p/CoDZMlQMIrd/'); + + //$info = $embed->get('https://www.facebook.com/Ressourcenmangel/posts/pfbid036kBZ29byhKFuxZqNnDeUwmsqVefuh8wEK2eidES4ExQ6PrqyGsTM7JjdfUw2Lvw5l'); + + //$info = $embed->get('https://soundcloud.com/user-898723330/manuchao-kingo-of-the-bongo'); + + $info = $embed->get($uriSanitized); + + $infoAll = []; + $infoAll += [ + 'meta_oembed_title' => $info->getMetas()->get('og:title') ?? '', + 'meta_oembed_description' => $info->getMetas()->get('og:description') ?? '', + 'meta_oembed_image' => $info->getMetas()->get('og:image') ?? '', + 'meta_oembed_url' => $info->getMetas()->get('og:url') ?? '', + ]; + + $infoAll += [ + //The page title + 'info_title' => $info->title, + //The page description + 'info_description' => $info->description, + //The canonical url + 'info_url' => $info->url, + //The page keywords + 'info_keywords' => $info->keywords, + //The thumbnail or main image + 'info_image' => $info->image, + //The code to embed the image, video, etc + 'info_code_html' => $info->code ? $info->code->html : '', + //The exact width of the embed code (if exists) + 'info_code_width' => $info->code ? $info->code->width : '', + //The exact height of the embed code (if exists) + 'info_code_height' => $info->code ? $info->code->height : '', + //The aspect ratio (width/height) + 'info_code_ratio' => $info->code ? $info->code->ratio : '', + //The resource author + 'info_author_name' => $info->authorName, + //The author url + 'info_author_url' => $info->authorUrl, + //The cms used + 'info_cms' => $info->cms, + //The language of the page + 'info_language' => $info->language, + //The alternative languages + 'info_languages' => $info->languages, + //The provider name of the page (Youtube, etc) + 'info_provider_name' => $info->providerName, + //The provider url + 'info_provider_url' => $info->providerUrl, + //The big icon of the site + 'info_icon' => $info->icon, + //The favicon of the site (an .ico file or a png with up to 32x32px) + 'info_favicon' => $info->favicon, + //The published time of the resource + 'info_published_time' => $info->publishedTime, + //The license url of the resource + 'info_license' => $info->license, + //The RSS/Atom feeds + 'info_feeds' => $info->feeds, + ]; + + $fieldArray['tx_rsmoembed_data'] = json_encode($infoAll, JSON_PRETTY_PRINT); + + } elseif ($uri) { + $fieldArray['tx_rsmoembed_url'] = ''; + $fieldArray['tx_rsmoembed_data'] = ''; + + $flashMessage = new FlashMessage( + 'URL is not valid: ' . $uri, + 'Use valid Url', + FlashMessage::ERROR + ); + $this->flashMessages($flashMessage); + } + } + } + + /** + * Post-process after save + * + * @param string $status + * @param string $table + * @param string $id + * @param array $fieldArray + * @param DataHandler $dataHandler + * @return mixed + * @throws \Exception + * + */ + public function processDatamap_afterDatabaseOperations( + string $status, + string $table, + $id, + array $fieldArray, + DataHandler $dataHandler + ): void + { + if ($table === 'tt_content' && ($status === 'new' || $status === 'update')) { + + if (strpos($id, 'NEW') !== false) { + // Replace NEW...-ID with real uid: + $id = $dataHandler->substNEWwithIDs[$id]; + } + + if (intval($id) > 0 ) { + $contentElement = BackendUtility::getRecord( + 'tt_content', + (int)$id + ); + // image download agreed + if ((int) $contentElement['tx_rsmoembed_image_download'] === 1) { + $return = $contentElement['tx_rsmoembed_data']; + $result = json_decode($return, true); + + // meta_oembed_image || info_image + + + if ((int)$contentElement['tx_rsmoembed_image'] < 1) { + $previewPathReturn = ''; + if ($result['info_provider_name'] && $result['info_image']) { + $previewPathReturn = $this->addFileFromUri($result['info_provider_name'], $result['info_image']); + $flashMessage = new FlashMessage( + 'Preview generated from: ' . $result['info_image'], + 'New Preview Image', + FlashMessage::OK + ); + $this->flashMessages($flashMessage); + + } elseif ($result['info_provider_name'] && $result['meta_oembed_image']) { + // TODO ... oembed_provider_name + oembed_thumbnail_url + $previewPathReturn = $this->addFileFromUri($result['oembed_provider_name'], $result['meta_oembed_image']); + $flashMessage = new FlashMessage( + 'Preview generated from: ' . $result['meta_oembed_image'], + 'New Preview Image', + FlashMessage::OK + ); + $this->flashMessages($flashMessage); + } else { + $flashMessage = new FlashMessage( + 'No preview image url given.', + 'Preview Image', + FlashMessage::WARNING + ); + $this->flashMessages($flashMessage); + + } + + if ($previewPathReturn) { + $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class); + try { + $fileObject = $resourceFactory->retrieveFileOrFolderObject($previewPathReturn); + } catch (\Exception $e) { + // silent die + } + + $fileObjectUid = $fileObject->getProperty('uid'); + + // Assemble DataHandler data + $newId = 'NEW1234'; + $data = []; + $data['sys_file_reference'][$newId] = [ + 'table_local' => 'sys_file', + 'uid_local' => $fileObjectUid, + 'tablenames' => 'tt_content', + 'uid_foreign' => $contentElement['uid'], + 'fieldname' => 'tx_rsmoembed_image', + 'pid' => $contentElement['pid'], + ]; + $data['tt_content'][$contentElement['uid']] = [ + 'tx_rsmoembed_image' => $newId, + 'tx_rsmoembed_image_download' => '', + 'pid' => $contentElement['pid'], + ]; + + $this->processData($data); + } + } elseif ( + (int) $fieldArray['tx_rsmoembed_image'] == 0 + && array_key_exists('tx_rsmoembed_url',$fieldArray) + ) { + $data['tt_content'][$contentElement['uid']] = [ + 'tx_rsmoembed_image_download' => '', + 'pid' => $contentElement['pid'], + ]; + $this->processData($data); + + $flashMessage = new FlashMessage( + 'No new preview image assigned, + to automatically assign a new preview remove the existing and save again.', + 'Check Preview Image', + FlashMessage::WARNING + ); + $this->flashMessages($flashMessage); + } elseif ( + (int)$fieldArray['tx_rsmoembed_image'] == 0 + && !array_key_exists('tx_rsmoembed_url',$fieldArray) + ) { + $data['tt_content'][$contentElement['uid']] = [ + 'tx_rsmoembed_image_download' => '', + 'pid' => $contentElement['pid'], + ]; + $this->processData($data); + } else { + $data['tt_content'][$contentElement['uid']] = [ + 'tx_rsmoembed_image_download' => '', + 'pid' => $contentElement['pid'], + ]; + $this->processData($data); + $flashMessage = new FlashMessage( + 'Please check the preview image.', + 'Check Preview Image', + FlashMessage::INFO + ); + $this->flashMessages($flashMessage); + } + } + + /// end of image assign + + } + + + } + } + + /** + * @param array $data + */ + private function processData(array $data) + { +// Get an instance of the DataHandler and process the data + /** @var DataHandler $dataHandler */ + $dataHandler = GeneralUtility::makeInstance(DataHandler::class); + $dataHandler->start($data, []); + $dataHandler->process_datamap(); + // Error or success reporting + if (count($dataHandler->errorLog) === 0) { + // Handle success + } else { + // Handle errors + } + } + private function addFileFromUri($provider, $thumbnail_url) + { + // some providers deliver cruel thumbnail urls with get vars + $thumbnailUrlWithoutQueryParams = strtok($thumbnail_url,'?'); + + $filename = strtolower($provider) + . '_' . sha1($thumbnail_url); + //. '_' . basename($thumbnailUrlWithoutQueryParams); + + $previewPathRelative = GeneralUtility::getFileAbsFileName('fileadmin/') . 'o_embed/' . $provider . '/'; + GeneralUtility::mkdir_deep($previewPathRelative); + $previewPathLocal = GeneralUtility::getFileAbsFileName($previewPathRelative) . $filename; + if (!pathinfo($previewPathLocal, PATHINFO_EXTENSION )) { + $previewPathLocal = $previewPathLocal . '.jpg'; + } + + $previewPathReturn = is_readable($previewPathLocal) ? $previewPathLocal : false; + if (!$previewPathReturn) { + $previewImageString = @file_get_contents($thumbnail_url); + + if ($previewImageString) { + file_put_contents($previewPathLocal, $previewImageString); + } + + $previewPathReturn = is_readable($previewPathLocal) ? $previewPathLocal : false; + + } + return $previewPathReturn; + } + + /** + * @param FlashMessage $flashMessage + * @throws \Exception + * @return mixed + */ + private function flashMessages(FlashMessage $flashMessage) + { + try { + /** @var FlashMessageService $flashMessageService */ + $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); + /** @var FlashMessageQueue $defaultFlashMessageQueue */ + $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); + $defaultFlashMessageQueue->enqueue($flashMessage); + } catch (\Exception $e) { + // Top level catch to ensure useful following exception handling, because FAL throws top level exceptions. + // TYPO3\CMS\Core\Database\ReferenceIndex::getRelations() will check the return value of this hook with is_array() + // so we return false to tell getRelations() to do nothing. + return false; + } + } + + /** + * Returns the current BE user. + * + * @return BackendUserAuthentication + */ + protected function getBackendUser(): BackendUserAuthentication + { + return $GLOBALS['BE_USER']; + } + + /** + * Simple debug logger, maybe helpful if you have trouble + * Why do you need this: Belly :-) Got me.... or not + * It can write parallel desired log infos, while having a valid JSON response for example + * + * This function should write a human-readable file to: + * typo3temp/FOLDER_SEE_BELOW/timeStamp . _debug . $fileSuffix . txt + * @usage $this->writeDebugFile($your_content, '_some_file_suffix'); + * @param mixed|null $content The content to debug + * @param string $fileSuffix The debug file suffix + */ + private function writeDebugFile($content, string $fileSuffix = 'default'): void + { + $debugFolder = '/typo3temp/simplereference_debug/'; + // Secure folder, may contain sensible data + if (!@is_file(Environment::getPublicPath() . $debugFolder . '.htaccess')) { + GeneralUtility::writeFileToTypo3tempDir( + Environment::getPublicPath() . $debugFolder . '.htaccess', + ' +# Apache < 2.3 + + Order allow,deny + Deny from all + Satisfy All + + +# Apache >= 2.3 + + Require all denied + +' + ); + } + + $debugFile = $debugFolder . microtime(true) . '_debug_' . $fileSuffix . '.txt'; + if (!@is_file(Environment::getPublicPath() . $debugFile)) { + GeneralUtility::writeFileToTypo3tempDir( + Environment::getPublicPath() . $debugFile, + print_r($content, true) + ); + } + } +} diff --git a/Classes/Middleware/Api.php b/Classes/Middleware/Api.php new file mode 100644 index 0000000..1408bf2 --- /dev/null +++ b/Classes/Middleware/Api.php @@ -0,0 +1,211 @@ +writeDebugFile($WHAT_TO_DEBUG, '_initializeAndCheckFeUser'); + * + * */ + +// @TODO: rework and create documentation +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Server\MiddlewareInterface; +use Psr\Http\Server\RequestHandlerInterface; +use TYPO3\CMS\Core\Context\Context; +use TYPO3\CMS\Core\Core\Environment; +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Http\JsonResponse; +use TYPO3\CMS\Core\Http\Response; +use TYPO3\CMS\Core\Http\Stream; +use TYPO3\CMS\Core\Routing\PageArguments; +use TYPO3\CMS\Core\Site\Entity\Site; +use TYPO3\CMS\Core\TypoScript\TemplateService; +use TYPO3\CMS\Core\Utility\DebugUtility; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Core\Utility\RootlineUtility; +use TYPO3\CMS\Fluid\View\StandaloneView; +use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; +use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; + +class Api implements MiddlewareInterface +{ + /** + * The prefix extension key / folder + * @var string $extKey + */ + private $extKey = 'rsmoembed'; + /** + * The prefix for GET or POST var array + * used like: ?requestKey[findOne]=123 + * @var string $requestKey + */ + private $requestKey = 'tx_rsmoembed_api'; + + /** + * The incoming _GET or _POST vars + * @var array $parameters + */ + private $parameters = []; + + /** + * The allowed functions / commands + * @var array $allowedCommands + */ + private $allowedCommands = [ + 'findOne', + ]; + + /** + * The main DB table used here + * @var string $baseTable + */ + private $baseTable = 'tt_content'; + + /** + * The content + * @var string $content + */ + private $content = ''; + + /** + * Main function, returns the final result + * @param ServerRequestInterface $request + * @param RequestHandlerInterface $handler + * @return ResponseInterface + */ + public function process( + ServerRequestInterface $request, + RequestHandlerInterface $handler + ): ResponseInterface + { + /** @var ServerRequestInterface $request */ + + + $this->parameters = $request->getParsedBody()[$this->requestKey] + ?? $request->getQueryParams()[$this->requestKey] + ?? null; + + + + if (is_array($this->parameters) + && array_key_exists('action', $this->parameters)) { + + // command is the function to call + // must be in the array of $allowedCommands + $command = (string)$this->parameters['action'] ?? ''; + + + if ($command + && in_array($command, $this->allowedCommands) + && method_exists($this, $command) + ) { + $this->$command(); + } else { + $this->content = "

Something went wrong. Maybe action: -| $command |- does not exist or is not allowed here.

"; + + } + + $body = new Stream('php://temp', 'rw'); + + $body->write($this->content); + + return (new Response()) + ->withHeader('Access-Control-Allow-Origin', '*') + ->withHeader('Expires', 'Sat, 26 Jul 1997 05:00:00 GMT') + ->withHeader('Cache-Control', 'private, no-store, no-cache, must-revalidate, post-check=0, pre-check=0') + ->withHeader('content-type', 'text/html; charset=utf-8') + ->withHeader('Pragma', 'no-cache') + ->withBody($body) + ->withStatus(200); + } + + return $handler->handle($request); + } + + + /** + * Find content element by uid + * @return void + */ + + private function findOne(): void + { + $connection = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable($this->baseTable); + $result = $connection + ->select('*') + ->from($this->baseTable) + ->where('uid=:theUid') + ->andWhere('CType in ("rsmoembed_default")') + ->setParameters( + [ + 'theUid' => $this->parameters['uid'], + ], [ + \PDO::PARAM_INT, + ] + ) + ->execute() + ->fetchAssociative(); + + if (is_array($result)) { + $this->content = $this->renderContent($result); + } else { + $this->content = ''; + } + } + + /** + * @param string $templateName + * @return mixed + */ + protected function renderContent($data) + { + // prepare own template + $fluidTemplateFile = GeneralUtility::getFileAbsFileName( + 'EXT:' . $this->extKey . '/Resources/Private/Api/Content.html' + ); + $view = GeneralUtility::makeInstance(StandaloneView::class); + $view->setTemplatePathAndFilename($fluidTemplateFile); + $view->assignMultiple([ + 'data' => $data, + 'oembedData' => json_decode($data['tx_rsmoembed_data'], true), + ]); + + return $view->render(); + } + + + /** + * Simple debug logger, maybe helpful if you have trouble + * This function writes a file to: + * typo3temp/api/time() . _debug . _some_file_suffix . txt + * @usage $this->writeDebugFile($your_content, '_some_file_suffix'); + * @param mixed|null $content The content to debug + * @param string $fileSuffix The debug file suffix + */ + private function writeDebugFile($content, string $fileSuffix = '1'): void + { + $debugFile = 'typo3temp/assets/sitedefault_api_debug/' . time() . '_debug_' . $fileSuffix . '.txt'; + if (!@is_file(Environment::getPublicPath() . '/' . $debugFile)) { + GeneralUtility::writeFileToTypo3tempDir( + Environment::getPublicPath() . '/' . $debugFile, + print_r($content, true) + ); + } + } +} diff --git a/Classes/ViewHelpers/JsonToObjectViewHelper.php b/Classes/ViewHelpers/JsonToObjectViewHelper.php new file mode 100644 index 0000000..243dfcd --- /dev/null +++ b/Classes/ViewHelpers/JsonToObjectViewHelper.php @@ -0,0 +1,52 @@ +registerArgument( + 'value', + 'string', + 'The incoming data to convert, or null if VH children should be used' + ); + } + + /** + * Applies json_decode() on the specified value. + * + * @param array $arguments + * @param \Closure $renderChildrenClosure + * @param RenderingContextInterface $renderingContext + * @see https://www.php.net/manual/function.json-decode.php + * @return object + */ + public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) + { + $value = $renderChildrenClosure(); + return json_decode($value, true); + } +} diff --git a/Configuration/RequestMiddlewares.php b/Configuration/RequestMiddlewares.php new file mode 100644 index 0000000..5fdf55a --- /dev/null +++ b/Configuration/RequestMiddlewares.php @@ -0,0 +1,15 @@ + [ + 'dimension/sitedefault/api' => [ + 'target' => \Ressourcenmangel\Rsmoembed\Middleware\Api::class, + 'after' => [ + 'typo3/cms-frontend/tsfe', + ], + 'before' => [ + 'typo3/cms-frontend/shortcut-and-mountpoint-redirect', + ], + ], + ] +]; diff --git a/Configuration/TCA/Overrides/sys_file_reference.php b/Configuration/TCA/Overrides/sys_file_reference.php new file mode 100644 index 0000000..f1de577 --- /dev/null +++ b/Configuration/TCA/Overrides/sys_file_reference.php @@ -0,0 +1,6 @@ + [ + 'exclude' => true, + 'label' => 'LLL:EXT:rsmoembed/Resources/Private/Language/locallang_db.xlf:tt_content.tx_rsmoembed_url', + 'config' => [ + 'type' => 'input', + 'size' => 100, + 'eval' => 'trim,required', + 'default' => '' + ], + ], + 'tx_rsmoembed_data' => [ + 'exclude' => true, + 'label' => 'LLL:EXT:rsmoembed/Resources/Private/Language/locallang_db.xlf:tt_content.tx_rsmoembed_data', + 'config' => [ + 'type' => 'text', + 'cols' => 100, + 'rows' => 5, + 'eval' => 'trim', + 'default' => '' + ] + ], + 'tx_rsmoembed_image_download' => [ + 'exclude' => true, + 'label' => 'LLL:EXT:rsmoembed/Resources/Private/Language/locallang_db.xlf:tt_content.tx_rsmoembed_image_download', + 'config' => [ + 'type' => 'check', + 'renderType' => 'checkboxToggle', + 'items' => [ + [ + 0 => 'LLL:EXT:rsmoembed/Resources/Private/Language/locallang_db.xlf:tt_content.tx_rsmoembed_image_download.0', + 1 => '', + ] + ], + 'default' => 0, + ] + ], + 'tx_rsmoembed_image' => [ + 'exclude' => true, + 'label' => 'LLL:EXT:rsmoembed/Resources/Private/Language/locallang_db.xlf:tt_content.tx_rsmoembed_image', + 'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig( + 'tx_rsmoembed_image', + [ + 'appearance' => [ + 'createNewRelationLinkTitle' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:images.addFileReference' + ], + 'overrideChildTca' => [ + 'types' => [ + '0' => [ + 'showitem' => ' + --palette--;;rsmoembed_title_alt__crop, + --palette--;;filePalette' + ], + \TYPO3\CMS\Core\Resource\File::FILETYPE_IMAGE => [ + 'showitem' => ' + --palette--;;rsmoembed_title_alt__crop, + --palette--;;filePalette' + ], + ], + ], + 'foreign_match_fields' => [ + 'fieldname' => 'tx_rsmoembed_image', + 'tablenames' => 'tt_content', + 'table_local' => 'sys_file', + ], + 'maxitems' => 1, + 'minitems' => 0 + ], + $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'] + ), + ], + ]; + + \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns( + 'tt_content', + $tmp_rsmoembed_columns + ); + + +////////////////////////////////////////////////////////////// +// CE Oembed Default Default +////////////////////////////////////////////////////////////// + $tmp_rsmoembed_ce = $tmp_rsmoembed_extkey . '_default'; + + \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItem( + 'tt_content', + 'CType', + [ + 'LLL:EXT:' . $tmp_rsmoembed_extkey . '/Resources/Private/Language/RsmoembedDefault/locallang_db.xlf:title', + $tmp_rsmoembed_ce, + $tmp_rsmoembed_ce, + ], + 'text', + 'after' + ); +//tx_rsmoembed_data, + $GLOBALS['TCA']['tt_content']['types'][$tmp_rsmoembed_ce] = [ + 'showitem' => ' + --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.general;general, + --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.headers;headers, + bodytext, + tx_rsmoembed_url, + + tx_rsmoembed_image_download, + tx_rsmoembed_image, + --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.appearance, + --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.frames;frames, + --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.appearanceLinks;appearanceLinks, + --div--;LLL:EXT:sitedefault/Resources/Private/Language/locallang_db.xlf:div.transitions, tx_sitedefault_flex_b,, + --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language, + --palette--;;language, + --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access, + --palette--;;hidden, + --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.access;access, + --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:categories, categories, + --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:notes, rowDescription, + --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:extended' + , + 'columnsOverrides' => [ + 'bodytext' => [ + 'config' => [ + 'softref' => 'typolink_tag,images,email[subst],url', + 'enableRichtext' => true, + ], + ], + ], + ]; +}); diff --git a/Configuration/TsConfig/All.tsconfig b/Configuration/TsConfig/All.tsconfig new file mode 100644 index 0000000..304435a --- /dev/null +++ b/Configuration/TsConfig/All.tsconfig @@ -0,0 +1,2 @@ +@import 'EXT:rsmoembed/Configuration/TsConfig/ContentElements/*.tsconfig' + diff --git a/Configuration/TsConfig/ContentElements/RsmoembedDefault.tsconfig b/Configuration/TsConfig/ContentElements/RsmoembedDefault.tsconfig new file mode 100644 index 0000000..c26e4e5 --- /dev/null +++ b/Configuration/TsConfig/ContentElements/RsmoembedDefault.tsconfig @@ -0,0 +1,23 @@ +mod.wizards.newContentElement.wizardItems.common { + elements.rsmoembed_default { + iconIdentifier = rsmoembed_default + title = LLL:EXT:rsmoembed/Resources/Private/Language/RsmoembedDefault/locallang_db.xlf:title + description = LLL:EXT:rsmoembed/Resources/Private/Language/RsmoembedDefault/locallang_db.xlf:description + tt_content_defValues { + CType = rsmoembed_default + } + + #saveAndClose = true + } + + show := addToList(rsmoembed_default) +} + +# =-=-=-=-=-=-=-=-=-=-=-=-=-= +# PREVIEW +# =-=-=-=-=-=-=-=-=-=-=-=-=-= +#mod.web_layout.tt_content { +# preview { +# rsmoembed_default = EXT:rsmoembed/Resources/Private/Backend/Templates/RsmoembedDefault.html +# } +#} diff --git a/Configuration/TypoScript/ContentElements/RsmoembedDefault.typoscript b/Configuration/TypoScript/ContentElements/RsmoembedDefault.typoscript new file mode 100644 index 0000000..e165035 --- /dev/null +++ b/Configuration/TypoScript/ContentElements/RsmoembedDefault.typoscript @@ -0,0 +1,25 @@ +tt_content.rsmoembed_default =< lib.contentElement +tt_content.rsmoembed_default { + + templateName = RsmoembedDefault + templateRootPaths { + 16753462650 = EXT:rsmoembed/Resources/Private/Templates/ + 16753462651 = {$plugin.tx_rsmoembed.view.templateRootPath} + } + partialRootPaths { + 16753462650 = EXT:rsmoembed/Resources/Private/Partials/ + 16753462651 = {$plugin.tx_rsmoembed.view.partialRootPath} + } + layoutRootPaths { + 16753462650 = EXT:rsmoembed/Resources/Private/Layouts/ + 16753462651 = {$plugin.tx_rsmoembed.view.layoutRootPath} + } + dataProcessing { + 10 = TYPO3\CMS\Frontend\DataProcessing\FilesProcessor + 10 { + references.table = tt_content + references.fieldName = tx_rsmoembed_image + as = images + } + } +} diff --git a/Configuration/TypoScript/constants.typoscript b/Configuration/TypoScript/constants.typoscript new file mode 100644 index 0000000..df3ec4c --- /dev/null +++ b/Configuration/TypoScript/constants.typoscript @@ -0,0 +1,10 @@ +plugin.tx_rsmoembed { + view { + # cat=rsmoembed templates/view/default; type=string; label=Path to templates root (FE) + templateRootPath = + # cat=rsmoembed templates/view/default; type=string; label=Path to templates partials (FE) + partialRootPath = + # cat=rsmoembed templates/view/default; type=string; label=Path to templates layouts (FE) + layoutRootPath = + } +} diff --git a/Configuration/TypoScript/setup.typoscript b/Configuration/TypoScript/setup.typoscript new file mode 100644 index 0000000..c25be4b --- /dev/null +++ b/Configuration/TypoScript/setup.typoscript @@ -0,0 +1,3 @@ + +@import 'EXT:rsmoembed/Configuration/TypoScript/ContentElements/*.typoscript' + diff --git a/Resources/Private/.htaccess b/Resources/Private/.htaccess new file mode 100644 index 0000000..96d0729 --- /dev/null +++ b/Resources/Private/.htaccess @@ -0,0 +1,11 @@ +# Apache < 2.3 + + Order allow,deny + Deny from all + Satisfy All + + +# Apache >= 2.3 + + Require all denied + diff --git a/Resources/Private/Api/Content.html b/Resources/Private/Api/Content.html new file mode 100644 index 0000000..fb54408 --- /dev/null +++ b/Resources/Private/Api/Content.html @@ -0,0 +1,25 @@ + + {rsm:jsonToObject(value: data.tx_rsmoembed_data)} + +

{oembedData.info_provider_name}

+
+ + + {oembedData.info_code_html->f:format.raw()} + + + + + + + +
{oembedData.info_provider_name}
+
+
+
+
+ diff --git a/Resources/Private/Language/RsmoembedDefault/de.locallang_db.xlf b/Resources/Private/Language/RsmoembedDefault/de.locallang_db.xlf new file mode 100644 index 0000000..c651288 --- /dev/null +++ b/Resources/Private/Language/RsmoembedDefault/de.locallang_db.xlf @@ -0,0 +1,18 @@ + + + +
+ + + Oembed Element + + + Ein Inhaltselement zum einfügen externer Dienste. + + + + diff --git a/Resources/Private/Language/RsmoembedDefault/locallang_db.xlf b/Resources/Private/Language/RsmoembedDefault/locallang_db.xlf new file mode 100644 index 0000000..97b5099 --- /dev/null +++ b/Resources/Private/Language/RsmoembedDefault/locallang_db.xlf @@ -0,0 +1,18 @@ + + + +
+ + + Oembed Element + + + Content Element to embed external Service. + + + + diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf new file mode 100644 index 0000000..ca321f9 --- /dev/null +++ b/Resources/Private/Language/locallang.xlf @@ -0,0 +1,24 @@ + + + +
+ + + Url + + + Data + + + Image Download + + + Image + + + + diff --git a/Resources/Private/Language/locallang_csh_tt_content.xlf b/Resources/Private/Language/locallang_csh_tt_content.xlf new file mode 100644 index 0000000..4296734 --- /dev/null +++ b/Resources/Private/Language/locallang_csh_tt_content.xlf @@ -0,0 +1,23 @@ + + + +
+ + + Url to embed + + + Fetched provider data + + + Download provider image as preview? + + + Preview Image + + + + diff --git a/Resources/Private/Language/locallang_db.xlf b/Resources/Private/Language/locallang_db.xlf new file mode 100644 index 0000000..f051d2a --- /dev/null +++ b/Resources/Private/Language/locallang_db.xlf @@ -0,0 +1,30 @@ + + + +
+ + + URL to grab Infos + + + Grabbed Data + + + Generate Preview Image automatically? (please remove existing preview manually) + + + Yes, try to download the external image and I do not infringe copyrights. + + + Preview Image + + + + + + + diff --git a/Resources/Private/PHP/embed/composer.json b/Resources/Private/PHP/embed/composer.json new file mode 100644 index 0000000..74eb6cc --- /dev/null +++ b/Resources/Private/PHP/embed/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "embed/embed": "^4.4" + } +} diff --git a/Resources/Private/PHP/embed/composer.lock b/Resources/Private/PHP/embed/composer.lock new file mode 100644 index 0000000..c0eb8a3 --- /dev/null +++ b/Resources/Private/PHP/embed/composer.lock @@ -0,0 +1,501 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "35d1daafe79b0c92a92c45d5e0431155", + "packages": [ + { + "name": "composer/ca-bundle", + "version": "1.3.5", + "source": { + "type": "git", + "url": "https://github.com/composer/ca-bundle.git", + "reference": "74780ccf8c19d6acb8d65c5f39cd72110e132bbd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/74780ccf8c19d6acb8d65c5f39cd72110e132bbd", + "reference": "74780ccf8c19d6acb8d65c5f39cd72110e132bbd", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "ext-pcre": "*", + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.55", + "psr/log": "^1.0", + "symfony/phpunit-bridge": "^4.2 || ^5", + "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0 || ^6.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.3.5" + }, + "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": "2023-01-11T08:27:00+00:00" + }, + { + "name": "embed/embed", + "version": "v4.4.7", + "source": { + "type": "git", + "url": "https://github.com/oscarotero/Embed.git", + "reference": "72ea7eb8226008dd10834bc0c9becc708f7a7871" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/oscarotero/Embed/zipball/72ea7eb8226008dd10834bc0c9becc708f7a7871", + "reference": "72ea7eb8226008dd10834bc0c9becc708f7a7871", + "shasum": "" + }, + "require": { + "composer/ca-bundle": "^1.0", + "ext-curl": "*", + "ext-dom": "*", + "ext-json": "*", + "ext-mbstring": "*", + "ml/json-ld": "^1.1", + "oscarotero/html-parser": "^0.1.4", + "php": "^7.4|^8", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0" + }, + "require-dev": { + "brick/varexporter": "^0.3.1", + "friendsofphp/php-cs-fixer": "^2.0", + "nyholm/psr7": "^1.2", + "oscarotero/php-cs-fixer-config": "^1.0", + "phpunit/phpunit": "^9.0", + "symfony/css-selector": "^5.0" + }, + "suggest": { + "symfony/css-selector": "If you want to get elements using css selectors" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Embed\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oscar Otero", + "email": "oom@oscarotero.com", + "homepage": "http://oscarotero.com", + "role": "Developer" + } + ], + "description": "PHP library to retrieve page info using oembed, opengraph, etc", + "homepage": "https://github.com/oscarotero/Embed", + "keywords": [ + "embed", + "embedly", + "oembed", + "opengraph", + "twitter cards" + ], + "support": { + "email": "oom@oscarotero.com", + "issues": "https://github.com/oscarotero/Embed/issues", + "source": "https://github.com/oscarotero/Embed/tree/v4.4.7" + }, + "funding": [ + { + "url": "https://paypal.me/oscarotero", + "type": "custom" + }, + { + "url": "https://github.com/oscarotero", + "type": "github" + }, + { + "url": "https://www.patreon.com/misteroom", + "type": "patreon" + } + ], + "time": "2022-12-12T14:45:19+00:00" + }, + { + "name": "ml/iri", + "version": "1.1.4", + "target-dir": "ML/IRI", + "source": { + "type": "git", + "url": "https://github.com/lanthaler/IRI.git", + "reference": "cbd44fa913e00ea624241b38cefaa99da8d71341" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lanthaler/IRI/zipball/cbd44fa913e00ea624241b38cefaa99da8d71341", + "reference": "cbd44fa913e00ea624241b38cefaa99da8d71341", + "shasum": "" + }, + "require": { + "lib-pcre": ">=4.0", + "php": ">=5.3.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "ML\\IRI": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Markus Lanthaler", + "email": "mail@markus-lanthaler.com", + "homepage": "http://www.markus-lanthaler.com", + "role": "Developer" + } + ], + "description": "IRI handling for PHP", + "homepage": "http://www.markus-lanthaler.com", + "keywords": [ + "URN", + "iri", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/lanthaler/IRI/issues", + "source": "https://github.com/lanthaler/IRI/tree/master" + }, + "time": "2014-01-21T13:43:39+00:00" + }, + { + "name": "ml/json-ld", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/lanthaler/JsonLD.git", + "reference": "537e68e87a6bce23e57c575cd5dcac1f67ce25d8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lanthaler/JsonLD/zipball/537e68e87a6bce23e57c575cd5dcac1f67ce25d8", + "reference": "537e68e87a6bce23e57c575cd5dcac1f67ce25d8", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ml/iri": "^1.1.1", + "php": ">=5.3.0" + }, + "require-dev": { + "json-ld/tests": "1.0", + "phpunit/phpunit": "^4" + }, + "type": "library", + "autoload": { + "psr-4": { + "ML\\JsonLD\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Markus Lanthaler", + "email": "mail@markus-lanthaler.com", + "homepage": "http://www.markus-lanthaler.com", + "role": "Developer" + } + ], + "description": "JSON-LD Processor for PHP", + "homepage": "http://www.markus-lanthaler.com", + "keywords": [ + "JSON-LD", + "jsonld" + ], + "support": { + "issues": "https://github.com/lanthaler/JsonLD/issues", + "source": "https://github.com/lanthaler/JsonLD/tree/1.2.1" + }, + "time": "2022-09-29T08:45:17+00:00" + }, + { + "name": "oscarotero/html-parser", + "version": "v0.1.7", + "source": { + "type": "git", + "url": "https://github.com/oscarotero/html-parser.git", + "reference": "0c5b619bdc7ac061f06a667d913e2af708ee3231" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/oscarotero/html-parser/zipball/0c5b619bdc7ac061f06a667d913e2af708ee3231", + "reference": "0c5b619bdc7ac061f06a667d913e2af708ee3231", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.11", + "phpunit/phpunit": "^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "HtmlParser\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oscar Otero", + "email": "oom@oscarotero.com", + "homepage": "http://oscarotero.com", + "role": "Developer" + } + ], + "description": "Parse html strings to DOMDocument", + "homepage": "https://github.com/oscarotero/html-parser", + "keywords": [ + "dom", + "html", + "parser" + ], + "support": { + "email": "oom@oscarotero.com", + "issues": "https://github.com/oscarotero/html-parser/issues", + "source": "https://github.com/oscarotero/html-parser/tree/v0.1.7" + }, + "time": "2022-12-17T09:48:58+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client/tree/master" + }, + "time": "2020-06-29T06:28:15+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/master" + }, + "time": "2019-04-30T12:38:16+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/master" + }, + "time": "2016-08-06T14:39:51+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.3.0" +} diff --git a/Resources/Private/PHP/embed/vendor/autoload.php b/Resources/Private/PHP/embed/vendor/autoload.php new file mode 100644 index 0000000..1e8f4fe --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/autoload.php @@ -0,0 +1,25 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see https://www.php-fig.org/psr/psr-0/ + * @see https://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + /** @var ?string */ + private $vendorDir; + + // PSR-4 + /** + * @var array[] + * @psalm-var array> + */ + private $prefixLengthsPsr4 = array(); + /** + * @var array[] + * @psalm-var array> + */ + private $prefixDirsPsr4 = array(); + /** + * @var array[] + * @psalm-var array + */ + private $fallbackDirsPsr4 = array(); + + // PSR-0 + /** + * @var array[] + * @psalm-var array> + */ + private $prefixesPsr0 = array(); + /** + * @var array[] + * @psalm-var array + */ + private $fallbackDirsPsr0 = array(); + + /** @var bool */ + private $useIncludePath = false; + + /** + * @var string[] + * @psalm-var array + */ + private $classMap = array(); + + /** @var bool */ + private $classMapAuthoritative = false; + + /** + * @var bool[] + * @psalm-var array + */ + private $missingClasses = array(); + + /** @var ?string */ + private $apcuPrefix; + + /** + * @var self[] + */ + private static $registeredLoaders = array(); + + /** + * @param ?string $vendorDir + */ + public function __construct($vendorDir = null) + { + $this->vendorDir = $vendorDir; + } + + /** + * @return string[] + */ + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); + } + + return array(); + } + + /** + * @return array[] + * @psalm-return array> + */ + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + /** + * @return array[] + * @psalm-return array + */ + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + /** + * @return array[] + * @psalm-return array + */ + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + /** + * @return string[] Array of classname => path + * @psalm-return array + */ + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param string[] $classMap Class to filename map + * @psalm-param array $classMap + * + * @return void + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * 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 string[]|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + * + * @return void + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * 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 string[]|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) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + 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; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * 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 string[]|string $paths The PSR-0 base directories + * + * @return void + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * 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 string[]|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + * + * @return void + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + 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; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + * + * @return void + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + * + * @return void + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * 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) + { + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; + } + + /** + * The APCu prefix in use, or null if APCu caching is not enabled. + * + * @return string|null + */ + public function getApcuPrefix() + { + return $this->apcuPrefix; + } + + /** + * 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 true|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + + return null; + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { + return false; + } + if (null !== $this->apcuPrefix) { + $file = apcu_fetch($this->apcuPrefix.$class, $hit); + if ($hit) { + return $file; + } + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if (false === $file && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if (null !== $this->apcuPrefix) { + apcu_add($this->apcuPrefix.$class, $file); + } + + if (false === $file) { + // Remember that this class does not exist. + $this->missingClasses[$class] = true; + } + + return $file; + } + + /** + * Returns the currently registered loaders indexed by their corresponding vendor directories. + * + * @return self[] + */ + public static function getRegisteredLoaders() + { + return self::$registeredLoaders; + } + + /** + * @param string $class + * @param string $ext + * @return string|false + */ + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + $subPath = $class; + while (false !== $lastPos = strrpos($subPath, '\\')) { + $subPath = substr($subPath, 0, $lastPos); + $search = $subPath . '\\'; + if (isset($this->prefixDirsPsr4[$search])) { + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); + foreach ($this->prefixDirsPsr4[$search] as $dir) { + if (file_exists($file = $dir . $pathEnd)) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + + return false; + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + * + * @param string $file + * @return void + * @private + */ +function includeFile($file) +{ + include $file; +} diff --git a/Resources/Private/PHP/embed/vendor/composer/InstalledVersions.php b/Resources/Private/PHP/embed/vendor/composer/InstalledVersions.php new file mode 100644 index 0000000..c6b54af --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/composer/InstalledVersions.php @@ -0,0 +1,352 @@ + + * 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 || empty($installed['versions'][$packageName]['dev_requirement']); + } + } + + 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($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')) { + $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php'; + 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') { + self::$installed = require __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + $installed[] = self::$installed; + + return $installed; + } +} diff --git a/Resources/Private/PHP/embed/vendor/composer/LICENSE b/Resources/Private/PHP/embed/vendor/composer/LICENSE new file mode 100644 index 0000000..f27399a --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) Nils Adermann, Jordi Boggiano + +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/Resources/Private/PHP/embed/vendor/composer/autoload_classmap.php b/Resources/Private/PHP/embed/vendor/composer/autoload_classmap.php new file mode 100644 index 0000000..0fb0a2c --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/composer/autoload_classmap.php @@ -0,0 +1,10 @@ + $vendorDir . '/composer/InstalledVersions.php', +); diff --git a/Resources/Private/PHP/embed/vendor/composer/autoload_files.php b/Resources/Private/PHP/embed/vendor/composer/autoload_files.php new file mode 100644 index 0000000..85fef52 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/composer/autoload_files.php @@ -0,0 +1,10 @@ + $vendorDir . '/embed/embed/src/functions.php', +); diff --git a/Resources/Private/PHP/embed/vendor/composer/autoload_namespaces.php b/Resources/Private/PHP/embed/vendor/composer/autoload_namespaces.php new file mode 100644 index 0000000..c27b051 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/composer/autoload_namespaces.php @@ -0,0 +1,10 @@ + array($vendorDir . '/ml/iri'), +); diff --git a/Resources/Private/PHP/embed/vendor/composer/autoload_psr4.php b/Resources/Private/PHP/embed/vendor/composer/autoload_psr4.php new file mode 100644 index 0000000..09899d8 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/composer/autoload_psr4.php @@ -0,0 +1,15 @@ + array($vendorDir . '/psr/http-message/src', $vendorDir . '/psr/http-factory/src'), + 'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'), + 'ML\\JsonLD\\' => array($vendorDir . '/ml/json-ld'), + 'HtmlParser\\' => array($vendorDir . '/oscarotero/html-parser/src'), + 'Embed\\' => array($vendorDir . '/embed/embed/src'), + 'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'), +); diff --git a/Resources/Private/PHP/embed/vendor/composer/autoload_real.php b/Resources/Private/PHP/embed/vendor/composer/autoload_real.php new file mode 100644 index 0000000..1773c46 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/composer/autoload_real.php @@ -0,0 +1,57 @@ +register(true); + + $includeFiles = \Composer\Autoload\ComposerStaticInit5589daf84e91f75864359115d22ca906::$files; + foreach ($includeFiles as $fileIdentifier => $file) { + composerRequire5589daf84e91f75864359115d22ca906($fileIdentifier, $file); + } + + return $loader; + } +} + +/** + * @param string $fileIdentifier + * @param string $file + * @return void + */ +function composerRequire5589daf84e91f75864359115d22ca906($fileIdentifier, $file) +{ + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + + require $file; + } +} diff --git a/Resources/Private/PHP/embed/vendor/composer/autoload_static.php b/Resources/Private/PHP/embed/vendor/composer/autoload_static.php new file mode 100644 index 0000000..07c7f3d --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/composer/autoload_static.php @@ -0,0 +1,89 @@ + __DIR__ . '/..' . '/embed/embed/src/functions.php', + ); + + public static $prefixLengthsPsr4 = array ( + 'P' => + array ( + 'Psr\\Http\\Message\\' => 17, + 'Psr\\Http\\Client\\' => 16, + ), + 'M' => + array ( + 'ML\\JsonLD\\' => 10, + ), + 'H' => + array ( + 'HtmlParser\\' => 11, + ), + 'E' => + array ( + 'Embed\\' => 6, + ), + 'C' => + array ( + 'Composer\\CaBundle\\' => 18, + ), + ); + + public static $prefixDirsPsr4 = array ( + 'Psr\\Http\\Message\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/http-message/src', + 1 => __DIR__ . '/..' . '/psr/http-factory/src', + ), + 'Psr\\Http\\Client\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/http-client/src', + ), + 'ML\\JsonLD\\' => + array ( + 0 => __DIR__ . '/..' . '/ml/json-ld', + ), + 'HtmlParser\\' => + array ( + 0 => __DIR__ . '/..' . '/oscarotero/html-parser/src', + ), + 'Embed\\' => + array ( + 0 => __DIR__ . '/..' . '/embed/embed/src', + ), + 'Composer\\CaBundle\\' => + array ( + 0 => __DIR__ . '/..' . '/composer/ca-bundle/src', + ), + ); + + public static $prefixesPsr0 = array ( + 'M' => + array ( + 'ML\\IRI' => + array ( + 0 => __DIR__ . '/..' . '/ml/iri', + ), + ), + ); + + public static $classMap = array ( + 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->prefixLengthsPsr4 = ComposerStaticInit5589daf84e91f75864359115d22ca906::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInit5589daf84e91f75864359115d22ca906::$prefixDirsPsr4; + $loader->prefixesPsr0 = ComposerStaticInit5589daf84e91f75864359115d22ca906::$prefixesPsr0; + $loader->classMap = ComposerStaticInit5589daf84e91f75864359115d22ca906::$classMap; + + }, null, ClassLoader::class); + } +} diff --git a/Resources/Private/PHP/embed/vendor/composer/ca-bundle/LICENSE b/Resources/Private/PHP/embed/vendor/composer/ca-bundle/LICENSE new file mode 100644 index 0000000..c5b5220 --- /dev/null +++ b/Resources/Private/PHP/embed/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/Resources/Private/PHP/embed/vendor/composer/ca-bundle/README.md b/Resources/Private/PHP/embed/vendor/composer/ca-bundle/README.md new file mode 100644 index 0000000..d8205ec --- /dev/null +++ b/Resources/Private/PHP/embed/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/Resources/Private/PHP/embed/vendor/composer/ca-bundle/composer.json b/Resources/Private/PHP/embed/vendor/composer/ca-bundle/composer.json new file mode 100644 index 0000000..ed6a1b3 --- /dev/null +++ b/Resources/Private/PHP/embed/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": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^4.2 || ^5", + "phpstan/phpstan": "^0.12.55", + "psr/log": "^1.0", + "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0 || ^6.0" + }, + "autoload": { + "psr-4": { + "Composer\\CaBundle\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Composer\\CaBundle\\": "tests" + } + }, + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "scripts": { + "test": "SYMFONY_PHPUNIT_REMOVE_RETURN_TYPEHINT=1 vendor/bin/simple-phpunit", + "phpstan": "vendor/bin/phpstan analyse" + } +} diff --git a/Resources/Private/PHP/embed/vendor/composer/ca-bundle/res/cacert.pem b/Resources/Private/PHP/embed/vendor/composer/ca-bundle/res/cacert.pem new file mode 100644 index 0000000..2ae7b6c --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/composer/ca-bundle/res/cacert.pem @@ -0,0 +1,3372 @@ +## +## Bundle of CA Root Certificates +## +## Certificate data from Mozilla as of: Tue Jan 10 04:12:06 2023 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: 90c470e705b4b5f36f09684dc50e2b79c8b86989a848b62cd1a7bd6460ee65f6 +## + + +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----- + +Security Communication Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw +8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM +DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX +5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd +DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2 +JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g +0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a +mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ +s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ +6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi +FL39vmwLAw== +-----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----- + +Hongkong Post Root CA 1 +======================= +-----BEGIN CERTIFICATE----- +MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT +DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx +NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n +IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1 +ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr +auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh +qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY +V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV +HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i +h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio +l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei +IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps +T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT +c4afU9hDDl3WY4JxHYB0yvbiAmvZWg== +-----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----- + +Autoridad de Certificacion Firmaprofesional CIF A62634068 +========================================================= +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA +BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw +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+JIwuwIDAQABo4HvMIHsMBIGA1Ud +EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH +DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp +cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA +bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx +ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx +51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk +R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP +T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f +Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl +osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR +crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR +saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD +KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi +6Et8Vcad+qMUu2WFbm5PEn4KPJ2V +-----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----- + +E-Tugra Certification Authority +=============================== +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w +DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls +ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN +ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw +NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx +QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl +cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD +DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd +hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K +CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g +ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ +BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0 +E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz +rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq +jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn +rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5 +dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB +/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG +MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK +kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO +XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807 +VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo +a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc +dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV +KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT +Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0 +8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G +C7TbO6Orb1wdtn7os4I07QZcJA== +-----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----- + +E-Tugra Global Root CA RSA v3 +============================= +-----BEGIN CERTIFICATE----- +MIIF8zCCA9ugAwIBAgIUDU3FzRYilZYIfrgLfxUGNPt5EDQwDQYJKoZIhvcNAQELBQAwgYAxCzAJ +BgNVBAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVncmEgRUJHIEEuUy4xHTAb +BgNVBAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290 +IENBIFJTQSB2MzAeFw0yMDAzMTgwOTA3MTdaFw00NTAzMTIwOTA3MTdaMIGAMQswCQYDVQQGEwJU +UjEPMA0GA1UEBxMGQW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRF +LVR1Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBSU0Eg +djMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCiZvCJt3J77gnJY9LTQ91ew6aEOErx +jYG7FL1H6EAX8z3DeEVypi6Q3po61CBxyryfHUuXCscxuj7X/iWpKo429NEvx7epXTPcMHD4QGxL +sqYxYdE0PD0xesevxKenhOGXpOhL9hd87jwH7eKKV9y2+/hDJVDqJ4GohryPUkqWOmAalrv9c/SF +/YP9f4RtNGx/ardLAQO/rWm31zLZ9Vdq6YaCPqVmMbMWPcLzJmAy01IesGykNz709a/r4d+ABs8q +QedmCeFLl+d3vSFtKbZnwy1+7dZ5ZdHPOrbRsV5WYVB6Ws5OUDGAA5hH5+QYfERaxqSzO8bGwzrw +bMOLyKSRBfP12baqBqG3q+Sx6iEUXIOk/P+2UNOMEiaZdnDpwA+mdPy70Bt4znKS4iicvObpCdg6 +04nmvi533wEKb5b25Y08TVJ2Glbhc34XrD2tbKNSEhhw5oBOM/J+JjKsBY04pOZ2PJ8QaQ5tndLB +eSBrW88zjdGUdjXnXVXHt6woq0bM5zshtQoK5EpZ3IE1S0SVEgpnpaH/WwAH0sDM+T/8nzPyAPiM +bIedBi3x7+PmBvrFZhNb/FAHnnGGstpvdDDPk1Po3CLW3iAfYY2jLqN4MpBs3KwytQXk9TwzDdbg +h3cXTJ2w2AmoDVf3RIXwyAS+XF1a4xeOVGNpf0l0ZAWMowIDAQABo2MwYTAPBgNVHRMBAf8EBTAD +AQH/MB8GA1UdIwQYMBaAFLK0ruYt9ybVqnUtdkvAG1Mh0EjvMB0GA1UdDgQWBBSytK7mLfcm1ap1 +LXZLwBtTIdBI7zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAImocn+M684uGMQQ +gC0QDP/7FM0E4BQ8Tpr7nym/Ip5XuYJzEmMmtcyQ6dIqKe6cLcwsmb5FJ+Sxce3kOJUxQfJ9emN4 +38o2Fi+CiJ+8EUdPdk3ILY7r3y18Tjvarvbj2l0Upq7ohUSdBm6O++96SmotKygY/r+QLHUWnw/q +ln0F7psTpURs+APQ3SPh/QMSEgj0GDSz4DcLdxEBSL9htLX4GdnLTeqjjO/98Aa1bZL0SmFQhO3s +SdPkvmjmLuMxC1QLGpLWgti2omU8ZgT5Vdps+9u1FGZNlIM7zR6mK7L+d0CGq+ffCsn99t2HVhjY +sCxVYJb6CH5SkPVLpi6HfMsg2wY+oF0Dd32iPBMbKaITVaA9FCKvb7jQmhty3QUBjYZgv6Rn7rWl +DdF/5horYmbDB7rnoEgcOMPpRfunf/ztAmgayncSd6YAVSgU7NbHEqIbZULpkejLPoeJVF3Zr52X +nGnnCv8PWniLYypMfUeUP95L6VPQMPHF9p5J3zugkaOj/s1YzOrfr28oO6Bpm4/srK4rVJ2bBLFH +IK+WEj5jlB0E5y67hscMmoi/dkfv97ALl2bSRM9gUgfh1SxKOidhd8rXj+eHDjD/DLsE4mHDosiX +YY60MGo8bcIHX0pzLz/5FooBZu+6kcpSV3uu1OYP3Qt6f4ueJiDPO++BcYNZ +-----END CERTIFICATE----- + +E-Tugra Global Root CA ECC v3 +============================= +-----BEGIN CERTIFICATE----- +MIICpTCCAiqgAwIBAgIUJkYZdzHhT28oNt45UYbm1JeIIsEwCgYIKoZIzj0EAwMwgYAxCzAJBgNV +BAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVncmEgRUJHIEEuUy4xHTAbBgNV +BAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENB +IEVDQyB2MzAeFw0yMDAzMTgwOTQ2NThaFw00NTAzMTIwOTQ2NThaMIGAMQswCQYDVQQGEwJUUjEP +MA0GA1UEBxMGQW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1 +Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBFQ0MgdjMw +djAQBgcqhkjOPQIBBgUrgQQAIgNiAASOmCm/xxAeJ9urA8woLNheSBkQKczLWYHMjLiSF4mDKpL2 +w6QdTGLVn9agRtwcvHbB40fQWxPa56WzZkjnIZpKT4YKfWzqTTKACrJ6CZtpS5iB4i7sAnCWH/31 +Rs7K3IKjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU/4Ixcj75xGZsrTie0bBRiKWQ +zPUwHQYDVR0OBBYEFP+CMXI++cRmbK04ntGwUYilkMz1MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjO +PQQDAwNpADBmAjEA5gVYaWHlLcoNy/EZCL3W/VGSGn5jVASQkZo1kTmZ+gepZpO6yGjUij/67W4W +Aie3AjEA3VoXK3YdZUKWpqxdinlW2Iob35reX8dQj7FbcQwm32pAAOwzkSFxvmjkI6TZraE3 +-----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----- diff --git a/Resources/Private/PHP/embed/vendor/composer/ca-bundle/src/CaBundle.php b/Resources/Private/PHP/embed/vendor/composer/ca-bundle/src/CaBundle.php new file mode 100644 index 0000000..d99c00f --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/composer/ca-bundle/src/CaBundle.php @@ -0,0 +1,431 @@ + + * + * 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(); + /** @var bool|null */ + private static $useOpensslParse; + + /** + * 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 + ); + + 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); + + // assume the CA is valid if php is vulnerable to + // https://www.sektioneins.de/advisories/advisory-012013-php-openssl_x509_parse-memory-corruption-vulnerability.html + if (!static::isOpensslParseSafe()) { + if (!$warned && $logger) { + $logger->warning(sprintf( + 'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.', + PHP_VERSION + )); + $warned = true; + } + + $isValid = !empty($contents); + } elseif (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() + { + if (null !== self::$useOpensslParse) { + return self::$useOpensslParse; + } + + if (PHP_VERSION_ID >= 50600) { + return self::$useOpensslParse = true; + } + + // Vulnerable: + // PHP 5.3.0 - PHP 5.3.27 + // PHP 5.4.0 - PHP 5.4.22 + // PHP 5.5.0 - PHP 5.5.6 + if ( + (PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328) + || (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423) + || PHP_VERSION_ID >= 50507 + ) { + // This version of PHP has the fix for CVE-2013-6420 applied. + return self::$useOpensslParse = true; + } + + if (defined('PHP_WINDOWS_VERSION_BUILD')) { + // Windows is probably insecure in this case. + return self::$useOpensslParse = false; + } + + $compareDistroVersionPrefix = function ($prefix, $fixedVersion) { + $regex = '{^'.preg_quote($prefix).'([0-9]+)$}'; + + if (preg_match($regex, PHP_VERSION, $m)) { + return ((int) $m[1]) >= $fixedVersion; + } + + return false; + }; + + // Hard coded list of PHP distributions with the fix backported. + if ( + $compareDistroVersionPrefix('5.3.3-7+squeeze', 18) // Debian 6 (Squeeze) + || $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) // Debian 7 (Wheezy) + || $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) // Ubuntu 12.04 (Precise) + ) { + return self::$useOpensslParse = true; + } + + // Symfony Process component is missing so we assume it is unsafe at this point + if (!class_exists('Symfony\Component\Process\PhpProcess')) { + return self::$useOpensslParse = false; + } + + // This is where things get crazy, because distros backport security + // fixes the chances are on NIX systems the fix has been applied but + // it's not possible to verify that from the PHP version. + // + // To verify exec a new PHP process and run the issue testcase with + // known safe input that replicates the bug. + + // Based on testcase in https://github.com/php/php-src/commit/c1224573c773b6845e83505f717fbf820fc18415 + // changes in https://github.com/php/php-src/commit/76a7fd893b7d6101300cc656058704a73254d593 + $cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K'; + $script = <<<'EOT' + +error_reporting(-1); +$info = openssl_x509_parse(base64_decode('%s')); +var_dump(PHP_VERSION, $info['issuer']['emailAddress'], $info['validFrom_time_t']); + +EOT; + $script = '<'."?php\n".sprintf($script, $cert); + + try { + $process = new PhpProcess($script); + $process->mustRun(); + } catch (\Exception $e) { + // In the case of any exceptions just accept it is not possible to + // determine the safety of openssl_x509_parse and bail out. + return self::$useOpensslParse = false; + } + + $output = preg_split('{\r?\n}', trim($process->getOutput())); + $errorOutput = trim($process->getErrorOutput()); + + if ( + is_array($output) + && count($output) === 3 + && $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION) + && $output[1] === 'string(27) "stefan.esser@sektioneins.de"' + && $output[2] === 'int(-1)' + && preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput) + ) { + // This PHP has the fix backported probably by a distro security team. + return self::$useOpensslParse = true; + } + + return self::$useOpensslParse = false; + } + + /** + * Resets the static caches + * @return void + */ + public static function reset() + { + self::$caFileValidity = array(); + self::$caPath = null; + self::$useOpensslParse = 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 + && static::isFile($certFile, $logger) + && static::isReadable($certFile, $logger) + && static::validateCaFile($certFile, $logger); + } + + /** + * @param string|false $certDir + * @param LoggerInterface|null $logger + * @return bool + */ + private static function caDirUsable($certDir, LoggerInterface $logger = null) + { + return $certDir + && static::isDir($certDir, $logger) + && static::isReadable($certDir, $logger) + && static::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/Resources/Private/PHP/embed/vendor/composer/installed.json b/Resources/Private/PHP/embed/vendor/composer/installed.json new file mode 100644 index 0000000..36eec89 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/composer/installed.json @@ -0,0 +1,512 @@ +{ + "packages": [ + { + "name": "composer/ca-bundle", + "version": "1.3.5", + "version_normalized": "1.3.5.0", + "source": { + "type": "git", + "url": "https://github.com/composer/ca-bundle.git", + "reference": "74780ccf8c19d6acb8d65c5f39cd72110e132bbd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/74780ccf8c19d6acb8d65c5f39cd72110e132bbd", + "reference": "74780ccf8c19d6acb8d65c5f39cd72110e132bbd", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "ext-pcre": "*", + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.55", + "psr/log": "^1.0", + "symfony/phpunit-bridge": "^4.2 || ^5", + "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0 || ^6.0" + }, + "time": "2023-01-11T08:27:00+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.3.5" + }, + "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": "embed/embed", + "version": "v4.4.7", + "version_normalized": "4.4.7.0", + "source": { + "type": "git", + "url": "https://github.com/oscarotero/Embed.git", + "reference": "72ea7eb8226008dd10834bc0c9becc708f7a7871" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/oscarotero/Embed/zipball/72ea7eb8226008dd10834bc0c9becc708f7a7871", + "reference": "72ea7eb8226008dd10834bc0c9becc708f7a7871", + "shasum": "" + }, + "require": { + "composer/ca-bundle": "^1.0", + "ext-curl": "*", + "ext-dom": "*", + "ext-json": "*", + "ext-mbstring": "*", + "ml/json-ld": "^1.1", + "oscarotero/html-parser": "^0.1.4", + "php": "^7.4|^8", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0" + }, + "require-dev": { + "brick/varexporter": "^0.3.1", + "friendsofphp/php-cs-fixer": "^2.0", + "nyholm/psr7": "^1.2", + "oscarotero/php-cs-fixer-config": "^1.0", + "phpunit/phpunit": "^9.0", + "symfony/css-selector": "^5.0" + }, + "suggest": { + "symfony/css-selector": "If you want to get elements using css selectors" + }, + "time": "2022-12-12T14:45:19+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Embed\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oscar Otero", + "email": "oom@oscarotero.com", + "homepage": "http://oscarotero.com", + "role": "Developer" + } + ], + "description": "PHP library to retrieve page info using oembed, opengraph, etc", + "homepage": "https://github.com/oscarotero/Embed", + "keywords": [ + "embed", + "embedly", + "oembed", + "opengraph", + "twitter cards" + ], + "support": { + "email": "oom@oscarotero.com", + "issues": "https://github.com/oscarotero/Embed/issues", + "source": "https://github.com/oscarotero/Embed/tree/v4.4.7" + }, + "funding": [ + { + "url": "https://paypal.me/oscarotero", + "type": "custom" + }, + { + "url": "https://github.com/oscarotero", + "type": "github" + }, + { + "url": "https://www.patreon.com/misteroom", + "type": "patreon" + } + ], + "install-path": "../embed/embed" + }, + { + "name": "ml/iri", + "version": "1.1.4", + "version_normalized": "1.1.4.0", + "target-dir": "ML/IRI", + "source": { + "type": "git", + "url": "https://github.com/lanthaler/IRI.git", + "reference": "cbd44fa913e00ea624241b38cefaa99da8d71341" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lanthaler/IRI/zipball/cbd44fa913e00ea624241b38cefaa99da8d71341", + "reference": "cbd44fa913e00ea624241b38cefaa99da8d71341", + "shasum": "" + }, + "require": { + "lib-pcre": ">=4.0", + "php": ">=5.3.0" + }, + "time": "2014-01-21T13:43:39+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "ML\\IRI": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Markus Lanthaler", + "email": "mail@markus-lanthaler.com", + "homepage": "http://www.markus-lanthaler.com", + "role": "Developer" + } + ], + "description": "IRI handling for PHP", + "homepage": "http://www.markus-lanthaler.com", + "keywords": [ + "URN", + "iri", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/lanthaler/IRI/issues", + "source": "https://github.com/lanthaler/IRI/tree/master" + }, + "install-path": "../ml/iri/ML/IRI" + }, + { + "name": "ml/json-ld", + "version": "1.2.1", + "version_normalized": "1.2.1.0", + "source": { + "type": "git", + "url": "https://github.com/lanthaler/JsonLD.git", + "reference": "537e68e87a6bce23e57c575cd5dcac1f67ce25d8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lanthaler/JsonLD/zipball/537e68e87a6bce23e57c575cd5dcac1f67ce25d8", + "reference": "537e68e87a6bce23e57c575cd5dcac1f67ce25d8", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ml/iri": "^1.1.1", + "php": ">=5.3.0" + }, + "require-dev": { + "json-ld/tests": "1.0", + "phpunit/phpunit": "^4" + }, + "time": "2022-09-29T08:45:17+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "ML\\JsonLD\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Markus Lanthaler", + "email": "mail@markus-lanthaler.com", + "homepage": "http://www.markus-lanthaler.com", + "role": "Developer" + } + ], + "description": "JSON-LD Processor for PHP", + "homepage": "http://www.markus-lanthaler.com", + "keywords": [ + "JSON-LD", + "jsonld" + ], + "support": { + "issues": "https://github.com/lanthaler/JsonLD/issues", + "source": "https://github.com/lanthaler/JsonLD/tree/1.2.1" + }, + "install-path": "../ml/json-ld" + }, + { + "name": "oscarotero/html-parser", + "version": "v0.1.7", + "version_normalized": "0.1.7.0", + "source": { + "type": "git", + "url": "https://github.com/oscarotero/html-parser.git", + "reference": "0c5b619bdc7ac061f06a667d913e2af708ee3231" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/oscarotero/html-parser/zipball/0c5b619bdc7ac061f06a667d913e2af708ee3231", + "reference": "0c5b619bdc7ac061f06a667d913e2af708ee3231", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.11", + "phpunit/phpunit": "^8.0" + }, + "time": "2022-12-17T09:48:58+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "HtmlParser\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oscar Otero", + "email": "oom@oscarotero.com", + "homepage": "http://oscarotero.com", + "role": "Developer" + } + ], + "description": "Parse html strings to DOMDocument", + "homepage": "https://github.com/oscarotero/html-parser", + "keywords": [ + "dom", + "html", + "parser" + ], + "support": { + "email": "oom@oscarotero.com", + "issues": "https://github.com/oscarotero/html-parser/issues", + "source": "https://github.com/oscarotero/html-parser/tree/v0.1.7" + }, + "install-path": "../oscarotero/html-parser" + }, + { + "name": "psr/http-client", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" + }, + "time": "2020-06-29T06:28:15+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client/tree/master" + }, + "install-path": "../psr/http-client" + }, + { + "name": "psr/http-factory", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "time": "2019-04-30T12:38:16+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/master" + }, + "install-path": "../psr/http-factory" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2016-08-06T14:39:51+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/master" + }, + "install-path": "../psr/http-message" + } + ], + "dev": true, + "dev-package-names": [] +} diff --git a/Resources/Private/PHP/embed/vendor/composer/installed.php b/Resources/Private/PHP/embed/vendor/composer/installed.php new file mode 100644 index 0000000..3caafce --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/composer/installed.php @@ -0,0 +1,95 @@ + 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, + ), + 'composer/ca-bundle' => array( + 'pretty_version' => '1.3.5', + 'version' => '1.3.5.0', + 'reference' => '74780ccf8c19d6acb8d65c5f39cd72110e132bbd', + 'type' => 'library', + 'install_path' => __DIR__ . '/./ca-bundle', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'embed/embed' => array( + 'pretty_version' => 'v4.4.7', + 'version' => '4.4.7.0', + 'reference' => '72ea7eb8226008dd10834bc0c9becc708f7a7871', + 'type' => 'library', + 'install_path' => __DIR__ . '/../embed/embed', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'ml/iri' => array( + 'pretty_version' => '1.1.4', + 'version' => '1.1.4.0', + 'reference' => 'cbd44fa913e00ea624241b38cefaa99da8d71341', + 'type' => 'library', + 'install_path' => __DIR__ . '/../ml/iri/ML/IRI', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'ml/json-ld' => array( + 'pretty_version' => '1.2.1', + 'version' => '1.2.1.0', + 'reference' => '537e68e87a6bce23e57c575cd5dcac1f67ce25d8', + 'type' => 'library', + 'install_path' => __DIR__ . '/../ml/json-ld', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'oscarotero/html-parser' => array( + 'pretty_version' => 'v0.1.7', + 'version' => '0.1.7.0', + 'reference' => '0c5b619bdc7ac061f06a667d913e2af708ee3231', + 'type' => 'library', + 'install_path' => __DIR__ . '/../oscarotero/html-parser', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/http-client' => array( + 'pretty_version' => '1.0.1', + 'version' => '1.0.1.0', + 'reference' => '2dfb5f6c5eff0e91e20e913f8c5452ed95b86621', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/http-client', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/http-factory' => array( + 'pretty_version' => '1.0.1', + 'version' => '1.0.1.0', + 'reference' => '12ac7fcd07e5b077433f5f2bee95b3a771bf61be', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/http-factory', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/http-message' => array( + 'pretty_version' => '1.0.1', + 'version' => '1.0.1.0', + 'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/http-message', + 'aliases' => array(), + 'dev_requirement' => false, + ), + ), +); diff --git a/Resources/Private/PHP/embed/vendor/composer/platform_check.php b/Resources/Private/PHP/embed/vendor/composer/platform_check.php new file mode 100644 index 0000000..580fa96 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/composer/platform_check.php @@ -0,0 +1,26 @@ += 70400)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 7.4.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/Resources/Private/PHP/embed/vendor/embed/embed/CHANGELOG.md b/Resources/Private/PHP/embed/vendor/embed/embed/CHANGELOG.md new file mode 100644 index 0000000..ded1eb8 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/CHANGELOG.md @@ -0,0 +1,239 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +## [4.4.7] - 2022-12-12 +### Fixed +- Href attributes with `undefined` values [#501], [#502] +- Deprecated warning for var interpolation in PHP 8.2 [#506] +- Prevent unsupported operand types exception [#507] + +## [4.4.6] - 2022-10-02 +### Fixed +- Some code issues detected by phpstan: [#495], [#496], [#497], [#498]. +- Fix for quotation marks in redirect URL [#499] + +## [4.4.5] - 2022-09-06 +### Fixed +- Updated oembed endpoints [#494] + +## [4.4.4] - 2022-04-13 +### Fixed +- Error getting data from Linked data [#481]. + +## [4.4.3] - 2022-03-13 +### Fixed +- PHP 8.1 deprecation notice [#480]. + +## [4.4.2] - 2022-02-13 +### Added +- Options to customize the CurlClient to perform http queries [#474]. + +## [4.4.1] - 2022-02-06 +### Fixed +- PHP 8.1 deprecation notice [#473]. + +## [4.4.0] - 2022-01-08 +### Added +- New settings option `twitter:token` to use Twitter API to get the data [#364] [#468]. + +### Fixed +- Headers not sent properly by curl [#466], [#467]. + +## [4.3.5] - 2021-10-10 +### Fixed +- Updated oEmbed endpoints +- Fixed embed code for Instagram [#456], [#459] + +### Security +- Fixed a possible XML Quadratic Blowup vulnerability. + +## [4.3.4] - 2021-06-22 +### Fixed +- Urls of images should include the same url for the `$info->image` value. [#452] + +## [4.3.3] - 2021-06-22 +### Fixed +- Facebook embed redirects to `/login`. [#450], [#451] + +## [4.3.2] - 2021-04-04 +### Fixed +- Add configured oEmbed query parameters to all oEmbed endpoints [#437] +- Updated oEmbed endpoints. +- Replaced Travis with Github workflows for testing + +## [4.3.1] - 2021-03-21 +### Added +- Support for binary files (video, audio, images, etc) [#412] [#413] + +### Fixed +- Oembed for facebook photos [#405] [#406] +- Oembed for facebook videos [#432] [#433] +- Added more ways to detect data using meta tags [#427] +- Bandcamp provider name [#429] [#430] + +## [4.3.0] - 2020-11-04 +### Added +- New function `$embed->setSettings()` to pass the settings before get the site info + +### Fixed +- PHP 8 compatibility [#394] +- Facebook and Instagram adapted to the new API changes [#392] [#399] + +## [4.2.7] - 2020-09-23 +### Added +- New option `twitch:parent` to fix Twitch embed with iframes [#384] + +### Fixed +- Added `datePublished` check to `PublishedTime` extractor [#385] [#386] +- Added `@property-read` for IDE suppport [#387] [#388] + +## [4.2.6] - 2020-08-28 +### Fixed +- Code width and height when the provided value is not numeric (ex: 100%) [#380] + +## [4.2.5] - 2020-08-01 +### Fixed +- Github TypeError exception with some urls [#375] + +## [4.2.4] - 2020-07-06 +### Fixed +- Ignore invalid urls instead throw an exception +- Updated oembed list of endpoints + +## [4.2.3] - 2020-06-12 +### Fixed +- Suppport for other non-latin alphabets such Persian or Arabic [#366] + +## [4.2.2] - 2020-05-31 +### Fixed +- Provided a fallback for oEmbed compatible sites like Instagram that redirects to login page [#357] + +## [4.2.1] - 2020-05-25 +### Fixed +- Redirect urls like `t.co`. + +## [4.2.0] - 2020-05-23 +### Added +- Added the `ignored_errors` settings to ignore some curls errors instead throw an exception [#355] +- Support for Twitch embeds [#332] + +### Fixed +- Ignored linkedData errors [#356] + +## [4.1.1] - 2020-04-24 +### Added +- Updated oembed endpoints from `oembed.com` +- Add support for tiktok.com + +## [4.1.0] - 2020-04-19 +### Added +- Ability to send settings to `CurlClient`. Added the `cookies_path` setting to customize the file used for cookies. [#345] +- `Document::selectCss()` function to select elements using css selectors instead xpath (it requires `symfony/css-selector`) +- `Document::removeCss()` function to remove elements using css selectors instead xpath (it requires `symfony/css-selector`) +- Ability to configure OEmbed parameters from the outside using the `oembed:query_parameters` setting [#346] + +## [4.0.0] - 2020-03-13 +Full library refactoring. + +### Added +- Support for multiple parallel request with `curl_multi` +- Support for PSR-7 Http Messages, PSR-17 Http Factories and PSR-18 Http Client +- `cms` value +- `language` to detect the page language +- `languages` to detect urls to versions in different languages +- `favicon` to detect small favicons (16 or 32px) +- `icon` to detect big icons (from 48px) + +### Changed +- Changed providers (oEmbed, Html, OpenGraph etc) by independent detectors (title, url, language etc). +- The `tags` value is renamed to `keywords` +- Use Psr standards instead custom interfaces. +- Improved tests using cached responses. + +### Removed +- Support for PHP<7.4 +- `type` value (is was very confusing) +- `images` value +- `providerImage` (use `favicon` or `icon` instead) +- Support for files (pdf, jpg, video, etc). + +[#332]: https://github.com/oscarotero/Embed/issues/332 +[#345]: https://github.com/oscarotero/Embed/issues/345 +[#346]: https://github.com/oscarotero/Embed/issues/346 +[#355]: https://github.com/oscarotero/Embed/issues/355 +[#356]: https://github.com/oscarotero/Embed/issues/356 +[#357]: https://github.com/oscarotero/Embed/issues/357 +[#364]: https://github.com/oscarotero/Embed/issues/364 +[#366]: https://github.com/oscarotero/Embed/issues/366 +[#375]: https://github.com/oscarotero/Embed/issues/375 +[#380]: https://github.com/oscarotero/Embed/issues/380 +[#384]: https://github.com/oscarotero/Embed/issues/384 +[#385]: https://github.com/oscarotero/Embed/issues/385 +[#386]: https://github.com/oscarotero/Embed/issues/386 +[#387]: https://github.com/oscarotero/Embed/issues/387 +[#388]: https://github.com/oscarotero/Embed/issues/388 +[#392]: https://github.com/oscarotero/Embed/issues/392 +[#394]: https://github.com/oscarotero/Embed/issues/394 +[#399]: https://github.com/oscarotero/Embed/issues/399 +[#405]: https://github.com/oscarotero/Embed/issues/405 +[#406]: https://github.com/oscarotero/Embed/issues/406 +[#412]: https://github.com/oscarotero/Embed/issues/412 +[#413]: https://github.com/oscarotero/Embed/issues/413 +[#427]: https://github.com/oscarotero/Embed/issues/427 +[#429]: https://github.com/oscarotero/Embed/issues/429 +[#430]: https://github.com/oscarotero/Embed/issues/430 +[#432]: https://github.com/oscarotero/Embed/issues/432 +[#433]: https://github.com/oscarotero/Embed/issues/433 +[#437]: https://github.com/oscarotero/Embed/issues/437 +[#450]: https://github.com/oscarotero/Embed/issues/450 +[#451]: https://github.com/oscarotero/Embed/issues/451 +[#452]: https://github.com/oscarotero/Embed/issues/452 +[#456]: https://github.com/oscarotero/Embed/issues/456 +[#459]: https://github.com/oscarotero/Embed/issues/459 +[#466]: https://github.com/oscarotero/Embed/issues/466 +[#467]: https://github.com/oscarotero/Embed/issues/467 +[#468]: https://github.com/oscarotero/Embed/issues/468 +[#473]: https://github.com/oscarotero/Embed/issues/473 +[#474]: https://github.com/oscarotero/Embed/issues/474 +[#480]: https://github.com/oscarotero/Embed/issues/480 +[#481]: https://github.com/oscarotero/Embed/issues/481 +[#494]: https://github.com/oscarotero/Embed/issues/494 +[#495]: https://github.com/oscarotero/Embed/issues/495 +[#496]: https://github.com/oscarotero/Embed/issues/496 +[#497]: https://github.com/oscarotero/Embed/issues/497 +[#498]: https://github.com/oscarotero/Embed/issues/498 +[#499]: https://github.com/oscarotero/Embed/issues/499 +[#501]: https://github.com/oscarotero/Embed/issues/501 +[#502]: https://github.com/oscarotero/Embed/issues/502 +[#506]: https://github.com/oscarotero/Embed/issues/506 +[#507]: https://github.com/oscarotero/Embed/issues/507 + +[4.4.7]: https://github.com/oscarotero/Embed/compare/v4.4.6...v4.4.7 +[4.4.6]: https://github.com/oscarotero/Embed/compare/v4.4.5...v4.4.6 +[4.4.5]: https://github.com/oscarotero/Embed/compare/v4.4.4...v4.4.5 +[4.4.4]: https://github.com/oscarotero/Embed/compare/v4.4.3...v4.4.4 +[4.4.3]: https://github.com/oscarotero/Embed/compare/v4.4.2...v4.4.3 +[4.4.2]: https://github.com/oscarotero/Embed/compare/v4.4.1...v4.4.2 +[4.4.1]: https://github.com/oscarotero/Embed/compare/v4.4.0...v4.4.1 +[4.4.0]: https://github.com/oscarotero/Embed/compare/v4.3.5...v4.4.0 +[4.3.5]: https://github.com/oscarotero/Embed/compare/v4.3.4...v4.3.5 +[4.3.4]: https://github.com/oscarotero/Embed/compare/v4.3.3...v4.3.4 +[4.3.3]: https://github.com/oscarotero/Embed/compare/v4.3.2...v4.3.3 +[4.3.2]: https://github.com/oscarotero/Embed/compare/v4.3.1...v4.3.2 +[4.3.1]: https://github.com/oscarotero/Embed/compare/v4.3.0...v4.3.1 +[4.3.0]: https://github.com/oscarotero/Embed/compare/v4.2.7...v4.3.0 +[4.2.7]: https://github.com/oscarotero/Embed/compare/v4.2.6...v4.2.7 +[4.2.6]: https://github.com/oscarotero/Embed/compare/v4.2.5...v4.2.6 +[4.2.5]: https://github.com/oscarotero/Embed/compare/v4.2.4...v4.2.5 +[4.2.4]: https://github.com/oscarotero/Embed/compare/v4.2.3...v4.2.4 +[4.2.3]: https://github.com/oscarotero/Embed/compare/v4.2.2...v4.2.3 +[4.2.2]: https://github.com/oscarotero/Embed/compare/v4.2.1...v4.2.2 +[4.2.1]: https://github.com/oscarotero/Embed/compare/v4.2.0...v4.2.1 +[4.2.0]: https://github.com/oscarotero/Embed/compare/v4.1.1...v4.2.0 +[4.1.1]: https://github.com/oscarotero/Embed/compare/v4.1.0...v4.1.1 +[4.1.0]: https://github.com/oscarotero/Embed/compare/v4.0.0...v4.1.0 +[4.0.0]: https://github.com/oscarotero/Embed/releases/tag/v4.0.0 diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/LICENSE b/Resources/Private/PHP/embed/vendor/embed/embed/LICENSE new file mode 100644 index 0000000..2385321 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017 Oscar Otero Marzoa + +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/Resources/Private/PHP/embed/vendor/embed/embed/README.md b/Resources/Private/PHP/embed/vendor/embed/embed/README.md new file mode 100644 index 0000000..a45e46e --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/README.md @@ -0,0 +1,360 @@ + +# Embed + +[![Latest Version on Packagist][ico-version]][link-packagist] +[![Total Downloads][ico-downloads]][link-packagist] +[![Monthly Downloads][ico-m-downloads]][link-packagist] +[![Software License][ico-license]](LICENSE) + +PHP library to get information from any web page (using oembed, opengraph, twitter-cards, scrapping the html, etc). It's compatible with any web service (youtube, vimeo, flickr, instagram, etc) and has adapters to some sites like (archive.org, github, facebook, etc). + +Requirements: + +* PHP 7.4+ +* Curl library installed +* PSR-17 implementation. By default these libraries are detected automatically: + * [laminas/laminas-diactoros](https://github.com/laminas/laminas-diactoros) + * [guzzle/psr7](https://github.com/guzzle/psr7) + * [nyholm/psr7](https://github.com/Nyholm/psr7) + * [sunrise/http-message](https://github.com/sunrise-php/http-message) + +> If you need PHP 5.5-7.3 support, [use the 3.x version](https://github.com/oscarotero/Embed/tree/v3.x) + +## Online demo + +http://oscarotero.com/embed/demo + +## Video Tutorial + [](https://youtu.be/4YCLRpKY1cs) + + +## Installation + +This package is installable and autoloadable via Composer as [embed/embed](https://packagist.org/packages/embed/embed). + +``` +$ composer require embed/embed +``` + +## Usage + +```php +use Embed\Embed; + +$embed = new Embed(); + +//Load any url: +$info = $embed->get('https://www.youtube.com/watch?v=PP1xn5wHtxE'); + +//Get content info + +$info->title; //The page title +$info->description; //The page description +$info->url; //The canonical url +$info->keywords; //The page keywords + +$info->image; //The thumbnail or main image + +$info->code->html; //The code to embed the image, video, etc +$info->code->width; //The exact width of the embed code (if exists) +$info->code->height; //The exact height of the embed code (if exists) +$info->code->ratio; //The aspect ratio (width/height) + +$info->authorName; //The resource author +$info->authorUrl; //The author url + +$info->cms; //The cms used +$info->language; //The language of the page +$info->languages; //The alternative languages + +$info->providerName; //The provider name of the page (Youtube, Twitter, Instagram, etc) +$info->providerUrl; //The provider url +$info->icon; //The big icon of the site +$info->favicon; //The favicon of the site (an .ico file or a png with up to 32x32px) + +$info->publishedTime; //The published time of the resource +$info->license; //The license url of the resource +$info->feeds; //The RSS/Atom feeds +``` + +## Parallel multiple requests + +```php +use Embed\Embed; + +$embed = new Embed(); + +//Load multiple urls asynchronously: +$infos = $embed->getMulti( + 'https://www.youtube.com/watch?v=PP1xn5wHtxE', + 'https://twitter.com/carlosmeixidefl/status/1230894146220625933', + 'https://en.wikipedia.org/wiki/Tordoia', +); + +foreach ($infos as $info) { + echo $info->title; +} +``` + +## Document + +The document is the object that store the html code of the page. You can use it to extract extra info from the html code: + +```php +//Get the document object +$document = $info->getDocument(); + +$document->link('image_src'); //Returns the href of a +$document->getDocument(); //Returns the DOMDocument instance +$html = (string) $document; //Returns the html code + +$document->select('.//h1'); //Search +``` + +You can perform xpath queries in order to select specific elements. A search always return an instance of a `Embed\QueryResult`: + +```php +//Search the A elements +$result = $document->select('.//a'); + +//Filter the results +$result->filter(fn ($node) => $node->getAttribute('href')); + +$id = $result->str('id'); //Return the id of the first result as string +$text = $result->str(); //Return the content of the first result + +$ids = $result->strAll('id'); //Return an array with the ids of all results as string +$texts = $result->strAll(); //Return an array with the content of all results as string + +$tabindex = $result->int('tabindex'); //Return the tabindex attribute of the first result as integer +$number = $result->int(); //Return the content of the first result as integer + +$href = $result->url('href'); //Return the href attribute of the first result as url (converts relative urls to absolutes) +$url = $result->url(); //Return the content of the first result as url + +$node = $result->node(); //Return the first node found (DOMElement) +$nodes = $result->nodes(); //Return all nodes found +``` + +## Metas + +For convenience, the object `Metas` stores the value of all `` elements located in the html, so you can get the values easier. The key of every meta is get from the `name`, `property` or `itemprop` attributes and the value is get from `content`. + +```php +//Get the Metas object +$metas = $info->getMetas(); + +$metas->all(); //Return all values +$metas->get('og:title'); //Return a key value +$metas->str('og:title'); //Return the value as string (remove html tags) +$metas->html('og:description'); //Return the value as html +$metas->int('og:video:width'); //Return the value as integer +$metas->url('og:url'); //Return the value as full url (converts relative urls to absolutes) +``` + +## OEmbed + +In addition to the html and metas, this library uses [oEmbed](https://oembed.com/) endpoints to get additional data. You can get this data as following: + +```php +//Get the oEmbed object +$oembed = $info->getOEmbed(); + +$oembed->all(); //Return all raw data +$oembed->get('title'); //Return a key value +$oembed->str('title'); //Return the value as string (remove html tags) +$oembed->html('html'); //Return the value as html +$oembed->int('width'); //Return the value as integer +$oembed->url('url'); //Return the value as full url (converts relative urls to absolutes) +``` + +Additional oEmbed parameters (like instagrams `hidecaption`) can also be provided: +```php +$embed = new Embed(); + +$result = $embed->get('https://www.instagram.com/p/B_C0wheCa4V/'); +$result->setSettings([ + 'oembed:query_parameters' => ['hidecaption' => true] +]); +$oembed = $info->getOEmbed(); +``` + +## LinkedData + +Another API available by default, used to extract info using the [JsonLD](https://www.w3.org/TR/json-ld/) schema. + +```php +//Get the linkedData object +$ld = $info->getLinkedData(); + +$ld->all(); //Return all data +$ld->get('name'); //Return a key value +$ld->str('name'); //Return the value as string (remove html tags) +$ld->html('description'); //Return the value as html +$ld->int('width'); //Return the value as integer +$ld->url('url'); //Return the value as full url (converts relative urls to absolutes) +``` + +## Other APIs + +Some sites like Wikipedia or Archive.org provide a custom API that is used to fetch more reliable data. You can get the API object with the method `getApi()` but note that not all results have this method. The Api object has the same methods than oEmbed: + +```php +//Get the API object +$api = $info->getApi(); + +$api->all(); //Return all raw data +$api->get('title'); //Return a key value +$api->str('title'); //Return the value as string (remove html tags) +$api->html('html'); //Return the value as html +$api->int('width'); //Return the value as integer +$api->url('url'); //Return the value as full url (converts relative urls to absolutes) +``` + +## Extending Embed + +Depending of your needs, you may want to extend this library with extra features or change the way it makes some operations. + +### PSR + +Embed use some PSR standards to be the most interoperable possible: + +- [PSR-7](https://www.php-fig.org/psr/psr-7/) Standard interfaces to represent http requests, responses and uris +- [PSR-17](https://www.php-fig.org/psr/psr-17/) Standard factories to create PSR-7 objects +- [PSR-18](https://www.php-fig.org/psr/psr-18/) Standard interface to send a http request and return a response + +Embed comes with a CURL client compatible with PSR-18 but you need to install a PSR-7 / PSR-17 library. [Here you can see a list of popular libraries](https://github.com/middlewares/awesome-psr15-middlewares#psr-7-implementations) and the library can detect automatically 'laminas\diactoros', 'guzzleHttp\psr7', 'slim\psr7', 'nyholm\psr7' and 'sunrise\http' (in this order). If you want to use a different PSR implementation, you can do it in this way: + +```php +use Embed\Embed; +use Embed\Http\Crawler; + +$client = new CustomHttpClient(); +$requestFactory = new CustomRequestFactory(); +$uriFactory = new CustomUriFactory(); + +//The Crawler is responsible for perform http queries +$crawler = new Crawler($client, $requestFactory, $uriFactory); + +//Create an embed instance passing the Crawler +$embed = new Embed($crawler); +``` + +### Adapters + +There are some sites with special needs: because they provide public APIs that allows to extract more info (like Wikipedia or Archive.org) or because we need to change how to extract the data in this particular site. For all that cases we have the adapters, that are classes extending the default classes to provide extra functionality. + +Before creating an adapter, you need to understand how Embed work: when you execute this code, you get a `Extractor` class + +```php +//Get the Extractor with all info +$info = $embed->get($url); + +//The extractor have document and oembed: +$document = $info->getDocument(); +$oembed = $info->getOEmbed(); +``` + +The `Extractor` class has many `Detectors`. Each detector is responsible to detect a specific piece of info. For example, there's a detector for the title, other for description, image, code, etc. + +So, an adapter is basically an extractor created specifically for a site. It can contains also custom detectors or apis. If you see the `src/Adapters` folder you can see all adapters. + +If you create an adapter, you need also register to Embed, so it knows in which website needs to use. To do that, there's the `ExtractorFactory` object, that is responsible for instantiate the right extractor for each site. + +```php +use Embed\Embed; + +$embed = new Embed(); + +$factory = $embed->getExtractorFactory(); + +//Use this MySite adapter for mysite.com +$factory->addAdapter('mysite.com', MySite::class); + +//Remove the adapter for pinterest.com, so it will use the default extractor +$factory->removeAdapter('pinterest.com'); + +//Change the default extractor +$factory->setDefault(CustomExtractor::class); +``` + +### Detectors + +Embed comes with several predefined detectors, but you may want to change or add more. Just create a class extending `Embed\Detectors\Detector` class and register it in the extractor factory. For example: + +```php +use Embed\Embed; +use Embed\Detectors\Detector; + +class Robots extends Detector +{ + public function detect(): ?string + { + $response = $this->extractor->getResponse(); + $metas = $this->extractor->getMetas(); + + return $response->getHeaderLine('x-robots-tag'), + ?: $metas->str('robots'); + } +} + +//Register the detector +$embed = new Embed(); +$embed->getExtractorFactory()->addDetector('robots', Robots::class); + +//Use it +$info = $embed->get('http://example.com'); +$robots = $info->robots; +``` + +### Settings + +If you need to pass settings to the CurlClient to perform http queries: + +```php +use Embed\Embed; +use Embed\Http\Crawler; +use Embed\Http\CurlClient; + +$client = new CurlClient(); +$client->setSettings([ + 'cookies_path' => $cookies_path, + 'ignored_errors' => [18], + 'max_redirs' => 3, // see CURLOPT_MAXREDIRS + 'connect_timeout' => 2, // see CURLOPT_CONNECTTIMEOUT + 'timeout' => 2, // see CURLOPT_TIMEOUT + 'ssl_verify_host' => 2, // see CURLOPT_SSL_VERIFYHOST + 'ssl_verify_peer' => 1, // see CURLOPT_SSL_VERIFYPEER + 'follow_location' => true, // see CURLOPT_FOLLOWLOCATION + 'user_agent' => 'Mozilla', // see CURLOPT_USERAGENT +]); + +$embed = new Embed(new Crawler($client)); +``` + +If you need to pass settings to your detectors, you can add settings to the `ExtractorFactory`: + +```php +use Embed\Embed; + +$embed = new Embed(); +$embed->setSettings([ + 'oembed:query_parameters' => [], //Extra parameters send to oembed + 'twitch:parent' => 'example.com', //Required to embed twitch videos as iframe + 'facebook:token' => '1234|5678', //Required to embed content from Facebook + 'instagram:token' => '1234|5678', //Required to embed content from Instagram + 'twitter:token' => 'asdf', //Improve the data from twitter +]); +$info = $embed->get($url); +``` + +Note: The built-in detectors does not require settings. This feature is only for convenience if you create a specific detector that requires settings. + +--- + +[ico-version]: https://poser.pugx.org/embed/embed/v/stable +[ico-license]: https://poser.pugx.org/embed/embed/license +[ico-downloads]: https://poser.pugx.org/embed/embed/downloads +[ico-m-downloads]: https://poser.pugx.org/embed/embed/d/monthly + +[link-packagist]: https://packagist.org/packages/embed/embed diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/composer.json b/Resources/Private/PHP/embed/vendor/embed/embed/composer.json new file mode 100644 index 0000000..522d432 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/composer.json @@ -0,0 +1,72 @@ +{ + "name": "embed/embed", + "type": "library", + "description": "PHP library to retrieve page info using oembed, opengraph, etc", + "keywords": [ + "oembed", + "opengraph", + "twitter cards", + "embed", + "embedly" + ], + "homepage": "https://github.com/oscarotero/Embed", + "license": "MIT", + "authors": [ + { + "name": "Oscar Otero", + "email": "oom@oscarotero.com", + "homepage": "http://oscarotero.com", + "role": "Developer" + } + ], + "support": { + "email": "oom@oscarotero.com", + "issues": "https://github.com/oscarotero/Embed/issues" + }, + "require": { + "php": "^7.4|^8", + "ext-curl": "*", + "ext-dom": "*", + "ext-json": "*", + "ext-mbstring": "*", + "composer/ca-bundle": "^1.0", + "oscarotero/html-parser": "^0.1.4", + "psr/http-message": "^1.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "ml/json-ld": "^1.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.0", + "friendsofphp/php-cs-fixer": "^2.0", + "nyholm/psr7": "^1.2", + "oscarotero/php-cs-fixer-config": "^1.0", + "brick/varexporter": "^0.3.1", + "symfony/css-selector": "^5.0" + }, + "suggest": { + "symfony/css-selector": "If you want to get elements using css selectors" + }, + "autoload": { + "psr-4": { + "Embed\\": "src" + }, + "files": [ + "src/functions.php" + ] + }, + "autoload-dev": { + "psr-4": { + "Embed\\Tests\\": "tests/" + } + }, + "scripts": { + "demo": "php -S localhost:8888 demo/index.php", + "test": "phpunit", + "cs-fix": "php-cs-fixer fix", + "update-resources": [ + "php scripts/update-oembed.php", + "php scripts/update-suffix.php" + ] + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Api.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Api.php new file mode 100644 index 0000000..aa10514 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Api.php @@ -0,0 +1,18 @@ +endpoint = $this->extractor->getUri()->withQuery('output=json'); + + return $this->fetchJSON($this->endpoint); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Detectors/AuthorName.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Detectors/AuthorName.php new file mode 100644 index 0000000..ea46725 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Detectors/AuthorName.php @@ -0,0 +1,17 @@ +extractor->getApi(); + + return $api->str('metadata', 'creator') + ?: parent::detect(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Detectors/Code.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Detectors/Code.php new file mode 100644 index 0000000..1840621 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Detectors/Code.php @@ -0,0 +1,37 @@ +extractor->getUri(); + $path = $uri->getPath(); + + if (!matchPath('/details/*', $path)) { + return null; + } + + $src = $uri->withPath(str_replace('/details/', '/embed/', $path)); + $width = 640; + $height = 480; + + $html = html('iframe', [ + 'src' => $src, + 'width' => $width, + 'height' => $height, + 'style' => 'border:none', + 'frameborder' => 0, + 'allowTransparency' => 'true', + ]); + + return new EmbedCode($html, $width, $height); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Detectors/Description.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Detectors/Description.php new file mode 100644 index 0000000..d3c3af1 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Detectors/Description.php @@ -0,0 +1,17 @@ +extractor->getApi(); + + return $api->str('metadata', 'extract') + ?: parent::detect(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Detectors/ProviderName.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Detectors/ProviderName.php new file mode 100644 index 0000000..e8a632a --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Detectors/ProviderName.php @@ -0,0 +1,14 @@ +extractor->getApi(); + + return $api->time('metadata', 'publicdate') + ?: $api->time('metadata', 'addeddate') + ?: $api->time('metadata', 'date') + ?: parent::detect(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Detectors/Title.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Detectors/Title.php new file mode 100644 index 0000000..4ba1dca --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Detectors/Title.php @@ -0,0 +1,17 @@ +extractor->getApi(); + + return $api->str('metadata', 'title') + ?: parent::detect(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Extractor.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Extractor.php new file mode 100644 index 0000000..ab941e0 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Archive/Extractor.php @@ -0,0 +1,30 @@ +api; + } + + public function createCustomDetectors(): array + { + $this->api = new Api($this); + + return [ + 'title' => new Detectors\Title($this), + 'description' => new Detectors\Description($this), + 'code' => new Detectors\Code($this), + 'authorName' => new Detectors\AuthorName($this), + 'providerName' => new Detectors\ProviderName($this), + 'publishedTime' => new Detectors\PublishedTime($this), + ]; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Bandcamp/Detectors/ProviderName.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Bandcamp/Detectors/ProviderName.php new file mode 100644 index 0000000..74575ae --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Bandcamp/Detectors/ProviderName.php @@ -0,0 +1,14 @@ + new Detectors\ProviderName($this), + ]; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/CadenaSer/Detectors/Code.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/CadenaSer/Detectors/Code.php new file mode 100644 index 0000000..d279e7b --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/CadenaSer/Detectors/Code.php @@ -0,0 +1,41 @@ +fallback(); + } + + private function fallback(): ?EmbedCode + { + $uri = $this->extractor->getUri(); + + if (!matchPath('/audio/*', $uri->getPath())) { + return null; + } + + $path = cleanPath('/widget/'.$uri->getPath()); + $src = $uri->withPath($path); + + $html = html('iframe', [ + 'src' => $src, + 'frameborder' => 0, + 'width' => '100%', + 'height' => '360', + 'allowTransparency' => 'true', + ]); + + return new EmbedCode($html, null, 360); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/CadenaSer/Extractor.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/CadenaSer/Extractor.php new file mode 100644 index 0000000..aa23777 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/CadenaSer/Extractor.php @@ -0,0 +1,16 @@ + new Detectors\Code($this), + ]; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Facebook/Detectors/Title.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Facebook/Detectors/Title.php new file mode 100644 index 0000000..b73a53f --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Facebook/Detectors/Title.php @@ -0,0 +1,21 @@ +extractor->getDocument(); + $oembed = $this->extractor->getOEmbed(); + + return $oembed->str('title') + ?: $document->select('.//head/title')->str(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Facebook/Extractor.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Facebook/Extractor.php new file mode 100644 index 0000000..5b4cb70 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Facebook/Extractor.php @@ -0,0 +1,18 @@ +oembed = new OEmbed($this); + + return [ + 'title' => new Detectors\Title($this), + ]; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Facebook/OEmbed.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Facebook/OEmbed.php new file mode 100644 index 0000000..84d5772 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Facebook/OEmbed.php @@ -0,0 +1,80 @@ +extractor->getSetting('facebook:token'); + + if (!$token) { + return null; + } + + $uri = $this->extractor->getUri(); + if (strpos($uri->getPath(), 'login') !== false) { + parse_str($uri->getQuery(), $params); + if (!empty($params['next'])) { + $uri = $this->extractor->getCrawler()->createUri($params['next']); + } + } + $queryParameters = $this->getOembedQueryParameters((string) $uri); + $queryParameters['access_token'] = $token; + + return $this->extractor->getCrawler() + ->createUri($this->getEndpointByPath($uri->getPath())) + ->withQuery(http_build_query($queryParameters)); + } + + private function getEndpointByPath(string $path): string + { + /* Videos + https://www.facebook.com/{page-name}/videos/{video-id}/ + https://www.facebook.com/{username}/videos/{video-id}/ + https://www.facebook.com/video.php?id={video-id} + https://www.facebook.com/video.php?v={video-id} + */ + if (strpos($path, '/video.php') === 0 + || strpos($path, '/videos/') !== false + ) { + return self::ENDPOINT_VIDEO; + } + + /* Posts + https://www.facebook.com/{page-name}/posts/{post-id} + https://www.facebook.com/{username}/posts/{post-id} + https://www.facebook.com/{username}/activity/{activity-id} + https://www.facebook.com/photo.php?fbid={photo-id} + https://www.facebook.com/photos/{photo-id} + https://www.facebook.com/permalink.php?story_fbid={post-id} + https://www.facebook.com/media/set?set={set-id} + https://www.facebook.com/questions/{question-id} + https://www.facebook.com/notes/{username}/{note-url}/{note-id} + + Not in the facebook docs: + https://www.facebook.com/{page-name}/photos/{post-id}/{photo-id} + */ + if (strpos($path, '/photo.php') === 0 + || strpos($path, '/photos/') !== false + || strpos($path, '/permalink.php') === 0 + || strpos($path, '/media/') === 0 + || strpos($path, '/questions/') === 0 + || strpos($path, '/notes/') === 0 + || strpos($path, '/posts/') !== false + || strpos($path, '/activity/') !== false + ) { + return self::ENDPOINT_POST; + } + + return self::ENDPOINT_PAGE; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Flickr/Detectors/Code.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Flickr/Detectors/Code.php new file mode 100644 index 0000000..1dfe50a --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Flickr/Detectors/Code.php @@ -0,0 +1,44 @@ +fallback(); + } + + private function fallback(): ?EmbedCode + { + $uri = $this->extractor->getUri(); + + if (!matchPath('/photos/*', $uri->getPath())) { + return null; + } + + $path = cleanPath($uri->getPath().'/player'); + $src = $uri->withPath($path); + $width = 640; + $height = 425; + + $html = html('iframe', [ + 'src' => $src, + 'width' => $width, + 'height' => $height, + 'style' => 'border:none', + 'frameborder' => 0, + 'allowTransparency' => 'true', + ]); + + return new EmbedCode($html, $width, $height); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Flickr/Extractor.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Flickr/Extractor.php new file mode 100644 index 0000000..fe18c9d --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Flickr/Extractor.php @@ -0,0 +1,16 @@ + new Detectors\Code($this), + ]; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Api.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Api.php new file mode 100644 index 0000000..a5f1004 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Api.php @@ -0,0 +1,19 @@ +extractor->getUri(); + $this->endpoint = $uri->withPath($uri->getPath().'.json'); + + return $this->fetchJSON($this->endpoint); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Detectors/AuthorName.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Detectors/AuthorName.php new file mode 100644 index 0000000..b31aea6 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Detectors/AuthorName.php @@ -0,0 +1,17 @@ +extractor->getApi(); + + return $api->str('owner') + ?: parent::detect(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Detectors/AuthorUrl.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Detectors/AuthorUrl.php new file mode 100644 index 0000000..1241429 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Detectors/AuthorUrl.php @@ -0,0 +1,22 @@ +extractor->getApi(); + $owner = $api->str('owner'); + + if ($owner) { + return $this->extractor->getCrawler()->createUri("https://github.com/{$owner}"); + } + + return parent::detect(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Detectors/Code.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Detectors/Code.php new file mode 100644 index 0000000..23960ee --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Detectors/Code.php @@ -0,0 +1,31 @@ +fallback(); + } + + private function fallback(): ?EmbedCode + { + $api = $this->extractor->getApi(); + + $code = $api->html('div'); + $stylesheet = $api->str('stylesheet'); + + if ($code && $stylesheet) { + return new EmbedCode( + html('link', ['rel' => 'stylesheet', 'href' => $stylesheet]).$code + ); + } + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Detectors/PublishedTime.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Detectors/PublishedTime.php new file mode 100644 index 0000000..1487524 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Detectors/PublishedTime.php @@ -0,0 +1,18 @@ +extractor->getApi(); + + return $api->time('created_at') + ?: parent::detect(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Extractor.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Extractor.php new file mode 100644 index 0000000..f9ac088 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Gist/Extractor.php @@ -0,0 +1,28 @@ +api; + } + + public function createCustomDetectors(): array + { + $this->api = new Api($this); + + return [ + 'authorName' => new Detectors\AuthorName($this), + 'authorUrl' => new Detectors\AuthorUrl($this), + 'publishedTime' => new Detectors\PublishedTime($this), + 'code' => new Detectors\Code($this), + ]; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Github/Detectors/Code.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Github/Detectors/Code.php new file mode 100644 index 0000000..350e15c --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Github/Detectors/Code.php @@ -0,0 +1,47 @@ +fallback(); + } + + private function fallback(): ?EmbedCode + { + $uri = $this->extractor->getUri(); + $path = $uri->getPath(); + + if (!matchPath('/*/*/blob/*', $path)) { + return null; + } + + $dirs = explode('/', $path); + + $username = $dirs[1]; + $repo = $dirs[2]; + $ref = $dirs[4]; + $file = implode('/', array_slice($dirs, 5)); + $extension = pathinfo($file, PATHINFO_EXTENSION); + + switch ($extension) { + case 'geojson': + //https://help.github.com/articles/mapping-geojson-files-on-github/#embedding-your-map-elsewhere + return new EmbedCode(html('script', ['src' => "https://embed.githubusercontent.com/view/geojson/{$username}/{$repo}/{$ref}/{$file}"])); + case 'stl': + //https://help.github.com/articles/3d-file-viewer/#embedding-your-model-elsewhere + return new EmbedCode(html('script', ['src' => "https://embed.githubusercontent.com/view/3d/{$username}/{$repo}/{$ref}/{$file}"])); + } + + return null; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Github/Extractor.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Github/Extractor.php new file mode 100644 index 0000000..0be9358 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Github/Extractor.php @@ -0,0 +1,16 @@ + new Detectors\Code($this), + ]; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Ideone/Detectors/Code.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Ideone/Detectors/Code.php new file mode 100644 index 0000000..0238981 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Ideone/Detectors/Code.php @@ -0,0 +1,31 @@ +fallback(); + } + + private function fallback(): ?EmbedCode + { + $uri = $this->extractor->getUri(); + $id = explode('/', $uri->getPath())[1]; + + if (empty($id)) { + return null; + } + + return new EmbedCode( + html('script', ['src' => "https://ideone.com/e.js/{$id}"]) + ); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Ideone/Extractor.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Ideone/Extractor.php new file mode 100644 index 0000000..aa7132f --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Ideone/Extractor.php @@ -0,0 +1,16 @@ + new Detectors\Code($this), + ]; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Api.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Api.php new file mode 100644 index 0000000..a5bc3ec --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Api.php @@ -0,0 +1,36 @@ +extractor->getUri(); + + if (!matchPath('/i/*', $uri->getPath())) { + $uri = $this->extractor->getRequest()->getUri(); + + if (!matchPath('/i/*', $uri->getPath())) { + return []; + } + } + + $id = getDirectory($uri->getPath(), 1); + + if (empty($id)) { + return []; + } + + $this->endpoint = $this->extractor->getCrawler()->createUri("https://api.imageshack.com/v2/images/{$id}"); + $data = $this->fetchJSON($this->endpoint); + return $data['result'] ?? []; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/AuthorName.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/AuthorName.php new file mode 100644 index 0000000..52c4ff5 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/AuthorName.php @@ -0,0 +1,17 @@ +extractor->getApi(); + + return $api->str('owner', 'username') + ?: parent::detect(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/AuthorUrl.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/AuthorUrl.php new file mode 100644 index 0000000..1578da5 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/AuthorUrl.php @@ -0,0 +1,22 @@ +extractor->getApi(); + $owner = $api->str('owner', 'username'); + + if ($owner) { + return $this->extractor->getCrawler()->createUri("https://imageshack.com/{$owner}"); + } + + return parent::detect(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/Description.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/Description.php new file mode 100644 index 0000000..a30638b --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/Description.php @@ -0,0 +1,17 @@ +extractor->getApi(); + + return $api->str('description') + ?: parent::detect(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/Image.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/Image.php new file mode 100644 index 0000000..102b761 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/Image.php @@ -0,0 +1,18 @@ +extractor->getApi(); + + return $api->url('direct_link') + ?: parent::detect(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/ProviderName.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/ProviderName.php new file mode 100644 index 0000000..661d45e --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/ProviderName.php @@ -0,0 +1,14 @@ +extractor->getApi(); + + return $api->time('creation_date') + ?: parent::detect(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/Title.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/Title.php new file mode 100644 index 0000000..6ea32d1 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Detectors/Title.php @@ -0,0 +1,17 @@ +extractor->getApi(); + + return $api->str('title') + ?: parent::detect(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Extractor.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Extractor.php new file mode 100644 index 0000000..c865c7e --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/ImageShack/Extractor.php @@ -0,0 +1,31 @@ +api; + } + + public function createCustomDetectors(): array + { + $this->api = new Api($this); + + return [ + 'authorName' => new Detectors\AuthorName($this), + 'authorUrl' => new Detectors\AuthorUrl($this), + 'description' => new Detectors\Description($this), + 'image' => new Detectors\Image($this), + 'providerName' => new Detectors\ProviderName($this), + 'publishedTime' => new Detectors\PublishedTime($this), + 'title' => new Detectors\Title($this), + ]; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Instagram/Extractor.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Instagram/Extractor.php new file mode 100644 index 0000000..8e0e73e --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Instagram/Extractor.php @@ -0,0 +1,20 @@ +oembed = new OEmbed($this); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Instagram/OEmbed.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Instagram/OEmbed.php new file mode 100644 index 0000000..427a7ed --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Instagram/OEmbed.php @@ -0,0 +1,33 @@ +extractor->getSetting('instagram:token'); + + if (!$token) { + return null; + } + + $uri = $this->extractor->getUri(); + if (strpos($uri->getPath(), 'login') !== false) { + $uri = $this->extractor->getRequest()->getUri(); + } + + $queryParameters = $this->getOembedQueryParameters((string) $uri); + $queryParameters['access_token'] = $token; + + return $this->extractor->getCrawler() + ->createUri(self::ENDPOINT) + ->withQuery(http_build_query($queryParameters)); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Pinterest/Detectors/Code.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Pinterest/Detectors/Code.php new file mode 100644 index 0000000..4d38724 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Pinterest/Detectors/Code.php @@ -0,0 +1,41 @@ +fallback(); + } + + private function fallback(): ?EmbedCode + { + $uri = $this->extractor->getUri(); + + if (!matchPath('/pin/*', $uri->getPath())) { + return null; + } + + $html = [ + html('a', [ + 'data-pin-do' => 'embedPin', + 'href' => $uri, + ]), + html('script', [ + 'async' => true, + 'defer' => true, + 'src' => '//assets.pinterest.com/js/pinit.js', + ]), + ]; + + return new EmbedCode(implode('', $html), 236, 442); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Pinterest/Extractor.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Pinterest/Extractor.php new file mode 100644 index 0000000..5b5c40f --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Pinterest/Extractor.php @@ -0,0 +1,16 @@ + new Detectors\Code($this), + ]; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Sassmeister/Detectors/Code.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Sassmeister/Detectors/Code.php new file mode 100644 index 0000000..7ad8374 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Sassmeister/Detectors/Code.php @@ -0,0 +1,45 @@ +fallback(); + } + + private function fallback(): ?EmbedCode + { + $uri = $this->extractor->getUri(); + + if (!matchPath('/gist/*', $uri->getPath())) { + return null; + } + + $id = explode('/', $uri->getPath())[2]; + $height = 480; + + $html = [ + html('p', [ + 'class' => 'sassmeister', + 'data-gist-id' => $id, + 'data-height' => $height, + 'data-theme' => 'tomorrow', + ], 'Play with this gist on SassMeister.'), + html('script', [ + 'src' => 'http://cdn.sassmeister.com/js/embed.js', + 'async' => true, + ]), + ]; + + return new EmbedCode(implode('', $html), null, $height); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Sassmeister/Extractor.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Sassmeister/Extractor.php new file mode 100644 index 0000000..e36e3dc --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Sassmeister/Extractor.php @@ -0,0 +1,16 @@ + new Detectors\Code($this), + ]; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Slides/Detectors/Code.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Slides/Detectors/Code.php new file mode 100644 index 0000000..5ae5142 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Slides/Detectors/Code.php @@ -0,0 +1,39 @@ +fallback(); + } + + private function fallback(): EmbedCode + { + $uri = $this->extractor->getUri(); + + $path = cleanPath($uri->getPath().'/embed'); + $src = $uri->withPath($path); + $width = 576; + $height = 420; + + $html = html('iframe', [ + 'src' => $src, + 'width' => $width, + 'height' => $height, + 'style' => 'border:none', + 'frameborder' => 0, + 'allowTransparency' => 'true', + ]); + + return new EmbedCode($html, $width, $height); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Slides/Extractor.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Slides/Extractor.php new file mode 100644 index 0000000..9690079 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Slides/Extractor.php @@ -0,0 +1,16 @@ + new Detectors\Code($this), + ]; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Snipplr/Detectors/Code.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Snipplr/Detectors/Code.php new file mode 100644 index 0000000..aadbb1d --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Snipplr/Detectors/Code.php @@ -0,0 +1,46 @@ +fallback(); + } + + private function fallback(): ?EmbedCode + { + $uri = $this->extractor->getUri(); + + if (!matchPath('/view/*', $uri->getPath())) { + return null; + } + + $id = explode('/', $uri->getPath())[2]; + + $html = [ + html('div', [ + 'id' => "snipplr_embed_{$id}", + 'class' => 'snipplr_embed', + ], 'View this snippet on Snipplr'), + html('script', [ + 'type' => 'text/javascript', + 'src' => 'https://snipplr.com/js/embed.js', + ]), + html('script', [ + 'type' => 'text/javascript', + 'src' => "https://snipplr.com/json/{$id}", + ]), + ]; + + return new EmbedCode(implode('', $html)); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Snipplr/Extractor.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Snipplr/Extractor.php new file mode 100644 index 0000000..a0a7308 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Snipplr/Extractor.php @@ -0,0 +1,16 @@ + new Detectors\Code($this), + ]; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitch/Detectors/Code.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitch/Detectors/Code.php new file mode 100644 index 0000000..1f333bc --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitch/Detectors/Code.php @@ -0,0 +1,82 @@ +fallback(); + } + + private function fallback(): ?EmbedCode + { + $path = $this->extractor->getUri()->getPath(); + $parent = $this->extractor->getSetting('twitch:parent'); + + if ($id = self::getVideoId($path)) { + $code = $parent + ? self::generateIframeCode(['id' => $id, 'parent' => $parent]) + : self::generateJsCode('video', $id); + return new EmbedCode($code, 620, 378); + } + + if ($id = self::getChannelId($path)) { + $code = $parent + ? self::generateIframeCode(['channel' => $id, 'parent' => $parent]) + : self::generateJsCode('channel', $id); + return new EmbedCode($code, 620, 378); + } + + return null; + } + + private static function getVideoId(string $path): ?string + { + if (preg_match('#^/videos/(\d+)$#', $path, $matches)) { + return $matches[1]; + } + + return null; + } + + private static function getChannelId(string $path): ?string + { + if (preg_match('#^/(\w+)$#', $path, $matches)) { + return $matches[1]; + } + + return null; + } + + private static function generateIframeCode(array $params): string + { + $query = http_build_query(['autoplay' => 'false'] + $params); + + return html('iframe', [ + 'src' => "https://player.twitch.tv/?{$query}", + 'frameborder' => 0, + 'allowfullscreen' => 'true', + 'scrolling' => 'no', + 'height' => 378, + 'width' => 620, + ]); + } + + private static function generateJsCode($key, $value) + { + return << + + + HTML; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitch/Extractor.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitch/Extractor.php new file mode 100644 index 0000000..a36d27f --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitch/Extractor.php @@ -0,0 +1,16 @@ + new Detectors\Code($this), + ]; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Api.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Api.php new file mode 100644 index 0000000..a03be6d --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Api.php @@ -0,0 +1,34 @@ +extractor->getSetting('twitter:token'); + + if (!$token) { + return []; + } + + $uri = $this->extractor->getUri(); + + $id = getDirectory($uri->getPath(), 2); + + if (empty($id)) { + return []; + } + + $this->extractor->getCrawler()->addDefaultHeaders(array('Authorization' => "Bearer $token")); + $this->endpoint = $this->extractor->getCrawler()->createUri("https://api.twitter.com/2/tweets/{$id}?expansions=author_id,attachments.media_keys&tweet.fields=created_at&media.fields=preview_image_url,url&user.fields=id,name"); + + return $this->fetchJSON($this->endpoint); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/AuthorName.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/AuthorName.php new file mode 100644 index 0000000..5409ad4 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/AuthorName.php @@ -0,0 +1,17 @@ +extractor->getApi(); + + return $api->str('includes', 'users', '0', 'name') + ?: parent::detect(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/AuthorUrl.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/AuthorUrl.php new file mode 100644 index 0000000..23a11d7 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/AuthorUrl.php @@ -0,0 +1,22 @@ +extractor->getApi(); + $username = $api->str('includes', 'users', '0', 'username'); + + if ($username) { + return $this->extractor->getCrawler()->createUri("https://twitter.com/{$username}"); + } + + return parent::detect(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/Description.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/Description.php new file mode 100644 index 0000000..2b19afa --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/Description.php @@ -0,0 +1,17 @@ +extractor->getApi(); + + return $api->str('data', 'text') + ?: parent::detect(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/Image.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/Image.php new file mode 100644 index 0000000..9034433 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/Image.php @@ -0,0 +1,28 @@ +extractor->getApi(); + $preview = $api->url('includes', 'media', '0', 'preview_image_url'); + + if ($preview) { + return $preview; + } + + $regular = $api->url('includes', 'media', '0', 'url'); + + if ($regular) { + return $regular; + } + + return parent::detect(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/ProviderName.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/ProviderName.php new file mode 100644 index 0000000..e5c99c0 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/ProviderName.php @@ -0,0 +1,14 @@ +extractor->getApi(); + + return $api->time('data', 'created_at') + ?: parent::detect(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/Title.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/Title.php new file mode 100644 index 0000000..58c770b --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Detectors/Title.php @@ -0,0 +1,21 @@ +extractor->getApi(); + $name = $api->str('includes', 'users', '0', 'name'); + + if ($name) { + return "Tweet by $name"; + } + + return parent::detect(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Extractor.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Extractor.php new file mode 100644 index 0000000..2cb2c45 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Twitter/Extractor.php @@ -0,0 +1,31 @@ +api; + } + + public function createCustomDetectors(): array + { + $this->api = new Api($this); + + return [ + 'authorName' => new Detectors\AuthorName($this), + 'authorUrl' => new Detectors\AuthorUrl($this), + 'description' => new Detectors\Description($this), + 'image' => new Detectors\Image($this), + 'providerName' => new Detectors\ProviderName($this), + 'publishedTime' => new Detectors\PublishedTime($this), + 'title' => new Detectors\Title($this), + ]; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Wikipedia/Api.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Wikipedia/Api.php new file mode 100644 index 0000000..36b5233 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Wikipedia/Api.php @@ -0,0 +1,40 @@ +extractor->getUri(); + + if (!matchPath('/wiki/*', $uri->getPath())) { + return []; + } + + $titles = getDirectory($uri->getPath(), 1); + + $this->endpoint = $uri + ->withPath('/w/api.php') + ->withQuery(http_build_query([ + 'action' => 'query', + 'format' => 'json', + 'continue' => '', + 'titles' => $titles, + 'prop' => 'extracts', + 'exchars' => 1000, + ])); + + $data = $this->fetchJSON($this->endpoint); + $pages = $data['query']['pages'] ?? null; + + return $pages ? current($pages) : null; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Wikipedia/Detectors/Description.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Wikipedia/Detectors/Description.php new file mode 100644 index 0000000..dc281dc --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Wikipedia/Detectors/Description.php @@ -0,0 +1,17 @@ +extractor->getApi(); + + return $api->str('extract') + ?: parent::detect(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Wikipedia/Detectors/Title.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Wikipedia/Detectors/Title.php new file mode 100644 index 0000000..0b53133 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Wikipedia/Detectors/Title.php @@ -0,0 +1,17 @@ +extractor->getApi(); + + return $api->str('title') + ?: parent::detect(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Wikipedia/Extractor.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Wikipedia/Extractor.php new file mode 100644 index 0000000..6cc0e1f --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Wikipedia/Extractor.php @@ -0,0 +1,26 @@ +api; + } + + public function createCustomDetectors(): array + { + $this->api = new Api($this); + + return [ + 'title' => new Detectors\Title($this), + 'description' => new Detectors\Description($this), + ]; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Youtube/Detectors/Feeds.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Youtube/Detectors/Feeds.php new file mode 100644 index 0000000..aac9553 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Youtube/Detectors/Feeds.php @@ -0,0 +1,35 @@ +fallback(); + } + + private function fallback(): array + { + $uri = $this->extractor->getUri(); + + if (!matchPath('/channel/*', $uri->getPath())) { + return []; + } + + $id = getDirectory($uri->getPath(), 1); + $feed = $this->extractor->getCrawler()->createUri("https://www.youtube.com/feeds/videos.xml?channel_id={$id}"); + + return [$feed]; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Youtube/Extractor.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Youtube/Extractor.php new file mode 100644 index 0000000..ce299d2 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Adapters/Youtube/Extractor.php @@ -0,0 +1,16 @@ + new Detectors\Feeds($this), + ]; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/ApiTrait.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/ApiTrait.php new file mode 100644 index 0000000..3dcb781 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/ApiTrait.php @@ -0,0 +1,107 @@ +extractor = $extractor; + } + + public function all(): array + { + if (!isset($this->data)) { + $this->data = $this->fetchData(); + } + + return $this->data; + } + + public function get(string ...$keys) + { + $data = $this->all(); + + foreach ($keys as $key) { + if (!isset($data[$key])) { + return null; + } + + $data = $data[$key]; + } + + return $data; + } + + public function str(string ...$keys): ?string + { + $value = $this->get(...$keys); + + if (is_array($value)) { + $value = array_shift($value); + } + + return $value ? clean((string) $value) : null; + } + + public function strAll(string ...$keys): array + { + $all = (array) $this->get(...$keys); + return array_filter(array_map(fn ($value) => clean($value), $all)); + } + + public function html(string ...$keys): ?string + { + $value = $this->get(...$keys); + + if (is_array($value)) { + $value = array_shift($value); + } + + return $value ? clean((string) $value, true) : null; + } + + public function int(string ...$keys): ?int + { + $value = $this->get(...$keys); + + if (is_array($value)) { + $value = array_shift($value); + } + + return is_numeric($value) ? (int) $value : null; + } + + public function url(string ...$keys): ?UriInterface + { + $url = $this->str(...$keys); + + try { + return $url ? $this->extractor->resolveUri($url) : null; + } catch (Throwable $error) { + return null; + } + } + + public function time(string ...$keys): ?DateTime + { + $time = $this->str(...$keys); + $datetime = $time ? date_create($time) : null; + + if (!$datetime && $time && ctype_digit($time)) { + $datetime = date_create_from_format('U', $time); + } + + return ($datetime && $datetime->getTimestamp() > 0) ? $datetime : null; + } + + abstract protected function fetchData(): array; +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/AuthorName.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/AuthorName.php new file mode 100644 index 0000000..17433c4 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/AuthorName.php @@ -0,0 +1,24 @@ +extractor->getOEmbed(); + $metas = $this->extractor->getMetas(); + + return $oembed->str('author_name') + ?: $metas->str( + 'article:author', + 'book:author', + 'sailthru.author', + 'lp.article:author', + 'twitter:creator', + 'dcterms.creator', + 'author' + ); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/AuthorUrl.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/AuthorUrl.php new file mode 100644 index 0000000..fe1b564 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/AuthorUrl.php @@ -0,0 +1,29 @@ +extractor->getOEmbed(); + + return $oembed->url('author_url') + ?: $this->detectFromTwitter(); + } + + private function detectFromTwitter(): ?UriInterface + { + $metas = $this->extractor->getMetas(); + $crawler = $this->extractor->getCrawler(); + + $user = $metas->str('twitter:creator'); + + return $user + ? $crawler->createUri(sprintf('https://twitter.com/%s', ltrim($user, '@'))) + : null; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Cms.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Cms.php new file mode 100644 index 0000000..c43f4d8 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Cms.php @@ -0,0 +1,68 @@ +extractor->url->getHost()); + + if ($cms) { + return $cms; + } + + $document = $this->extractor->getDocument(); + $generators = $document->select('.//meta', ['name' => 'generator'])->strAll('content'); + + foreach ($generators as $generator) { + if ($cms = self::detectFromGenerator($generator)) { + return $cms; + } + } + + return null; + } + + private static function detectFromHost(string $host): ?string + { + if (strpos($host, '.blogspot.com') !== false) { + return self::BLOGSPOT; + } + + if (strpos($host, '.wordpress.com') !== false) { + return self::WORDPRESS; + } + + return null; + } + + private static function detectFromGenerator(string $generator): ?string + { + $generator = strtolower($generator); + + if ($generator === 'blogger') { + return self::BLOGSPOT; + } + + if (strpos($generator, 'mediawiki') === 0) { + return self::MEDIAWIKI; + } + + if (strpos($generator, 'wordpress') === 0) { + return self::WORDPRESS; + } + + if (strpos($generator, 'opennemas') === 0) { + return self::OPENNEMAS; + } + + return null; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Code.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Code.php new file mode 100644 index 0000000..a7b9160 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Code.php @@ -0,0 +1,142 @@ +detectFromEmbed() + ?: $this->detectFromOpenGraph() + ?: $this->detectFromTwitter() + ?: $this->detectFromContentType(); + } + + private function detectFromEmbed(): ?EmbedCode + { + $oembed = $this->extractor->getOEmbed(); + $html = $oembed->html('html'); + + if (!$html) { + return null; + } + + return new EmbedCode( + $html, + $oembed->int('width'), + $oembed->int('height') + ); + } + + private function detectFromOpenGraph(): ?EmbedCode + { + $metas = $this->extractor->getMetas(); + + $url = $metas->url('og:video:secure_url', 'og:video:url', 'og:video'); + + if (!$url) { + return null; + } + + if (!($type = pathinfo($url->getPath(), PATHINFO_EXTENSION))) { + $type = $metas->str('og:video_type'); + } + + $width = $metas->int('twitter:player:width'); + $height = $metas->int('twitter:player:height'); + + switch ($type) { + case 'swf': + case 'application/x-shockwave-flash': + return null; //Ignore flash + case 'mp4': + case 'ogg': + case 'ogv': + case 'webm': + case 'application/mp4': + case 'video/mp4': + case 'video/ogg': + case 'video/ogv': + case 'video/webm': + $code = html('video', [ + 'src' => $url, + 'width' => $width, + 'height' => $height, + ]); + break; + default: + $code = html('iframe', [ + 'src' => $url, + 'frameborder' => 0, + 'width' => $width, + 'height' => $height, + 'allowTransparency' => 'true', + ]); + } + + return new EmbedCode($code, $width, $height); + } + + private function detectFromTwitter(): ?EmbedCode + { + $metas = $this->extractor->getMetas(); + + $url = $metas->url('twitter:player'); + + if (!$url) { + return null; + } + + $width = $metas->int('twitter:player:width'); + $height = $metas->int('twitter:player:height'); + + $code = html('iframe', [ + 'src' => $url, + 'frameborder' => 0, + 'width' => $width, + 'height' => $height, + 'allowTransparency' => 'true', + ]); + + return new EmbedCode($code, $width, $height); + } + + private function detectFromContentType() + { + if (!$this->extractor->getResponse()->hasHeader('content-type')) { + return null; + } + + $contentType = $this->extractor->getResponse()->getHeader('content-type')[0]; + $isBinary = !preg_match('/(text|html|json)/', strtolower($contentType)); + if (!$isBinary) { + return null; + } + + $url = $this->extractor->getRequest()->getUri(); + + if (strpos($contentType, 'video/') === 0 || $contentType === 'application/mp4') { + $code = html('video', [ + 'src' => $url, + 'controls' => true, + ]); + } elseif (strpos($contentType, 'audio/') === 0) { + $code = html('audio', [ + 'src' => $url, + 'controls' => true, + ]); + } elseif (strpos($contentType, 'image/') === 0) { + $code = html('img', [ + 'src' => $url, + ]); + } else { + return null; + } + + return new EmbedCode($code); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Description.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Description.php new file mode 100644 index 0000000..90892d1 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Description.php @@ -0,0 +1,28 @@ +extractor->getOEmbed(); + $metas = $this->extractor->getMetas(); + $ld = $this->extractor->getLinkedData(); + + return $oembed->str('description') + ?: $metas->str( + 'og:description', + 'twitter:description', + 'lp:description', + 'description', + 'article:description', + 'dcterms.description', + 'sailthru.description', + 'excerpt', + 'article.summary' + ) + ?: $ld->str('description'); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Detector.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Detector.php new file mode 100644 index 0000000..1d6bfb0 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Detector.php @@ -0,0 +1,31 @@ +extractor = $extractor; + } + + public function get() + { + if (!isset($this->cache)) { + $this->cache = [ + 'cached' => true, + 'value' => $this->detect(), + ]; + } + + return $this->cache['value']; + } + + abstract public function detect(); +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Favicon.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Favicon.php new file mode 100644 index 0000000..93a0a28 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Favicon.php @@ -0,0 +1,18 @@ +extractor->getDocument(); + + return $document->link('shortcut icon') + ?: $document->link('icon') + ?: $this->extractor->getUri()->withPath('/favicon.ico')->withQuery(''); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Feeds.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Feeds.php new file mode 100644 index 0000000..dab87f0 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Feeds.php @@ -0,0 +1,35 @@ +extractor->getDocument(); + $feeds = []; + + foreach (self::$types as $type) { + $href = $document->link('alternate', ['type' => $type]); + + if ($href) { + $feeds[] = $href; + } + } + + return $feeds; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Icon.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Icon.php new file mode 100644 index 0000000..0d114f0 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Icon.php @@ -0,0 +1,20 @@ +extractor->getDocument(); + + return $document->link('apple-touch-icon-precomposed') + ?: $document->link('apple-touch-icon') + ?: $document->link('icon', ['sizes' => '144x144']) + ?: $document->link('icon', ['sizes' => '96x96']) + ?: $document->link('icon', ['sizes' => '48x48']); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Image.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Image.php new file mode 100644 index 0000000..04562f2 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Image.php @@ -0,0 +1,38 @@ +extractor->getOEmbed(); + $document = $this->extractor->getDocument(); + $metas = $this->extractor->getMetas(); + $ld = $this->extractor->getLinkedData(); + + return $oembed->url('image') + ?: $oembed->url('thumbnail') + ?: $oembed->url('thumbnail_url') + ?: $metas->url('og:image', 'og:image:url', 'og:image:secure_url', 'twitter:image', 'twitter:image:src', 'lp:image') + ?: $document->link('image_src') + ?: $ld->url('image.url') + ?: $this->detectFromContentType(); + } + + private function detectFromContentType() + { + if (!$this->extractor->getResponse()->hasHeader('content-type')) { + return null; + } + + $contentType = $this->extractor->getResponse()->getHeader('content-type')[0]; + + if (strpos($contentType, 'image/') === 0) { + return $this->extractor->getUri(); + } + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Keywords.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Keywords.php new file mode 100644 index 0000000..000a1e0 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Keywords.php @@ -0,0 +1,63 @@ +extractor->getMetas(); + $ld = $this->extractor->getLinkedData(); + + $types = [ + 'keywords', + 'og:video:tag', + 'og:article:tag', + 'og:video:tag', + 'og:book:tag', + 'lp.article:section', + 'dcterms.subject', + ]; + + foreach ($types as $type) { + $value = $metas->strAll($type); + + if ($value) { + $tags = array_merge($tags, self::toArray($value)); + } + } + + $value = $ld->strAll('keywords'); + + if ($value) { + $tags = array_merge($tags, self::toArray($value)); + } + + $tags = array_map('mb_strtolower', $tags); + $tags = array_unique($tags); + $tags = array_filter($tags); + $tags = array_values($tags); + + return $tags; + } + + private static function toArray(array $keywords): array + { + $all = []; + + foreach ($keywords as $keyword) { + $tags = explode(',', $keyword); + $tags = array_map('trim', $tags); + $tags = array_filter( + $tags, + fn ($value) => !empty($value) && substr($value, -3) !== '...' + ); + + $all = array_merge($all, $tags); + } + + return $all; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Language.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Language.php new file mode 100644 index 0000000..e328260 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Language.php @@ -0,0 +1,20 @@ +extractor->getDocument(); + $metas = $this->extractor->getMetas(); + $ld = $this->extractor->getLinkedData(); + + return $document->select('/html')->str('lang') + ?: $document->select('/html')->str('xml:lang') + ?: $metas->str('language', 'lang', 'og:locale', 'dc:language') + ?: $document->select('.//meta', ['http-equiv' => 'content-language'])->str('content') + ?: $ld->str('inLanguage'); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Languages.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Languages.php new file mode 100644 index 0000000..6fbe4e3 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Languages.php @@ -0,0 +1,31 @@ +extractor->getDocument(); + $languages = []; + + foreach ($document->select('.//link[@hreflang]')->nodes() as $node) { + $language = $node->getAttribute('hreflang'); + $href = $node->getAttribute('href'); + + if (isEmpty($language, $href)) { + continue; + } + + $languages[$language] = $this->extractor->resolveUri($href); + } + + return $languages; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/License.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/License.php new file mode 100644 index 0000000..5afddbf --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/License.php @@ -0,0 +1,16 @@ +extractor->getOEmbed(); + $metas = $this->extractor->getMetas(); + + return $oembed->str('license_url') + ?: $metas->str('copyright'); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/ProviderName.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/ProviderName.php new file mode 100644 index 0000000..e92f2fc --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/ProviderName.php @@ -0,0 +1,56 @@ +extractor->getOEmbed(); + $metas = $this->extractor->getMetas(); + + return $oembed->str('provider_name') + ?: $metas->str( + 'og:site_name', + 'dcterms.publisher', + 'publisher', + 'article:publisher' + ) + ?: ucfirst($this->fallback()); + } + + private function fallback(): string + { + $host = $this->extractor->getUri()->getHost(); + + $host = array_reverse(explode('.', $host)); + + switch (count($host)) { + case 1: + return $host[0]; + case 2: + return $host[1]; + default: + $tld = $host[1].'.'.$host[0]; + $suffixes = self::getSuffixes(); + + if (in_array($tld, $suffixes, true)) { + return $host[2]; + } + + return $host[1]; + } + } + + private static function getSuffixes(): array + { + if (!isset(self::$suffixes)) { + self::$suffixes = require dirname(__DIR__).'/resources/suffix.php'; + } + + return self::$suffixes; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/ProviderUrl.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/ProviderUrl.php new file mode 100644 index 0000000..9ca9ab6 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/ProviderUrl.php @@ -0,0 +1,24 @@ +extractor->getOEmbed(); + $metas = $this->extractor->getMetas(); + + return $oembed->url('provider_url') + ?: $metas->url('og:website') + ?: $this->fallback(); + } + + private function fallback(): UriInterface + { + return $this->extractor->getUri()->withPath('')->withQuery('')->withFragment(''); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/PublishedTime.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/PublishedTime.php new file mode 100644 index 0000000..f168120 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/PublishedTime.php @@ -0,0 +1,60 @@ +extractor->getOEmbed(); + $metas = $this->extractor->getMetas(); + $ld = $this->extractor->getLinkedData(); + + return $oembed->time('pubdate') + ?: $metas->time( + 'article:published_time', + 'created', + 'date', + 'datepublished', + 'music:release_date', + 'video:release_date', + 'newsrepublic:publish_date' + ) + ?: $ld->time( + 'pagePublished', + 'datePublished' + ) + ?: $this->detectFromPath() + ?: $metas->time( + 'pagerender', + 'pub_date', + 'publication-date', + 'lp.article:published_time', + 'lp.article:modified_time', + 'publish-date', + 'rc.datecreation', + 'timestamp', + 'sailthru.date', + 'article:modified_time', + 'dcterms.date' + ); + } + + /** + * Some sites using WordPress have the published time in the url + * For example: mysite.com/2020/05/19/post-title + */ + private function detectFromPath(): ?DateTime + { + $path = $this->extractor->getUri()->getPath(); + + if (preg_match('#/(19|20)\d{2}/[0-1]?\d/[0-3]?\d/#', $path, $matches)) { + return date_create_from_format('/Y/m/d/', $matches[0]) ?: null; + } + + return null; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Redirect.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Redirect.php new file mode 100644 index 0000000..79edee0 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Redirect.php @@ -0,0 +1,26 @@ +extractor->getDocument(); + $value = $document->select('.//meta', ['http-equiv' => 'refresh'])->str('content'); + + return $value ? $this->extract($value) : null; + } + + private function extract(string $value): ?UriInterface + { + if (preg_match('/url=(.+)$/i', $value, $match)) { + return $this->extractor->resolveUri(trim($match[1], '\'"')); + } + + return null; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Title.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Title.php new file mode 100644 index 0000000..352bff0 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Title.php @@ -0,0 +1,27 @@ +extractor->getOEmbed(); + $document = $this->extractor->getDocument(); + $metas = $this->extractor->getMetas(); + + return $oembed->str('title') + ?: $metas->str( + 'og:title', + 'twitter:title', + 'lp:title', + 'dcterms.title', + 'article:title', + 'headline', + 'article.headline', + 'parsely-title' + ) + ?: $document->select('.//head/title')->str(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Url.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Url.php new file mode 100644 index 0000000..358dbfd --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Detectors/Url.php @@ -0,0 +1,18 @@ +extractor->getOEmbed(); + + return $oembed->url('url') + ?: $oembed->url('web_page') + ?: $this->extractor->getUri(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Document.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Document.php new file mode 100644 index 0000000..648a204 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Document.php @@ -0,0 +1,124 @@ +extractor = $extractor; + + $html = (string) $extractor->getResponse()->getBody(); + $html = str_replace('
', "\n
", $html); + $html = str_replace('
document = !empty($html) ? Parser::parse($html) : new DOMDocument(); + $this->initXPath(); + } + + private function initXPath() + { + $this->xpath = new DOMXPath($this->document); + $this->xpath->registerNamespace('php', 'http://php.net/xpath'); + $this->xpath->registerPhpFunctions(); + } + + public function __clone() + { + $this->document = clone $this->document; + $this->initXPath(); + } + + public function remove(string $query): void + { + $nodes = iterator_to_array($this->xpath->query($query), false); + + foreach ($nodes as $node) { + $node->parentNode->removeChild($node); + } + } + + public function removeCss(string $query): void + { + $this->remove(self::cssToXpath($query)); + } + + public function getDocument(): DOMDocument + { + return $this->document; + } + + /** + * Helper to build xpath queries easily and case insensitive + */ + private static function buildQuery(string $startQuery, array $attributes): string + { + $selector = [$startQuery]; + + foreach ($attributes as $name => $value) { + $selector[] = sprintf('[php:functionString("strtolower", @%s)="%s"]', $name, mb_strtolower($value)); + } + + return implode('', $selector); + } + + /** + * Select a element in the dom + */ + public function select(string $query, array $attributes = null, DOMNode $context = null): QueryResult + { + if (!empty($attributes)) { + $query = self::buildQuery($query, $attributes); + } + + return new QueryResult($this->xpath->query($query, $context), $this->extractor); + } + + /** + * Select a element in the dom using a css selector + */ + public function selectCss(string $query, DOMNode $context = null): QueryResult + { + return $this->select(self::cssToXpath($query), null, $context); + } + + /** + * Shortcut to select a element and return the href + */ + public function link(string $rel, array $extra = []): ?UriInterface + { + return $this->select('.//link', ['rel' => $rel] + $extra)->url('href'); + } + + public function __toString(): string + { + return Parser::stringify($this->getDocument()); + } + + private static function cssToXpath(string $selector): string + { + if (!isset(self::$cssConverter)) { + if (!class_exists(CssSelectorConverter::class)) { + throw new RuntimeException('You need to install "symfony/css-selector" to use css selectors'); + } + + self::$cssConverter = new CssSelectorConverter(); + } + + return self::$cssConverter->toXpath($selector); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Embed.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Embed.php new file mode 100644 index 0000000..ca360e3 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Embed.php @@ -0,0 +1,89 @@ +crawler = $crawler ?: new Crawler(); + $this->extractorFactory = $extractorFactory ?: new ExtractorFactory(); + } + + public function get(string $url): Extractor + { + $request = $this->crawler->createRequest('GET', $url); + $response = $this->crawler->sendRequest($request); + + return $this->extract($request, $response); + } + + /** + * @return Extractor[] + */ + public function getMulti(string ...$urls): array + { + $requests = array_map( + fn ($url) => $this->crawler->createRequest('GET', $url), + $urls + ); + + $responses = $this->crawler->sendRequests(...$requests); + + $return = []; + + foreach ($responses as $k => $response) { + $return[] = $this->extract($requests[$k], $responses[$k]); + } + + return $return; + } + + public function getCrawler(): Crawler + { + return $this->crawler; + } + + public function getExtractorFactory(): ExtractorFactory + { + return $this->extractorFactory; + } + + public function setSettings(array $settings): void + { + $this->extractorFactory->setSettings($settings); + } + + private function extract(RequestInterface $request, ResponseInterface $response, bool $redirect = true): Extractor + { + $uri = $this->crawler->getResponseUri($response) ?: $request->getUri(); + + $extractor = $this->extractorFactory->createExtractor($uri, $request, $response, $this->crawler); + + if (!$redirect || !$this->mustRedirect($extractor)) { + return $extractor; + } + + $request = $this->crawler->createRequest('GET', $extractor->redirect); + $response = $this->crawler->sendRequest($request); + + return $this->extract($request, $response, false); + } + + private function mustRedirect(Extractor $extractor): bool + { + if (!empty($extractor->getOembed()->all())) { + return false; + } + + return $extractor->redirect !== null; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/EmbedCode.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/EmbedCode.php new file mode 100644 index 0000000..712ddb7 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/EmbedCode.php @@ -0,0 +1,42 @@ +html = $html; + $this->width = $width; + $this->height = $height; + + if ($width && $height) { + $this->ratio = round(($height / $width) * 100, 3); + } + } + + public function __toString(): string + { + return $this->html; + } + + #[ReturnTypeWillChange] + public function jsonSerialize() + { + return [ + 'html' => $this->html, + 'width' => $this->width, + 'height' => $this->height, + 'ratio' => $this->ratio, + ]; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Extractor.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Extractor.php new file mode 100644 index 0000000..469dd6b --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Extractor.php @@ -0,0 +1,222 @@ +uri = $uri; + $this->request = $request; + $this->response = $response; + $this->crawler = $crawler; + + //APIs + $this->document = new Document($this); + $this->oembed = new OEmbed($this); + $this->linkedData = new LinkedData($this); + $this->metas = new Metas($this); + + //Detectors + $this->authorName = new AuthorName($this); + $this->authorUrl = new AuthorUrl($this); + $this->cms = new Cms($this); + $this->code = new Code($this); + $this->description = new Description($this); + $this->favicon = new Favicon($this); + $this->feeds = new Feeds($this); + $this->icon = new Icon($this); + $this->image = new Image($this); + $this->keywords = new Keywords($this); + $this->language = new Language($this); + $this->languages = new Languages($this); + $this->license = new License($this); + $this->providerName = new ProviderName($this); + $this->providerUrl = new ProviderUrl($this); + $this->publishedTime = new PublishedTime($this); + $this->redirect = new Redirect($this); + $this->title = new Title($this); + $this->url = new Url($this); + } + + public function __get(string $name) + { + $detector = $this->customDetectors[$name] ?? $this->$name ?? null; + + if (!$detector || !($detector instanceof Detector)) { + throw new DomainException(sprintf('Invalid key "%s". No detector found for this value', $name)); + } + + return $detector->get(); + } + + public function createCustomDetectors(): array + { + return []; + } + + public function addDetector(string $name, Detector $detector): void + { + $this->customDetectors[$name] = $detector; + } + + public function setSettings(array $settings): void + { + $this->settings = $settings; + } + + public function getSettings(): array + { + return $this->settings; + } + + public function getSetting(string $key) + { + return $this->settings[$key] ?? null; + } + + public function getDocument(): Document + { + return $this->document; + } + + public function getOEmbed(): OEmbed + { + return $this->oembed; + } + + public function getLinkedData(): LinkedData + { + return $this->linkedData; + } + + public function getMetas(): Metas + { + return $this->metas; + } + + public function getRequest(): RequestInterface + { + return $this->request; + } + + public function getResponse(): ResponseInterface + { + return $this->response; + } + + public function getUri(): UriInterface + { + return $this->uri; + } + + /** + * @param UriInterface|string $uri + */ + public function resolveUri($uri): UriInterface + { + if (is_string($uri)) { + if (!isHttp($uri)) { + throw new InvalidArgumentException(sprintf('Uri string must use http or https scheme (%s)', $uri)); + } + + $uri = $this->crawler->createUri($uri); + } + + if (!($uri instanceof UriInterface)) { + throw new InvalidArgumentException('Uri must be a string or an instance of UriInterface'); + } + + return resolveUri($this->uri, $uri); + } + + public function getCrawler(): Crawler + { + return $this->crawler; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/ExtractorFactory.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/ExtractorFactory.php new file mode 100644 index 0000000..846e1b3 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/ExtractorFactory.php @@ -0,0 +1,93 @@ + Adapters\Slides\Extractor::class, + 'pinterest.com' => Adapters\Pinterest\Extractor::class, + 'flickr.com' => Adapters\Flickr\Extractor::class, + 'snipplr.com' => Adapters\Snipplr\Extractor::class, + 'play.cadenaser.com' => Adapters\CadenaSer\Extractor::class, + 'ideone.com' => Adapters\Ideone\Extractor::class, + 'gist.github.com' => Adapters\Gist\Extractor::class, + 'github.com' => Adapters\Github\Extractor::class, + 'wikipedia.org' => Adapters\Wikipedia\Extractor::class, + 'archive.org' => Adapters\Archive\Extractor::class, + 'sassmeister.com' => Adapters\Sassmeister\Extractor::class, + 'facebook.com' => Adapters\Facebook\Extractor::class, + 'instagram.com' => Adapters\Instagram\Extractor::class, + 'imageshack.com' => Adapters\ImageShack\Extractor::class, + 'youtube.com' => Adapters\Youtube\Extractor::class, + 'twitch.tv' => Adapters\Twitch\Extractor::class, + 'bandcamp.com' => Adapters\Bandcamp\Extractor::class, + 'twitter.com' => Adapters\Twitter\Extractor::class, + ]; + private array $customDetectors = []; + private array $settings; + + public function __construct(?array $settings = []) + { + $this->settings = $settings ?? []; + } + + public function createExtractor(UriInterface $uri, RequestInterface $request, ResponseInterface $response, Crawler $crawler): Extractor + { + $host = $uri->getHost(); + $class = $this->default; + + foreach ($this->adapters as $adapterHost => $adapter) { + if (substr($host, -strlen($adapterHost)) === $adapterHost) { + $class = $adapter; + break; + } + } + + /** @var Extractor $extractor */ + $extractor = new $class($uri, $request, $response, $crawler); + $extractor->setSettings($this->settings); + + foreach ($this->customDetectors as $name => $detector) { + $extractor->addDetector($name, new $detector($extractor)); + } + + foreach ($extractor->createCustomDetectors() as $name => $detector) { + $extractor->addDetector($name, $detector); + } + + return $extractor; + } + + public function addAdapter(string $pattern, string $class): void + { + $this->adapters[$pattern] = $class; + } + + public function addDetector(string $name, string $class): void + { + $this->customDetectors[$name] = $class; + } + + public function removeAdapter(string $pattern): void + { + unset($this->adapters[$pattern]); + } + + public function setDefault(string $class): void + { + $this->default = $class; + } + + public function setSettings(array $settings): void + { + $this->settings = $settings; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Http/Crawler.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Http/Crawler.php new file mode 100644 index 0000000..933b3bb --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Http/Crawler.php @@ -0,0 +1,77 @@ + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:73.0) Gecko/20100101 Firefox/73.0', + 'Cache-Control' => 'max-age=0', + ]; + + public function __construct(ClientInterface $client = null, RequestFactoryInterface $requestFactory = null, UriFactoryInterface $uriFactory = null) + { + $this->client = $client ?: new CurlClient(); + $this->requestFactory = $requestFactory ?: FactoryDiscovery::getRequestFactory(); + $this->uriFactory = $uriFactory ?: FactoryDiscovery::getUriFactory(); + } + + public function addDefaultHeaders(array $headers): void + { + $this->defaultHeaders = $headers + $this->defaultHeaders; + } + + /** + * @param UriInterface|string $uri The URI associated with the request. + */ + public function createRequest(string $method, $uri): RequestInterface + { + $request = $this->requestFactory->createRequest($method, $uri); + + foreach ($this->defaultHeaders as $name => $value) { + $request = $request->withHeader($name, $value); + } + + return $request; + } + + public function createUri(string $uri = ''): UriInterface + { + return $this->uriFactory->createUri($uri); + } + + public function sendRequest(RequestInterface $request): ResponseInterface + { + return $this->client->sendRequest($request); + } + + public function sendRequests(RequestInterface ...$requests): array + { + if ($this->client instanceof CurlClient) { + return $this->client->sendRequests(...$requests); + } + + return array_map( + fn ($request) => $this->client->sendRequest($request), + $requests + ); + } + + public function getResponseUri(ResponseInterface $response): ?UriInterface + { + $location = $response->getHeaderLine('Content-Location'); + + return $location ? $this->uriFactory->createUri($location) : null; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Http/CurlClient.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Http/CurlClient.php new file mode 100644 index 0000000..3e4e91c --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Http/CurlClient.php @@ -0,0 +1,40 @@ +responseFactory = $responseFactory ?: FactoryDiscovery::getResponseFactory(); + } + + public function setSettings(array $settings): void + { + $this->settings = $settings + $this->settings; + } + + public function sendRequest(RequestInterface $request): ResponseInterface + { + $responses = CurlDispatcher::fetch($this->settings, $this->responseFactory, $request); + + return $responses[0]; + } + + public function sendRequests(RequestInterface ...$request): array + { + return CurlDispatcher::fetch($this->settings, $this->responseFactory, ...$request); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Http/CurlDispatcher.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Http/CurlDispatcher.php new file mode 100644 index 0000000..8f61e39 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Http/CurlDispatcher.php @@ -0,0 +1,207 @@ +exec($responseFactory)]; + } + + //Init connections + $multi = curl_multi_init(); + $connections = []; + + foreach ($requests as $request) { + $connection = new static($settings, $request); + curl_multi_add_handle($multi, $connection->curl); + + $connections[] = $connection; + } + + //Run + $active = null; + do { + $status = curl_multi_exec($multi, $active); + + if ($active) { + curl_multi_select($multi); + } + + $info = curl_multi_info_read($multi); + + if ($info) { + foreach ($connections as $connection) { + if ($connection->curl === $info['handle']) { + $connection->result = $info['result']; + break; + } + } + } + } while ($active && $status == CURLM_OK); + + //Close connections + foreach ($connections as $connection) { + curl_multi_remove_handle($multi, $connection->curl); + } + + curl_multi_close($multi); + + return array_map( + fn ($connection) => $connection->exec($responseFactory), + $connections + ); + } + + private function __construct(array $settings, RequestInterface $request) + { + $this->request = $request; + $this->curl = curl_init((string) $request->getUri()); + $this->settings = $settings; + + $cookies = $settings['cookies_path'] ?? str_replace('//', '/', sys_get_temp_dir().'/embed-cookies.txt'); + + curl_setopt_array($this->curl, [ + CURLOPT_HTTPHEADER => $this->getRequestHeaders(), + CURLOPT_POST => strtoupper($request->getMethod()) === 'POST', + CURLOPT_MAXREDIRS => $settings['max_redirs'] ?? 10, + CURLOPT_CONNECTTIMEOUT => $settings['connect_timeout'] ?? 10, + CURLOPT_TIMEOUT => $settings['timeout'] ?? 10, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_SSL_VERIFYHOST => $settings['ssl_verify_host'] ?? 0, + CURLOPT_SSL_VERIFYPEER => $settings['ssl_verify_peer'] ?? false, + CURLOPT_ENCODING => '', + CURLOPT_CAINFO => CaBundle::getSystemCaRootBundlePath(), + CURLOPT_AUTOREFERER => true, + CURLOPT_FOLLOWLOCATION => $settings['follow_location'] ?? true, + CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4, + CURLOPT_USERAGENT => $settings['user_agent'] ?? $request->getHeaderLine('User-Agent'), + CURLOPT_COOKIEJAR => $cookies, + CURLOPT_COOKIEFILE => $cookies, + CURLOPT_HEADERFUNCTION => [$this, 'writeHeader'], + CURLOPT_WRITEFUNCTION => [$this, 'writeBody'], + ]); + } + + private function exec(ResponseFactoryInterface $responseFactory): ResponseInterface + { + curl_exec($this->curl); + + $info = curl_getinfo($this->curl); + + if ($this->error) { + $this->error(curl_strerror($this->error), $this->error); + } + + if (curl_errno($this->curl)) { + $this->error(curl_error($this->curl), curl_errno($this->curl)); + } + + curl_close($this->curl); + + $response = $responseFactory->createResponse($info['http_code']); + + foreach ($this->headers as $header) { + list($name, $value) = $header; + $response = $response->withAddedHeader($name, $value); + } + + $response = $response + ->withAddedHeader('Content-Location', $info['url']) + ->withAddedHeader('X-Request-Time', sprintf('%.3f ms', $info['total_time'])); + + if ($this->body) { + //5Mb max + $response->getBody()->write(stream_get_contents($this->body, 5000000, 0)); + } + + return $response; + } + + private function error(string $message, int $code) + { + $ignored = $this->settings['ignored_errors'] ?? null; + + if ($ignored === true || (is_array($ignored) && in_array($code, $ignored))) { + return; + } + + if ($this->isBinary && $code === CURLE_WRITE_ERROR) { + // The write callback aborted the request to prevent a download of the binary file + return; + } + + throw new NetworkException($message, $code, $this->request); + } + + private function getRequestHeaders(): array + { + $headers = []; + + foreach ($this->request->getHeaders() as $name => $values) { + switch (strtolower($name)) { + case 'user-agent': + break; + default: + $headers[] = $name . ':' . implode(', ', $values); + } + } + + return $headers; + } + + private function writeHeader($curl, $string): int + { + if (preg_match('/^([\w-]+):(.*)$/', $string, $matches)) { + $name = strtolower($matches[1]); + $value = trim($matches[2]); + $this->headers[] = [$name, $value]; + + if ($name === 'content-type') { + $this->isBinary = !preg_match('/(text|html|json)/', strtolower($value)); + } + } elseif ($this->headers) { + $key = array_key_last($this->headers); + $this->headers[$key][1] .= ' '.trim($string); + } + + return strlen($string); + } + + private function writeBody($curl, $string): int + { + if ($this->isBinary) { + return -1; + } + + if (!$this->body) { + $this->body = fopen('php://temp', 'w+'); + } + + return fwrite($this->body, $string); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Http/FactoryDiscovery.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Http/FactoryDiscovery.php new file mode 100644 index 0000000..75ccf37 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Http/FactoryDiscovery.php @@ -0,0 +1,72 @@ +request = $request; + } + + public function getRequest(): RequestInterface + { + return $this->request; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Http/RequestException.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Http/RequestException.php new file mode 100644 index 0000000..bfa9b4e --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Http/RequestException.php @@ -0,0 +1,23 @@ +request = $request; + } + + public function getRequest(): RequestInterface + { + return $this->request; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/HttpApiTrait.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/HttpApiTrait.php new file mode 100644 index 0000000..fa69743 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/HttpApiTrait.php @@ -0,0 +1,32 @@ +endpoint; + } + + private function fetchJSON(UriInterface $uri): array + { + $crawler = $this->extractor->getCrawler(); + $request = $crawler->createRequest('GET', $uri); + $response = $crawler->sendRequest($request); + + try { + return json_decode((string) $response->getBody(), true) ?: []; + } catch (Exception $exception) { + return []; + } + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/LinkedData.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/LinkedData.php new file mode 100644 index 0000000..1e3962d --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/LinkedData.php @@ -0,0 +1,111 @@ +getGraph(); + + if (!$graph) { + return null; + } + + foreach ($keys as $key) { + $subkeys = explode('.', $key); + + foreach ($graph->getNodes() as $node) { + $value = self::getValue($node, ...$subkeys); + + if ($value) { + return $value; + } + } + } + + return null; + } + + private function getGraph(string $name = null): ?GraphInterface + { + if (!isset($this->document)) { + try { + $this->document = LdDocument::load(json_encode($this->all())); + } catch (Throwable $throwable) { + $this->document = LdDocument::load('{}'); + return null; + } + } + + return $this->document->getGraph(); + } + + protected function fetchData(): array + { + $document = $this->extractor->getDocument(); + $content = $document->select('.//script', ['type' => 'application/ld+json'])->str(); + + if (empty($content)) { + return []; + } + + try { + return json_decode($content, true) ?: []; + } catch (Exception $exception) { + return []; + } + } + + private static function getValue(Node $node, string ...$keys) + { + foreach ($keys as $key) { + if (is_array($node)) { + $node = array_shift($node); + } + if (!$node instanceof Node) { + return null; + } + + $node = $node->getProperty("http://schema.org/{$key}"); + + if (!$node) { + return null; + } + } + + return self::detectValue($node); + } + + private static function detectValue($value) + { + if (is_array($value)) { + return array_map( + fn ($val) => self::detectValue($val), + array_values($value) + ); + } + + if (is_scalar($value)) { + return $value; + } + + if ($value instanceof Node) { + return $value->getId(); + } + + return $value->getValue(); + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/Metas.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/Metas.php new file mode 100644 index 0000000..70abe6c --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/Metas.php @@ -0,0 +1,43 @@ +extractor->getDocument(); + + foreach ($document->select('.//meta')->nodes() as $node) { + $type = $node->getAttribute('name') ?: $node->getAttribute('property') ?: $node->getAttribute('itemprop'); + $value = $node->getAttribute('content'); + + if (!empty($value) && !empty($type)) { + $type = strtolower($type); + $data[$type] ??= []; + $data[$type][] = $value; + } + } + + return $data; + } + + public function get(string ...$keys) + { + $data = $this->all(); + + foreach ($keys as $key) { + $values = $data[$key] ?? null; + + if ($values) { + return $values; + } + } + + return null; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/OEmbed.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/OEmbed.php new file mode 100644 index 0000000..e089150 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/OEmbed.php @@ -0,0 +1,173 @@ + $url, 'format' => 'json']; + + return array_merge($queryParameters, $this->extractor->getSetting('oembed:query_parameters') ?? []); + } + + protected function fetchData(): array + { + $this->endpoint = $this->detectEndpoint(); + + if (empty($this->endpoint)) { + return []; + } + + $crawler = $this->extractor->getCrawler(); + $request = $crawler->createRequest('GET', $this->endpoint); + $response = $crawler->sendRequest($request); + + if (self::isXML($request->getUri())) { + return $this->extractXML((string) $response->getBody()); + } + + return $this->extractJSON((string) $response->getBody()); + } + + protected function detectEndpoint(): ?UriInterface + { + $document = $this->extractor->getDocument(); + + $endpoint = $document->link('alternate', ['type' => 'application/json+oembed']) + ?: $document->link('alternate', ['type' => 'text/json+oembed']) + ?: $document->link('alternate', ['type' => 'application/xml+oembed']) + ?: $document->link('alternate', ['type' => 'text/xml+oembed']) + ?: null; + + if ($endpoint === null) { + return $this->detectEndpointFromProviders(); + } + + // Add configured OEmbed query parameters + parse_str($endpoint->getQuery(), $query); + $query = array_merge($query, $this->extractor->getSetting('oembed:query_parameters') ?? []); + $endpoint = $endpoint->withQuery(http_build_query($query)); + + return $endpoint; + } + + private function detectEndpointFromProviders(): ?UriInterface + { + $url = (string) $this->extractor->getUri(); + + if ($endpoint = $this->detectEndpointFromUrl($url)) { + return $endpoint; + } + + $initialUrl = (string) $this->extractor->getRequest()->getUri(); + + if ($initialUrl !== $url && ($endpoint = $this->detectEndpointFromUrl($initialUrl))) { + $this->defaults['url'] = $initialUrl; + return $endpoint; + } + + return null; + } + + private function detectEndpointFromUrl(string $url): ?UriInterface + { + $endpoint = self::searchEndpoint(self::getProviders(), $url); + + if (!$endpoint) { + return null; + } + + return $this->extractor->getCrawler() + ->createUri($endpoint) + ->withQuery(http_build_query($this->getOembedQueryParameters($url))); + } + + private static function searchEndpoint(array $providers, string $url): ?string + { + foreach ($providers as $endpoint => $patterns) { + foreach ($patterns as $pattern) { + if (preg_match($pattern, $url)) { + return $endpoint; + } + } + } + + return null; + } + + private static function isXML(UriInterface $uri): bool + { + $extension = pathinfo($uri->getPath(), PATHINFO_EXTENSION); + + if (strtolower($extension) === 'xml') { + return true; + } + + parse_str($uri->getQuery(), $params); + $format = $params['format'] ?? null; + + if ($format && strtolower($format) === 'xml') { + return true; + } + + return false; + } + + private function extractXML(string $xml): array + { + try { + // Remove the DOCTYPE declaration for to prevent XML Quadratic Blowup vulnerability + $xml = preg_replace('/^]*+>/i', '', $xml, 1); + $data = []; + $errors = libxml_use_internal_errors(true); + $content = new SimpleXMLElement($xml); + libxml_use_internal_errors($errors); + + foreach ($content as $element) { + $value = trim((string) $element); + + if (stripos($value, 'getName(); + $data[$name] = $value; + } + + return $data ? ($data + $this->defaults) : []; + } catch (Exception $exception) { + return []; + } + } + + private function extractJSON(string $json): array + { + try { + $data = json_decode($json, true); + + return is_array($data) ? ($data + $this->defaults) : []; + } catch (Exception $exception) { + return []; + } + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/QueryResult.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/QueryResult.php new file mode 100644 index 0000000..41212e8 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/QueryResult.php @@ -0,0 +1,112 @@ +nodes = iterator_to_array($result, false); + $this->extractor = $extractor; + } + + public function node(): ?DOMElement + { + return $this->nodes[0] ?? null; + } + + public function nodes(): array + { + return $this->nodes; + } + + public function filter(Closure $callback): self + { + $this->nodes = array_filter($this->nodes, $callback); + + return $this; + } + + public function get(string $attribute = null) + { + $node = $this->node(); + + if (!$node) { + return null; + } + + return $attribute ? self::getAttribute($node, $attribute) : $node->nodeValue; + } + + public function getAll(string $attribute = null): array + { + $nodes = $this->nodes(); + + return array_filter( + array_map( + fn ($node) => $attribute ? self::getAttribute($node, $attribute) : $node->nodeValue, + $nodes + ) + ); + } + + public function str(string $attribute = null): ?string + { + $value = $this->get($attribute); + + return $value ? clean($value) : null; + } + + public function strAll(string $attribute = null): array + { + return array_filter(array_map(fn ($value) => clean($value), $this->getAll($attribute))); + } + + public function int(string $attribute = null): ?int + { + $value = $this->get($attribute); + + return $value ? (int) $value : null; + } + + public function url(string $attribute = null): ?UriInterface + { + $value = $this->get($attribute); + + if (!$value) { + return null; + } + + try { + return $this->extractor->resolveUri($value); + } catch (Throwable $error) { + return null; + } + } + + private static function getAttribute(DOMElement $node, string $name): ?string + { + //Don't use $node->getAttribute() because it does not work with namespaces (ex: xml:lang) + $attributes = $node->attributes; + + for ($i = 0; $i < $attributes->length; ++$i) { + $attribute = $attributes->item($i); + + if ($attribute->name === $name) { + return $attribute->nodeValue; + } + } + + return null; + } +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/functions.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/functions.php new file mode 100644 index 0000000..93c18ed --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/functions.php @@ -0,0 +1,156 @@ + $value) { + if ($value === null) { + continue; + } elseif ($value === true) { + $html .= " $name"; + } elseif ($value !== false) { + $html .= ' '.$name.'="'.htmlspecialchars((string) $value).'"'; + } + } + + if ($tagName === 'img') { + return "$html />"; + } + + return "{$html}>{$content}"; +} + +/** + * Resolve a uri within this document + * (useful to get absolute uris from relative) + */ +function resolveUri(UriInterface $base, UriInterface $uri): UriInterface +{ + $uri = $uri->withPath(resolvePath($base->getPath(), $uri->getPath())); + + if (!$uri->getHost()) { + $uri = $uri->withHost($base->getHost()); + } + + if (!$uri->getScheme()) { + $uri = $uri->withScheme($base->getScheme()); + } + + return $uri + ->withPath(cleanPath($uri->getPath())) + ->withFragment(''); +} + +function isHttp(string $uri): bool +{ + if (preg_match('/^(\w+):/', $uri, $matches)) { + return in_array(strtolower($matches[1]), ['http', 'https']); + } + + return true; +} + +function resolvePath(string $base, string $path): string +{ + if ($path === '') { + return ''; + } + + if ($path[0] === '/') { + return $path; + } + + if (substr($base, -1) !== '/') { + $position = strrpos($base, '/'); + $base = substr($base, 0, $position); + } + + $path = "{$base}/{$path}"; + + $parts = array_filter(explode('/', $path), 'strlen'); + $absolutes = []; + + foreach ($parts as $part) { + if ('.' == $part) { + continue; + } + + if ('..' == $part) { + array_pop($absolutes); + continue; + } + + $absolutes[] = $part; + } + + return implode('/', $absolutes); +} + +function cleanPath(string $path): string +{ + if ($path === '') { + return '/'; + } + + $path = preg_replace('|[/]{2,}|', '/', $path); + + if (strpos($path, ';jsessionid=') !== false) { + $path = preg_replace('/^(.*)(;jsessionid=.*)$/i', '$1', $path); + } + + return $path; +} + +function matchPath(string $pattern, string $subject): bool +{ + $pattern = str_replace('\\*', '.*', preg_quote($pattern, '|')); + + return (bool) preg_match("|^{$pattern}$|i", $subject); +} + +function getDirectory(string $path, int $position): ?string +{ + $dirs = explode('/', $path); + return $dirs[$position + 1] ?? null; +} + +/** + * Determine whether at least one of the supplied variables is empty. + * + * @param mixed ...$values The values to check. + * + * @return boolean + */ +function isEmpty(mixed ...$values): bool +{ + $skipValues = array( + 'undefined', + ); + + foreach ($values as $value) { + if (empty($value) || in_array($value, $skipValues)) { + return true; + } + } + + return false; +} diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/resources/oembed.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/resources/oembed.php new file mode 100644 index 0000000..5f39c9f --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/resources/oembed.php @@ -0,0 +1,1134 @@ + [ + '|^https?://www\\.23hq\\.com/.*/photo/.*$|i', + ], + 'https://api.abraia.me/oembed' => [ + '|^https?://store\\.abraia\\.me/.*$|i', + ], + 'https://secure.actblue.com/cf/oembed' => [ + '|^https?://secure\\.actblue\\.com/donate/.*$|i', + ], + 'https://adilo.bigcommand.com/web/oembed' => [ + '|^https?://adilo\\.bigcommand\\.com/watch/.*$|i', + ], + 'http://play.adpaths.com/oembed/*' => [ + '|^https?://play\\.adpaths\\.com/experience/.*$|i', + ], + 'https://openapi.afreecatv.com/oembed/embedinfo' => [ + '|^https?://v\\.afree\\.ca/ST/$|i', + '|^https?://vod\\.afreecatv\\.com/ST/$|i', + '|^https?://vod\\.afreecatv\\.com/PLAYER/STATION/$|i', + '|^https?://play\\.afreecatv\\.com/$|i', + ], + 'https://viewer.altium.com/shell/oembed' => [ + '|^https?://altium\\.com/viewer/.*$|i', + ], + 'https://api.altrulabs.com/api/v1/social/oembed' => [ + '|^https?://app\\.altrulabs\\.com/.*/.*\\?answer_id\\=.*$|i', + '|^https?://app\\.altrulabs\\.com/player/.*$|i', + ], + 'https://live.amcharts.com/oembed' => [ + '|^https?://live\\.amcharts\\.com/.*$|i', + ], + 'https://api.amtraker.com/v2/oembed' => [ + '|^https?://amtraker\\.com/trains/.*$|i', + '|^https?://beta\\.amtraker\\.com/trains/.*$|i', + ], + 'https://animatron.com/oembed/json' => [ + '|^https?://www\\.animatron\\.com/project/.*$|i', + '|^https?://animatron\\.com/project/.*$|i', + ], + 'http://animoto.com/oembeds/create' => [ + '|^https?://animoto\\.com/play/.*$|i', + ], + 'https://api.anniemusic.app/api/v1/oembed' => [ + '|^https?://anniemusic\\.app/t/.*$|i', + '|^https?://anniemusic\\.app/p/.*$|i', + ], + 'https://display.apester.com/oembed' => [ + '|^https?://renderer\\.apester\\.com/v2/.*\\?preview\\=true&iframe_preview\\=true$|i', + ], + 'https://storymaps.arcgis.com/oembed' => [ + '|^https?://storymaps\\.arcgis\\.com/stories/.*$|i', + ], + 'https://app.archivos.digital/oembed/' => [ + '|^https?://app\\.archivos\\.digital/app/view/.*$|i', + ], + 'https://audioboom.com/publishing/oembed.json' => [ + '|^https?://audioboom\\.com/channels/.*$|i', + '|^https?://audioboom\\.com/channel/.*$|i', + '|^https?://audioboom\\.com/playlists/.*$|i', + '|^https?://audioboom\\.com/podcasts/.*$|i', + '|^https?://audioboom\\.com/podcast/.*$|i', + '|^https?://audioboom\\.com/posts/.*$|i', + '|^https?://audioboom\\.com/episodes/.*$|i', + ], + 'https://audioclip.naver.com/oembed' => [ + '|^https?://audioclip\\.naver\\.com/channels/.*/clips/.*$|i', + '|^https?://audioclip\\.naver\\.com/audiobooks/.*$|i', + ], + 'https://audiomack.com/oembed' => [ + '|^https?://audiomack\\.com/.*/song/.*$|i', + '|^https?://audiomack\\.com/.*/album/.*$|i', + '|^https?://audiomack\\.com/.*/playlist/.*$|i', + ], + 'https://podcasts.audiomeans.fr/services/oembed' => [ + '|^https?://podcasts\\.audiomeans\\.fr/.*$|i', + ], + 'https://stage-embed.avocode.com/api/oembed' => [ + '|^https?://app\\.avocode\\.com/view/.*$|i', + ], + 'https://backtracks.fm/oembed' => [ + '|^https?://backtracks\\.fm/.*/.*/e/.*$|i', + '|^https?://backtracks\\.fm/.*/s/.*/.*$|i', + '|^https?://backtracks\\.fm/.*/.*/.*/.*/e/.*/.*$|i', + '|^https?://backtracks\\.fm/.*$|i', + ], + 'https://www.beautiful.ai/api/oembed' => [ + '|^https?://www\\.beautiful\\.ai/.*$|i', + ], + 'https://blackfire.io/oembed' => [ + '|^https?://blackfire\\.io/profiles/.*/graph$|i', + '|^https?://blackfire\\.io/profiles/compare/.*/graph$|i', + ], + 'https://blogcast.host/oembed' => [ + '|^https?://blogcast\\.host/embed/.*$|i', + '|^https?://blogcast\\.host/embedly/.*$|i', + ], + 'https://bookingmood.com/api/oembed' => [ + '|^https?://www\\.bookingmood\\.com/embed/.*/.*$|i', + ], + 'http://boxofficebuz.com/oembed' => [ + '|^https?://boxofficebuz\\.com.*$|i', + ], + 'https://view.briovr.com/api/v1/worlds/oembed/' => [ + '|^https?://view\\.briovr\\.com/api/v1/worlds/oembed/.*$|i', + ], + 'https://www.bumper.com/oembed/bumper' => [ + '|^https?://www\\.bumper\\.com/oembed/bumper$|i', + '|^https?://www\\.bumper\\.com/oembed\\-s/bumper$|i', + ], + 'https://buttondown.email/embed' => [ + '|^https?://buttondown\\.email/.*$|i', + ], + 'https://cmc.byzart.eu/oembed/' => [ + '|^https?://cmc\\.byzart\\.eu/files/.*$|i', + ], + 'http://cacoo.com/oembed.json' => [ + '|^https?://cacoo\\.com/diagrams/.*$|i', + ], + 'https://minesweeper.today/api/oembed' => [ + '|^https?://minesweeper\\.today/.*$|i', + ], + 'https://www.catapult.app/_hcms/api/video/oembed' => [ + '|^https?://www\\-catapult\\-app\\.sandbox\\.hs\\-sites\\.com/video\\-page.*$|i', + '|^https?://www\\-catapult\\.app/video\\-page.*$|i', + ], + 'http://img.catbo.at/oembed.json' => [ + '|^https?://img\\.catbo\\.at/.*$|i', + ], + 'http://view.ceros.com/oembed' => [ + '|^https?://view\\.ceros\\.com/.*$|i', + ], + 'https://www.chainflix.net/video/oembed' => [ + '|^https?://chainflix\\.net/video/.*$|i', + '|^https?://chainflix\\.net/video/embed/.*$|i', + '|^https?://.*\\.chainflix\\.net/video/.*$|i', + '|^https?://.*\\.chainflix\\.net/video/embed/.*$|i', + ], + 'http://embed.chartblocks.com/1.0/oembed' => [ + '|^https?://public\\.chartblocks\\.com/c/.*$|i', + ], + 'http://chirb.it/oembed.json' => [ + '|^https?://chirb\\.it/.*$|i', + ], + 'https://chroco.ooo/embed' => [ + '|^https?://chroco\\.ooo/mypage/.*$|i', + '|^https?://chroco\\.ooo/story/.*$|i', + ], + 'https://www.circuitlab.com/circuit/oembed/' => [ + '|^https?://www\\.circuitlab\\.com/circuit/.*$|i', + ], + 'https://www.clipland.com/api/oembed' => [ + '|^https?://www\\.clipland\\.com/v/.*$|i', + ], + 'http://api.clyp.it/oembed/' => [ + '|^https?://clyp\\.it/.*$|i', + '|^https?://clyp\\.it/playlist/.*$|i', + ], + 'https://app.ilovecoco.video/api/oembed.json' => [ + '|^https?://app\\.ilovecoco\\.video/.*/embed$|i', + ], + 'https://codehs.com/api/sharedprogram/*/oembed/' => [ + '|^https?://codehs\\.com/editor/share_abacus/.*$|i', + ], + 'https://codepen.io/api/oembed' => [ + '|^https?://codepen\\.io/.*$|i', + ], + 'https://codepoints.net/api/v1/oembed' => [ + '|^https?://codepoints\\.net/.*$|i', + '|^https?://www\\.codepoints\\.net/.*$|i', + ], + 'https://codesandbox.io/oembed' => [ + '|^https?://codesandbox\\.io/s/.*$|i', + '|^https?://codesandbox\\.io/embed/.*$|i', + ], + 'http://www.collegehumor.com/oembed.json' => [ + '|^https?://www\\.collegehumor\\.com/video/.*$|i', + ], + 'https://commaful.com/api/oembed/' => [ + '|^https?://commaful\\.com/play/.*$|i', + ], + 'http://coub.com/api/oembed.json' => [ + '|^https?://coub\\.com/view/.*$|i', + '|^https?://coub\\.com/embed/.*$|i', + ], + 'http://crowdranking.com/api/oembed.json' => [ + '|^https?://crowdranking\\.com/.*/.*$|i', + ], + 'https://crumb.sh/oembed/' => [ + '|^https?://crumb\\.sh/.*$|i', + ], + 'https://gql.cueup.io/oembed' => [ + '|^https?://cueup\\.io/user/.*/sounds/.*$|i', + ], + 'https://api.curated.co/oembed' => [ + '|^https?://.*\\.curated\\.co/.*$|i', + ], + 'https://app.customerdb.com/embed' => [ + '|^https?://app\\.customerdb\\.com/share/.*$|i', + ], + 'https://app.dadan.io/api/video/oembed' => [ + '|^https?://app\\.dadan\\.io/.*$|i', + '|^https?://stage\\.dadan\\.io/.*$|i', + ], + 'https://www.dailymotion.com/services/oembed' => [ + '|^https?://www\\.dailymotion\\.com/video/.*$|i', + ], + 'https://dalexni.com/oembed/' => [ + '|^https?://dalexni\\.com/i/.*$|i', + ], + 'https://api.datawrapper.de/v3/oembed/' => [ + '|^https?://datawrapper\\.dwcdn\\.net/.*$|i', + ], + 'https://embed.deseret.com/' => [ + '|^https?://.*\\.deseret\\.com/.*$|i', + ], + 'http://backend.deviantart.com/oembed' => [ + '|^https?://.*\\.deviantart\\.com/art/.*$|i', + '|^https?://.*\\.deviantart\\.com/.*\\#/d.*$|i', + '|^https?://fav\\.me/.*$|i', + '|^https?://sta\\.sh/.*$|i', + '|^https?://.*\\.deviantart\\.com/.*/art/.*$|i', + '|^https?://sta\\.sh/.*",$|i', + '|^https?://.*\\.deviantart\\.com/.*\\#/d.*"$|i', + ], + 'https://*.didacte.com/cards/oembed' => [ + '|^https?://.*\\.didacte\\.com/a/course/.*$|i', + ], + 'https://www.ultimedia.com/api/search/oembed' => [ + '|^https?://www\\.ultimedia\\.com/central/video/edit/id/.*/topic_id/.*/$|i', + '|^https?://www\\.ultimedia\\.com/default/index/videogeneric/id/.*/showtitle/1/viewnc/1$|i', + '|^https?://www\\.ultimedia\\.com/default/index/videogeneric/id/.*$|i', + ], + 'https://www.docdroid.net/api/oembed' => [ + '|^https?://.*\\.docdroid\\.net/.*$|i', + '|^https?://docdro\\.id/.*$|i', + '|^https?://.*\\.docdroid\\.com/.*$|i', + ], + 'http://dotsub.com/services/oembed' => [ + '|^https?://dotsub\\.com/view/.*$|i', + ], + 'https://dreambroker.com/channel/oembed' => [ + '|^https?://www\\.dreambroker\\.com/channel/.*/.*$|i', + ], + 'https://api.d.tube/oembed' => [ + '|^https?://d\\.tube/v/.*$|i', + ], + 'https://www.edumedia-sciences.com/oembed.json' => [ + '|^https?://www\\.edumedia\\-sciences\\.com/.*$|i', + ], + 'https://www.edumedia-sciences.com/oembed.xml' => [ + '|^https?://www\\.edumedia\\-sciences\\.com/.*$|i', + ], + 'http://egliseinfo.catholique.fr/api/oembed' => [ + '|^https?://egliseinfo\\.catholique\\.fr/.*$|i', + ], + 'https://embedery.com/api/oembed' => [ + '|^https?://embedery\\.com/widget/.*$|i', + ], + 'http://api.embed.ly/1/oembed' => [ + '|^https?://api\\.embed\\.ly/.*$|i', + ], + 'https://music.enystre.com/oembed' => [ + '|^https?://music\\.enystre\\.com/lyrics/.*$|i', + ], + 'https://ethfiddle.com/services/oembed/' => [ + '|^https?://ethfiddle\\.com/.*$|i', + ], + 'https://evt.live/api/oembed' => [ + '|^https?://evt\\.live/.*$|i', + '|^https?://evt\\.live/.*/.*$|i', + '|^https?://live\\.eventlive\\.pro/.*$|i', + '|^https?://live\\.eventlive\\.pro/.*/.*$|i', + ], + 'https://api.everviz.com/oembed' => [ + '|^https?://app\\.everviz\\.com/embed/.*$|i', + ], + 'https://oembed.ex.co/item' => [ + '|^https?://app\\.ex\\.co/stories/.*$|i', + '|^https?://www\\.playbuzz\\.com/.*$|i', + ], + 'https://eyrie.io/v1/oembed' => [ + '|^https?://eyrie\\.io/board/.*$|i', + '|^https?://eyrie\\.io/sparkfun/.*$|i', + ], + 'https://graph.facebook.com/v10.0/oembed_post' => [ + '|^https?://www\\.facebook\\.com/.*/posts/.*$|i', + '|^https?://www\\.facebook\\.com/.*/activity/.*$|i', + '|^https?://www\\.facebook\\.com/.*/photos/.*$|i', + '|^https?://www\\.facebook\\.com/photo\\.php\\?fbid\\=.*$|i', + '|^https?://www\\.facebook\\.com/photos/.*$|i', + '|^https?://www\\.facebook\\.com/permalink\\.php\\?story_fbid\\=.*$|i', + '|^https?://www\\.facebook\\.com/media/set\\?set\\=.*$|i', + '|^https?://www\\.facebook\\.com/questions/.*$|i', + '|^https?://www\\.facebook\\.com/notes/.*/.*/.*$|i', + ], + 'https://graph.facebook.com/v10.0/oembed_video' => [ + '|^https?://www\\.facebook\\.com/.*/videos/.*$|i', + '|^https?://www\\.facebook\\.com/video\\.php\\?id\\=.*$|i', + '|^https?://www\\.facebook\\.com/video\\.php\\?v\\=.*$|i', + ], + 'https://graph.facebook.com/v10.0/oembed_page' => [ + '|^https?://www\\.facebook\\.com/.*$|i', + ], + 'https://app.getfader.com/api/oembed' => [ + '|^https?://app\\.getfader\\.com/projects/.*/publish$|i', + ], + 'https://faithlifetv.com/api/oembed' => [ + '|^https?://faithlifetv\\.com/items/.*$|i', + '|^https?://faithlifetv\\.com/items/resource/.*/.*$|i', + '|^https?://faithlifetv\\.com/media/.*$|i', + '|^https?://faithlifetv\\.com/media/assets/.*$|i', + '|^https?://faithlifetv\\.com/media/resource/.*/.*$|i', + ], + 'https://www.fireworktv.com/oembed' => [ + '|^https?://.*\\.fireworktv\\.com/.*$|i', + '|^https?://.*\\.fireworktv\\.com/embed/.*/v/.*$|i', + ], + 'https://www.fite.tv/oembed' => [ + '|^https?://www\\.fite\\.tv/watch/.*$|i', + ], + 'https://flat.io/services/oembed' => [ + '|^https?://flat\\.io/score/.*$|i', + '|^https?://.*\\.flat\\.io/score/.*$|i', + ], + 'https://www.flickr.com/services/oembed/' => [ + '|^https?://.*\\.flickr\\.com/photos/.*$|i', + '|^https?://flic\\.kr/p/.*$|i', + '|^https?://.*\\..*\\.flickr\\.com/.*/.*$|i', + ], + 'https://app.flourish.studio/api/v1/oembed' => [ + '|^https?://public\\.flourish\\.studio/visualisation/.*$|i', + '|^https?://public\\.flourish\\.studio/story/.*$|i', + ], + 'https://fiso.foxsports.com.au/oembed' => [ + '|^https?://fiso\\.foxsports\\.com\\.au/isomorphic\\-widget/.*$|i', + ], + 'https://framebuzz.com/oembed/' => [ + '|^https?://framebuzz\\.com/v/.*$|i', + ], + 'https://api.framer.com/web/oembed' => [ + '|^https?://framer\\.com/share/.*$|i', + '|^https?://framer\\.com/embed/.*$|i', + ], + 'http://api.geograph.org.uk/api/oembed' => [ + '|^https?://.*\\.geograph\\.org\\.uk/.*$|i', + '|^https?://.*\\.geograph\\.co\\.uk/.*$|i', + '|^https?://.*\\.geograph\\.ie/.*$|i', + '|^https?://.*\\.wikimedia\\.org/.*_geograph\\.org\\.uk_.*$|i', + ], + 'http://www.geograph.org.gg/api/oembed' => [ + '|^https?://.*\\.geograph\\.org\\.gg/.*$|i', + '|^https?://.*\\.geograph\\.org\\.je/.*$|i', + '|^https?://channel\\-islands\\.geograph\\.org/.*$|i', + '|^https?://channel\\-islands\\.geographs\\.org/.*$|i', + '|^https?://.*\\.channel\\.geographs\\.org/.*$|i', + ], + 'http://geo.hlipp.de/restapi.php/api/oembed' => [ + '|^https?://geo\\-en\\.hlipp\\.de/.*$|i', + '|^https?://geo\\.hlipp\\.de/.*$|i', + '|^https?://germany\\.geograph\\.org/.*$|i', + ], + 'http://embed.gettyimages.com/oembed' => [ + '|^https?://gty\\.im/.*$|i', + ], + 'https://api.gfycat.com/v1/oembed' => [ + '|^https?://gfycat\\.com/.*$|i', + '|^https?://www\\.gfycat\\.com/.*$|i', + ], + 'https://www.gifnote.com/services/oembed' => [ + '|^https?://www\\.gifnote\\.com/play/.*$|i', + ], + 'https://giphy.com/services/oembed' => [ + '|^https?://giphy\\.com/gifs/.*$|i', + '|^https?://giphy\\.com/clips/.*$|i', + '|^https?://gph\\.is/.*$|i', + '|^https?://media\\.giphy\\.com/media/.*/giphy\\.gif$|i', + ], + 'https://gloria.tv/oembed/' => [ + '|^https?://gloria\\.tv/.*$|i', + ], + 'https://embed.gmetri.com/oembed/' => [ + '|^https?://view\\.gmetri\\.com/.*$|i', + '|^https?://.*\\.gmetri\\.com/.*$|i', + ], + 'https://app.gong.io/oembed' => [ + '|^https?://app\\.gong\\.io/call\\?id\\=.*$|i', + ], + 'https://api.grain.com/_/api/oembed' => [ + '|^https?://grain\\.co/highlight/.*$|i', + '|^https?://grain\\.co/share/.*$|i', + '|^https?://grain\\.com/share/.*$|i', + ], + 'https://api.luminery.com/oembed' => [ + '|^https?://gtchannel\\.com/watch/.*$|i', + ], + 'https://api.gyazo.com/api/oembed' => [ + '|^https?://gyazo\\.com/.*$|i', + ], + 'https://api.hash.ai/oembed' => [ + '|^https?://core\\.hash\\.ai/@.*$|i', + ], + 'https://hearthis.at/oembed/?format=json' => [ + '|^https?://hearthis\\.at/.*/.*/$|i', + '|^https?://hearthis\\.at/.*/set/.*/$|i', + ], + 'https://heyzine.com/api1/oembed' => [ + '|^https?://heyzine\\.com/flip\\-book/.*$|i', + '|^https?://.*\\.hflip\\.co/.*$|i', + '|^https?://.*\\.aflip\\.in/.*$|i', + ], + 'https://player.hihaho.com/services/oembed' => [ + '|^https?://player\\.hihaho\\.com/.*$|i', + ], + 'https://www.hippovideo.io/services/oembed' => [ + '|^https?://.*\\.hippovideo\\.io/.*$|i', + ], + 'https://homey.app/api/oembed/flow' => [ + '|^https?://homey\\.app/f/.*$|i', + '|^https?://homey\\.app/.*/flow/.*$|i', + ], + 'http://huffduffer.com/oembed' => [ + '|^https?://huffduffer\\.com/.*/.*$|i', + ], + 'http://www.hulu.com/api/oembed.json' => [ + '|^https?://www\\.hulu\\.com/watch/.*$|i', + ], + 'https://oembed.idomoo.com/oembed' => [ + '|^https?://.*\\.idomoo\\.com/.*$|i', + ], + 'http://www.ifixit.com/Embed' => [ + '|^https?://www\\.ifixit\\.com/Guide/View/.*$|i', + ], + 'http://www.ifttt.com/oembed/' => [ + '|^https?://ifttt\\.com/recipes/.*$|i', + ], + 'https://www.iheart.com/oembed' => [ + '|^https?://www\\.iheart\\.com/podcast/.*/.*$|i', + ], + 'https://qr.imenupro.com/api/oembed' => [ + '|^https?://qr\\.imenupro\\.com/.*$|i', + ], + 'https://oembed.incredible.dev/oembed' => [ + '|^https?://incredible\\.dev/watch/.*$|i', + ], + 'https://player.indacolive.com/services/oembed' => [ + '|^https?://player\\.indacolive\\.com/player/jwp/clients/.*$|i', + ], + 'https://infogram.com/oembed' => [ + '|^https?://infogram\\.com/.*$|i', + ], + 'https://infoveave.net/services/oembed/' => [ + '|^https?://.*\\.infoveave\\.net/E/.*$|i', + '|^https?://.*\\.infoveave\\.net/P/.*$|i', + ], + 'https://www.injurymap.com/services/oembed' => [ + '|^https?://www\\.injurymap\\.com/exercises/.*$|i', + ], + 'https://www.inoreader.com/oembed/api/' => [ + '|^https?://www\\.inoreader\\.com/oembed/$|i', + ], + 'http://api.inphood.com/oembed' => [ + '|^https?://.*\\.inphood\\.com/.*$|i', + ], + 'https://graph.facebook.com/v10.0/instagram_oembed' => [ + '|^https?://instagram\\.com/.*/p/.*,$|i', + '|^https?://www\\.instagram\\.com/.*/p/.*,$|i', + '|^https?://instagram\\.com/p/.*$|i', + '|^https?://instagr\\.am/p/.*$|i', + '|^https?://www\\.instagram\\.com/p/.*$|i', + '|^https?://www\\.instagr\\.am/p/.*$|i', + '|^https?://instagram\\.com/tv/.*$|i', + '|^https?://instagr\\.am/tv/.*$|i', + '|^https?://www\\.instagram\\.com/tv/.*$|i', + '|^https?://www\\.instagr\\.am/tv/.*$|i', + '|^https?://www\\.instagram\\.com/reel/.*$|i', + '|^https?://instagram\\.com/reel/.*$|i', + '|^https?://instagr\\.am/reel/.*$|i', + ], + 'https://www.insticator.com/oembed' => [ + '|^https?://ppa\\.insticator\\.com/embed\\-unit/.*$|i', + ], + 'https://issuu.com/oembed' => [ + '|^https?://issuu\\.com/.*/docs/.*$|i', + ], + 'https://api.jovian.ai/oembed.json' => [ + '|^https?://jovian\\.ml/.*$|i', + '|^https?://jovian\\.ml/viewer.*$|i', + '|^https?://.*\\.jovian\\.ml/.*$|i', + '|^https?://jovian\\.ai/.*$|i', + '|^https?://jovian\\.ai/viewer.*$|i', + '|^https?://.*\\.jovian\\.ai/.*$|i', + ], + 'https://tv.kakao.com/oembed' => [ + '|^https?://tv\\.kakao\\.com/channel/.*/cliplink/.*$|i', + '|^https?://tv\\.kakao\\.com/m/channel/.*/cliplink/.*$|i', + '|^https?://tv\\.kakao\\.com/channel/v/.*$|i', + '|^https?://tv\\.kakao\\.com/channel/.*/livelink/.*$|i', + '|^https?://tv\\.kakao\\.com/m/channel/.*/livelink/.*$|i', + '|^https?://tv\\.kakao\\.com/channel/l/.*$|i', + ], + 'http://www.kickstarter.com/services/oembed' => [ + '|^https?://www\\.kickstarter\\.com/projects/.*$|i', + ], + 'https://www.kidoju.com/api/oembed' => [ + '|^https?://www\\.kidoju\\.com/en/x/.*/.*$|i', + '|^https?://www\\.kidoju\\.com/fr/x/.*/.*$|i', + ], + 'https://halaman.email/service/oembed' => [ + '|^https?://halaman\\.email/form/.*$|i', + '|^https?://aplikasi\\.kirim\\.email/form/.*$|i', + ], + 'https://embed.kit.co/oembed' => [ + '|^https?://kit\\.co/.*/.*$|i', + ], + 'http://www.kitchenbowl.com/oembed' => [ + '|^https?://www\\.kitchenbowl\\.com/recipe/.*$|i', + ], + 'https://api.kmdr.sh/services/oembed' => [ + '|^https?://app\\.kmdr\\.sh/h/.*$|i', + '|^https?://app\\.kmdr\\.sh/history/.*$|i', + ], + 'https://jdr.knacki.info/oembed' => [ + '|^https?://jdr\\.knacki\\.info/meuh/.*$|i', + ], + 'https://api.spoonacular.com/knowledge/oembed' => [ + '|^https?://knowledgepad\\.co/\\#/knowledge/.*$|i', + ], + 'https://embed.kooapp.com/services/oembed' => [ + '|^https?://.*\\.kooapp\\.com/koo/.*$|i', + ], + 'http://learningapps.org/oembed.php' => [ + '|^https?://learningapps\\.org/.*$|i', + ], + 'https://umotion-test.univ-lemans.fr/oembed' => [ + '|^https?://umotion\\-test\\.univ\\-lemans\\.fr/video/.*$|i', + ], + 'https://pod.univ-lille.fr/oembed' => [ + '|^https?://pod\\.univ\\-lille\\.fr/video/.*$|i', + ], + 'https://place.line.me/oembed' => [ + '|^https?://place\\.line\\.me/businesses/.*$|i', + ], + 'https://livestream.com/oembed' => [ + '|^https?://livestream\\.com/accounts/.*/events/.*$|i', + '|^https?://livestream\\.com/accounts/.*/events/.*/videos/.*$|i', + '|^https?://livestream\\.com/.*/events/.*$|i', + '|^https?://livestream\\.com/.*/events/.*/videos/.*$|i', + '|^https?://livestream\\.com/.*/.*$|i', + '|^https?://livestream\\.com/.*/.*/videos/.*$|i', + ], + 'https://embed.lottiefiles.com/oembed' => [ + '|^https?://lottiefiles\\.com/.*$|i', + '|^https?://.*\\.lottiefiles\\.com/.*$|i', + ], + 'https://app.ludus.one/oembed' => [ + '|^https?://app\\.ludus\\.one/.*$|i', + ], + 'https://admin.lumiere.is/api/services/oembed' => [ + '|^https?://.*\\.lumiere\\.is/v/.*$|i', + ], + 'http://mathembed.com/oembed' => [ + '|^https?://mathembed\\.com/latex\\?inputText\\=.*$|i', + ], + 'https://my.matterport.com/api/v1/models/oembed/' => [ + '|^https?://matterport\\.com/.*$|i', + ], + 'https://me.me/oembed' => [ + '|^https?://me\\.me/i/.*$|i', + ], + 'https://*.medialab.(co|app)/api/oembed/' => [ + '|^https?://.*\\.medialab\\.app/share/watch/.*$|i', + '|^https?://.*\\.medialab\\.co/share/watch/.*$|i', + '|^https?://.*\\.medialab\\.app/share/social/.*$|i', + '|^https?://.*\\.medialab\\.co/share/social/.*$|i', + '|^https?://.*\\.medialab\\.app/share/embed/.*$|i', + '|^https?://.*\\.medialab\\.co/share/embed/.*$|i', + ], + 'https://medienarchiv.zhdk.ch/oembed.json' => [ + '|^https?://medienarchiv\\.zhdk\\.ch/entries/.*$|i', + ], + 'https://mermaid.ink/services/oembed' => [ + '|^https?://mermaid\\.ink/img/.*$|i', + '|^https?://mermaid\\.ink/svg/.*$|i', + ], + 'https://web.microsoftstream.com/oembed' => [ + '|^https?://.*\\.microsoftstream\\.com/video/.*$|i', + '|^https?://.*\\.microsoftstream\\.com/channel/.*$|i', + ], + 'https://oembed.minervaknows.com' => [ + '|^https?://www\\.minervaknows\\.com/featured\\-recipes/.*$|i', + '|^https?://www\\.minervaknows\\.com/themes/.*$|i', + '|^https?://www\\.minervaknows\\.com/themes/.*/recipes/.*$|i', + '|^https?://app\\.minervaknows\\.com/recipes/.*$|i', + '|^https?://app\\.minervaknows\\.com/recipes/.*/follow$|i', + ], + 'https://www.mixcloud.com/oembed/' => [ + '|^https?://www\\.mixcloud\\.com/.*/.*/$|i', + ], + 'http://api.mobypicture.com/oEmbed' => [ + '|^https?://www\\.mobypicture\\.com/user/.*/view/.*$|i', + '|^https?://moby\\.to/.*$|i', + ], + 'https://musicboxmaniacs.com/embed/' => [ + '|^https?://musicboxmaniacs\\.com/explore/melody/.*$|i', + ], + 'https://mybeweeg.com/services/oembed' => [ + '|^https?://mybeweeg\\.com/w/.*$|i', + ], + 'https://namchey.com/api/oembed' => [ + '|^https?://namchey\\.com/embeds/.*$|i', + ], + 'https://www.nanoo.tv/services/oembed' => [ + '|^https?://.*\\.nanoo\\.tv/link/.*$|i', + '|^https?://nanoo\\.tv/link/.*$|i', + '|^https?://.*\\.nanoo\\.pro/link/.*$|i', + '|^https?://nanoo\\.pro/link/.*$|i', + '|^https?://media\\.zhdk\\.ch/signatur/.*$|i', + '|^https?://new\\.media\\.zhdk\\.ch/signatur/.*$|i', + ], + 'https://api.nb.no/catalog/v1/oembed' => [ + '|^https?://www\\.nb\\.no/items/.*$|i', + ], + 'https://naturalatlas.com/oembed.json' => [ + '|^https?://naturalatlas\\.com/.*$|i', + '|^https?://naturalatlas\\.com/.*/.*$|i', + '|^https?://naturalatlas\\.com/.*/.*/.*$|i', + '|^https?://naturalatlas\\.com/.*/.*/.*/.*$|i', + ], + 'http://www.nfb.ca/remote/services/oembed/' => [ + '|^https?://.*\\.nfb\\.ca/film/.*$|i', + ], + 'https://www.nftndx.io/oembed' => [ + '|^https?://www\\.nftndx\\.io/.*$|i', + ], + 'https://oembed.nopaste.ml' => [ + '|^https?://nopaste\\.ml/.*$|i', + ], + 'https://api.observablehq.com/oembed' => [ + '|^https?://observablehq\\.com/@.*/.*$|i', + '|^https?://observablehq\\.com/d/.*$|i', + '|^https?://observablehq\\.com/embed/.*$|i', + ], + 'https://www.odds.com.au/api/oembed/' => [ + '|^https?://www\\.odds\\.com\\.au/.*$|i', + '|^https?://odds\\.com\\.au/.*$|i', + ], + 'https://song.link/oembed' => [ + '|^https?://song\\.link/.*$|i', + '|^https?://album\\.link/.*$|i', + '|^https?://artist\\.link/.*$|i', + '|^https?://playlist\\.link/.*$|i', + '|^https?://pods\\.link/.*$|i', + '|^https?://mylink\\.page/.*$|i', + '|^https?://odesli\\.co/.*$|i', + ], + 'https://odysee.com/$/oembed' => [ + '|^https?://odysee\\.com/.*/.*$|i', + '|^https?://odysee\\.com/.*$|i', + ], + 'http://official.fm/services/oembed.json' => [ + '|^https?://official\\.fm/tracks/.*$|i', + '|^https?://official\\.fm/playlists/.*$|i', + ], + 'https://omniscope.me/_global_/oembed/json' => [ + '|^https?://omniscope\\.me/.*$|i', + ], + 'https://omny.fm/oembed' => [ + '|^https?://omny\\.fm/shows/.*$|i', + ], + 'https://www.ora.tv/oembed/*?format=json' => [ + '|^https?://www\\.ora\\.tv/.*$|i', + ], + 'http://orbitvu.co/service/oembed' => [ + '|^https?://orbitvu\\.co/001/.*/ov3601/view$|i', + '|^https?://orbitvu\\.co/001/.*/ov3601/.*/view$|i', + '|^https?://orbitvu\\.co/001/.*/ov3602/.*/view$|i', + '|^https?://orbitvu\\.co/001/.*/2/orbittour/.*/view$|i', + '|^https?://orbitvu\\.co/001/.*/1/2/orbittour/.*/view$|i', + ], + 'https://outplayed.tv/oembed' => [ + '|^https?://outplayed\\.tv/media/.*$|i', + ], + 'https://overflow.io/services/oembed' => [ + '|^https?://overflow\\.io/s/.*$|i', + '|^https?://overflow\\.io/embed/.*$|i', + ], + 'https://core.oz.com/oembed' => [ + '|^https?://www\\.oz\\.com/.*/video/.*$|i', + ], + 'https://padlet.com/oembed/' => [ + '|^https?://padlet\\.com/.*$|i', + ], + 'https://api-v2.pandavideo.com.br/oembed' => [ + '|^https?://.*\\.tv\\.pandavideo\\.com\\.br/embed/\\?v\\=.*$|i', + '|^https?://.*\\.tv\\.pandavideo\\.com\\.br/.*/playlist\\.m3u8$|i', + '|^https?://dashboard\\.pandavideo\\.com\\.br/\\#/videos/.*$|i', + ], + 'https://www.pastery.net/oembed' => [ + '|^https?://pastery\\.net/.*$|i', + '|^https?://www\\.pastery\\.net/.*$|i', + ], + 'https://api.picturelfy.com/service/oembed/' => [ + '|^https?://www\\.picturelfy\\.com/p/.*$|i', + ], + 'https://beta.pingvp.com.kpnis.nl/p/oembed.php' => [ + '|^https?://www\\.pingvp\\.com/.*$|i', + ], + 'https://tools.pinpoll.com/oembed' => [ + '|^https?://tools\\.pinpoll\\.com/embed/.*$|i', + ], + 'https://www.pinterest.com/oembed.json' => [ + '|^https?://www\\.pinterest\\.com/.*$|i', + ], + 'https://*.pitchhub.com.com/en/public/oembed' => [ + '|^https?://.*\\.pitchhub\\.com/en/public/player/.*$|i', + ], + 'https://store.pixdor.com/oembed' => [ + '|^https?://store\\.pixdor\\.com/place\\-marker\\-widget/.*/show$|i', + '|^https?://store\\.pixdor\\.com/map/.*/show$|i', + ], + 'https://app.plusdocs.com/oembed' => [ + '|^https?://app\\.plusdocs\\.com/.*/snapshots/.*$|i', + '|^https?://app\\.plusdocs\\.com/.*/pages/edit/.*$|i', + '|^https?://app\\.plusdocs\\.com/.*/pages/share/.*$|i', + ], + 'https://api.podbean.com/v1/oembed' => [ + '|^https?://.*\\.podbean\\.com/e/.*$|i', + ], + 'http://polldaddy.com/oembed/' => [ + '|^https?://.*\\.polldaddy\\.com/s/.*$|i', + '|^https?://.*\\.polldaddy\\.com/poll/.*$|i', + '|^https?://.*\\.polldaddy\\.com/ratings/.*$|i', + ], + 'https://api.portfolium.com/oembed' => [ + '|^https?://portfolium\\.com/entry/.*$|i', + ], + 'https://gateway.cobalt.run/present/decks/oembed' => [ + '|^https?://present\\.do/decks/.*$|i', + ], + 'https://prezi.com/v/oembed' => [ + '|^https?://prezi\\.com/v/.*$|i', + '|^https?://.*\\.prezi\\.com/v/.*$|i', + ], + 'http://www.quiz.biz/api/oembed' => [ + '|^https?://www\\.quiz\\.biz/quizz\\-.*\\.html$|i', + ], + 'http://www.quizz.biz/api/oembed' => [ + '|^https?://www\\.quizz\\.biz/quizz\\-.*\\.html$|i', + ], + 'https://oembed.radiopublic.com/oembed' => [ + '|^https?://play\\.radiopublic\\.com/.*$|i', + '|^https?://radiopublic\\.com/.*$|i', + '|^https?://www\\.radiopublic\\.com/.*$|i', + '|^https?://.*\\.radiopublic\\.com/.*$|i', + ], + 'https://pub.raindrop.io/api/oembed' => [ + '|^https?://raindrop\\.io/.*$|i', + '|^https?://raindrop\\.io/.*/.*$|i', + '|^https?://raindrop\\.io/.*/.*/.*$|i', + '|^https?://raindrop\\.io/.*/.*/.*/.*$|i', + ], + 'https://animatron.com/oembed' => [ + '|^https?://www\\.rcvis\\.com/v/.*$|i', + '|^https?://www\\.rcvis\\.com/visualize\\=.*$|i', + '|^https?://www\\.rcvis\\.com/ve/.*$|i', + '|^https?://www\\.rcvis\\.com/visualizeEmbedded\\=.*$|i', + ], + 'https://www.reddit.com/oembed' => [ + '|^https?://reddit\\.com/r/.*/comments/.*/.*$|i', + '|^https?://www\\.reddit\\.com/r/.*/comments/.*/.*$|i', + ], + 'http://publisher.releasewire.com/oembed/' => [ + '|^https?://rwire\\.com/.*$|i', + ], + 'https://replit.com/data/oembed' => [ + '|^https?://repl\\.it/@.*/.*$|i', + '|^https?://replit\\.com/@.*/.*$|i', + ], + 'https://www.reverbnation.com/oembed' => [ + '|^https?://www\\.reverbnation\\.com/.*$|i', + '|^https?://www\\.reverbnation\\.com/.*/songs/.*$|i', + ], + 'http://roomshare.jp/en/oembed.json' => [ + '|^https?://roomshare\\.jp/post/.*$|i', + '|^https?://roomshare\\.jp/en/post/.*$|i', + ], + 'https://roosterteeth.com/oembed' => [ + '|^https?://roosterteeth\\.com/.*$|i', + ], + 'https://rumble.com/api/Media/oembed.json' => [ + '|^https?://rumble\\.com/.*$|i', + ], + 'https://embed.runkit.com/oembed' => [ + '|^https?://embed\\.runkit\\.com/.*,$|i', + ], + 'https://octopus.saooti.com/oembed' => [ + '|^https?://octopus\\.saooti\\.com/main/pub/podcast/.*$|i', + ], + 'http://videos.sapo.pt/oembed' => [ + '|^https?://videos\\.sapo\\.pt/.*$|i', + ], + 'https://api.screen9.com/oembed' => [ + '|^https?://console\\.screen9\\.com/.*$|i', + '|^https?://.*\\.screen9\\.tv/.*$|i', + ], + 'https://api.screencast.com/external/oembed' => [ + '|^https?://www\\.screencast\\.com/.*$|i', + ], + 'http://www.screenr.com/api/oembed.json' => [ + '|^https?://www\\.screenr\\.com/.*/$|i', + ], + 'https://scribblemaps.com/api/services/oembed.json' => [ + '|^https?://www\\.scribblemaps\\.com/maps/view/.*$|i', + '|^https?://scribblemaps\\.com/maps/view/.*$|i', + ], + 'http://www.scribd.com/services/oembed/' => [ + '|^https?://www\\.scribd\\.com/doc/.*$|i', + '|^https?://www\\.scribd\\.com/document/.*$|i', + ], + 'https://embed.sendtonews.com/services/oembed' => [ + '|^https?://embed\\.sendtonews\\.com/oembed/.*$|i', + ], + 'https://www.shortnote.jp/oembed/' => [ + '|^https?://www\\.shortnote\\.jp/view/notes/.*$|i', + ], + 'http://shoudio.com/api/oembed' => [ + '|^https?://shoudio\\.com/.*$|i', + '|^https?://shoud\\.io/.*$|i', + ], + 'https://api.getshow.io/oembed.json' => [ + '|^https?://app\\.getshow\\.io/iframe/.*$|i', + '|^https?://.*\\.getshow\\.io/share/.*$|i', + ], + 'https://showtheway.io/oembed' => [ + '|^https?://showtheway\\.io/to/.*$|i', + ], + 'https://simplecast.com/oembed' => [ + '|^https?://simplecast\\.com/s/.*$|i', + ], + 'https://onsizzle.com/oembed' => [ + '|^https?://onsizzle\\.com/i/.*$|i', + ], + 'http://sketchfab.com/oembed' => [ + '|^https?://sketchfab\\.com/.*models/.*$|i', + '|^https?://sketchfab\\.com/.*/folders/.*$|i', + ], + 'https://*.slateapp.com/api/v2/oembed' => [ + '|^https?://.*\\.slateapp\\.com/work/.*$|i', + ], + 'https://www.slideshare.net/api/oembed/2' => [ + '|^https?://www\\.slideshare\\.net/.*/.*$|i', + '|^https?://fr\\.slideshare\\.net/.*/.*$|i', + '|^https?://de\\.slideshare\\.net/.*/.*$|i', + '|^https?://es\\.slideshare\\.net/.*/.*$|i', + '|^https?://pt\\.slideshare\\.net/.*/.*$|i', + ], + 'https://smashnotes.com/services/oembed' => [ + '|^https?://smashnotes\\.com/p/.*$|i', + '|^https?://smashnotes\\.com/p/.*/e/.* \\- smashnotes\\.com/p/.*/e/.*/s/.*$|i', + ], + 'https://open.smeme.com/api/oembed' => [ + '|^https?://open\\.smeme\\.com/.*$|i', + ], + 'https://www.smrthi.com/api/oembed' => [ + '|^https?://www\\.smrthi\\.com/book/.*$|i', + ], + 'https://api.smugmug.com/services/oembed/' => [ + '|^https?://.*\\.smugmug\\.com/.*$|i', + ], + 'https://www.socialexplorer.com/services/oembed/' => [ + '|^https?://www\\.socialexplorer\\.com/.*/explore$|i', + '|^https?://www\\.socialexplorer\\.com/.*/view$|i', + '|^https?://www\\.socialexplorer\\.com/.*/edit$|i', + '|^https?://www\\.socialexplorer\\.com/.*/embed$|i', + ], + 'https://soundcloud.com/oembed' => [ + '|^https?://soundcloud\\.com/.*$|i', + '|^https?://on\\.soundcloud\\.com/.*$|i', + '|^https?://soundcloud\\.app\\.goog\\.gl/.*$|i', + ], + 'https://speakerdeck.com/oembed.json' => [ + '|^https?://speakerdeck\\.com/.*/.*$|i', + ], + 'https://open.spotify.com/oembed' => [ + '|^https?://open\\.spotify\\.com/.*$|i', + '|^https?://spotify\\:.*$|i', + ], + 'https://api.spreaker.com/oembed' => [ + '|^https?://.*\\.spreaker\\.com/.*$|i', + ], + 'http://sproutvideo.com/oembed.json' => [ + '|^https?://sproutvideo\\.com/videos/.*$|i', + '|^https?://.*\\.vids\\.io/videos/.*$|i', + ], + 'https://purl.stanford.edu/embed.json' => [ + '|^https?://purl\\.stanford\\.edu/.*$|i', + ], + 'https://api.streamable.com/oembed.json' => [ + '|^https?://streamable\\.com/.*$|i', + ], + 'https://streamio.com/api/v1/oembed' => [ + '|^https?://s3m\\.io/.*$|i', + '|^https?://23m\\.io/.*$|i', + ], + 'https://subscribi.io/api/oembed' => [ + '|^https?://subscribi\\.io/api/oembed.*$|i', + ], + 'https://www.sudomemo.net/oembed' => [ + '|^https?://www\\.sudomemo\\.net/watch/.*$|i', + '|^https?://flipnot\\.es/.*$|i', + ], + 'https://www.sutori.com/api/oembed' => [ + '|^https?://www\\.sutori\\.com/story/.*$|i', + ], + 'https://sway.com/api/v1.0/oembed' => [ + '|^https?://sway\\.com/.*$|i', + '|^https?://www\\.sway\\.com/.*$|i', + ], + 'https://sway.office.com/api/v1.0/oembed' => [ + '|^https?://sway\\.office\\.com/.*$|i', + ], + 'https://player.switcherstudio.com/oembed' => [ + '|^https?://player\\.switcherstudio\\.com/.*$|i', + ], + 'https://69jr5v75rc.execute-api.eu-west-1.amazonaws.com/prod/v2/oembed' => [ + '|^https?://share\\.synthesia\\.io/.*$|i', + ], + 'https://www.ted.com/services/v1/oembed.json' => [ + '|^https?://ted\\.com/talks/.*$|i', + '|^https?://www\\.ted\\.com/talks/.*$|i', + ], + 'https://www.nytimes.com/svc/oembed/json/' => [ + '|^https?://www\\.nytimes\\.com/svc/oembed$|i', + '|^https?://nytimes\\.com/.*$|i', + '|^https?://.*\\.nytimes\\.com/.*$|i', + ], + 'https://theysaidso.com/extensions/oembed/' => [ + '|^https?://theysaidso\\.com/image/.*$|i', + ], + 'https://www.tickcounter.com/oembed' => [ + '|^https?://www\\.tickcounter\\.com/countdown/.*$|i', + '|^https?://www\\.tickcounter\\.com/countup/.*$|i', + '|^https?://www\\.tickcounter\\.com/ticker/.*$|i', + '|^https?://www\\.tickcounter\\.com/worldclock/.*$|i', + ], + 'https://www.tiktok.com/oembed' => [ + '|^https?://www\\.tiktok\\.com/.*/video/.*$|i', + '|^https?://.*\\.tiktok\\.com/.*$|i', + ], + 'https://widget.toornament.com/oembed' => [ + '|^https?://www\\.toornament\\.com/tournaments/.*/information$|i', + '|^https?://www\\.toornament\\.com/tournaments/.*/registration/$|i', + '|^https?://www\\.toornament\\.com/tournaments/.*/matches/schedule$|i', + '|^https?://www\\.toornament\\.com/tournaments/.*/stages/.*/$|i', + ], + 'http://www.topy.se/oembed/' => [ + '|^https?://www\\.topy\\.se/image/.*$|i', + ], + 'https://app-test.totango.com/oembed' => [ + '|^https?://app\\-test\\.totango\\.com/.*$|i', + ], + 'https://trinitymedia.ai/player/trinity-oembed' => [ + '|^https?://trinitymedia\\.ai/player/.*$|i', + ], + 'https://www.tumblr.com/oembed/1.0' => [ + '|^https?://.*\\.tumblr\\.com/post/.*$|i', + ], + 'https://www.tuxx.be/services/oembed' => [ + '|^https?://www\\.tuxx\\.be/.*$|i', + ], + 'https://play.tvcf.co.kr/rest/oembed' => [ + '|^https?://play\\.tvcf\\.co\\.kr/.*$|i', + '|^https?://.*\\.tvcf\\.co\\.kr/.*$|i', + ], + 'https://twinmotion.unrealengine.com/oembed' => [ + '|^https?://twinmotion\\.unrealengine\\.com/presentation/.*$|i', + '|^https?://twinmotion\\.unrealengine\\.com/panorama/.*$|i', + ], + 'https://publish.twitter.com/oembed' => [ + '|^https?://twitter\\.com/.*$|i', + '|^https?://twitter\\.com/.*/status/.*$|i', + '|^https?://.*\\.twitter\\.com/.*/status/.*$|i', + ], + 'https://play.typecast.ai/oembed' => [ + '|^https?://play\\.typecast\\.ai/s/.*$|i', + '|^https?://play\\.typecast\\.ai/e/.*$|i', + '|^https?://play\\.typecast\\.ai/.*$|i', + ], + 'https://typlog.com/oembed' => [ + '|^https?://typlog\\.com.*$|i', + ], + 'https://uapod.univ-antilles.fr/oembed' => [ + '|^https?://uapod\\.univ\\-antilles\\.fr/video/.*$|i', + ], + 'https://map.cam.ac.uk/oembed/' => [ + '|^https?://map\\.cam\\.ac\\.uk/.*$|i', + ], + 'https://mediatheque.univ-paris1.fr/oembed' => [ + '|^https?://mediatheque\\.univ\\-paris1\\.fr/video/.*$|i', + ], + 'https://pod.u-pec.fr/oembed' => [ + '|^https?://pod\\.u\\-pec\\.fr/video/.*$|i', + ], + 'http://www.ustream.tv/oembed' => [ + '|^https?://.*\\.ustream\\.tv/.*$|i', + '|^https?://.*\\.ustream\\.com/.*$|i', + ], + 'https://app.ustudio.com/api/v2/oembed' => [ + '|^https?://.*\\.ustudio\\.com/embed/.*$|i', + '|^https?://.*\\.ustudio\\.com/embed/.*/.*$|i', + ], + 'https://api.veer.tv/oembed' => [ + '|^https?://veer\\.tv/videos/.*$|i', + ], + 'https://api.veervr.tv/oembed' => [ + '|^https?://veervr\\.tv/videos/.*$|i', + ], + 'http://verse.com/services/oembed/' => [ + '|^https?://verse\\.com/.*$|i', + ], + 'https://www.vevo.com/oembed' => [ + '|^https?://www\\.vevo\\.com/.*$|i', + ], + 'https://videfit.com/oembed' => [ + '|^https?://videfit\\.com/videos/.*$|i', + ], + 'https://vidmount.com/oembed' => [ + '|^https?://vidmount\\.com/.*$|i', + ], + 'https://api.vidyard.com/dashboard/v1.1/oembed' => [ + '|^https?://.*\\.vidyard\\.com/.*$|i', + '|^https?://.*\\.hubs\\.vidyard\\.com/.*$|i', + ], + 'https://vimeo.com/api/oembed.json' => [ + '|^https?://vimeo\\.com/.*$|i', + '|^https?://vimeo\\.com/album/.*/video/.*$|i', + '|^https?://vimeo\\.com/channels/.*/.*$|i', + '|^https?://vimeo\\.com/groups/.*/videos/.*$|i', + '|^https?://vimeo\\.com/ondemand/.*/.*$|i', + '|^https?://player\\.vimeo\\.com/video/.*$|i', + ], + 'https://www.viously.com/oembed' => [ + '|^https?://www\\.viously\\.com/.*/.*$|i', + ], + 'https://vizydrop.com/oembed' => [ + '|^https?://vizydrop\\.com/shared/.*$|i', + ], + 'https://vlipsy.com/oembed' => [ + '|^https?://vlipsy\\.com/.*$|i', + ], + 'https://www.vlive.tv/oembed' => [ + '|^https?://www\\.vlive\\.tv/video/.*$|i', + ], + 'https://embed.vouchfor.com/v1/oembed' => [ + '|^https?://.*\\.vouchfor\\.com/.*$|i', + ], + 'https://data.voxsnap.com/oembed' => [ + '|^https?://article\\.voxsnap\\.com/.*/.*$|i', + ], + 'https://waltrack.net/oembed' => [ + '|^https?://waltrack\\.net/product/.*$|i', + ], + 'https://embed.wave.video/oembed' => [ + '|^https?://watch\\.wave\\.video/.*$|i', + '|^https?://embed\\.wave\\.video/.*$|i', + ], + 'https://play.wecandeo.com/oembed/' => [ + '|^https?://play\\.wecandeo\\.com/video/v/.*$|i', + ], + 'http://*.wiredrive.com/present-oembed/' => [ + '|^https?://.*\\.wiredrive\\.com/.*$|i', + ], + 'https://fast.wistia.com/oembed.json' => [ + '|^https?://fast\\.wistia\\.com/embed/iframe/.*$|i', + '|^https?://fast\\.wistia\\.com/embed/playlists/.*$|i', + '|^https?://.*\\.wistia\\.com/medias/.*$|i', + ], + 'https://app.wizer.me/api/oembed.json' => [ + '|^https?://.*\\.wizer\\.me/learn/.*$|i', + '|^https?://.*\\.wizer\\.me/preview/.*$|i', + ], + 'https://wokwi.com/api/oembed' => [ + '|^https?://wokwi\\.com/share/.*$|i', + ], + 'https://www.wolframcloud.com/oembed' => [ + '|^https?://.*\\.wolframcloud\\.com/.*$|i', + ], + 'http://public-api.wordpress.com/oembed/' => [ + '|^https?://wordpress\\.com/.*$|i', + '|^https?://.*\\.wordpress\\.com/.*$|i', + '|^https?://.*\\..*\\.wordpress\\.com/.*$|i', + '|^https?://wp\\.me/.*$|i', + ], + 'https://www.youtube.com/oembed' => [ + '|^https?://.*\\.youtube\\.com/watch.*$|i', + '|^https?://.*\\.youtube\\.com/v/.*$|i', + '|^https?://youtu\\.be/.*$|i', + '|^https?://.*\\.youtube\\.com/playlist\\?list\\=.*$|i', + '|^https?://youtube\\.com/playlist\\?list\\=.*$|i', + '|^https?://.*\\.youtube\\.com/shorts.*$|i', + '|^https?://.*\\.youtube\\.com/playlist\\?.*$|i', + ], + 'https://app.zeplin.io/embed' => [ + '|^https?://app\\.zeplin\\.io/project/.*/screen/.*$|i', + '|^https?://app\\.zeplin\\.io/project/.*/screen/.*/version/.*$|i', + '|^https?://app\\.zeplin\\.io/project/.*/styleguide/components\\?coid\\=.*$|i', + '|^https?://app\\.zeplin\\.io/styleguide/.*/components\\?coid\\=.*$|i', + ], + 'https://app.zingsoft.com/oembed' => [ + '|^https?://app\\.zingsoft\\.com/embed/.*$|i', + '|^https?://app\\.zingsoft\\.com/view/.*$|i', + ], + 'https://api.znipe.tv/v3/oembed/' => [ + '|^https?://.*\\.znipe\\.tv/.*$|i', + ], + 'https://srv2.zoomable.ca/oembed' => [ + '|^https?://srv2\\.zoomable\\.ca/viewer\\.php.*$|i', + ], + 'http://jsbin.com/oembed' => [ + '|^https?://output\\.jsbin\\.com/.*$|i', + ], + 'https://api.crowdsignal.com/oembed' => [ + '|^https?://polldaddy\\.com/poll/.*$|i', + '|^https?://poll\\.fm/.*$|i', + ], + 'https://api.imgur.com/oembed' => [ + '|^https?://imgur\\.com/.*$|i', + '|^https?://i\\.imgur\\.com/.*$|i', + ], +]; diff --git a/Resources/Private/PHP/embed/vendor/embed/embed/src/resources/suffix.php b/Resources/Private/PHP/embed/vendor/embed/embed/src/resources/suffix.php new file mode 100644 index 0000000..f917283 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/embed/embed/src/resources/suffix.php @@ -0,0 +1,8002 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\IRI; + +/** + * IRI represents an IRI as per RFC3987. + * + * @author Markus Lanthaler + * + * @link http://tools.ietf.org/html/rfc3987 RFC3987 + */ +class IRI +{ + /** + * The scheme + * + * @var string|null + */ + private $scheme = null; + + /** + * The user information + * + * @var string|null + */ + private $userinfo = null; + + /** + * The host + * + * @var string|null + */ + private $host = null; + + /** + * The port + * + * @var string|null + */ + private $port = null; + + /** + * The path + * + * @var string + */ + private $path = ''; + + /** + * The query component + * + * @var string|null + */ + private $query = null; + + /** + * The fragment identifier + * + * @var string|null + */ + private $fragment = null; + + + /** + * Constructor + * + * @param null|string|IRI $iri The IRI. + * + * @throws \InvalidArgumentException If an invalid IRI is passed. + * + * @api + */ + public function __construct($iri = null) + { + if (null === $iri) { + return; + } elseif (is_string($iri)) { + $this->parse($iri); + } elseif ($iri instanceof IRI) { + $this->scheme = $iri->scheme; + $this->userinfo = $iri->userinfo; + $this->host = $iri->host; + $this->port = $iri->port; + $this->path = $iri->path; + $this->query = $iri->query; + $this->fragment = $iri->fragment; + } else { + throw new \InvalidArgumentException( + 'Expecting a string or an IRI, got ' . + (is_object($iri) ? get_class($iri) : gettype($iri)) + ); + } + } + + /** + * Get the scheme + * + * @return string|null Returns the scheme or null if not set. + */ + public function getScheme() + { + return $this->scheme; + } + + /** + * Get the authority + * + * @return string|null Returns the authority or null if not set. + */ + public function getAuthority() + { + $authority = null; + + if (null !== $this->host) { + + if (null !== $this->userinfo) { + $authority .= $this->userinfo . '@'; + } + $authority .= $this->host; + if (null !== $this->port) { + $authority .= ':' . $this->port; + } + } + + return $authority; + } + + /** + * Get the user information + * + * @return string|null Returns the user information or null if not set. + */ + public function getUserInfo() + { + return $this->userinfo; + } + + /** + * Get the host + * + * @return string|null Returns the host or null if not set. + */ + public function getHost() + { + return $this->host; + } + + /** + * Get the port + * + * @return string|null Returns the port or null if not set. + */ + public function getPort() + { + return $this->port; + } + + /** + * Get the path + * + * @return string Returns the path which might be empty. + */ + public function getPath() + { + return $this->path; + } + + /** + * Get the query component + * + * @return string|null Returns the query component or null if not set. + */ + public function getQuery() + { + return $this->query; + } + + /** + * Get the fragment identifier + * + * @return string|null Returns the fragment identifier or null if not set. + */ + public function getFragment() + { + return $this->fragment; + } + + /** + * Find out whether the IRI is absolute + * + * @return bool Returns true if the IRI is absolute, false otherwise. + * + * @api + */ + public function isAbsolute() + { + return (null !== $this->scheme); + } + + /** + * Get as absolute IRI, i.e., without fragment identifier + * + * @return IRI The absolute IRI, i.e., without fragment identifier + * + * @throws \UnexpectedValueException If the IRI is a relative IRI. + * + * @link http://tools.ietf.org/html/rfc3987#section-2.2 RFC3987 absolute-IRI + * + * @api + */ + public function getAbsoluteIri() + { + if (false === $this->isAbsolute()) { + throw new \UnexpectedValueException('Cannot get the absolute IRI of a relative IRI.'); + } + + $absolute = clone $this; + $absolute->fragment = null; + + return $absolute; + } + + /** + * Check whether the passed IRI is equal + * + * @param IRI|string $iri IRI to compare to this instance. + * + * @return bool Returns true if the two IRIs are equal, false otherwise. + * + * @api + */ + public function equals($iri) + { + // Make sure both instances are strings + return ($this->__toString() === (string)$iri); + } + + /** + * Resolve a (relative) IRI reference against this IRI + * + * @param IRI|string $reference The (relative) IRI reference that should + * be resolved against this IRI. + * + * @return IRI The resolved IRI. + * + * @throws \InvalidArgumentException If an invalid IRI is passed. + * + * @link http://tools.ietf.org/html/rfc3986#section-5.2 + * + * @api + */ + public function resolve($reference) + { + $reference = new IRI($reference); + + $scheme = null; + $authority = null; + $path = ''; + $query = null; + $fragment = null; + + // The Transform References algorithm as specified by RFC3986 + // see: http://tools.ietf.org/html/rfc3986#section-5.2.2 + if ($reference->scheme) { + $scheme = $reference->scheme; + $authority = $reference->getAuthority(); + $path = self::removeDotSegments($reference->path); + $query = $reference->query; + } else { + if (null !== $reference->getAuthority()) { + $authority = $reference->getAuthority(); + $path = self::removeDotSegments($reference->path); + $query = $reference->query; + } else { + if (0 === strlen($reference->path)) { + $path = $this->path; + if (null !== $reference->query) { + $query = $reference->query; + } else { + $query = $this->query; + } + } else { + if ('/' === $reference->path[0]) { + $path = self::removeDotSegments($reference->path); + } else { + // T.path = merge(Base.path, R.path); + if ((null !== $this->getAuthority()) && ('' === $this->path)) { + $path = '/' . $reference->path; + } else { + if (false !== ($end = strrpos($this->path, '/'))) { + $path = substr($this->path, 0, $end + 1); + } + $path .= $reference->path; + } + $path = self::removeDotSegments($path); + } + $query = $reference->query; + } + + $authority = $this->getAuthority(); + } + $scheme = $this->scheme; + } + + $fragment = $reference->fragment; + + + // The Component Recomposition algorithm as specified by RFC3986 + // see: http://tools.ietf.org/html/rfc3986#section-5.3 + $result = ''; + + if ($scheme) { + $result = $scheme . ':'; + } + + if (null !== $authority) { + $result .= '//' . $authority; + } + + $result .= $path; + + if (null !== $query) { + $result .= '?' . $query; + } + + if (null !== $fragment) { + $result .= '#' . $fragment; + } + + return new IRI($result); + } + + /** + * Transform this IRI to a IRI reference relative to the passed base IRI + * + * @param IRI|string $base The (relative) IRI reference that should be + * be used as base IRI. + * @param bool Defines whether schema-relative IRIs such + * as `//example.com` should be created (`true`) + * or not (`false`). + * + * @return IRI The IRI reference relative to the passed base IRI. + * + * @throws \InvalidArgumentException If an invalid IRI is passed. + * + * @api + */ + public function relativeTo($base, $schemaRelative = false) + { + if (false === ($base instanceof IRI)) { + $base = new IRI($base); + } + $relative = clone $this; + + // Compare scheme + if ($relative->scheme !== $base->scheme) { + return $relative; + } + + // Compare authority + if ($relative->getAuthority() !== $base->getAuthority()) { + if (true === $schemaRelative) { + $relative->scheme = null; + } + + return $relative; + } + $relative->scheme = null; + $relative->host = null; + $relative->userinfo = null; + $relative->port = null; + + // Compare path + $baseSegments = explode('/', $base->path); + $relativeSegments = explode('/', $relative->path); + $len = min(count($baseSegments), count($relativeSegments)) - 1; // do not move beyond last segment + + $pos = 0; + + while (($baseSegments[$pos] === $relativeSegments[$pos]) && ($pos < $len)) { + $pos++; + } + + $relative->path = ''; + $numBaseSegments = count($baseSegments) - $pos - 1; + if ($numBaseSegments > 0) { + $relative->path .= str_repeat('../', $numBaseSegments); + } + + if (($baseSegments[$pos] !== $relativeSegments[$pos]) || + ((null === $relative->query) && (null === $relative->fragment))) { + // if the two paths differ or if there's neither a query component nor a fragment, + // we need to consider this IRI's path + + if (($relative->path === '') && (false !== strpos($relativeSegments[$pos], ':'))) { + // if the first path segment contains a colon, we need to + // prepend a ./ to distinguish it from an absolute IRI + $relative->path .= './'; + } + + $relative->path .= implode('/', array_slice($relativeSegments, $pos)); + + // .. and ensure that the resulting path isn't empty + if (($relative->path === '')) { + $relative->path .= './'; + } + } + + if ($relative->query !== $base->query) { + return $relative; + } + + if (null !== $relative->fragment) { + $relative->query = null; + } + + return $relative; + } + + /** + * Convert an IRI to a relative IRI reference using this IRI as base + * + * This method provides a more convenient interface than the + * {@link IRI::relativeTo()} method if the base IRI stays the same while + * the IRIs to convert to relative IRI references change. + * + * @param string|IRI $iri The IRI to convert to a relative reference + * @param bool Defines whether schema-relative IRIs such + * as `//example.com` should be created (`true`) + * or not (`false`). + * + * @throws \InvalidArgumentException If an invalid IRI is passed. + * + * @see \ML\IRI\IRI::relativeTo() + * + * @return IRI The relative IRI reference + */ + public function baseFor($iri, $schemaRelative = false) + { + if (false === ($iri instanceof IRI)) { + $iri = new IRI($iri); + } + + return $iri->relativeTo($this, $schemaRelative); + } + + /** + * Get a string representation of this IRI object + * + * @return string A string representation of this IRI instance. + * + * @api + */ + public function __toString() + { + $result = ''; + + if ($this->scheme) { + $result .= $this->scheme . ':'; + } + + if (null !== ($authority = $this->getAuthority())) { + $result .= '//' . $authority; + } + + $result .= $this->path; + + if (null !== $this->query) { + $result .= '?' . $this->query; + } + + if (null !== $this->fragment) { + $result .= '#' . $this->fragment; + } + + return $result; + } + + /** + * Parse an IRI into it's components + * + * This is done according to + * {@link http://tools.ietf.org/html/rfc3986#section-3.1 RFC3986}. + * + * @param string $iri The IRI to parse. + */ + protected function parse($iri) + { + // Parse IRI by using the regular expression as specified by + // http://tools.ietf.org/html/rfc3986#appendix-B + $regex = '|^((?P[^:/?#]+):)?' . + '((?P//)(?P[^/?#]*))?(?P[^?#]*)' . + '((?P\?)(?P[^#]*))?(#(?P.*))?|'; + preg_match($regex, $iri, $match); + + // Extract scheme + if (false === empty($match['scheme'])) { + $this->scheme = $match['scheme']; + } + + // Parse authority (http://tools.ietf.org/html/rfc3986#section-3.2) + if ('//' === $match['doubleslash']) { + if (0 === strlen($match['authority'])) { + $this->host = ''; + } else { + $authority = $match['authority']; + + // Split authority into userinfo and host + // (use last @ to ignore unescaped @ symbols) + if (false !== ($pos = strrpos($authority, '@'))) { + $this->userinfo = substr($authority, 0, $pos); + $authority = substr($authority, $pos + 1); + } + + // Split authority into host and port + $hostEnd = 0; + if (('[' === $authority[0]) && (false !== ($pos = strpos($authority, ']')))) { + $hostEnd = $pos; + } + + if ((false !== ($pos = strrpos($authority, ':'))) && ($pos > $hostEnd)) { + $this->host = substr($authority, 0, $pos); + $this->port = substr($authority, $pos + 1); + } else { + $this->host = $authority; + } + } + } + + // Extract path (http://tools.ietf.org/html/rfc3986#section-3.3) + // The path is always present but might be empty + $this->path = $match['path']; + + // Extract query (http://tools.ietf.org/html/rfc3986#section-3.4) + if (false === empty($match['querydef'])) { + $this->query = $match['query']; + } + + // Extract fragment (http://tools.ietf.org/html/rfc3986#section-3.5) + if (isset($match['fragment'])) { + $this->fragment = $match['fragment']; + } + } + + /** + * Remove dot-segments + * + * This method removes the special "." and ".." complete path segments + * from an IRI. + * + * @param string $input The IRI from which dot segments should be removed. + * + * @return string The IRI with all dot-segments removed. + * + * @link http://tools.ietf.org/html/rfc3986#section-5.2.4 + */ + private static function removeDotSegments($input) + { + $output = ''; + + while (strlen($input) > 0) { + if (('../' === substr($input, 0, 3)) || ('./' === substr($input, 0, 2))) { + $input = substr($input, strpos($input, '/')); + } elseif ('/./' === substr($input, 0, 3)) { + $input = substr($input, 2); + } elseif ('/.' === $input) { + $input = '/'; + } elseif (('/../' === substr($input, 0, 4)) || ('/..' === $input)) { + if ($input == '/..') { + $input = '/'; + } else { + $input = substr($input, 3); + } + + if (false !== ($end = strrpos($output, '/'))) { + $output = substr($output, 0, $end); + } else { + $output = ''; + } + } elseif (('..' === $input) || ('.' === $input)) { + $input = ''; + } else { + if (false === ($end = strpos($input, '/', 1))) { + $output .= $input; + $input = ''; + } else { + $output .= substr($input, 0, $end); + $input = substr($input, $end); + } + } + } + return $output; + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/LICENSE b/Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/LICENSE new file mode 100644 index 0000000..ec64dbb --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2012-2013 Markus Lanthaler + +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/Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/README.md b/Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/README.md new file mode 100644 index 0000000..32bb304 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/README.md @@ -0,0 +1,47 @@ +IRI +============== + +This is a simple PHP class to ease IRI handling. Currently it just supports +parsing of IRIs and relative IRI resolution. In the future I will extend it +to support validation and normalization and perhaps also support for IRI +templates. + +With more than 700 tests, this class is extensively unit tested: +[![Build Status](https://secure.travis-ci.org/lanthaler/IRI.png?branch=master)](http://travis-ci.org/lanthaler/IRI) + + +Installation +------------ + +The easiest way to use IRI is to integrate it as a dependency in your project's +[composer.json](http://getcomposer.org/doc/00-intro.md) file: + +```json +{ + "require": { + "ml/iri": "1.*" + } +} +``` + +Installing is then a matter of running composer + + php composer.phar install + +... and including Composer's autoloader to your project + +```php +require('vendor/autoload.php'); +``` + + +Of course you can also just download an [archive](https://github.com/lanthaler/IRI/downloads) +from Github. + + +Credits +------------ + +Most test cases come either directly from the [URI specification](http://tools.ietf.org/html/rfc3986), +from [Graham Klyne's](http://www.ninebynine.org/Software/HaskellUtils/Network/URITestDescriptions.html), +or [Tim Berners-Lee's](http://dig.csail.mit.edu/2005/ajar/ajaw/test/uri-test-doc.html) test suite. diff --git a/Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/Test/IriTest.php b/Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/Test/IriTest.php new file mode 100644 index 0000000..83ae742 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/Test/IriTest.php @@ -0,0 +1,1078 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\IRI\Test; + +use ML\IRI\IRI; + +/** + * The IRI test suite. + * + * @author Markus Lanthaler + */ +class IriTest extends \PHPUnit_Framework_TestCase +{ + /** + * Test parsing + * + * This test checks whether decomposing IRIs in their subcomponents works. + * + * @param string $iri The IRI to decompose. + * @param string|null $scheme The scheme. + * @param string|null $userinfo The user information. + * @param string|null $host The host. + * @param string|null $port The port. + * @param string|null $path The path. + * @param string|null $query The query component. + * @param string|null $fragment The fragment identifier. + * + * @dataProvider decompositionProvider + */ + public function testDecomposition($iri, $scheme, $userinfo, $host, $port, $path, $query, $fragment) + { + $iri = new IRI($iri); + $test = new IRI($iri); // test copy-constructor + + $this->assertEquals($scheme, $test->getScheme(), 'Scheme of ' . $iri); + $this->assertEquals($userinfo, $test->getUserInfo(), 'User info of ' . $iri); + $this->assertEquals($host, $test->getHost(), 'Host of ' . $iri); + $this->assertEquals($port, $test->getPort(), 'Port of ' . $iri); + $this->assertEquals($path, $test->getPath(), 'Path of ' . $iri); + $this->assertEquals($query, $test->getQuery(), 'Query component of ' . $iri); + $this->assertEquals($fragment, $test->getFragment(), 'Fragment of ' . $iri); + $this->assertEquals($iri, $test->__toString(), 'Recomposition of ' . $iri); + $this->assertTrue($test->equals($iri), 'Test equality of parsed ' . $iri); + } + + /** + * Decomposition test cases + * + * These test cases were taken from the + * {@link http://tools.ietf.org/html/rfc3986#section-1.1.2 URI specification} + * and from {@link http://www.ninebynine.org/Software/HaskellUtils/Network/URITestDescriptions.html}. + * + * @return array The decomposition test cases. + */ + public function decompositionProvider() + { + return array( //$iri, $scheme, $userinfo, $host, $port, $path, $query, $fragment + // http://tools.ietf.org/html/rfc3986#section-1.1.2 + array('ftp://ftp.is.co.za/rfc/rfc1808.txt', 'ftp', null, 'ftp.is.co.za', null, '/rfc/rfc1808.txt', null, null), + array('http://www.ietf.org/rfc/rfc2396.txt#frag', 'http', null, 'www.ietf.org', null, '/rfc/rfc2396.txt', null, 'frag'), + array('ldap://[2001:db8::7]/c=GB?objectClass?one', 'ldap', null, '[2001:db8::7]', null, '/c=GB', 'objectClass?one', null), + array('mailto:John.Doe@example.com', 'mailto', null, null, null, 'John.Doe@example.com', null, null), + array('news:comp.infosystems.www.servers.unix', 'news', null, null, null, 'comp.infosystems.www.servers.unix', null, null), + array('tel:+1-816-555-1212', 'tel', null, null, null, '+1-816-555-1212', null, null), + array('telnet://192.0.2.16:80/', 'telnet', null, '192.0.2.16', '80', '/', null, null), + array('urn:oasis:names:specification:docbook:dtd:xml:4.1.2', 'urn', null, null, null, 'oasis:names:specification:docbook:dtd:xml:4.1.2', null, null), + // http://www.ninebynine.org/Software/HaskellUtils/Network/URITestDescriptions.html + array('http://user:pass@example.org:99/aaa/bbb?qqq#fff', 'http', 'user:pass', 'example.org', '99', '/aaa/bbb' , 'qqq', 'fff'), + // INVALID IRI array('http://user:pass@example.org:99aaa/bbb'), + array('http://user:pass@example.org:99?aaa/bbb', 'http', 'user:pass', 'example.org', '99', '', 'aaa/bbb', null), + array('http://user:pass@example.org:99#aaa/bbb', 'http', 'user:pass', 'example.org', '99' , '', null, 'aaa/bbb'), + array('http://example.com?query', 'http', null, 'example.com', null, '', 'query', null) + ); + } + + /** + * Test whether parsing invalid values leads to an exception + * + * @expectedException InvalidArgumentException + */ + public function testParseInvalidValue() + { + new IRI(2); + } + + /** + * Test whether an IRI is an absolute IRI or a relative one + * + * @param string $iri The IRI to test. + * @param bool $isAbsolute True if the IRI is absolute, false otherwise. + * + * @dataProvider isAbsoluteProvider + */ + public function testIsAbsolute($iri, $isAbsolute) + { + $iri = new IRI($iri); + $this->assertEquals($isAbsolute, $iri->isAbsolute()); + } + + + /** + * Absolute/relative IRI test cases + * + * These tests were taken from the + * {@link http://tools.ietf.org/html/rfc3986#section-5.4 URI specification} and from + * {@link http://www.ninebynine.org/Software/HaskellUtils/Network/URITestDescriptions.html}. + * + * @return array The absolute/relative IRI test cases. + */ + public function isAbsoluteProvider() + { + return array( + // http://tools.ietf.org/html/rfc3986#section-5.4 + array('http:g', true), + array('g:h', true), + array('g', false), + array('./g', false), + array('g/', false), + array('/g', false), + array('//g', false), + array('?y', false), + array('g?y', false), + array('#s', false), + array('g#s', false), + array('g?y#s', false), + array(';x', false), + array('g;x', false), + array('g;x?y#s', false), + array('', false), + array('.', false), + array('./', false), + array('..', false), + array('../', false), + array('../g', false), + array('../..', false), + array('../../', false), + array('../../g', false), + array('../../../g', false), + array('../../../../g', false), + array('/./g', false), + array('/../g', false), + array('g.', false), + array('.g', false), + array('g..', false), + array('..g', false), + array('./../g', false), + array('./g/.', false), + array('g/./h', false), + array('g/../h', false), + array('g;x=1/./y', false), + array('g;x=1/../y', false), + array('g?y/./x', false), + array('g?y/../x', false), + array('g#s/./x', false), + array('g#s/../x', false), + // http://www.ninebynine.org/Software/HaskellUtils/Network/URITestDescriptions.html + array('http://example.org/aaa/bbb#ccc', true), + array('mailto:local@domain.org', true), + array('mailto:local@domain.org#frag', true), + array('HTTP://EXAMPLE.ORG/AAA/BBB#CCC', true), + array('http://example.org/aaa%2fbbb#ccc', true), + array('http://example.org/aaa%2Fbbb#ccc', true), + array('http://example.org:80/aaa/bbb#ccc', true), + array('http://example.org:/aaa/bbb#ccc', true), + array('http://example.org./aaa/bbb#ccc', true), + array('http://example.123./aaa/bbb#ccc', true), + array('http://example.org', true), + array('http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html', true), + array('http://[1080:0:0:0:8:800:200C:417A]/index.html', true), + array('http://[3ffe:2a00:100:7031::1]', true), + array('http://[1080::8:800:200C:417A]/foo', true), + array('http://[::192.9.5.5]/ipng', true), + array('http://[::FFFF:129.144.52.38]:80/index.html', true), + array('http://[2010:836B:4179::836B:4179]', true), + array('http://example/Andrȷ', true), + array('file:///C:/DEV/Haskell/lib/HXmlToolbox-3.01/examples/', true), + array('http://46229EFFE16A9BD60B9F1BE88B2DB047ADDED785/demo.mp3', true), + array('//example.org/aaa/bbb#ccc', false), + array('/aaa/bbb#ccc', false), + array('bbb#ccc', false), + array('#ccc', false), + array('#', false), + array('/', false), + array('%2F', false), + array('aaa%2Fbbb', false), + array('//[2010:836B:4179::836B:4179]', false), + array("A'C", false), + array('A$C', false), + array('A@C', false), + array('"A,C"', false) + ); + } + + /** + * Test conversion to absolute IRI, i.e., removal of the fragment + */ + public function testGetAbsoluteIri() + { + $iri = new IRI('http://example.org/aaa%2fbbb#ccc'); + $this->assertEquals('http://example.org/aaa%2fbbb', (string) $iri->getAbsoluteIri()); + + $iri = new IRI('http://example.org/iri#with-fragment/looking/like/a/path?and&query'); + $this->assertEquals('http://example.org/iri', (string) $iri->getAbsoluteIri()); + } + + /** + * Test conversion to absolute IRI for a relative IRI + * + * @expectedException UnexpectedValueException + */ + public function testGetAbsoluteIriOnRelativeIri() + { + $iri = new IRI('/relative#with-fragment'); + $iri->getAbsoluteIri(); + } + + /** + * Test relative reference resolution + * + * @param string $base The base IRI. + * @param string $reference The reference to resolve. + * @param string $expected The expected absolute IRI. + * + * @dataProvider referenceResolutionProvider + */ + public function testReferenceResolution($base, $reference, $expected) + { + $base = new IRI($base); + $this->assertEquals($expected, (string)$base->resolve($reference)); + } + + /** + * Reference resolution test cases + * + * These test cases were taken from the + * {@link http://tools.ietf.org/html/rfc3986#section-5.4 URI specification}, + * from {@link http://www.w3.org/2004/04/uri-rel-test.html}, + * {@link http://dig.csail.mit.edu/2005/ajar/ajaw/test/uri-test-doc.html}, + * {@link http://www.ninebynine.org/Software/HaskellUtils/Network/URITestDescriptions.html}, + * and {@link http://greenbytes.de/tech/tc/uris/}. + * + * @return array The reference resolution test cases. + */ + public function referenceResolutionProvider() + { + return array( // $base, $relative, $absolute + array('', '../a/b', '/a/b'), + array('', '/.', '/'), + array(null, '', ''), + array('', null, ''), + array(null, null, ''), + // http://tools.ietf.org/html/rfc3986#section-5.4 + array('http://a/b/c/d;p?q', 'g:h', 'g:h'), + array('http://a/b/c/d;p?q', 'g', 'http://a/b/c/g'), + array('http://a/b/c/d;p?q', './g', 'http://a/b/c/g'), + array('http://a/b/c/d;p?q', 'g/', 'http://a/b/c/g/'), + array('http://a/b/c/d;p?q', '/g', 'http://a/g'), + array('http://a/b/c/d;p?q', '//g', 'http://g'), + array('http://a/b/c/d;p?q', '?y', 'http://a/b/c/d;p?y'), + array('http://a/b/c/d;p?q', 'g?y', 'http://a/b/c/g?y'), + array('http://a/b/c/d;p?q', '#s', 'http://a/b/c/d;p?q#s'), + array('http://a/b/c/d;p?q', 'g#s', 'http://a/b/c/g#s'), + array('http://a/b/c/d;p?q', 'g?y#s', 'http://a/b/c/g?y#s'), + array('http://a/b/c/d;p?q', ';x', 'http://a/b/c/;x'), + array('http://a/b/c/d;p?q', 'g;x', 'http://a/b/c/g;x'), + array('http://a/b/c/d;p?q', 'g;x?y#s', 'http://a/b/c/g;x?y#s'), + array('http://a/b/c/d;p?q', '', 'http://a/b/c/d;p?q'), + array('http://a/b/c/d;p?q', '.', 'http://a/b/c/'), + array('http://a/b/c/d;p?q', './', 'http://a/b/c/'), + array('http://a/b/c/d;p?q', '..', 'http://a/b/'), + array('http://a/b/c/d;p?q', '../', 'http://a/b/'), + array('http://a/b/c/d;p?q', '../g', 'http://a/b/g'), + array('http://a/b/c/d;p?q', '../..', 'http://a/'), + array('http://a/b/c/d;p?q', '../../', 'http://a/'), + array('http://a/b/c/d;p?q', '../../g', 'http://a/g'), + array('http://a/b/c/d;p?q', '../../../g', 'http://a/g'), + array('http://a/b/c/d;p?q', '../../../../g', 'http://a/g'), + array('http://a/b/c/d;p?q', '/./g', 'http://a/g'), + array('http://a/b/c/d;p?q', '/../g', 'http://a/g'), + array('http://a/b/c/d;p?q', 'g.', 'http://a/b/c/g.'), + array('http://a/b/c/d;p?q', '.g', 'http://a/b/c/.g'), + array('http://a/b/c/d;p?q', 'g..', 'http://a/b/c/g..'), + array('http://a/b/c/d;p?q', '..g', 'http://a/b/c/..g'), + array('http://a/b/c/d;p?q', './../g', 'http://a/b/g'), + array('http://a/b/c/d;p?q', './g/.', 'http://a/b/c/g/'), + array('http://a/b/c/d;p?q', 'g/./h', 'http://a/b/c/g/h'), + array('http://a/b/c/d;p?q', 'g/../h', 'http://a/b/c/h'), + array('http://a/b/c/d;p?q', 'g;x=1/./y', 'http://a/b/c/g;x=1/y'), + array('http://a/b/c/d;p?q', 'g;x=1/../y', 'http://a/b/c/y'), + array('http://a/b/c/d;p?q', 'g?y/./x', 'http://a/b/c/g?y/./x'), + array('http://a/b/c/d;p?q', 'g?y/../x', 'http://a/b/c/g?y/../x'), + array('http://a/b/c/d;p?q', 'g#s/./x', 'http://a/b/c/g#s/./x'), + array('http://a/b/c/d;p?q', 'g#s/../x', 'http://a/b/c/g#s/../x'), + array('http://a/b/c/d;p?q', 'http:g', 'http:g'), + // http://www.w3.org/2004/04/uri-rel-test.html + array('http://a/b/c/d;p?q', './g:h', 'http://a/b/c/g:h'), + // http://dig.csail.mit.edu/2005/ajar/ajaw/test/uri-test-doc.html}, + // http://www.ninebynine.org/Software/HaskellUtils/Network/URITestDescriptions.html}. + array('foo:xyz', 'bar:abc', 'bar:abc'), + array('http://example/x/y/z', '../abc', 'http://example/x/abc'), + array('http://example2/x/y/z', '//example/x/abc', 'http://example/x/abc'), + array('http://example2/x/y/z', 'http://example/x/abc', 'http://example/x/abc'), + array('http://ex/x/y/z', '../r', 'http://ex/x/r'), + array('http://ex/x/y/z', '/r', 'http://ex/r'), + array('http://ex/x/y/z', 'q/r', 'http://ex/x/y/q/r'), + array('http://ex/x/y', 'q/r#s', 'http://ex/x/q/r#s'), + array('http://ex/x/y', 'q/r#s/t', 'http://ex/x/q/r#s/t'), + array('http://ex/x/y', 'ftp://ex/x/q/r', 'ftp://ex/x/q/r'), + array('http://ex/x/y', '', 'http://ex/x/y'), + array('http://ex/x/y/', '', 'http://ex/x/y/'), + array('http://ex/x/y/pdq', '', 'http://ex/x/y/pdq'), + array('http://ex/x/y/', 'z/', 'http://ex/x/y/z/'), + array('file:/swap/test/animal.rdf', '#Animal', 'file:/swap/test/animal.rdf#Animal'), + array('file:/e/x/y/z', '../abc', 'file:/e/x/abc'), + array('file:/example2/x/y/z', '/example/x/abc', 'file:/example/x/abc'), + array('file:/ex/x/y/z', '../r', 'file:/ex/x/r'), + array('file:/ex/x/y/z', '/r', 'file:/r'), + array('file:/ex/x/y', 'q/r', 'file:/ex/x/q/r'), + array('file:/ex/x/y', 'q/r#s', 'file:/ex/x/q/r#s'), + array('file:/ex/x/y', 'q/r#', 'file:/ex/x/q/r#'), + array('file:/ex/x/y', 'q/r#s/t', 'file:/ex/x/q/r#s/t'), + array('file:/ex/x/y', 'ftp://ex/x/q/r', 'ftp://ex/x/q/r'), + array('file:/ex/x/y', '', 'file:/ex/x/y'), + array('file:/ex/x/y/', '', 'file:/ex/x/y/'), + array('file:/ex/x/y/pdq', '', 'file:/ex/x/y/pdq'), + array('file:/ex/x/y/', 'z/', 'file:/ex/x/y/z/'), + array('file:/devel/WWW/2000/10/swap/test/reluri-1.n3', '//meetings.example.com/cal#m1', 'file://meetings.example.com/cal#m1'), + array('file:/home/connolly/w3ccvs/WWW/2000/10/swap/test/reluri-1.n3', '//meetings.example.com/cal#m1', 'file://meetings.example.com/cal#m1'), + array('file:/some/dir/foo', './#blort', 'file:/some/dir/#blort'), + array('file:/some/dir/foo', './#', 'file:/some/dir/#'), + array('http://ex/x/y', './q:r', 'http://ex/x/q:r'), + array('http://ex/x/y', './p=q:r', 'http://ex/x/p=q:r'), + array('http://ex/x/y?pp/qq', '?pp/rr', 'http://ex/x/y?pp/rr'), + array('http://ex/x/y?pp/qq', 'y/z', 'http://ex/x/y/z'), + array('mailto:local', 'local/qual@domain.org#frag', 'mailto:local/qual@domain.org#frag'), + array('mailto:local/qual1@domain1.org', 'more/qual2@domain2.org#frag', 'mailto:local/more/qual2@domain2.org#frag'), + array('http://ex/x/z?q', 'y?q', 'http://ex/x/y?q'), + array('http://ex?p', '/x/y?q', 'http://ex/x/y?q'), + array('foo:a/b', 'c/d', 'foo:a/c/d'), + array('foo:a/b', '/c/d', 'foo:/c/d'), + array('foo:a/b?c#d', '', 'foo:a/b?c'), + array('foo:a', 'b/c', 'foo:b/c'), + array('foo:/a/y/z', '../b/c', 'foo:/a/b/c'), + // TODO Check this test, shouldn't the result be foo:/b/c? array('foo:a', './b/c', 'foo:b/c'), + array('foo:a', '/./b/c', 'foo:/b/c'), + array('foo://a//b/c', '../../d', 'foo://a/d'), + array('foo:a', '.', 'foo:'), + array('foo:a', '..', 'foo:'), + array('http://example/x/y%2Fz', 'abc', 'http://example/x/abc'), + array('http://example/a/x/y/z', '../../x%2Fabc', 'http://example/a/x%2Fabc'), + array('http://example/a/x/y%2Fz', '../x%2Fabc', 'http://example/a/x%2Fabc'), + array('http://example/x%2Fy/z', 'abc', 'http://example/x%2Fy/abc'), + array('http://ex/x/y', 'q%3Ar', 'http://ex/x/q%3Ar'), + array('http://example/x/y%2Fz', '/x%2Fabc', 'http://example/x%2Fabc'), + array('http://example/x/y/z', '/x%2Fabc', 'http://example/x%2Fabc'), + array('http://example/x/y%2Fz', '/x%2Fabc', 'http://example/x%2Fabc'), + array('ftp://example/x/y', 'http://example/a/b/../../c', 'http://example/c'), + array('ftp://example/x/y', 'http://example/a/b/c/../../', 'http://example/a/'), + array('ftp://example/x/y', 'http://example/a/b/c/./', 'http://example/a/b/c/'), + array('ftp://example/x/y', 'http://example/a/b/c/.././', 'http://example/a/b/'), + array('ftp://example/x/y', 'http://example/a/b/c/d/../../../../e', 'http://example/e'), + array('ftp://example/x/y', 'http://example/a/b/c/d/../.././../../e', 'http://example/e'), + array('mailto:local1@domain1?query1', 'local2@domain2', 'mailto:local2@domain2'), + array('mailto:local1@domain1', 'local2@domain2?query2', 'mailto:local2@domain2?query2'), + array('mailto:local1@domain1?query1', 'local2@domain2?query2', 'mailto:local2@domain2?query2'), + array('mailto:local@domain?query1', '?query2', 'mailto:local@domain?query2'), + array('mailto:?query1', 'local@domain?query2', 'mailto:local@domain?query2'), + array('mailto:local@domain?query1', '?query2', 'mailto:local@domain?query2'), + array('foo:bar', 'http://example/a/b?c/../d', 'http://example/a/b?c/../d'), + array('foo:bar', 'http://example/a/b#c/../d', 'http://example/a/b#c/../d'), + array('http://example.org/base/uri', 'this', 'http://example.org/base/this'), // Fixed absolute from http:this + array('http://example.org/base/uri', 'http:this', 'http:this'), + array('http:base', 'http:this', 'http:this'), + array('f:/a', './/g', 'f://g'), + array('f://example.org/base/a', 'b/c//d/e', 'f://example.org/base/b/c//d/e'), + array('mid:m@example.ord/c@example.org', 'm2@example.ord/c2@example.org', 'mid:m@example.ord/m2@example.ord/c2@example.org'), + array('file:///C:/DEV/Haskell/lib/HXmlToolbox-3.01/examples/', 'mini1.xml', 'file:///C:/DEV/Haskell/lib/HXmlToolbox-3.01/examples/mini1.xml'), + array('foo:a/y/z', '../b/c', 'foo:a/b/c'), + array('http://ex', '/x/y?q', 'http://ex/x/y?q'), + array('http://ex', 'x/y?q', 'http://ex/x/y?q'), + array('http://ex?p', '/x/y?q', 'http://ex/x/y?q'), + array('http://ex?p', 'x/y?q', 'http://ex/x/y?q'), + array('http://ex#f', '/x/y?q', 'http://ex/x/y?q'), + array('http://ex#f', 'x/y?q', 'http://ex/x/y?q'), + array('http://ex?p', '/x/y#g', 'http://ex/x/y#g'), + array('http://ex?p', 'x/y#g', 'http://ex/x/y#g'), + array('http://ex', '/', 'http://ex/'), + array('http://ex', './', 'http://ex/'), + array('http://ex', '/a/b', 'http://ex/a/b'), + array('http://ex/a/b', './', 'http://ex/a/'), + array('mailto:local/option@domain.org?notaquery#frag', 'more@domain', 'mailto:local/more@domain'), + array('mailto:local/option@domain.org?notaquery#frag', '#newfrag', 'mailto:local/option@domain.org?notaquery#newfrag'), + array('mailto:local/option@domain.org?notaquery#frag', 'l1/q1@domain', 'mailto:local/l1/q1@domain'), + array('mailto:local1@domain1?query1', 'mailto:local2@domain2', 'mailto:local2@domain2'), + array('mailto:local1@domain1', 'mailto:local2@domain2?query2', 'mailto:local2@domain2?query2'), + array('mailto:local1@domain1?query1', 'mailto:local2@domain2?query2', 'mailto:local2@domain2?query2'), + array('mailto:local@domain?query1', 'mailto:local@domain?query2', 'mailto:local@domain?query2'), + array('mailto:?query1', 'mailto:local@domain?query2', 'mailto:local@domain?query2'), + array('mailto:local@domain?query1', '?query2', 'mailto:local@domain?query2'), + array('info:name/1234/../567', 'name/9876/../543', 'info:name/name/543'), + array('info:/name/1234/../567', 'name/9876/../543', 'info:/name/name/543'), + array('http://ex/x/y', 'q/r', 'http://ex/x/q/r'), + array('file:/devel/WWW/2000/10/swap/test/reluri-1.n3', 'file://meetings.example.com/cal#m1', 'file://meetings.example.com/cal#m1'), + array('file:/home/connolly/w3ccvs/WWW/2000/10/swap/test/reluri-1.n3', 'file://meetings.example.com/cal#m1', 'file://meetings.example.com/cal#m1'), + array('http://example/x/abc.efg', './', 'http://example/x/'), + array('http://www.w3.org/People/Berners-Lee/card.rdf', '../../2002/01/tr-automation/tr.rdf', 'http://www.w3.org/2002/01/tr-automation/tr.rdf'), + array('http://example.com/', '.', 'http://example.com/'), + array('http://example.com/.meta.n3', '.meta.n3', 'http://example.com/.meta.n3'), + // http://greenbytes.de/tech/tc/uris/ + array('data:text/plain;charset=iso-8859-7,%be%fg%be', 'http://a/b/c/d;p?q', 'http://a/b/c/d;p?q'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', 'g:h', 'g:h'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', '', 'data:text/plain;charset=iso-8859-7,%be%fg%be'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', 'g', 'data:text/g'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', './g', 'data:text/g'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', 'g/', 'data:text/g/'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', '/g', 'data:/g'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', '//g', 'data://g'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', '?y', 'data:text/plain;charset=iso-8859-7,%be%fg%be?y'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', 'g?y', 'data:text/g?y'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', '#s', 'data:text/plain;charset=iso-8859-7,%be%fg%be#s'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', 'g#s', 'data:text/g#s'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', 'g?y#s', 'data:text/g?y#s'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', ';x', 'data:text/;x'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', 'g;x', 'data:text/g;x'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', 'g;x?y#s', 'data:text/g;x?y#s'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', '', 'data:text/plain;charset=iso-8859-7,%be%fg%be'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', '.', 'data:text/'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', './', 'data:text/'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', '..', 'data:/'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', '../', 'data:/'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', '../g', 'data:/g'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', '../..', 'data:/'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', '../../', 'data:/'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', '../../g', 'data:/g'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', '../../../g', 'data:/g'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', '../../../../g', 'data:/g'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', '/./g', 'data:/g'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', '/../g', 'data:/g'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', 'g.', 'data:text/g.'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', '.g', 'data:text/.g'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', 'g..', 'data:text/g..'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', '..g', 'data:text/..g'), + array('http://a/b/c/d;p?q', 'data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAwAAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFzByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSpa/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJlZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uisF81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PHhhx4dbgYKAAA7', 'data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAwAAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFzByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSpa/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJlZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uisF81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PHhhx4dbgYKAAA7'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', 'data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAwAAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFzByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSpa/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJlZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uisF81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PHhhx4dbgYKAAA7', 'data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAwAAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFzByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSpa/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJlZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uisF81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PHhhx4dbgYKAAA7'), + array('http://a/b/c/d;p?q', 'data:text/plain;charset=iso-8859-7,%be%fg%be', 'data:text/plain;charset=iso-8859-7,%be%fg%be'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', 'data:text/plain;charset=iso-8859-7,%be%fg%be', 'data:text/plain;charset=iso-8859-7,%be%fg%be'), + array('http://a/b/c/d;p?q', 'http://www.example.org/Dürst', 'http://www.example.org/Dürst'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', 'http://www.example.org/Dürst', 'http://www.example.org/Dürst'), + array('http://a/b/c/d;p?q', 'http://www.example.org/foo bar/qux<>?\^`{|}', 'http://www.example.org/foo bar/qux<>?\^`{|}'), + array('data:text/plain;charset=iso-8859-7,%be%fg%be', 'http://www.example.org/foo bar/qux<>?\^`{|}', 'http://www.example.org/foo bar/qux<>?\^`{|}'), + array('http://example.com/b;bar', ';foo', 'http://example.com/;foo'), + array('http://1.example.org/path1/file1.ext', 'http://2.example.org#frag2', 'http://2.example.org#frag2'), + array('http://example.org/a/b', '?x', 'http://example.org/a/b?x'), + array('http://example.org/foo/bar', 'http:test', 'http:test'), + array('http://www.example.com/#', 'hello, world', 'http://www.example.com/hello, world'), + array('http://www.example.com/#', '%c2%a9', 'http://www.example.com/%c2%a9'), + array('http://www.example.com/#', '%41%a', 'http://www.example.com/%41%a'), + array('http://www.example.com/#', 'asdf#qwer', 'http://www.example.com/asdf#qwer'), + array('http://www.example.com/#', '#asdf', 'http://www.example.com/#asdf'), + array('http://www.example.com/foo/bar', 'file:c:\\\\foo\\\\bar.html', 'file:c:\\\\foo\\\\bar.html'), + array('http://www.example.com/foo/bar', 'File:c|////foo\\\\bar.html', 'File:c|////foo\\\\bar.html'), + array('http://www.example.com/foo/bar', 'file:', 'file:'), + array('http://www.example.com/foo/bar', 'file:UNChost/path', 'file:UNChost/path'), + array('http://www.example.com/foo/bar', 'c:\\\\foo\\\\bar', 'c:\\\\foo\\\\bar'), + array('http://www.example.com/foo/bar', 'C|/foo/bar', 'http://www.example.com/foo/C|/foo/bar'), + array('http://www.example.com/foo/bar', '/C|\\\\foo\\\\bar', 'http://www.example.com/C|\\\\foo\\\\bar'), + array('http://www.example.com/foo/bar', '//C|/foo/bar', 'http://C|/foo/bar'), + array('http://www.example.com/foo/bar', '//server/file', 'http://server/file'), + array('http://www.example.com/foo/bar', '\\\\\\\\server\\\\file', 'http://www.example.com/foo/\\\\\\\\server\\\\file'), + array('http://www.example.com/foo/bar', '/\\\\server/file', 'http://www.example.com/\\\\server/file'), + array('http://www.example.com/foo/bar', 'file:c:foo/bar.html', 'file:c:foo/bar.html'), + array('http://www.example.com/foo/bar', 'file:/\\\\/\\\\C:\\\\\\\\//foo\\\\bar.html', 'file:/\\\\/\\\\C:\\\\\\\\//foo\\\\bar.html'), + array('http://www.example.com/foo/bar', 'file:///foo/bar.txt', 'file:///foo/bar.txt'), + array('http://www.example.com/foo/bar', 'FILE:/\\\\/\\\\7:\\\\\\\\//foo\\\\bar.html', 'FILE:/\\\\/\\\\7:\\\\\\\\//foo\\\\bar.html'), + array('http://www.example.com/foo/bar', 'file:filer/home\\\\me', 'file:filer/home\\\\me'), + array('http://www.example.com/foo/bar', 'file:///C:/foo/../../../bar.html', 'file:///bar.html'), + array('http://www.example.com/foo/bar', 'file:///C:/asdf#\\%c2', 'file:///C:/asdf#\\%c2'), + array('http://www.example.com/foo/bar', 'file:///home/me', 'file:///home/me'), + array('http://www.example.com/foo/bar', 'file:c:\\\\foo\\\\bar.html', 'file:c:\\\\foo\\\\bar.html'), + array('http://www.example.com/foo/bar', 'file:c|//foo\\\\bar.html', 'file:c|//foo\\\\bar.html'), + array('http://www.example.com/foo/bar', '//', 'http://'), + array('http://www.example.com/foo/bar', '///', 'http:///'), + array('http://www.example.com/foo/bar', '///test', 'http:///test'), + array('http://www.example.com/foo/bar', 'file://test', 'file://test'), + array('http://www.example.com/foo/bar', 'file://localhost/', 'file://localhost/'), + array('http://www.example.com/foo/bar', 'file://localhost/test', 'file://localhost/test'), + array('file:///tmp/mock/path', 'file:c:\\\\foo\\\\bar.html', 'file:c:\\\\foo\\\\bar.html'), + array('file:///tmp/mock/path', 'File:c|////foo\\\\bar.html', 'File:c|////foo\\\\bar.html'), + array('file:///tmp/mock/path', 'file:', 'file:'), + array('file:///tmp/mock/path', 'file:UNChost/path', 'file:UNChost/path'), + array('file:///tmp/mock/path', 'c:\\\\foo\\\\bar', 'c:\\\\foo\\\\bar'), + array('file:///tmp/mock/path', 'C|/foo/bar', 'file:///tmp/mock/C|/foo/bar'), + array('file:///tmp/mock/path', '/C|\\\\foo\\\\bar', 'file:///C|\\\\foo\\\\bar'), + array('file:///tmp/mock/path', '//C|/foo/bar', 'file://C|/foo/bar'), + array('file:///tmp/mock/path', '//server/file', 'file://server/file'), + array('file:///tmp/mock/path', '\\\\\\\\server\\\\file', 'file:///tmp/mock/\\\\\\\\server\\\\file'), + array('file:///tmp/mock/path', '/\\\\server/file', 'file:///\\\\server/file'), + array('file:///tmp/mock/path', 'file:c:foo/bar.html', 'file:c:foo/bar.html'), + array('file:///tmp/mock/path', 'file:/\\\\/\\\\C:\\\\\\\\//foo\\\\bar.html', 'file:/\\\\/\\\\C:\\\\\\\\//foo\\\\bar.html'), + array('file:///tmp/mock/path', 'file:///foo/bar.txt', 'file:///foo/bar.txt'), + array('file:///tmp/mock/path', 'FILE:/\\\\/\\\\7:\\\\\\\\//foo\\\\bar.html', 'FILE:/\\\\/\\\\7:\\\\\\\\//foo\\\\bar.html'), + array('file:///tmp/mock/path', 'file:filer/home\\\\me', 'file:filer/home\\\\me'), + array('file:///tmp/mock/path', 'file:///C:/foo/../../../bar.html', 'file:///bar.html'), + array('file:///tmp/mock/path', 'file:///C:/asdf#\\%c2', 'file:///C:/asdf#\\%c2'), + array('file:///tmp/mock/path', 'file:///home/me', 'file:///home/me'), + array('file:///tmp/mock/path', 'file:c:\\\\foo\\\\bar.html', 'file:c:\\\\foo\\\\bar.html'), + array('file:///tmp/mock/path', 'file:c|//foo\\\\bar.html', 'file:c|//foo\\\\bar.html'), + array('file:///tmp/mock/path', '//', 'file://'), + array('file:///tmp/mock/path', '///', 'file:///'), + array('file:///tmp/mock/path', '///test', 'file:///test'), + array('file:///tmp/mock/path', 'file://test', 'file://test'), + array('file:///tmp/mock/path', 'file://localhost/', 'file://localhost/'), + array('file:///tmp/mock/path', 'file://localhost/test', 'file://localhost/test'), + array('http://', 'GoOgLe.CoM', 'http:///GoOgLe.CoM'), + array('http://', 'Goo%20 goo%7C|.com', 'http:///Goo%20 goo%7C|.com'), + array('http://', '%ef%b7%90zyx.com', 'http:///%ef%b7%90zyx.com'), + array('http://', '%ef%bc%85%ef%bc%94%ef%bc%91.com', 'http:///%ef%bc%85%ef%bc%94%ef%bc%91.com'), + array('http://', '%ef%bc%85%ef%bc%90%ef%bc%90.com', 'http:///%ef%bc%85%ef%bc%90%ef%bc%90.com'), + array('http://', '%zz%66%a', 'http:///%zz%66%a'), + array('http://', '%25', 'http:///%25'), + array('http://', 'hello%00', 'http:///hello%00'), + array('http://', '%30%78%63%30%2e%30%32%35%30.01', 'http:///%30%78%63%30%2e%30%32%35%30.01'), + array('http://', '%30%78%63%30%2e%30%32%35%30.01%2e', 'http:///%30%78%63%30%2e%30%32%35%30.01%2e'), + array('http://', '%3g%78%63%30%2e%30%32%35%30%2E.01', 'http:///%3g%78%63%30%2e%30%32%35%30%2E.01'), + array('http://', '192.168.0.1 hello', 'http:///192.168.0.1 hello'), + array('http://', '192.168.0.257', 'http:///192.168.0.257'), + array('http://', '[google.com]', 'http:///[google.com]'), + array('http://', 'go\\@ogle.com', 'http:///go\\@ogle.com'), + array('http://', 'go/@ogle.com', 'http:///go/@ogle.com'), + array('http://', 'www.lookout.net::==80::==443::', 'www.lookout.net::==80::==443::'), + array('http://', 'www.lookout.net::80::443', 'www.lookout.net::80::443'), + array('http://', '\\\\', 'http:///\\\\'), + array('http://', '\\\\\\/', 'http:///\\\\\\/'), + array('http://', '\\\\./', 'http:///\\\\./'), + array('http://', '//:@/', 'http://:@/'), + array('http://', '\\google.com/foo', 'http:///\\google.com/foo'), + array('http://', '\\\\google.com/foo', 'http:///\\\\google.com/foo'), + array('http://', '//asdf@/', 'http://asdf@/'), + array('http://', '//:81', 'http://:81'), + array('http://', '://', 'http:///://'), + array('http://', 'c:', 'c:'), + array('http://', 'xxxx:', 'xxxx:'), + array('http://', '.:.', '.:'), + array('http://', '////@google.com/', 'http:////@google.com/'), + array('http://', '@google.com', 'http:///@google.com'), + array('http://', 'gOoGle.com', 'http:///gOoGle.com'), + array('http://', '-foo.bar.com', 'http:///-foo.bar.com'), + array('http://', 'foo-.bar.com', 'http:///foo-.bar.com'), + array('http://', 'ab--cd.com', 'http:///ab--cd.com'), + array('http://', 'xn--0.com', 'http:///xn--0.com'), + array('http://', '.', 'http:///'), + array('http://', '192.168.0.1', 'http:///192.168.0.1'), + array('http://', '0300.0250.00.01', 'http:///0300.0250.00.01'), + array('http://', '0xC0.0Xa8.0x0.0x1', 'http:///0xC0.0Xa8.0x0.0x1'), + array('http://', '192.168.9.com', 'http:///192.168.9.com'), + array('http://', '19a.168.0.1', 'http:///19a.168.0.1'), + array('http://', '0308.0250.00.01', 'http:///0308.0250.00.01'), + array('http://', '0xCG.0xA8.0x0.0x1', 'http:///0xCG.0xA8.0x0.0x1'), + array('http://', '192', 'http:///192'), + array('http://', '0xC0a80001', 'http:///0xC0a80001'), + array('http://', '030052000001', 'http:///030052000001'), + array('http://', '000030052000001', 'http:///000030052000001'), + array('http://', '192.168', 'http:///192.168'), + array('http://', '192.0x00A80001', 'http:///192.0x00A80001'), + array('http://', '0xc0.052000001', 'http:///0xc0.052000001'), + array('http://', '192.168.1', 'http:///192.168.1'), + array('http://', '192.168.0.0.1', 'http:///192.168.0.0.1'), + array('http://', '192.168.0.1.', 'http:///192.168.0.1.'), + array('http://', '192.168.0.1. hello', 'http:///192.168.0.1. hello'), + array('http://', '192.168.0.1..', 'http:///192.168.0.1..'), + array('http://', '192.168..1', 'http:///192.168..1'), + array('http://', '0x100.0', 'http:///0x100.0'), + array('http://', '0x100.0.0', 'http:///0x100.0.0'), + array('http://', '0x100.0.0.0', 'http:///0x100.0.0.0'), + array('http://', '0.0x100.0.0', 'http:///0.0x100.0.0'), + array('http://', '0.0.0x100.0', 'http:///0.0.0x100.0'), + array('http://', '0.0.0.0x100', 'http:///0.0.0.0x100'), + array('http://', '0.0.0x10000', 'http:///0.0.0x10000'), + array('http://', '0.0x1000000', 'http:///0.0x1000000'), + array('http://', '0x100000000', 'http:///0x100000000'), + array('http://', '0xFF.0', 'http:///0xFF.0'), + array('http://', '0xFF.0.0', 'http:///0xFF.0.0'), + array('http://', '0xFF.0.0.0', 'http:///0xFF.0.0.0'), + array('http://', '0.0xFF.0.0', 'http:///0.0xFF.0.0'), + array('http://', '0.0.0xFF.0', 'http:///0.0.0xFF.0'), + array('http://', '0.0.0.0xFF', 'http:///0.0.0.0xFF'), + array('http://', '0.0.0xFFFF', 'http:///0.0.0xFFFF'), + array('http://', '0.0xFFFFFF', 'http:///0.0xFFFFFF'), + array('http://', '0xFFFFFFFF', 'http:///0xFFFFFFFF'), + array('http://', '276.256.0xf1a2.077777', 'http:///276.256.0xf1a2.077777'), + array('http://', '192.168.0.257', 'http:///192.168.0.257'), + array('http://', '192.168.0xa20001', 'http:///192.168.0xa20001'), + array('http://', '192.015052000001', 'http:///192.015052000001'), + array('http://', '0X12C0a80001', 'http:///0X12C0a80001'), + array('http://', '276.1.2', 'http:///276.1.2'), + array('http://', '192.168.0.1 hello', 'http:///192.168.0.1 hello'), + array('http://', '0000000000000300.0x00000000000000fF.00000000000000001', 'http:///0000000000000300.0x00000000000000fF.00000000000000001'), + array('http://', '0000000000000300.0xffffffffFFFFFFFF.3022415481470977', 'http:///0000000000000300.0xffffffffFFFFFFFF.3022415481470977'), + array('http://', '00000000000000000001', 'http:///00000000000000000001'), + array('http://', '0000000000000000100000000000000001', 'http:///0000000000000000100000000000000001'), + array('http://', '0.0.0.000000000000000000z', 'http:///0.0.0.000000000000000000z'), + array('http://', '0.0.0.100000000000000000z', 'http:///0.0.0.100000000000000000z'), + array('http://', '0.00.0x.0x0', 'http:///0.00.0x.0x0'), + array('http://', '[', 'http:///['), + array('http://', '[:', '[:'), + array('http://', ']', 'http:///]'), + array('http://', ':]', 'http:///:]'), + array('http://', '[]', 'http:///[]'), + array('http://', '[:]', '[:]'), + array('http://', '2001:db8::1', '2001:db8::1'), + array('http://', '[2001:db8::1', '[2001:db8::1'), + array('http://', '2001:db8::1]', '2001:db8::1]'), + array('http://', '[::]', '[::]'), + array('http://', '[::1]', '[::1]'), + array('http://', '[1::]', '[1::]'), + array('http://', '[::192.168.0.1]', '[::192.168.0.1]'), + array('http://', '[::ffff:192.168.0.1]', '[::ffff:192.168.0.1]'), + array('http://', '[000:01:02:003:004:5:6:007]', '[000:01:02:003:004:5:6:007]'), + array('http://', '[A:b:c:DE:fF:0:1:aC]', '[A:b:c:DE:fF:0:1:aC]'), + array('http://', '[1:0:0:2::3:0]', '[1:0:0:2::3:0]'), + array('http://', '[1::2:0:0:3:0]', '[1::2:0:0:3:0]'), + array('http://', '[::eeee:192.168.0.1]', '[::eeee:192.168.0.1]'), + array('http://', '[2001::192.168.0.1]', '[2001::192.168.0.1]'), + array('http://', '[1:2:192.168.0.1:5:6]', '[1:2:192.168.0.1:5:6]'), + array('http://', '[::ffff:192.1.2]', '[::ffff:192.1.2]'), + array('http://', '[::ffff:0xC0.0Xa8.0x0.0x1]', '[::ffff:0xC0.0Xa8.0x0.0x1]'), + array('http://', '[0:0::0:0:8]', '[0:0::0:0:8]'), + array('http://', '[2001:db8::1]', '[2001:db8::1]'), + array('http://', '[2001::db8::1]', '[2001::db8::1]'), + array('http://', '[2001:db8:::1]', '[2001:db8:::1]'), + array('http://', '[:::]', '[:::]'), + array('http://', '[2001::.com]', '[2001::.com]'), + array('http://', '[::192.168.0.0.1]', '[::192.168.0.0.1]'), + array('http://', '[::ffff:192.168.0.0.1]', '[::ffff:192.168.0.0.1]'), + array('http://', '[1:2:3:4:5:6:7:8:9]', '[1:2:3:4:5:6:7:8:9]'), + array('http://', '[0:0:0:0:0:0:0:192.168.0.1]', '[0:0:0:0:0:0:0:192.168.0.1]'), + array('http://', '[1:2:3:4:5:6::192.168.0.1]', '[1:2:3:4:5:6::192.168.0.1]'), + array('http://', '[1:2:3:4:5:6::8]', '[1:2:3:4:5:6::8]'), + array('http://', '[1:2:3:4:5:6:7:8:]', '[1:2:3:4:5:6:7:8:]'), + array('http://', '[1:2:3:4:5:6:192.168.0.1:]', '[1:2:3:4:5:6:192.168.0.1:]'), + array('http://', '[-1:2:3:4:5:6:7:8]', '[-1:2:3:4:5:6:7:8]'), + array('http://', '[1::%1]', '[1::%1]'), + array('http://', '[1::%eth0]', '[1::%eth0]'), + array('http://', '[1::%]', '[1::%]'), + array('http://', '[%]', 'http:///[%]'), + array('http://', '[::%:]', '[::%:]'), + array('http://', '[:0:0::0:0:8]', '[:0:0::0:0:8]'), + array('http://', '[0:0::0:0:8:]', '[0:0::0:0:8:]'), + array('http://', '[:0:0::0:0:8:]', '[:0:0::0:0:8:]'), + array('http://', '[::192.168..1]', '[::192.168..1]'), + array('http://', '[::1 hello]', '[::1 hello]'), + array('mailto:', 'addr1', 'mailto:addr1'), + array('mailto:', 'addr1@foo.com', 'mailto:addr1@foo.com'), + array('mailto:', 'addr1 \\t', 'mailto:addr1 \\t'), + array('mailto:', 'addr1?to=jon', 'mailto:addr1?to=jon'), + array('mailto:', 'addr1,addr2', 'mailto:addr1,addr2'), + array('mailto:', 'addr1, addr2', 'mailto:addr1, addr2'), + array('mailto:', 'addr1%2caddr2', 'mailto:addr1%2caddr2'), + array('mailto:', 'addr1?', 'mailto:addr1?'), + array('http://www.example.com', '/././foo', 'http://www.example.com/foo'), + array('http://www.example.com', '/./.foo', 'http://www.example.com/.foo'), + array('http://www.example.com', '/foo/.', 'http://www.example.com/foo/'), + array('http://www.example.com', '/foo/./', 'http://www.example.com/foo/'), + array('http://www.example.com', '/foo/bar/..', 'http://www.example.com/foo/'), + array('http://www.example.com', '/foo/bar/../', 'http://www.example.com/foo/'), + array('http://www.example.com', '/foo/..bar', 'http://www.example.com/foo/..bar'), + array('http://www.example.com', '/foo/bar/../ton', 'http://www.example.com/foo/ton'), + array('http://www.example.com', '/foo/bar/../ton/../../a', 'http://www.example.com/a'), + array('http://www.example.com', '/foo/../../..', 'http://www.example.com/'), + array('http://www.example.com', '/foo/../../../ton', 'http://www.example.com/ton'), + array('http://www.example.com', '/foo/%2e', 'http://www.example.com/foo/%2e'), + array('http://www.example.com', '/foo/%2e%2', 'http://www.example.com/foo/%2e%2'), + array('http://www.example.com', '/foo/%2e./%2e%2e/.%2e/%2e.bar', 'http://www.example.com/foo/%2e./%2e%2e/.%2e/%2e.bar'), + array('http://www.example.com', '////../..', 'http:///'), + array('http://www.example.com', '/foo/bar//../..', 'http://www.example.com/foo/'), + array('http://www.example.com', '/foo/bar//..', 'http://www.example.com/foo/bar/'), + array('http://www.example.com', '/foo/bar/..', 'http://www.example.com/foo/'), + array('http://www.example.com', '/foo', 'http://www.example.com/foo'), + array('http://www.example.com', '/%20foo', 'http://www.example.com/%20foo'), + array('http://www.example.com', '/foo%', 'http://www.example.com/foo%'), + array('http://www.example.com', '/foo%2', 'http://www.example.com/foo%2'), + array('http://www.example.com', '/foo%2zbar', 'http://www.example.com/foo%2zbar'), + array('http://www.example.com', '/foo%41%7a', 'http://www.example.com/foo%41%7a'), + array('http://www.example.com', '/foo%00%51', 'http://www.example.com/foo%00%51'), + array('http://www.example.com', '/(%28:%3A%29)', 'http://www.example.com/(%28:%3A%29)'), + array('http://www.example.com', '/%3A%3a%3C%3c', 'http://www.example.com/%3A%3a%3C%3c'), + array('http://www.example.com', '/foo\\tbar', 'http://www.example.com/foo\\tbar'), + array('http://www.example.com', '\\\\foo\\\\bar', 'http://www.example.com/\\\\foo\\\\bar'), + array('http://www.example.com', '/%7Ffp3%3Eju%3Dduvgw%3Dd', 'http://www.example.com/%7Ffp3%3Eju%3Dduvgw%3Dd'), + array('http://www.example.com', '/@asdf%40', 'http://www.example.com/@asdf%40'), + array('http://www.example.com:', 'as df', 'http://www.example.com:/as df'), + array('http://www.example.com:', '-2', 'http://www.example.com:/-2'), + array('http://www.example.com:', '80', 'http://www.example.com:/80'), + array('http://www.example.com:', '8080', 'http://www.example.com:/8080'), + array('http://www.example.com:', '', 'http://www.example.com:'), + array('http://www.example.com/?', 'foo=bar', 'http://www.example.com/foo=bar'), + array('http://www.example.com/?', 'as?df', 'http://www.example.com/as?df'), + array('http://www.example.com/?', '\\%02hello%7f bye', 'http://www.example.com/\\%02hello%7f bye'), + array('http://www.example.com/?', '%40%41123', 'http://www.example.com/%40%41123'), + array('http://www.example.com/?', 'q=<asdf>', 'http://www.example.com/q=<asdf>'), + array('http://www.example.com/?', 'q=\\"asdf\\"', 'http://www.example.com/q=\\"asdf\\"'), + array('http://host/a', '\\\\\\\\Another\\\\path', 'http://host/\\\\\\\\Another\\\\path'), + array('http://host/a', '/c:\\\\foo', 'http://host/c:\\\\foo'), + array('http://host/a', '//c:\\\\foo', 'http://c:\\\\foo'), + array('file:///C:/foo', 'http://host/', 'http://host/'), + array('file:///C:/foo', 'bar', 'file:///C:/bar'), + array('file:///C:/foo', '../../../bar.html', 'file:///bar.html'), + array('file:///C:/foo', '/../bar.html', 'file:///bar.html'), + array('http://host/a', '\\\\\\\\another\\\\path', 'http://host/\\\\\\\\another\\\\path'), + array('file:///C:/something', '//c:/foo', 'file://c:/foo'), + array('file:///C:/something', '//localhost/c:/foo', 'file://localhost/c:/foo'), + array('file:///C:/foo', 'c:', 'c:'), + array('file:///C:/foo', 'c:/foo', 'c:/foo'), + array('http://host/a', 'c:\\\\foo', 'c:\\\\foo'), + array('file:///C:/foo', '/z:/bar', 'file:///z:/bar'), + array('file:///C:/foo', '/bar', 'file:///bar'), + array('file://localhost/C:/foo', '/bar', 'file://localhost/bar'), + array('file:///C:/foo/com/', '/bar', 'file:///bar'), + array('file:///C:/something', '//somehost/path', 'file://somehost/path'), + array('file:///C:/something', '/\\\\//somehost/path', 'file:///\\\\//somehost/path'), + array('http://host/a', 'http://another/', 'http://another/'), + array('http://host/a', 'http:////another/', 'http:////another/'), + array('http://foo/bar', '', 'http://foo/bar'), + array('http://foo/bar#ref', '', 'http://foo/bar'), + array('http://foo/bar#', '', 'http://foo/bar'), + array('http://foo/bar', ' another ', 'http://foo/ another '), + array('http://foo/bar', ' . ', 'http://foo/ . '), + array('http://foo/bar', ' \\t', 'http://foo/ \\t'), + array('http://host/a', 'http:path', 'http:path'), + array('http://host/a/', 'http:path', 'http:path'), + array('http://host/a', 'http:/path', 'http:/path'), + array('http://host/a', 'HTTP:/path', 'HTTP:/path'), + array('http://host/a', 'https:host2', 'https:host2'), + array('http://host/a', 'htto:/host2', 'htto:/host2'), + array('http://host/a', '/b/c/d', 'http://host/b/c/d'), + array('http://host/a', '\\\\b\\\\c\\\\d', 'http://host/\\\\b\\\\c\\\\d'), + array('http://host/a', '/b/../c', 'http://host/c'), + array('http://host/a?b#c', '/b/../c', 'http://host/c'), + array('http://host/a', '\\\\b/../c?x#y', 'http://host/c?x#y'), + array('http://host/a?b#c', '/b/../c?x#y', 'http://host/c?x#y'), + array('http://host/a', 'b', 'http://host/b'), + array('http://host/a', 'bc/de', 'http://host/bc/de'), + array('http://host/a/', 'bc/de?query#ref', 'http://host/a/bc/de?query#ref'), + array('http://host/a/', '.', 'http://host/a/'), + array('http://host/a/', '..', 'http://host/'), + array('http://host/a/', './..', 'http://host/'), + array('http://host/a/', '../.', 'http://host/'), + array('http://host/a/', '././.', 'http://host/a/'), + array('http://host/a?query#ref', '../../../foo', 'http://host/foo'), + array('http://host/a', '?foo=bar', 'http://host/a?foo=bar'), + array('http://host/a?x=y#z', '?', 'http://host/a?'), + array('http://host/a?x=y#z', '?foo=bar#com', 'http://host/a?foo=bar#com'), + array('http://host/a', '#ref', 'http://host/a#ref'), + array('http://host/a#b', '#', 'http://host/a#'), + array('http://host/a?foo=bar#hello', '#bye', 'http://host/a?foo=bar#bye'), + array('data:foobar', 'baz.html', 'data:baz.html'), + array('data:foobar', 'data:baz', 'data:baz'), + array('data:foobar', 'data:/base', 'data:/base'), + array('data:foobar', 'http://host/', 'http://host/'), + array('data:foobar', 'http:host', 'http:host'), + array('http://foo/bar', './asd:fgh', 'http://foo/asd:fgh'), + array('http://foo/bar', ':foo', 'http://foo/:foo'), + array('http://foo/bar', ' hello world', 'http://foo/ hello world'), + array('data:asdf', ':foo', 'data::foo'), + array('http://host/a', ';foo', 'http://host/;foo'), + array('http://host/a;', ';foo', 'http://host/;foo'), + array('http://host/a', ';/../bar', 'http://host/bar'), + array('http://host/a', '//another', 'http://another'), + array('http://host/a', '//another/path?query#ref', 'http://another/path?query#ref'), + array('http://host/a', '///another/path', 'http:///another/path'), + array('http://host/a', '//Another\\\\path', 'http://Another\\\\path'), + array('http://host/a', '//', 'http://'), + array('http://host/a', '\\\\/another/path', 'http://host/\\\\/another/path'), + array('http://host/a', '/\\\\Another\\\\path', 'http://host/\\\\Another\\\\path'), + array('data:text/plain,baseURL', 'http://user:pass@foo:21/bar;par?b#c', 'http://user:pass@foo:21/bar;par?b#c'), + array('data:text/plain,baseURL', 'http:foo.com', 'http:foo.com'), + array('data:text/plain,baseURL', ' foo.com ', 'data:text/ foo.com '), + array('data:text/plain,baseURL', 'http://f:21/ b ? d # e ', 'http://f:21/ b ? d # e '), + array('data:text/plain,baseURL', 'http://f:/c', 'http://f:/c'), + array('data:text/plain,baseURL', 'http://f:0/c', 'http://f:0/c'), + array('data:text/plain,baseURL', 'http://f:00000000000000/c', 'http://f:00000000000000/c'), + array('data:text/plain,baseURL', 'http://f:00000000000000000000080/c', 'http://f:00000000000000000000080/c'), + array('data:text/plain,baseURL', 'http://f:b/c', 'http://f:b/c'), + array('data:text/plain,baseURL', 'http://f: /c', 'http://f: /c'), + array('data:text/plain,baseURL', 'http://f:fifty-two/c', 'http://f:fifty-two/c'), + array('data:text/plain,baseURL', 'http://f:999999/c', 'http://f:999999/c'), + array('data:text/plain,baseURL', 'http://f: 21 / b ? d # e ', 'http://f: 21 / b ? d # e '), + array('data:text/plain,baseURL', '', 'data:text/plain,baseURL'), + array('data:text/plain,baseURL', ':foo.com/', 'data:text/:foo.com/'), + array('data:text/plain,baseURL', ':foo.com\\\\', 'data:text/:foo.com\\\\'), + array('data:text/plain,baseURL', ':', 'data:text/:'), + array('data:text/plain,baseURL', ':a', 'data:text/:a'), + array('data:text/plain,baseURL', ':/', 'data:text/:/'), + array('data:text/plain,baseURL', ':\\\\', 'data:text/:\\\\'), + array('data:text/plain,baseURL', ':#', 'data:text/:#'), + array('data:text/plain,baseURL', '#', 'data:text/plain,baseURL#'), + array('data:text/plain,baseURL', '#/', 'data:text/plain,baseURL#/'), + array('data:text/plain,baseURL', '#\\\\', 'data:text/plain,baseURL#\\\\'), + array('data:text/plain,baseURL', '#;?', 'data:text/plain,baseURL#;?'), + array('data:text/plain,baseURL', '?', 'data:text/plain,baseURL?'), + array('data:text/plain,baseURL', '/', 'data:/'), + array('data:text/plain,baseURL', ':23', 'data:text/:23'), + array('data:text/plain,baseURL', '/:23', 'data:/:23'), + array('data:text/plain,baseURL', '//', 'data://'), + array('data:text/plain,baseURL', '::', 'data:text/::'), + array('data:text/plain,baseURL', '::23', 'data:text/::23'), + array('data:text/plain,baseURL', 'foo://', 'foo://'), + array('data:text/plain,baseURL', 'http://a:b@c:29/d', 'http://a:b@c:29/d'), + array('data:text/plain,baseURL', 'http::@c:29', 'http::@c:29'), + array('data:text/plain,baseURL', 'http://&a:foo(b]c@d:2/', 'http://&a:foo(b]c@d:2/'), + array('data:text/plain,baseURL', 'http://::@c@d:2', 'http://::@c@d:2'), + array('data:text/plain,baseURL', 'http://foo.com:b@d/', 'http://foo.com:b@d/'), + array('data:text/plain,baseURL', 'http://foo.com/\\\\@', 'http://foo.com/\\\\@'), + array('data:text/plain,baseURL', 'http:\\\\\\\\foo.com\\\\', 'http:\\\\\\\\foo.com\\\\'), + array('data:text/plain,baseURL', 'http:\\\\\\\\a\\\\b:c\\\\d@foo.com\\\\', 'http:\\\\\\\\a\\\\b:c\\\\d@foo.com\\\\'), + array('data:text/plain,baseURL', 'foo:/', 'foo:/'), + array('data:text/plain,baseURL', 'foo:/bar.com/', 'foo:/bar.com/'), + array('data:text/plain,baseURL', 'foo://///////', 'foo://///////'), + array('data:text/plain,baseURL', 'foo://///////bar.com/', 'foo://///////bar.com/'), + array('data:text/plain,baseURL', 'foo:////://///', 'foo:////://///'), + array('data:text/plain,baseURL', 'c:/foo', 'c:/foo'), + array('data:text/plain,baseURL', '//foo/bar', 'data://foo/bar'), + array('data:text/plain,baseURL', 'http://foo/path;a??e#f#g', 'http://foo/path;a??e#f#g'), + array('data:text/plain,baseURL', 'http://foo/abcd?efgh?ijkl', 'http://foo/abcd?efgh?ijkl'), + array('data:text/plain,baseURL', 'http://foo/abcd#foo?bar', 'http://foo/abcd#foo?bar'), + array('data:text/plain,baseURL', '[61:24:74]:98', '[61:24:74]:98'), + array('data:text/plain,baseURL', 'http://[61:27]:98', 'http://[61:27]:98'), + array('data:text/plain,baseURL', 'http:[61:27]/:foo', 'http:[61:27]/:foo'), + array('data:text/plain,baseURL', 'http://[1::2]:3:4', 'http://[1::2]:3:4'), + array('data:text/plain,baseURL', 'http://2001::1', 'http://2001::1'), + array('data:text/plain,baseURL', 'http://[2001::1', 'http://[2001::1'), + array('data:text/plain,baseURL', 'http://2001::1]', 'http://2001::1]'), + array('data:text/plain,baseURL', 'http://2001::1]:80', 'http://2001::1]:80'), + array('data:text/plain,baseURL', 'http://[2001::1]', 'http://[2001::1]'), + array('data:text/plain,baseURL', 'http://[2001::1]:80', 'http://[2001::1]:80'), + array('data:text/plain,baseURL', 'http://[[::]]', 'http://[[::]]'), + array('http://www.example.com/foo/bar', 'http://user:pass@foo:21/bar;par?b#c', 'http://user:pass@foo:21/bar;par?b#c'), + array('http://www.example.com/foo/bar', 'http:foo.com', 'http:foo.com'), + array('http://www.example.com/foo/bar', ' foo.com ', 'http://www.example.com/foo/ foo.com '), + array('http://www.example.com/foo/bar', 'http://f:21/ b ? d # e ', 'http://f:21/ b ? d # e '), + array('http://www.example.com/foo/bar', 'http://f:/c', 'http://f:/c'), + array('http://www.example.com/foo/bar', 'http://f:0/c', 'http://f:0/c'), + array('http://www.example.com/foo/bar', 'http://f:00000000000000/c', 'http://f:00000000000000/c'), + array('http://www.example.com/foo/bar', 'http://f:00000000000000000000080/c', 'http://f:00000000000000000000080/c'), + array('http://www.example.com/foo/bar', 'http://f:b/c', 'http://f:b/c'), + array('http://www.example.com/foo/bar', 'http://f: /c', 'http://f: /c'), + array('http://www.example.com/foo/bar', 'http://f:fifty-two/c', 'http://f:fifty-two/c'), + array('http://www.example.com/foo/bar', 'http://f:999999/c', 'http://f:999999/c'), + array('http://www.example.com/foo/bar', 'http://f: 21 / b ? d # e ', 'http://f: 21 / b ? d # e '), + array('http://www.example.com/foo/bar', '', 'http://www.example.com/foo/bar'), + array('http://www.example.com/foo/bar', ':foo.com/', 'http://www.example.com/foo/:foo.com/'), + array('http://www.example.com/foo/bar', ':foo.com\\\\', 'http://www.example.com/foo/:foo.com\\\\'), + array('http://www.example.com/foo/bar', ':', 'http://www.example.com/foo/:'), + array('http://www.example.com/foo/bar', ':a', 'http://www.example.com/foo/:a'), + array('http://www.example.com/foo/bar', ':/', 'http://www.example.com/foo/:/'), + array('http://www.example.com/foo/bar', ':\\\\', 'http://www.example.com/foo/:\\\\'), + array('http://www.example.com/foo/bar', ':#', 'http://www.example.com/foo/:#'), + array('http://www.example.com/foo/bar', '#', 'http://www.example.com/foo/bar#'), + array('http://www.example.com/foo/bar', '#/', 'http://www.example.com/foo/bar#/'), + array('http://www.example.com/foo/bar', '#\\\\', 'http://www.example.com/foo/bar#\\\\'), + array('http://www.example.com/foo/bar', '#;?', 'http://www.example.com/foo/bar#;?'), + array('http://www.example.com/foo/bar', '?', 'http://www.example.com/foo/bar?'), + array('http://www.example.com/foo/bar', '/', 'http://www.example.com/'), + array('http://www.example.com/foo/bar', ':23', 'http://www.example.com/foo/:23'), + array('http://www.example.com/foo/bar', '/:23', 'http://www.example.com/:23'), + array('http://www.example.com/foo/bar', '//', 'http://'), + array('http://www.example.com/foo/bar', '::', 'http://www.example.com/foo/::'), + array('http://www.example.com/foo/bar', '::23', 'http://www.example.com/foo/::23'), + array('http://www.example.com/foo/bar', 'foo://', 'foo://'), + array('http://www.example.com/foo/bar', 'http://a:b@c:29/d', 'http://a:b@c:29/d'), + array('http://www.example.com/foo/bar', 'http::@c:29', 'http::@c:29'), + array('http://www.example.com/foo/bar', 'http://&a:foo(b]c@d:2/', 'http://&a:foo(b]c@d:2/'), + array('http://www.example.com/foo/bar', 'http://::@c@d:2', 'http://::@c@d:2'), + array('http://www.example.com/foo/bar', 'http://foo.com:b@d/', 'http://foo.com:b@d/'), + array('http://www.example.com/foo/bar', 'http://foo.com/\\\\@', 'http://foo.com/\\\\@'), + array('http://www.example.com/foo/bar', 'http:\\\\\\\\foo.com\\\\', 'http:\\\\\\\\foo.com\\\\'), + array('http://www.example.com/foo/bar', 'http:\\\\\\\\a\\\\b:c\\\\d@foo.com\\\\', 'http:\\\\\\\\a\\\\b:c\\\\d@foo.com\\\\'), + array('http://www.example.com/foo/bar', 'foo:/', 'foo:/'), + array('http://www.example.com/foo/bar', 'foo:/bar.com/', 'foo:/bar.com/'), + array('http://www.example.com/foo/bar', 'foo://///////', 'foo://///////'), + array('http://www.example.com/foo/bar', 'foo://///////bar.com/', 'foo://///////bar.com/'), + array('http://www.example.com/foo/bar', 'foo:////://///', 'foo:////://///'), + array('http://www.example.com/foo/bar', 'c:/foo', 'c:/foo'), + array('http://www.example.com/foo/bar', '//foo/bar', 'http://foo/bar'), + array('http://www.example.com/foo/bar', 'http://foo/path;a??e#f#g', 'http://foo/path;a??e#f#g'), + array('http://www.example.com/foo/bar', 'http://foo/abcd?efgh?ijkl', 'http://foo/abcd?efgh?ijkl'), + array('http://www.example.com/foo/bar', 'http://foo/abcd#foo?bar', 'http://foo/abcd#foo?bar'), + array('http://www.example.com/foo/bar', '[61:24:74]:98', '[61:24:74]:98'), + array('http://www.example.com/foo/bar', 'http://[61:27]:98', 'http://[61:27]:98'), + array('http://www.example.com/foo/bar', 'http:[61:27]/:foo', 'http:[61:27]/:foo'), + array('http://www.example.com/foo/bar', 'http://[1::2]:3:4', 'http://[1::2]:3:4'), + array('http://www.example.com/foo/bar', 'http://2001::1', 'http://2001::1'), + array('http://www.example.com/foo/bar', 'http://[2001::1', 'http://[2001::1'), + array('http://www.example.com/foo/bar', 'http://2001::1]', 'http://2001::1]'), + array('http://www.example.com/foo/bar', 'http://2001::1]:80', 'http://2001::1]:80'), + array('http://www.example.com/foo/bar', 'http://[2001::1]', 'http://[2001::1]'), + array('http://www.example.com/foo/bar', 'http://[2001::1]:80', 'http://[2001::1]:80'), + array('http://www.example.com/foo/bar', 'http://[[::]]', 'http://[[::]]'), + array('http://example.org/foo/bar', 'http://example.com/', 'http://example.com/'), + array('http://example.org/foo/bar', 'http://example.com/', 'http://example.com/'), + array('http://example.org/foo/bar', '/', 'http://example.org/'), + array('http://iris.test.ing/', '?value= foo bar', 'http://iris.test.ing/?value= foo bar'), + array('http://user%40', 'example.com', 'http://user%40/example.com'), + array('http://user%3Ainfo%40', 'example.com', 'http://user%3Ainfo%40/example.com'), + array('http://user@', 'example.com', 'http://user@/example.com'), + array('http://user:info@', 'example.com', 'http://user:info@/example.com') + ); + } + + /** + * Test conversion to relative IRI reference + * + * @param string $iri The reference IRI to convert to a + * relative reference. + * @param string $base The base IRI. + * @param bool $schemaRelative Should schema-relative IRIs be created? + * @param string $expected The expected IRI reference. + * + * @dataProvider relativizeProvider + */ + public function testRelativize($iri, $base, $schemaRelative, $expected) + { + $iri = new IRI($iri); + $this->assertEquals($expected, (string)$iri->relativeTo($base, $schemaRelative)); + + $base = new IRI($base); + $this->assertEquals($expected, (string)$base->baseFor((string)$iri, $schemaRelative)); + } + + /** + * Conversion to relative IRI reference test cases + * + * These test cases are adaptations of the tests in + * {@link http://dig.csail.mit.edu/2005/ajar/ajaw/test/uri-test-doc.html}. + * + * @return array The test cases. + */ + public function relativizeProvider() + { + return array( // $iri, $base, $schemaRelative, $expected + array('http://ex/x/y/z', 'http://ex/x/y/z', false, 'z'), + array('https://example.com/x/y/z', 'http://example.com/x/y/z', false, 'https://example.com/x/y/z'), + array('http://example.com/x/y/z/', 'http://example.com/x/y/z/', false, './'), + array('http://example.com/x/y/z/?query', 'http://example.com/x/y/z/', false, '?query'), + array('http://example.com/x/y/z/#fragment', 'http://example.com/x/y/z/', false, '#fragment'), + array('http://example.com/x/y/z', 'http://example.com/x/y/z', false, 'z'), + array('http://example.com/x/y/z?query', 'http://example.com/x/y/z', false, '?query'), + array('http://example.com/x/y/z#fragment', 'http://example.com/x/y/z', false, '#fragment'), + array('http://example.com/x/y/z:a', 'http://example.com/x/y/', false, './z:a'), + array('http://example.com/x/y/z', 'http://example.com/x/y', false, 'y/z'), + array('http://example.com/x/y/z', 'http://example.com/a/b/c', false, '../../x/y/z'), + array('http://example.com/x/y/z?query', 'http://example.com/a/b/c', false, '../../x/y/z?query'), + array('http://example.com/x/y/z#fragment', 'http://example.com/a/b/c', false, '../../x/y/z#fragment'), + array('http://example.com/x/y/z?query#fragment', 'http://example.com/a/b/c', false, '../../x/y/z?query#fragment'), + array('http://example.org/x/y/z', 'http://example.com/a/b/c', false, 'http://example.org/x/y/z'), + array('http://example.org/x/y/z', 'http://example.com/a/b/c', true, '//example.org/x/y/z'), + array('http://example/x/abc', 'http://example/x/y/z', false, '../abc'), + array('file:/ex/x/q/r#s', 'file:/ex/x/y', false, 'q/r#s'), + array('http://ex/x/y', null, false, 'http://ex/x/y'), + array('http://example.com/a', 'http://example.com/a/', false, '../a'), + array('http://example.com/a', 'http://example.com/a/b', false, '../a'), + array('http://example.com/a/b/c?query', 'http://example.com/a/b/c?query', false, '?query'), + array('http://ex/r', 'http://ex/x/y/z', false, '../../r'), + // http://dig.csail.mit.edu/2005/ajar/ajaw/test/uri-test-doc.html + array('bar:abc', 'foo:xyz', false, 'bar:abc'), + array('http://example/x/abc', 'http://example/x/y/z', false, '../abc'), + array('http://example/x/abc', 'http://example2/x/y/z', false, 'http://example/x/abc'), + array('http://example/x/abc', 'http://example2/x/y/z', true, '//example/x/abc'), + array('http://ex/x/r', 'http://ex/x/y/z', false, '../r'), + array('http://ex/x/q/r', 'http://ex/x/y', false, 'q/r'), + array('http://ex/x/q/r#s', 'http://ex/x/y', false, 'q/r#s'), + array('http://ex/x/q/r#s/t', 'http://ex/x/y', false, 'q/r#s/t'), + array('ftp://ex/x/q/r', 'http://ex/x/y', false, 'ftp://ex/x/q/r'), + array('http://ex/x/y/z/', 'http://ex/x/y', false, 'y/z/'), + array('file:/swap/test/animal.rdf#Animal', 'file:/swap/test/animal.rdf', false, '#Animal'), + array('file:/e/x/abc', 'file:/e/x/y/z', false, '../abc'), + array('file:/example/x/abc', 'file:/example2/x/y/z', false, '../../../example/x/abc'), + array('file:/ex/x/r', 'file:/ex/x/y/z', false, '../r'), + array('file:/r', 'file:/ex/x/y/z', false, '../../../r'), + array('file:/ex/x/q/r', 'file:/ex/x/y/z', false, '../q/r'), + array('file:/ex/x/q/r#s', 'file:/ex/x/y', false, 'q/r#s'), + array('file:/ex/x/q/r#', 'file:/ex/x/y', false, 'q/r#'), + array('file:/ex/x/q/r#s/t', 'file:/ex/x/y', false, 'q/r#s/t'), + array('ftp://ex/x/q/r', 'file:/ex/x/y', false, 'ftp://ex/x/q/r'), + array('file:/ex/x/y/z/', 'file:/ex/x/y/', false, 'z/'), + array('file://meetings.example.com/cal#m1', 'file:/devel/WWW/2000/10/swap/test/reluri-1.n3', false, 'file://meetings.example.com/cal#m1'), + array('file://meetings.example.com/cal#m1', 'file:/devel/WWW/2000/10/swap/test/reluri-1.n3', true, '//meetings.example.com/cal#m1'), + array('file://meetings.example.com/cal#m1', 'file:/home/connolly/w3ccvs/WWW/2000/10/swap/test/reluri-1.n3', false, 'file://meetings.example.com/cal#m1'), + array('file://meetings.example.com/cal#m1', 'file:/home/connolly/w3ccvs/WWW/2000/10/swap/test/reluri-1.n3', true, '//meetings.example.com/cal#m1'), + array('file:/some/dir/#blort', 'file:/some/dir/foo', false, './#blort'), + array('file:/some/dir/#', 'file:/some/dir/foo', false, './#'), + array('http://example/x/abc', 'http://example/x/y%2Fz', false, 'abc'), + array('http://example/x%2Fabc', 'http://example/x/y/z', false, '../../x%2Fabc'), + array('http://example/x%2Fabc', 'http://example/x/y%2Fz', false, '../x%2Fabc'), + array('http://example/x%2Fy/abc', 'http://example/x%2Fy/z', false, 'abc'), + array('http://example/x/', 'http://example/x/abc.efg', false, './'), // ??? + array('http://www.w3.org/2002/01/tr-automation/tr.rdf', 'http://www.w3.org/People/Berners-Lee/card.rdf', false, '../../2002/01/tr-automation/tr.rdf'), + ); + } + + /** + * Invalid IRI test cases + * + * These test cases were taken from + * {@link http://www.ninebynine.org/Software/HaskellUtils/Network/URITestDescriptions.html}. + * + * @return array The invalid IRI test cases. + */ + public function invalidIriProvider() + { + return array( + array('[2010:836B:4179::836B:4179]'), + array('http://foo.org:80Path/More'), + array('::'), + array(' '), // is this an invalid IRI?? + array('%'), + array('A%Z'), + array('%ZZ'), + array('%AZ'), + array('A C'), + array('A\C"'), + array('A`C'), + array('AC'), + array('A^C'), + array('A\\C'), + array('A{C'), + array('A|C'), + array('A}C'), + array('A[C'), + array('A]C'), + array('A[**]C'), + array('http://[xyz]/'), + array('http://]/'), + array('http://example.org/[2010:836B:4179::836B:4179]'), + array('http://example.org/abc#[2010:836B:4179::836B:4179]'), + array('http://example.org/xxx/[qwerty]#a[b]'), + array('http://example.org/xxx/qwerty#a#b'), + array('http://user:pass@example.org:99aaa/bbb') + ); + } + + /** + * Normalization test cases + * + * These test cases were taken from + * {@link http://www.ninebynine.org/Software/HaskellUtils/Network/URITestDescriptions.html}. + * + * @return array The normalization test cases. + */ + public function normalizationProvider() + { + return array( + // Case normalization; cf. RFC3986 section 6.2.2.1 (NOTE: authority case normalization is not performed) + array('HTTP://EXAMPLE.com/Root/%2a?%2b#%2c', 'http://EXAMPLE.com/Root/%2A?%2B#%2C'), + // Encoding normalization; cf. RFC3986 section 6.2.2.2 + array('HTTP://EXAMPLE.com/Root/%7eMe/', 'HTTP://EXAMPLE.com/Root/~Me/'), + array('foo:%40%41%5a%5b%60%61%7a%7b%2f%30%39%3a%2d%2e%5f%7e', 'foo:%40AZ%5b%60az%7b%2f09%3a-._~'), + array('foo:%3a%2f%3f%23%5b%5d%40', 'foo:%3a%2f%3f%23%5b%5d%40'), + // Path segment normalization; cf. RFC3986 section 6.2.2.3 + array('http://example/a/b/../../c', 'http://example/c'), + array('http://example/a/b/c/../../', 'http://example/a/'), + array('http://example/a/b/c/./', 'http://example/a/b/c/'), + array('http://example/a/b/c/.././', 'http://example/a/b/'), + array('http://example/a/b/c/d/../../../../e', 'http://example/e'), + array('http://example/a/b/c/d/../.././../../e', 'http://example/e'), + array('http://example/a/b/../.././../../e', 'http://example/e'), + array('foo:a/b/../.././../../e', 'foo:e') + ); + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/Test/bootstrap.php b/Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/Test/bootstrap.php new file mode 100644 index 0000000..ef2301b --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/Test/bootstrap.php @@ -0,0 +1,12 @@ +=5.3.0", + "lib-pcre": ">=4.0" + }, + "autoload": { + "psr-0": { "ML\\IRI": "" } + }, + "target-dir": "ML/IRI" +} diff --git a/Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/phpunit.xml.dist b/Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/phpunit.xml.dist new file mode 100644 index 0000000..efab2c4 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/iri/ML/IRI/phpunit.xml.dist @@ -0,0 +1,32 @@ + + + + + + ./Test/ + + + + + + ./ + + ./Test + + + + + + + + + diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/.devcontainer/Dockerfile b/Resources/Private/PHP/embed/vendor/ml/json-ld/.devcontainer/Dockerfile new file mode 100644 index 0000000..e3fc24d --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/.devcontainer/Dockerfile @@ -0,0 +1,16 @@ +# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/php/.devcontainer/base.Dockerfile + +# [Choice] PHP version (use -bullseye variants on local arm64/Apple Silicon): 8, 8.1, 8.0, 7, 7.4, 7.3, 8-bullseye, 8.1-bullseye, 8.0-bullseye, 7-bullseye, 7.4-bullseye, 7.3-bullseye, 8-buster, 8.1-buster, 8.0-buster, 7-buster, 7.4-buster +ARG VARIANT="8.1-apache-bullseye" +FROM mcr.microsoft.com/vscode/devcontainers/php:0-${VARIANT} + +# [Choice] Node.js version: none, lts/*, 16, 14, 12, 10 +ARG NODE_VERSION="none" +RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi + +# Enables Xdebug code coverage analysis to generate code coverage reports, mainly in combination with PHPUnit. +RUN echo "xdebug.mode = coverage" >> /usr/local/etc/php/conf.d/xdebug.ini \ + && echo "xdebug.start_with_request = trigger" >> /usr/local/etc/php/conf.d/xdebug.ini + +# [Optional] Uncomment this line to install global node packages. +# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g " 2>&1 diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/.devcontainer/devcontainer.json b/Resources/Private/PHP/embed/vendor/ml/json-ld/.devcontainer/devcontainer.json new file mode 100644 index 0000000..5476a00 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/.devcontainer/devcontainer.json @@ -0,0 +1,46 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: +// https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/php +{ + "name": "PHP", + "build": { + "dockerfile": "Dockerfile", + "args": { + // Update VARIANT to pick a PHP version: 8, 8.1, 8.0, 7, 7.4 + // Append -bullseye or -buster to pin to an OS version. + // Use -bullseye variants on local on arm64/Apple Silicon. + "VARIANT": "7.4", + "NODE_VERSION": "lts/*" + } + }, + + // Configure tool-specific properties. + "customizations": { + // Configure properties specific to VS Code. + "vscode": { + // Set *default* container specific settings.json values on container create. + "settings": { + "php.validate.executablePath": "/usr/local/bin/php", + "debug.console.collapseIdenticalLines": false + }, + + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "xdebug.php-debug", + "bmewburn.vscode-intelephense-client", + "mrmlnc.vscode-apache" + ] + } + }, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + "forwardPorts": [8080], + + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "sudo chmod a+x \"$(pwd)\" && sudo rm -rf /var/www/html && sudo ln -s \"$(pwd)\" /var/www/html" + + // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. + "remoteUser": "vscode", + "features": { + "git": "os-provided" + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/.github/workflows/ci.yaml b/Resources/Private/PHP/embed/vendor/ml/json-ld/.github/workflows/ci.yaml new file mode 100644 index 0000000..8189752 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/.github/workflows/ci.yaml @@ -0,0 +1,43 @@ +name: Continuous integration + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + ci: + runs-on: ubuntu-latest + + env: + extensions: intl, mbstring, xdebug + + strategy: + matrix: + php-version: + - "5.3" + - "5.4" + - "5.5" + - "5.6" + - "7.0" + - "7.1" + - "7.2" + - "7.3" + - "7.4" + + steps: + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + php-version: "${{ matrix.php-version }}" + extensions: "${{ env.extensions }}" + ini-values: "memory_limit=-1, error_reporting=E_ALL, display_errors=On" + coverage: xdebug + tools: composer + - name: Checkout code + uses: actions/checkout@v3 + - name: Download dependencies + run: composer update --no-interaction --no-progress + - name: Run tests + run: vendor/bin/phpunit diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/.gitignore b/Resources/Private/PHP/embed/vendor/ml/json-ld/.gitignore new file mode 100644 index 0000000..777eafd --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/.gitignore @@ -0,0 +1,4 @@ +/vendor +/composer.lock +/phpunit.xml +/earl-report.jsonld diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/.vscode/launch.json b/Resources/Private/PHP/embed/vendor/ml/json-ld/.vscode/launch.json new file mode 100644 index 0000000..7febb3c --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/.vscode/launch.json @@ -0,0 +1,29 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Listen for Xdebug", + "type": "php", + "request": "launch", + "port": 9000 + }, + { + "name": "Run tests", + "type": "php", + "request": "launch", + "program": "${workspaceFolder}/vendor/bin/phpunit", + "cwd": "${workspaceFolder}", + "port": 9000, + "runtimeArgs": [ + "-dxdebug.start_with_request=yes" + ], + "env": { + "XDEBUG_MODE": "debug,develop,coverage", + "XDEBUG_CONFIG": "client_port=${port}" + } + } + ] +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/DefaultDocumentFactory.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/DefaultDocumentFactory.php new file mode 100644 index 0000000..50a33e4 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/DefaultDocumentFactory.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +/** + * DefaultDocumentFactory creates new Documents + * + * @see Document + * + * @author Markus Lanthaler + */ +class DefaultDocumentFactory implements DocumentFactoryInterface +{ + /** + * {@inheritdoc} + */ + public function createDocument($iri = null) + { + return new Document($iri); + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Document.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/Document.php new file mode 100644 index 0000000..4cfb403 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Document.php @@ -0,0 +1,206 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +use stdClass as JsonObject; +use ML\IRI\IRI; + +/** + * A Document represents a JSON-LD document. + * + * Named graphs are not supported yet. + * + * @author Markus Lanthaler + */ +class Document implements DocumentInterface, JsonLdSerializable +{ + /** + * @var IRI The document's IRI + */ + protected $iri = null; + + /** + * @var GraphInterface The default graph + */ + protected $defaultGraph = null; + + /** + * @var array An associative array holding all named graphs in the document + */ + protected $namedGraphs = array(); + + /** + * Parses a JSON-LD document and returns it as a Document + * + * The document can be supplied directly as a string or by passing a + * file path or an IRI. + * + * Usage: + * + * $document = Document::load('document.jsonld'); + * + * + * Please note that currently all data is merged into the + * default graph, named graphs are not supported yet! + * + * It is possible to configure the processing by setting the options + * parameter accordingly. Available options are: + * + * - base The base IRI of the input document. + * + * @param string|array|JsonObject $document The JSON-LD document to process. + * @param null|array|JsonObject $options Options to configure the processing. + * + * @return Document The parsed JSON-LD document. + * + * @throws ParseException If the JSON-LD input document is invalid. + */ + public static function load($document, $options = null) + { + return JsonLD::getDocument($document, $options); + } + + /** + * Constructor + * + * @param null|string|IRI $iri The document's IRI + */ + public function __construct($iri = null) + { + $this->iri = new IRI($iri); + $this->defaultGraph = new Graph($this); + } + + /** + * {@inheritdoc} + */ + public function setIri($iri) + { + $this->iri = new IRI($iri); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getIri($asObject = false) + { + return ($asObject) ? $this->iri : (string) $this->iri; + } + + /** + * {@inheritdoc} + */ + public function createGraph($name) + { + $name = (string) $this->iri->resolve($name); + + if (isset($this->namedGraphs[$name])) { + return $this->namedGraphs[$name]; + } + + return $this->namedGraphs[$name] = new Graph($this, $name); + } + + /** + * {@inheritdoc} + */ + public function getGraph($name = null) + { + if (null === $name) { + return $this->defaultGraph; + } + + $name = (string) $this->iri->resolve($name); + + return isset($this->namedGraphs[$name]) + ? $this->namedGraphs[$name] + : null; + } + + /** + * {@inheritdoc} + */ + public function getGraphNames() + { + return array_keys($this->namedGraphs); + } + + /** + * {@inheritdoc} + */ + public function containsGraph($name) + { + $name = (string) $this->iri->resolve($name); + + return isset($this->namedGraphs[$name]); + } + + /** + * {@inheritdoc} + */ + public function removeGraph($graph = null) + { + // The default graph can't be "removed", it can just be reset + if (null === $graph) { + $this->defaultGraph = new Graph($this); + + return $this; + } + + + if ($graph instanceof GraphInterface) { + foreach ($this->namedGraphs as $n => $g) { + if ($g === $graph) { + $name = $n; + break; + } + } + } else { + $name = (string) $this->iri->resolve($graph); + } + + if (isset($this->namedGraphs[$name])) { + if ($this->namedGraphs[$name]->getDocument() === $this) { + $this->namedGraphs[$name]->removeFromDocument(); + } + + unset($this->namedGraphs[$name]); + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function toJsonLd($useNativeTypes = true) + { + $defGraph = $this->defaultGraph->toJsonLd($useNativeTypes); + + if (0 === count($this->namedGraphs)) { + return $defGraph; + } + + foreach ($this->namedGraphs as $graphName => $graph) { + $namedGraph = new JsonObject(); + $namedGraph->{'@id'} = $graphName; + $namedGraph->{'@graph'} = $graph->toJsonLd($useNativeTypes); + + $defGraph[] = $namedGraph; + } + + $document = new JsonObject(); + $document->{'@graph'} = $defGraph; + + return array($document); + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/DocumentFactoryInterface.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/DocumentFactoryInterface.php new file mode 100644 index 0000000..1452ce1 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/DocumentFactoryInterface.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +/** + * Interface for factories to create DocumentInterface objects + * + * @see DocumentInterface + * + * @author Markus Lanthaler + */ +interface DocumentFactoryInterface +{ + /** + * Creates a new document + * + * @param null|string $iri The document's IRI. + * + * @return DocumentInterface The document. + */ + public function createDocument($iri = null); +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/DocumentInterface.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/DocumentInterface.php new file mode 100644 index 0000000..965fb1d --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/DocumentInterface.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +use ML\IRI\IRI; + +/** + * JSON-LD document interface + * + * @author Markus Lanthaler + */ +interface DocumentInterface +{ + /** + * Set the document's IRI + * + * @param string|IRI The IRI. + * + * @return self + */ + public function setIri($iri); + + /** + * Get the document's IRI + * + * @param boolean $asObject If set to true, the return value will be an + * {@link IRI} object; otherwise a string. + * + * @return string|IRI The document's IRI (might be empty). + */ + public function getIri($asObject = false); + + /** + * Creates a new graph which is linked to this document + * + * If there exists already a graph with the passed name in the document, + * that graph will be returned instead of creating a new one. + * + * @param string|IRI $name The graph's name. + * + * @return GraphInterface The newly created graph. + */ + public function createGraph($name); + + /** + * Get a graph by name + * + * @param null|string $name The name of the graph to retrieve. If null + * is passed, the default will be returned. + * + * @return GraphInterface|null Returns the graph if found; null otherwise. + */ + public function getGraph($name = null); + + /** + * Get graph names + * + * @return string[] Returns the names of all graphs in the document. + */ + public function getGraphNames(); + + /** + * Check whether the document contains a graph with the specified name + * + * @param string $name The graph name. + * + * @return bool Returns true if the document contains a graph with the + * specified name; false otherwise. + */ + public function containsGraph($name); + + /** + * Removes a graph from the document + * + * @param null|string|GraphInterface $graph The graph (or its name) to + * remove. If null is passed, + * the default will be reset. + * + * @return self + */ + public function removeGraph($graph = null); +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/DocumentLoaderInterface.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/DocumentLoaderInterface.php new file mode 100644 index 0000000..cf6f78b --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/DocumentLoaderInterface.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +use ML\JsonLD\Exception\JsonLdException; + +/** + * Interface for (remote) document loaders + * + * @author Markus Lanthaler + */ +interface DocumentLoaderInterface +{ + /** + * Load a (remote) document or context + * + * @param string $url The URL or path of the document to load. + * + * @return RemoteDocument The loaded document. + * + * @throws JsonLdException + */ + public function loadDocument($url); +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Exception/InvalidQuadException.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/Exception/InvalidQuadException.php new file mode 100644 index 0000000..9d9db9c --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Exception/InvalidQuadException.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD\Exception; + +use ML\JsonLD\Quad; + +/** + * Exception that is thrown when an invalid quad is detected. + * + * @author Markus Lanthaler + */ +class InvalidQuadException extends \RuntimeException +{ + /** + * The quad that triggered this exception + * + * @var Quad + */ + private $quad; + + /** + * Constructor. + * + * @param string $message The error message + * @param Quad $quad The quad + * @param null|\Exception $previous The previous exception + */ + public function __construct($message, $quad, \Exception $previous = null) + { + $this->quad = $quad; + + parent::__construct($this->message, 0, $previous); + } + + /** + * Gets the quad + * + * @return Quad The quad. + */ + public function getQuad() + { + return $this->quad; + } + + /** + * Sets the quad + * + * @param Quad $quad The quad. + */ + public function setQuad($quad) + { + $this->quad = $quad; + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Exception/JsonLdException.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/Exception/JsonLdException.php new file mode 100644 index 0000000..6638301 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Exception/JsonLdException.php @@ -0,0 +1,307 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD\Exception; + +use ML\JsonLD\JsonLD; + +/** + * Exception class thrown when an error occurs during parsing. + * + * @author Markus Lanthaler + */ +class JsonLdException extends \RuntimeException +{ + /** + * An unspecified error code (none was standardized yet) + */ + const UNSPECIFIED = 'unknown'; + + /** + * The document could not be loaded or parsed as JSON. + */ + const LOADING_DOCUMENT_FAILED = "loading document failed"; + + /** + * A list of lists was detected. List of lists are not supported in + * this version of JSON-LD due to the algorithmic complexity. + */ + const LIST_OF_LISTS = "list of lists"; + + /** + * An @index member was encountered whose value was not a string. + */ + const INVALID_INDEX_VALUE = "invalid @index value"; + + /** + * Multiple conflicting indexes have been found for the same node. + */ + const CONFLICTING_INDEXES = "conflicting indexes"; + + /** + * An @id member was encountered whose value was not a string. + */ + const INVALID_ID_VALUE = "invalid @id value"; + + /** + * In invalid local context was detected. + */ + const INVALID_LOCAL_CONTEXT = "invalid local context"; + + /** + * Multiple HTTP Link Headers [RFC5988] using th + * http://www.w3.org/ns/json-ld#context link relation have been detected. + */ + const MULTIPLE_CONTEXT_LINK_HEADERS = "multiple context link headers"; + + /** + * There was a problem encountered loading a remote context. + */ + const LOADING_REMOTE_CONTEXT_FAILED = "loading remote context failed"; + + /** + * No valid context document has been found for a referenced, + * remote context. + */ + const INVALID_REMOTE_CONTEXT = "invalid remote context"; + + /** + * A cycle in remote context inclusions has been detected. + */ + const RECURSIVE_CONTEXT_INCLUSION = "recursive context inclusion"; + + /** + * An invalid base IRI has been detected, i.e., it is neither an + * absolute IRI nor null. + */ + const INVALID_BASE_IRI = "invalid base IRI"; + + /** + * An invalid vocabulary mapping has been detected, i.e., it is + * neither an absolute IRI nor null. + */ + const INVALID_VOCAB_MAPPING = "invalid vocab mapping"; + + /** + * The value of the default language is not a string or null and + * thus invalid. + */ + const INVALID_DEFAULT_LANGUAGE = "invalid default language"; + + /** + * A keyword redefinition has been detected. + */ + const KEYWORD_REDEFINITION = "keyword redefinition"; + + /** + * An invalid term definition has been detected. + */ + const INVALID_TERM_DEFINITION = "invalid term definition"; + + /** + * An invalid reverse property definition has been detected. + */ + const INVALID_REVERSE_PROPERTY = "invalid reverse property"; + + /** + * IRI mapping A local context contains a term that has an invalid + * or missing IRI mapping. + */ + const INVALID_IRI_MAPPING = "invalid IRI mapping"; + + /** + * IRI mapping A cycle in IRI mappings has been detected. + */ + const CYCLIC_IRI_MAPPING = "cyclic IRI mapping"; + + /** + * An invalid keyword alias definition has been encountered. + */ + const INVALID_KEYWORD_ALIAS = "invalid keyword alias"; + + /** + * An @type member in a term definition was encountered whose value + * could not be expanded to an absolute IRI. + */ + const INVALID_TYPE_MAPPING = "invalid type mapping"; + + /** + * An @language member in a term definition was encountered whose + * value was neither a string nor null and thus invalid. + */ + const INVALID_LANGUAGE_MAPPING = "invalid language mapping"; + + /** + * Two properties which expand to the same keyword have been detected. + * This might occur if a keyword and an alias thereof are used at the + * same time. + */ + const COLLIDING_KEYWORDS = "colliding keywords"; + + /** + * An @container member was encountered whose value was not one of + * the following strings: @list, @set, or @index. + */ + const INVALID_CONTAINER_MAPPING = "invalid container mapping"; + + /** + * An invalid value for an @type member has been detected, i.e., the + * value was neither a string nor an array of strings. + */ + const INVALID_TYPE_VALUE = "invalid type value"; + + /** + * A value object with disallowed members has been detected. + */ + const INVALID_VALUE_OBJECT = "invalid value object"; + + /** + * An invalid value for the @value member of a value object has been + * detected, i.e., it is neither a scalar nor null. + */ + const INVALID_VALUE_OBJECT_VALUE = "invalid value object value"; + + /** + * A language-tagged string with an invalid language value was detected. + */ + const INVALID_LANGUAGE_TAGGED_STRING = "invalid language-tagged string"; + + /** + * A number, true, or false with an associated language tag was detected. + */ + const INVALID_LANGUAGE_TAGGED_VALUE = "invalid language-tagged value"; + + /** + * A typed value with an invalid type was detected. + */ + const INVALID_TYPED_VALUE = "invalid typed value"; + + /** + * A set object or list object with disallowed members has been detected. + */ + const INVALID_SET_OR_LIST_OBJECT = "invalid set or list object"; + + /** + * An invalid value in a language map has been detected. It has to be + * a string or an array of strings. + */ + const INVALID_LANGUAGE_MAP_VALUE = "invalid language map value"; + + /** + * The compacted document contains a list of lists as multiple lists + * have been compacted to the same term. + */ + const COMPACTION_TO_LIST_OF_LISTS = "compaction to list of lists"; + + /** + * An invalid reverse property map has been detected. No keywords apart + * from @context are allowed in reverse property maps. + */ + const INVALID_REVERSE_PROPERTY_MAP = "invalid reverse property map"; + + /** + * An invalid value for an @reverse member has been detected, i.e., the + * value was not a JSON object. + */ + const INVALID_REVERSE_VALUE = "invalid @reverse value"; + + /** + * An invalid value for a reverse property has been detected. The value + * of an inverse property must be a node object. + */ + const INVALID_REVERSE_PROPERTY_VALUE = "invalid reverse property value"; + + /** + * The JSON-LD snippet that triggered the error + * + * @var null|string + */ + private $snippet; + + /** + * The document that triggered the error + * + * @var null|string + */ + private $document; + + /** + * The raw error message (containing place-holders) + * + * @var string + */ + private $rawMessage; + + /** + * Constructor. + * + * @param string $code The error code + * @param null|string $message The error message + * @param null|mixed $snippet The code snippet + * @param null|string $document The document that triggered the error + * @param null|\Exception $previous The previous exception + */ + public function __construct($code, $message = null, $snippet = null, $document = null, \Exception $previous = null) + { + $this->code = $code; + $this->document = $document; + $this->snippet = ($snippet) ? JsonLD::toString($snippet) : $snippet; + $this->rawMessage = $message; + + $this->updateMessage(); + + parent::__construct($this->message, 0, $previous); + } + + /** + * Gets the snippet of code near the error. + * + * @return null|string The snippet of code + */ + public function getSnippet() + { + return $this->snippet; + } + + /** + * Gets the document that triggered the error + * + * @return null|string The document that triggered the error + */ + public function getParsedFile() + { + return $this->document; + } + + /** + * Updates the exception message by including the file name if available. + */ + private function updateMessage() + { + $this->message = $this->rawMessage; + + $dot = false; + if ('.' === substr($this->message, -1)) { + $this->message = substr($this->message, 0, -1); + $dot = true; + } + + if (null !== $this->document) { + $this->message .= sprintf(' in %s', $this->document); + } + + if ($this->snippet) { + $this->message .= sprintf(' (near %s)', $this->snippet); + } + + if ($dot) { + $this->message .= '.'; + } + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/FileGetContentsLoader.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/FileGetContentsLoader.php new file mode 100644 index 0000000..42deee4 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/FileGetContentsLoader.php @@ -0,0 +1,197 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +use ML\JsonLD\Exception\JsonLdException; +use ML\IRI\IRI; + +/** + * The FileGetContentsLoader loads remote documents by calling file_get_contents + * + * @author Markus Lanthaler + */ +class FileGetContentsLoader implements DocumentLoaderInterface +{ + /** + * {@inheritdoc} + */ + public function loadDocument($url) + { + // if input looks like a file, try to retrieve it + $input = trim($url); + if (false === (isset($input[0]) && ("{" === $input[0]) || ("[" === $input[0]))) { + $remoteDocument = new RemoteDocument($url); + + $streamContextOptions = array( + 'method' => 'GET', + 'header' => "Accept: application/ld+json, application/json; q=0.9, */*; q=0.1\r\n" + . "User-Agent: lanthaler JsonLD\r\n", + 'timeout' => Processor::REMOTE_TIMEOUT + ); + + $context = stream_context_create(array( + 'http' => $streamContextOptions, + 'https' => $streamContextOptions + )); + + $httpHeadersOffset = 0; + + stream_context_set_params($context, array('notification' => + function ($code, $severity, $msg, $msgCode, $bytesTx, $bytesMax) use ( + &$remoteDocument, &$http_response_header, &$httpHeadersOffset + ) { + if ($code === STREAM_NOTIFY_MIME_TYPE_IS) { + $remoteDocument->mediaType = $msg; + } elseif ($code === STREAM_NOTIFY_REDIRECTED) { + $remoteDocument->documentUrl = $msg; + $remoteDocument->mediaType = null; + + $httpHeadersOffset = isset($http_response_header) ? count($http_response_header) : 0; + } + } + )); + + if (false === ($input = @file_get_contents($url, false, $context))) { + throw new JsonLdException( + JsonLdException::LOADING_DOCUMENT_FAILED, + sprintf('Unable to load the remote document "%s".', $url), + $http_response_header + ); + } + + // Extract HTTP Link headers + $linkHeaderValues = array(); + if (is_array($http_response_header)) { + for ($i = count($http_response_header) - 1; $i > $httpHeadersOffset; $i--) { + if (0 === substr_compare($http_response_header[$i], 'Link:', 0, 5, true)) { + $value = substr($http_response_header[$i], 5); + $linkHeaderValues[] = $value; + } + } + } + + $linkHeaderValues = $this->parseLinkHeaders($linkHeaderValues, new IRI($url)); + + $contextLinkHeaders = array_filter($linkHeaderValues, function ($link) { + return (isset($link['rel']) + && in_array('http://www.w3.org/ns/json-ld#context', explode(' ', $link['rel']))); + }); + + if (count($contextLinkHeaders) === 1) { + $remoteDocument->contextUrl = $contextLinkHeaders[0]['uri']; + } elseif (count($contextLinkHeaders) > 1) { + throw new JsonLdException( + JsonLdException::MULTIPLE_CONTEXT_LINK_HEADERS, + 'Found multiple contexts in HTTP Link headers', + $http_response_header + ); + } + + // If we got a media type, we verify it + if ($remoteDocument->mediaType) { + // Drop any media type parameters such as profiles + if (false !== ($pos = strpos($remoteDocument->mediaType, ';'))) { + $remoteDocument->mediaType = substr($remoteDocument->mediaType, 0, $pos); + } + + $remoteDocument->mediaType = trim($remoteDocument->mediaType); + + if ('application/ld+json' === $remoteDocument->mediaType) { + $remoteDocument->contextUrl = null; + } else { + // If the Media type was not as expected, check to see if the desired content type + // is being offered in a Link header (this is what schema.org now does). + $altLinkHeaders = array_filter($linkHeaderValues, function ($link) { + return (isset($link['rel']) && isset($link['type']) + && ($link['rel'] === 'alternate') && ($link['type'] === 'application/ld+json')); + }); + + // The spec states 'A response MUST NOT contain more than one HTTP Link Header + // using the alternate link relation with type="application/ld+json"' + if (count($altLinkHeaders) === 1) { + return $this->loadDocument($altLinkHeaders[0]['uri']); + } elseif (count($altLinkHeaders) > 1) { + throw new JsonLdException( + JsonLdException::LOADING_DOCUMENT_FAILED, + 'Received multiple alternate link headers' + ); + } + + if (('application/json' !== $remoteDocument->mediaType) && + (0 !== substr_compare($remoteDocument->mediaType, '+json', -5))) { + throw new JsonLdException( + JsonLdException::LOADING_DOCUMENT_FAILED, + 'Invalid media type', + $remoteDocument->mediaType + ); + } + } + } + + $remoteDocument->document = Processor::parse($input); + + return $remoteDocument; + } + + return new RemoteDocument($url, Processor::parse($input)); + } + + /** + * Parse HTTP Link headers + * + * @param array $values An array of HTTP Link headers. + * @param IRI $baseIri The document's URL (used to expand relative URLs to absolutes). + * + * @return array A structured representation of the Link header values. + * + * @internal Do not use this method directly, it's only temporarily accessible for testing. + */ + public function parseLinkHeaders(array $values, IRI $baseIri) + { + // Separate multiple links contained in a single header value + for ($i = 0, $total = count($values); $i < $total; $i++) { + if (strpos($values[$i], ',') !== false) { + foreach (preg_split('/,(?=([^"]*"[^"]*")*[^"]*$)/', $values[$i]) as $v) { + $values[] = trim($v); + } + unset($values[$i]); + } + } + + $contexts = $matches = array(); + $trimWhitespaceCallback = function ($str) { + return trim($str, "\"' \n\t"); + }; + + // Split the header in key-value pairs + $result = array(); + + foreach ($values as $val) { + $part = array(); + + foreach (preg_split('/;(?=([^"]*"[^"]*")*[^"]*$)/', $val) as $kvp) { + preg_match_all('/<[^>]+>|[^=]+/', $kvp, $matches); + $pieces = array_map($trimWhitespaceCallback, $matches[0]); + + if (count($pieces) > 1) { + $part[$pieces[0]] = $pieces[1]; + } elseif (count($pieces) === 1) { + $part['uri'] = (string) $baseIri->resolve(trim($pieces[0], '<> ')); + } + } + + if (!empty($part)) { + $result[] = $part; + } + } + + return $result; + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Graph.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/Graph.php new file mode 100644 index 0000000..9dc1104 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Graph.php @@ -0,0 +1,273 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +use ML\IRI\IRI; + +/** + * A Graph represents a JSON-LD graph. + * + * @author Markus Lanthaler + */ +class Graph implements GraphInterface, JsonLdSerializable +{ + /** + * @var DocumentInterface The document this graph belongs to. + */ + private $document; + + /** + * @var array An associative array holding all nodes in the graph + */ + protected $nodes = array(); + + /** + * A term map containing terms/prefixes mapped to IRIs. This is similar + * to a JSON-LD context but ignores all definitions except the IRI. + * + * @var array + */ + protected $termMap = array(); + + /** + * @var int Blank node counter + */ + private $blankNodeCounter = 0; + + /** + * Constructor + * + * @param null|DocumentInterface $document The document the graph belongs to. + */ + public function __construct(DocumentInterface $document = null) + { + $this->document = $document; + } + + /** + * {@inheritdoc} + */ + public function createNode($id = null, $preserveBnodeId = false) + { + if (!is_string($id) || (!$preserveBnodeId && ('_:' === substr($id, 0, 2)))) { + $id = $this->createBlankNodeId(); + } else { + $id = (string) $this->resolveIri($id); + if (isset($this->nodes[$id])) { + return $this->nodes[$id]; + } + } + + return $this->nodes[$id] = new Node($this, $id); + } + + /** + * {@inheritdoc} + */ + public function removeNode(NodeInterface $node) + { + if ($node->getGraph() === $this) { + $node->removeFromGraph(); + } + + $id = $node->getId(); + + if (!$node->isBlankNode()) { + $id = (string) $this->resolveIri($id); + } + + unset($this->nodes[$id]); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getNodes() + { + return array_values($this->nodes); + } + + /** + * {@inheritdoc} + */ + public function getNode($id) + { + if (!((strlen($id) >= 2) && ('_:' === substr($id, 0, 2)))) { + $id = (string) $this->resolveIri($id); + } + + return isset($this->nodes[$id]) + ? $this->nodes[$id] + : null; + } + + /** + * {@inheritdoc} + */ + public function getNodesByType($type) + { + if (is_string($type)) { + if (null === ($type = $this->getNode($type))) { + return array(); + } + } + + return $type->getNodesWithThisType(); + } + + /** + * {@inheritdoc} + */ + public function containsNode($id) + { + $node = $id; + + if ($node instanceof Node) { + $id = $node->getId(); + } + + if ((null === $id) || !is_string($id)) { + return false; + } + + if ((strlen($id) >= 2) && ('_:' === substr($id, 0, 2))) { + if (isset($this->nodes[$id]) && ($node === $this->nodes[$id])) { + return true; + } + + return false; + } + + $id = (string) $this->resolveIri($id); + + return isset($this->nodes[$id]); + } + + /** + * {@inheritdoc} + */ + public function getDocument() + { + return $this->document; + } + + /** + * {@inheritdoc} + */ + public function removeFromDocument() + { + $doc = $this->document; + $this->document = null; + + $doc->removeGraph($this); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function merge(GraphInterface $graph) + { + $nodes = $graph->getNodes(); + $bnodeMap = array(); + + foreach ($nodes as $node) { + if ($node->isBlankNode()) { + if (false === isset($bnodeMap[$node->getId()])) { + $bnodeMap[$node->getId()] = $this->createNode(); + } + $n = $bnodeMap[$node->getId()]; + } else { + $n = $this->createNode($node->getId()); + } + + foreach ($node->getProperties() as $property => $values) { + if (false === is_array($values)) { + $values = array($values); + } + + foreach ($values as $val) { + if ($val instanceof NodeInterface) { + // If the value is another node, we just need to + // create a reference to the corresponding node + // in this graph. The properties will be merged + // in the outer loop + if ($val->isBlankNode()) { + if (false === isset($bnodeMap[$val->getId()])) { + $bnodeMap[$val->getId()] = $this->createNode(); + } + $val = $bnodeMap[$val->getId()]; + } else { + $val = $this->createNode($val->getId()); + } + } elseif (is_object($val)) { + // Clone typed values and language-tagged strings + $val = clone $val; + } + + $n->addPropertyValue($property, $val); + } + } + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function toJsonLd($useNativeTypes = true) + { + // Bring nodes into a deterministic order + $nodes = $this->nodes; + ksort($nodes); + $nodes = array_values($nodes); + + $serializeNode = function ($node) use ($useNativeTypes) { + return $node->toJsonLd($useNativeTypes); + }; + + return array_map($serializeNode, $nodes); + } + + /** + * Create a new blank node identifier unique to the document. + * + * @return string The new blank node identifier. + */ + protected function createBlankNodeId() + { + return '_:b' . $this->blankNodeCounter++; + } + + /** + * Resolves an IRI against the document's IRI + * + * If the graph isn't attached to a document or the document's IRI is + * not set, the IRI is returned as-is. + * + * @param string|IRI $iri The (relative) IRI to resolve + * + * @return IRI The resolved IRI. + */ + protected function resolveIri($iri) + { + if (null === $this->document) { + $base = new IRI(); + } else { + $base = $this->document->getIri(true); + } + + return $base->resolve($iri); + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/GraphInterface.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/GraphInterface.php new file mode 100644 index 0000000..6f448ab --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/GraphInterface.php @@ -0,0 +1,117 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +/** + * JSON-LD graph interface + * + * @author Markus Lanthaler + */ +interface GraphInterface +{ + /** + * Creates a new node which is linked to this document + * + * If a blank node identifier or an invalid ID is passed, the ID will be + * ignored and a new blank node identifier unique to the document is + * created for the node. + * + * If there exists already a node with the passed ID in the document, + * that node will be returned instead of creating a new one. + * + * @param null|string $id The ID of the node. + * @param bool $preserveBnodeId If set to false, blank nodes are + * relabeled to avoid collisions; + * otherwise the blank node identifier + * is preserved. + * + * @return Node The newly created node. + */ + public function createNode($id = null, $preserveBnodeId = false); + + /** + * Removes a node from the document + * + * This will also eliminate all references to the node within the + * document. + * + * @param NodeInterface $node The node to remove from the document. + * + * @return self + */ + public function removeNode(NodeInterface $node); + + /** + * Get all nodes + * + * @return Node[] Returns an array containing all nodes defined in the + * document. + */ + public function getNodes(); + + /** + * Get a node by ID + * + * @param string $id The ID of the node to retrieve. + * + * @return Node|null Returns the node if found; null otherwise. + */ + public function getNode($id); + + /** + * Get nodes by type + * + * @param string|Node $type The type + * + * @return Node[] Returns an array containing all nodes of the specified + * type in the document. + */ + public function getNodesByType($type); + + /** + * Check whether the document already contains a node with the + * specified ID + * + * @param string|Node $id The node ID to check. Blank node identifiers + * will always return false except a node instance + * which is part of the document will be passed + * instead of a string. + * + * @return bool Returns true if the document contains a node with the + * specified ID; false otherwise. + */ + public function containsNode($id); + + /** + * Get the document the node belongs to + * + * @return null|DocumentInterface Returns the document the node belongs + * to or null if the node doesn't belong + * to any document. + */ + public function getDocument(); + + /** + * Removes the graph from the document + * + * @return self + */ + public function removeFromDocument(); + + /** + * Merges the specified graph into the current graph + * + * @param GraphInterface $graph The graph that should be merged into the + * current graph. + * + * @return self + */ + public function merge(GraphInterface $graph); +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/JsonLD.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/JsonLD.php new file mode 100644 index 0000000..c259b6c --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/JsonLD.php @@ -0,0 +1,692 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +use stdClass as JsonObject; +use ML\JsonLD\Exception\JsonLdException; +use ML\JsonLD\Exception\InvalidQuadException; +use ML\IRI\IRI; + +/** + * JsonLD + * + * JsonLD implements the algorithms defined by the + * {@link http://www.w3.org/TR/json-ld-api/ JSON-LD 1.0 API and Processing Algorithms specification}. + * Its interface is, apart from the usage of Promises, exactly the same as the one + * defined by the specification. + * + * Furthermore, it implements an enhanced version of the + * {@link http://json-ld.org/spec/latest/json-ld-framing/ JSON-LD Framing 1.0 draft} + * and an object-oriented interface to access and manipulate JSON-LD documents. + * + * @api + * + * @author Markus Lanthaler + */ +class JsonLD +{ + /** Identifier for the default graph */ + const DEFAULT_GRAPH = '@default'; + + /** Identifier for the merged graph */ + const MERGED_GRAPH = '@merged'; + + private static $documentLoader = null; + + /** + * Load and parse a JSON-LD document + * + * The document can be supplied directly as string, by passing a file + * path, or by passing a URL. + * + * Usage: + * + * $document = JsonLD::getDocument('document.jsonld'); + * print_r($document->getGraphNames()); + * + * It is possible to configure the processing by setting the options + * parameter accordingly. Available options are: + * + *
+ *
base
+ *
The base IRI of the input document.
+ * + *
expandContext
+ *
An optional context to use additionally to the context embedded + * in input when expanding the input.
+ * + *
documentFactory
+ *
The document factory.
+ * + *
documentLoader
+ *
The document loader.
+ *
+ * + * The options parameter might be passed as associative array or as + * object. + * + * @param string|JsonObject|array $input The JSON-LD document to process. + * @param null|array|JsonObject $options Options to configure the processing. + * + * @return Document The parsed JSON-LD document. + * + * @throws JsonLdException + * + * @api + */ + public static function getDocument($input, $options = null) + { + $options = self::mergeOptions($options); + + $input = self::expand($input, $options); + + $processor = new Processor($options); + + return $processor->getDocument($input); + } + + /** + * Expand a JSON-LD document + * + * The document can be supplied directly as string, by passing a file + * path, or by passing a URL. + * + * Usage: + * + * $expanded = JsonLD::expand('document.jsonld'); + * print_r($expanded); + * + * It is possible to configure the expansion process by setting the options + * parameter accordingly. Available options are: + * + *
+ *
base
+ *
The base IRI of the input document.
+ * + *
expandContext
+ *
An optional context to use additionally to the context embedded + * in input when expanding the input.
+ * + *
documentLoader
+ *
The document loader.
+ *
+ * + * The options parameter might be passed as associative array or as + * object. + * + * @param string|JsonObject|array $input The JSON-LD document to expand. + * @param null|array|JsonObject $options Options to configure the expansion + * process. + * + * @return array The expanded JSON-LD document. + * + * @throws JsonLdException + * + * @api + */ + public static function expand($input, $options = null) + { + $options = self::mergeOptions($options); + + $processor = new Processor($options); + $activectx = array('@base' => null); + + if (is_string($input)) { + $remoteDocument = $options->documentLoader->loadDocument($input); + + $input = $remoteDocument->document; + $activectx['@base'] = new IRI($remoteDocument->documentUrl); + + if (null !== $remoteDocument->contextUrl) { + $processor->processContext($remoteDocument->contextUrl, $activectx); + } + } + + if ($options->base) { + $activectx['@base'] = $options->base; + } + + if (null !== $options->expandContext) { + $processor->processContext($options->expandContext, $activectx); + } + + $processor->expand($input, $activectx); + + // optimize away default graph (@graph as the only property at the top-level object) + if (is_object($input) && property_exists($input, '@graph') && (1 === count(get_object_vars($input)))) { + $input = $input->{'@graph'}; + } + + if (false === is_array($input)) { + $input = (null === $input) ? array() : array($input); + } + + return $input; + } + + /** + * Compact a JSON-LD document according a supplied context + * + * Both the document and the context can be supplied directly as string, + * by passing a file path, or by passing a URL. + * + * Usage: + * + * $compacted = JsonLD::compact('document.jsonld', 'context.jsonld'); + * print_r($compacted); + * + * It is possible to configure the compaction process by setting the + * options parameter accordingly. Available options are: + * + *
+ *
base
+ *
The base IRI of the input document.
+ * + *
expandContext
+ *
An optional context to use additionally to the context embedded + * in input when expanding the input.
+ * + *
optimize
+ *
If set to true, the processor is free to optimize the result to + * produce an even compacter representation than the algorithm + * described by the official JSON-LD specification.
+ * + *
compactArrays
+ *
If set to true, arrays holding just one element are compacted + * to scalars, otherwise the arrays are kept as arrays.
+ * + *
documentLoader
+ *
The document loader.
+ *
+ * + * The options parameter might be passed as associative array or as + * object. + * + * @param string|JsonObject|array $input The JSON-LD document to + * compact. + * @param null|string|JsonObject|array $context The context. + * @param null|array|JsonObject $options Options to configure the + * compaction process. + * + * @return JsonObject The compacted JSON-LD document. + * + * @throws JsonLdException + * + * @api + */ + public static function compact($input, $context = null, $options = null) + { + $options = self::mergeOptions($options); + + $expanded = self::expand($input, $options); + + return self::doCompact($expanded, $context, $options); + } + + /** + * Compact a JSON-LD document according a supplied context + * + * In contrast to {@link compact()}, this method assumes that the input + * has already been expanded. + * + * @param array $input The JSON-LD document to + * compact. + * @param null|string|JsonObject|array $context The context. + * @param JsonObject $options Options to configure the + * compaction process. + * @param bool $alwaysGraph If set to true, the resulting + * document will always explicitly + * contain the default graph at + * the top-level. + * + * @return JsonObject The compacted JSON-LD document. + * + * @throws JsonLdException + */ + private static function doCompact($input, $context, $options, $alwaysGraph = false) + { + if (is_string($context)) { + $context = $options->documentLoader->loadDocument($context)->document; + } + + if (is_object($context) && property_exists($context, '@context')) { + $context = $context->{'@context'}; + } + + if (is_object($context) && (0 === count(get_object_vars($context)))) { + $context = null; + } elseif (is_array($context) && (0 === count($context))) { + $context = null; + } + + $activectx = array('@base' => $options->base); + $processor = new Processor($options); + + $processor->processContext($context, $activectx); + $inversectx = $processor->createInverseContext($activectx); + + $processor->compact($input, $activectx, $inversectx); + + $compactedDocument = new JsonObject(); + if (null !== $context) { + $compactedDocument->{'@context'} = $context; + } + + if ((false === is_array($input)) || (0 === count($input))) { + if (false === $alwaysGraph) { + $compactedDocument = (object) ((array) $compactedDocument + (array) $input); + + return $compactedDocument; + } + + if (false === is_array($input)) { + $input = array($input); + } + } + + $graphKeyword = (isset($inversectx['@graph']['term'])) + ? $inversectx['@graph']['term'] + : '@graph'; + + $compactedDocument->{$graphKeyword} = $input; + + return $compactedDocument; + } + + /** + * Flatten a JSON-LD document + * + * Both the document and the context can be supplied directly as string, + * by passing a file path, or by passing a URL. + * + * Usage: + * + * $flattened = JsonLD::flatten('document.jsonld'); + * print_r($flattened); + * + * It is possible to configure the flattening process by setting the options + * parameter accordingly. Available options are: + * + *
+ *
base
+ *
The base IRI of the input document.
+ * + *
expandContext
+ *
An optional context to use additionally to the context embedded + * in input when expanding the input.
+ * + *
graph
+ *
The graph whose flattened representation should be returned. + * The default graph is identified by {@link DEFAULT_GRAPH} and the + * merged dataset graph by {@link MERGED_GRAPH}. If null is + * passed, all graphs will be returned.
+ * + *
documentLoader
+ *
The document loader.
+ *
+ * + * The options parameter might be passed as associative array or as + * object. + * + * @param string|JsonObject|array $input The JSON-LD document to flatten. + * @param null|string|JsonObject|array $context The context to compact the + * flattened document. If + * null is passed, the + * result will not be compacted. + * @param null|array|JsonObject $options Options to configure the + * flattening process. + * + * @return JsonObject The flattened JSON-LD document. + * + * @throws JsonLdException + * + * @api + */ + public static function flatten($input, $context = null, $options = null) + { + $options = self::mergeOptions($options); + + $input = self::expand($input, $options); + + $processor = new Processor($options); + $flattened = $processor->flatten($input); + + if (null === $context) { + return $flattened; + } + + return self::doCompact($flattened, $context, $options, true); + } + + /** + * Convert a JSON-LD document to RDF quads + * + * The document can be supplied directly as string, by passing a file + * path, or by passing a URL. + * + * Usage: + * + * $quads = JsonLD::toRdf('document.jsonld'); + * print_r($quads); + * + * It is possible to configure the extraction process by setting the options + * parameter accordingly. Available options are: + * + *
+ *
base
+ *
The base IRI of the input document.
+ * + *
expandContext
+ *
An optional context to use additionally to the context embedded + * in input when expanding the input.
+ * + *
documentLoader
+ *
The document loader.
+ *
+ * + * The options parameter might be passed as associative array or as + * object. + * + * @param string|JsonObject|array $input The JSON-LD document to expand. + * @param null|array|JsonObject $options Options to configure the expansion + * process. + * + * @return Quad[] The extracted quads. + * + * @throws JsonLdException + * + * @api + */ + public static function toRdf($input, $options = null) + { + $options = self::mergeOptions($options); + + $expanded = self::expand($input, $options); + + $processor = new Processor($options); + + return $processor->toRdf($expanded); + } + + /** + * Convert an array of RDF quads to a JSON-LD document + * + * Usage: + * + * $document = JsonLD::fromRdf($quads); + * print(JsonLD::toString($document, true)); + * + * It is possible to configure the conversion process by setting the options + * parameter accordingly. Available options are: + * + *
+ *
base
+ *
The base IRI of the input document.
+ * + *
useNativeTypes
+ *
If set to true, native types are used for xsd:integer, + * xsd:double, and xsd:boolean; otherwise, + * typed strings will be used instead.
+ * + *
useRdfType
+ *
If set to true, rdf:type will be used instead of @type + * + *
documentLoader
+ *
The document loader.
+ *
+ * + * The options parameter might be passed as associative array or as + * object. + * + * @param Quad[] $quads Array of quads. + * @param null|array|JsonObject $options Options to configure the expansion + * process. + * + * @return array The JSON-LD document in expanded form. + * + * @throws InvalidQuadException If an invalid quad was detected. + * @throws JsonLdException If converting the quads to a JSON-LD document failed. + * + * @api + */ + public static function fromRdf(array $quads, $options = null) + { + $options = self::mergeOptions($options); + + $processor = new Processor($options); + + return $processor->fromRdf($quads); + } + + /** + * Frame a JSON-LD document according a supplied frame + * + * Both the document and the frame can be supplied directly as string, + * by passing a file path, or by passing a URL. + * + * Usage: + * + * $result = JsonLD::frame('document.jsonld', 'frame.jsonldf'); + * print_r($compacted); + * + * It is possible to configure the framing process by setting the options + * parameter accordingly. Available options are: + * + *
+ *
base
+ *
The base IRI of the input document.
+ * + *
expandContext
+ *
An optional context to use additionally to the context embedded + * in input when expanding the input.
+ * + *
optimize
+ *
If set to true, the processor is free to optimize the result to + * produce an even compacter representation than the algorithm + * described by the official JSON-LD specification.
+ * + *
compactArrays
+ *
If set to true, arrays holding just one element are compacted + * to scalars, otherwise the arrays are kept as arrays.
+ * + *
documentLoader
+ *
The document loader.
+ *
+ * + * The options parameter might be passed as associative array or as + * object. + * + * @param string|JsonObject|array $input The JSON-LD document to compact. + * @param string|JsonObject $frame The frame. + * @param null|array|JsonObject $options Options to configure the framing + * process. + * + * @return JsonObject The framed JSON-LD document. + * + * @throws JsonLdException + * + * @api + */ + public static function frame($input, $frame, $options = null) + { + $options = self::mergeOptions($options); + + $input = self::expand($input, $options); + $frame = (is_string($frame)) + ? $options->documentLoader->loadDocument($frame)->document + : $frame; + + if (false === is_object($frame)) { + throw new JsonLdException( + JsonLdException::UNSPECIFIED, + 'Invalid frame detected. It must be an object.', + $frame + ); + } + + $processor = new Processor($options); + + // Store the frame's context as $frame gets modified + $frameContext = new JsonObject(); + if (property_exists($frame, '@context')) { + $frameContext->{'@context'} = $frame->{'@context'}; + } + + // Expand the frame + $processor->expand($frame, array(), null, true); + + // and optimize away default graph (@graph as the only property at the top-level object) + if (is_object($frame) && property_exists($frame, '@graph') && (1 === count(get_object_vars($frame)))) { + $frame = $frame->{'@graph'}; + } + + if (false === is_array($frame)) { + $frame = array($frame); + } + + // Frame the input document + $result = $processor->frame($input, $frame); + + // Compact the result using the frame's active context + return self::doCompact($result, $frameContext, $options, true); + } + + /** + * Convert the PHP structure returned by the various processing methods + * to a string + * + * Usage: + * + * $compacted = JsonLD::compact('document.jsonld', 'context.jsonld'); + * $prettyString = JsonLD::toString($compacted, true); + * print($prettyString); + * + * @param mixed $value The value to convert. + * @param bool $pretty Use whitespace in returned string to format it + * (this just works in PHP >=5.4)? + * + * @return string + */ + public static function toString($value, $pretty = false) + { + $options = 0; + + if (PHP_VERSION_ID >= 50400) { + $options |= JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE; + + if ($pretty) { + $options |= JSON_PRETTY_PRINT; + } + + return json_encode($value, $options); + } else { + $result = json_encode($value); + $result = str_replace('\\/', '/', $result); // unescape slahes + + // unescape unicode + return preg_replace_callback( + '/\\\\u([a-f0-9]{4})/', + function ($match) { + return iconv('UCS-4LE', 'UTF-8', pack('V', hexdec($match[1]))); + }, + $result + ); + } + } + + /** + * Merge the passed options with the options' default values. + * + * @param null|array|JsonObject $options The options. + * + * @return JsonObject The merged options. + */ + private static function mergeOptions($options) + { + $result = (object) array( + 'base' => null, + 'expandContext' => null, + 'compactArrays' => true, + 'optimize' => false, + 'graph' => null, + 'useNativeTypes' => false, + 'useRdfType' => false, + 'produceGeneralizedRdf' => false, + 'documentFactory' => null, + 'documentLoader' => new FileGetContentsLoader() + ); + + if (is_array($options) || is_object($options)) { + $options = (object) $options; + if (isset($options->{'base'})) { + if (is_string($options->{'base'})) { + $result->base = new IRI($options->{'base'}); + } elseif (($options->{'base'} instanceof IRI) && $options->{'base'}->isAbsolute()) { + $result->base = clone $options->{'base'}; + } else { + throw new \InvalidArgumentException('The "base" option must be set to null or an absolute IRI.'); + } + } + if (property_exists($options, 'compactArrays') && is_bool($options->compactArrays)) { + $result->compactArrays = $options->compactArrays; + } + if (property_exists($options, 'optimize') && is_bool($options->optimize)) { + $result->optimize = $options->optimize; + } + if (property_exists($options, 'graph') && is_string($options->graph)) { + $result->graph = $options->graph; + } + if (property_exists($options, 'useNativeTypes') && is_bool($options->useNativeTypes)) { + $result->useNativeTypes = $options->useNativeTypes; + } + if (property_exists($options, 'useRdfType') && is_bool($options->useRdfType)) { + $result->useRdfType = $options->useRdfType; + } + if (property_exists($options, 'produceGeneralizedRdf') && is_bool($options->produceGeneralizedRdf)) { + $result->produceGeneralizedRdf = $options->produceGeneralizedRdf; + } + if (property_exists($options, 'documentFactory') && + ($options->documentFactory instanceof DocumentFactoryInterface)) { + $result->documentFactory = $options->documentFactory; + } + if (property_exists($options, 'documentLoader') && + ($options->documentLoader instanceof DocumentLoaderInterface)) { + $result->documentLoader = $options->documentLoader; + } elseif (null !== self::$documentLoader) { + $result->documentLoader = self::$documentLoader; + } + if (property_exists($options, 'expandContext')) { + if (is_string($options->expandContext)) { + $result->expandContext = $result->documentLoader->loadDocument($options->expandContext)->document; + } elseif (is_object($options->expandContext)) { + $result->expandContext = $options->expandContext; + } + if (is_object($result->expandContext) && property_exists($result->expandContext, '@context')) { + $result->expandContext = $result->expandContext->{'@context'}; + } + } + } + + return $result; + } + + /** + * Set the default document loader. + * + * It can be overridden in individual operations by setting the + * `documentLoader` option. + * + * @param DocumentLoaderInterface $documentLoader + */ + public static function setDefaultDocumentLoader(DocumentLoaderInterface $documentLoader) + { + self::$documentLoader = $documentLoader; + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/JsonLdSerializable.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/JsonLdSerializable.php new file mode 100644 index 0000000..ba1f366 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/JsonLdSerializable.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +/** + * The JsonLdSerializable interface + * + * Objects implementing JsonLdSerializable can be serialized to JSON-LD. + * + * @author Markus Lanthaler + */ +interface JsonLdSerializable +{ + /** + * Convert to expanded and flattened JSON-LD + * + * The result can then be serialized to JSON-LD by {@see JsonLD::toString()}. + * + * @param boolean $useNativeTypes If set to true, native types are used + * for xsd:integer, xsd:double, and + * xsd:boolean, otherwise typed strings + * will be used instead. + * + * @return mixed Returns data which can be serialized by + * {@see JsonLD::toString()} (which is a value of any type + * other than a resource) to expanded JSON-LD. + * + * @see JsonLD::toString() + */ + public function toJsonLd($useNativeTypes = true); +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/LICENSE b/Resources/Private/PHP/embed/vendor/ml/json-ld/LICENSE new file mode 100644 index 0000000..34bdeb0 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2012-2016 Markus Lanthaler + +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/Resources/Private/PHP/embed/vendor/ml/json-ld/LanguageTaggedString.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/LanguageTaggedString.php new file mode 100644 index 0000000..d3407d2 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/LanguageTaggedString.php @@ -0,0 +1,95 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +use stdClass as JsonObject; + +/** + * A LanguageTaggedString is a string which is tagged with a language. + * + * @author Markus Lanthaler + */ +final class LanguageTaggedString extends Value +{ + /** + * The language code associated with the string. Language codes are tags + * according to {@link http://tools.ietf.org/html/bcp47 BCP47}. + * + * @var string + */ + private $language; + + /** + * Constructor + * + * @param string $value The string's value. + * @param string $language The string's language. + */ + public function __construct($value, $language) + { + $this->setValue($value); + $this->setLanguage($language); + } + + /** + * Set the language + * + * @param string $language The language. + * + * @return self + * + * @throws \InvalidArgumentException If the language is not a string. No + * further checks are currently done. + */ + public function setLanguage($language) + { + if (!is_string($language)) { + throw new \InvalidArgumentException('language must be a string.'); + } + + $this->language = $language; + + return $this; + } + + /** + * Get the language + * + * @return string The language. + */ + public function getLanguage() + { + return $this->language; + } + + /** + * {@inheritdoc} + */ + public function toJsonLd($useNativeTypes = true) + { + $result = new JsonObject(); + $result->{'@value'} = $this->value; + $result->{'@language'} = $this->language; + + return $result; + } + + /** + * {@inheritdoc} + */ + public function equals($other) + { + if (get_class($this) !== get_class($other)) { + return false; + } + + return ($this->value === $other->value) && ($this->language === $other->language); + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/NQuads.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/NQuads.php new file mode 100644 index 0000000..0b6e7b1 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/NQuads.php @@ -0,0 +1,176 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +use ML\JsonLD\Exception\InvalidQuadException; +use ML\IRI\IRI; + +/** + * NQuads serializes quads to the NQuads format + * + * @author Markus Lanthaler + */ +class NQuads implements QuadSerializerInterface, QuadParserInterface +{ + /** + * {@inheritdoc} + */ + public function serialize(array $quads) + { + $result = ''; + foreach ($quads as $quad) { + $result .= ('_' === $quad->getSubject()->getScheme()) + ? $quad->getSubject() + : '<' . $quad->getSubject() . '>'; + $result .= ' '; + + $result .= ('_' === $quad->getProperty()->getScheme()) + ? $quad->getProperty() + : '<' . $quad->getProperty() . '>'; + $result .= ' '; + + if ($quad->getObject() instanceof IRI) { + $result .= ('_' === $quad->getObject()->getScheme()) + ? $quad->getObject() + : '<' . $quad->getObject() . '>'; + } else { + $result .= '"' . str_replace( + array("\n", '"'), + array('\n', '\"'), + $quad->getObject()->getValue()) . '"'; + $result .= ($quad->getObject() instanceof TypedValue) + ? (RdfConstants::XSD_STRING === $quad->getObject()->getType()) + ? '' + : '^^<' . $quad->getObject()->getType() . '>' + : '@' . $quad->getObject()->getLanguage(); + } + $result .= ' '; + + if ($quad->getGraph()) { + $result .= ('_' === $quad->getGraph()->getScheme()) + ? $quad->getGraph() : + '<' . $quad->getGraph() . '>'; + $result .= ' '; + } + $result .= ".\n"; + } + + return $result; + } + + /** + * {@inheritdoc} + * + * This method is heavily based on DigitalBazaar's implementation used + * in their {@link https://github.com/digitalbazaar/php-json-ld php-json-ld}. + * + * @throws InvalidQuadException If an invalid quad that can't be parsed is + * encountered. + */ + public function parse($input) + { + // define partial regexes + $iri = '(?:<([^>]*)>)'; + + // blank node labels based on https://www.w3.org/TR/n-quads/#BNodes + $bnode = '(_:(?:[A-Za-z0-9_]|[A-Za-z0-9_][A-Za-z0-9_\-.]*[A-Za-z0-9_\-]))'; + + $plain = '"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"'; + $datatype = "\\^\\^$iri"; + $language = '(?:@([a-z]+(?:-[a-z0-9]+)*))'; + $literal = "(?:$plain(?:$datatype|$language)?)"; + $ws = '[ \\t]'; + $comment = "#.*"; + + $subject = "(?:$iri|$bnode)$ws+"; + $property = "$iri$ws+"; + $object = "(?:$iri|$bnode|$literal)"; + $graph = "$ws+(?:$iri|$bnode)"; + + // full regexes + $eoln = '/(?:(\r\n)|[\n\r])/'; + $quadRegex = "/^$ws*$subject$property$object$graph?$ws*.$ws*$/"; + $ignoreRegex = "/^$ws*(?:$comment)?$/"; + + // build RDF statements + $statements = array(); + + // split N-Quad input into lines + $lines = preg_split($eoln, $input); + $line_number = 0; + + foreach ($lines as $line) { + $line_number++; + + // skip empty lines + if (preg_match($ignoreRegex, $line)) { + continue; + } + + // parse quad + if (!preg_match($quadRegex, $line, $match)) { + throw new InvalidQuadException( + sprintf( + 'Error while parsing N-Quads. Invalid quad in line %d: %s', + $line_number, + $line + ), + $line + ); + } + + // get subject + if ($match[1] !== '') { + $subject = new IRI($match[1]); + } else { + $subject = new IRI($match[2]); + } + + // get property + $property = new IRI($match[3]); + + // get object + if ($match[4] !== '') { + $object = new IRI($match[4]); // IRI + } elseif ($match[5] !== '') { + $object = new IRI($match[5]); // bnode + } else { + $unescaped = str_replace( + array('\"', '\t', '\n', '\r', '\\\\'), + array('"', "\t", "\n", "\r", '\\'), + $match[6] + ); + + if (isset($match[7]) && $match[7] !== '') { + $object = new TypedValue($unescaped, $match[7]); + } elseif (isset($match[8]) && $match[8] !== '') { + $object = new LanguageTaggedString($unescaped, $match[8]); + } else { + $object = new TypedValue($unescaped, RdfConstants::XSD_STRING); + } + } + + // get graph + $graph = null; + if (isset($match[9]) && $match[9] !== '') { + $graph = new IRI($match[9]); + } elseif (isset($match[10]) && $match[10] !== '') { + $graph = new IRI($match[10]); + } + + $quad = new Quad($subject, $property, $object, $graph); + + // TODO Make sure that quads are unique?? + $statements[] = $quad; + } + + return $statements; + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Node.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/Node.php new file mode 100644 index 0000000..2af17ff --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Node.php @@ -0,0 +1,509 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +use stdClass as JsonObject; + +/** + * A Node represents a node in a JSON-LD graph. + * + * @author Markus Lanthaler + */ +class Node implements NodeInterface, JsonLdSerializable +{ + /** The @type constant. */ + const TYPE = '@type'; + + /** + * @var GraphInterface The graph the node belongs to. + */ + private $graph; + + /** + * @var string The ID of the node + */ + private $id; + + /** + * @var array An associative array holding all properties of the node except it's ID + */ + private $properties = array(); + + /** + * An associative array holding all reverse properties of this node, i.e., + * a pointers to all nodes that link to this node. + * + * @var array + */ + private $revProperties = array(); + + /** + * Constructor + * + * @param GraphInterface $graph The graph the node belongs to. + * @param null|string $id The ID of the node. + */ + public function __construct(GraphInterface $graph, $id = null) + { + $this->graph = $graph; + $this->id = $id; + } + + /** + * {@inheritdoc} + */ + public function getId() + { + return $this->id; + } + + /** + * {@inheritdoc} + */ + public function setType($type) + { + if ((null !== $type) && !($type instanceof NodeInterface)) { + if (is_array($type)) { + foreach ($type as $val) { + if ((null !== $val) && !($val instanceof NodeInterface)) { + throw new \InvalidArgumentException('type must be null, a Node, or an array of Nodes'); + } + } + } else { + throw new \InvalidArgumentException('type must be null, a Node, or an array of Nodes'); + } + } + + $this->setProperty(self::TYPE, $type); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function addType(NodeInterface $type) + { + $this->addPropertyValue(self::TYPE, $type); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function removeType(NodeInterface $type) + { + $this->removePropertyValue(self::TYPE, $type); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getType() + { + return $this->getProperty(self::TYPE); + } + + /** + * {@inheritdoc} + */ + public function getNodesWithThisType() + { + if (null === ($nodes = $this->getReverseProperty(self::TYPE))) { + return array(); + } + + return (is_array($nodes)) ? $nodes : array($nodes); + } + + /** + * {@inheritdoc} + */ + public function getGraph() + { + return $this->graph; + } + + /** + * {@inheritdoc} + */ + public function removeFromGraph() + { + // Remove other node's properties and reverse properties pointing to + // this node + foreach ($this->revProperties as $property => $nodes) { + foreach ($nodes as $node) { + $node->removePropertyValue($property, $this); + } + } + + foreach ($this->properties as $property => $values) { + if (!is_array($values)) { + $values = array($values); + } + + foreach ($values as $value) { + if ($value instanceof NodeInterface) { + $this->removePropertyValue($property, $value); + } + } + } + + $g = $this->graph; + $this->graph = null; + + $g->removeNode($this); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function isBlankNode() + { + return ((null === $this->id) || ('_:' === substr($this->id, 0, 2))); + } + + /** + * {@inheritdoc} + */ + public function setProperty($property, $value) + { + if (null === $value) { + $this->removeProperty($property); + } else { + $this->doMergeIntoProperty((string) $property, array(), $value); + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function addPropertyValue($property, $value) + { + $existing = (isset($this->properties[(string) $property])) + ? $this->properties[(string) $property] + : array(); + + if (!is_array($existing)) { + $existing = array($existing); + } + + $this->doMergeIntoProperty((string) $property, $existing, $value); + + return $this; + } + + /** + * Merge a value into a set of existing values. + * + * @param string $property The name of the property. + * @param array $existingValues The existing values. + * @param mixed $value The value to merge into the existing + * values. This MUST NOT be an array. + * + * @throws \InvalidArgumentException If value is an array or an object + * which is neither a language-tagged + * string nor a typed value or a node. + */ + private function doMergeIntoProperty($property, $existingValues, $value) + { + // TODO: Handle lists! + + if (null === $value) { + return; + } + + if (!$this->isValidPropertyValue($value)) { + throw new \InvalidArgumentException( + 'value must be a scalar, a node, a language-tagged string, or a typed value' + ); + } + + $normalizedValue = $this->normalizePropertyValue($value); + + foreach ($existingValues as $existing) { + if ($this->equalValues($existing, $normalizedValue)) { + return; + } + } + + $existingValues[] = $normalizedValue; + + if (1 === count($existingValues)) { + $existingValues = $existingValues[0]; + } + + $this->properties[$property] = $existingValues; + + if ($normalizedValue instanceof NodeInterface) { + $value->addReverseProperty($property, $this); + } + } + + /** + * {@inheritdoc} + */ + public function removeProperty($property) + { + if (!isset($this->properties[(string) $property])) { + return $this; + } + + $values = is_array($this->properties[(string) $property]) + ? $this->properties[(string) $property] + : array($this->properties[(string) $property]); + + foreach ($values as $value) { + if ($value instanceof NodeInterface) { + $value->removeReverseProperty((string) $property, $this); + } + } + + unset($this->properties[(string) $property]); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function removePropertyValue($property, $value) + { + if (!$this->isValidPropertyValue($value) || !isset($this->properties[(string) $property])) { + return $this; + } + + $normalizedValue = $this->normalizePropertyValue($value); + + $values =& $this->properties[(string) $property]; + + if (!is_array($this->properties[(string) $property])) { + $values = array($values); + } + + for ($i = 0, $length = count($values); $i < $length; $i++) { + if ($this->equalValues($values[$i], $normalizedValue)) { + if ($normalizedValue instanceof NodeInterface) { + $normalizedValue->removeReverseProperty((string) $property, $this); + } + + unset($values[$i]); + break; + } + } + + if (0 === count($values)) { + unset($this->properties[(string) $property]); + + return $this; + } + + $this->properties[(string) $property] = array_values($values); // re-index the array + + if (1 === count($this->properties[(string) $property])) { + $this->properties[(string) $property] = $this->properties[(string) $property][0]; + } + } + + /** + * {@inheritdoc} + */ + public function getProperties() + { + return $this->properties; + } + + /** + * {@inheritdoc} + */ + public function getProperty($property) + { + return (isset($this->properties[(string) $property])) + ? $this->properties[(string) $property] + : null; + } + + /** + * {@inheritdoc} + */ + public function getReverseProperties() + { + $result = array(); + foreach ($this->revProperties as $key => $nodes) { + $result[$key] = array_values($nodes); + } + + return $result; + } + + /** + * {@inheritdoc} + */ + public function getReverseProperty($property) + { + if (!isset($this->revProperties[(string) $property])) { + return null; + } + + $result = array_values($this->revProperties[(string) $property]); + + return (1 === count($result)) + ? $result[0] + : $result; + } + + /** + * {@inheritdoc} + */ + public function equals(NodeInterface $other) + { + return $this === $other; + } + + /** + * {@inheritdoc} + */ + public function toJsonLd($useNativeTypes = true) + { + $node = new \stdClass(); + + // Only label blank nodes if other nodes point to it + if ((false === $this->isBlankNode()) || (count($this->getReverseProperties()) > 0)) { + $node->{'@id'} = $this->getId(); + } + + $properties = $this->getProperties(); + + foreach ($properties as $prop => $values) { + if (false === is_array($values)) { + $values = array($values); + } + + if (self::TYPE === $prop) { + $node->{'@type'} = array(); + foreach ($values as $val) { + $node->{'@type'}[] = $val->getId(); + } + + continue; + } + + $node->{$prop} = array(); + + foreach ($values as $value) { + if ($value instanceof NodeInterface) { + $ref = new \stdClass(); + $ref->{'@id'} = $value->getId(); + $node->{$prop}[] = $ref; + } elseif (is_object($value)) { // language-tagged string or typed value + $node->{$prop}[] = $value->toJsonLd($useNativeTypes); + } else { + $val = new JsonObject(); + $val->{'@value'} = $value; + $node->{$prop}[] = $val; + } + } + + } + + return $node; + } + + /** + * Add a reverse property. + * + * @param string $property The name of the property. + * @param NodeInterface $node The node which has a property pointing + * to this node instance. + */ + protected function addReverseProperty($property, NodeInterface $node) + { + $this->revProperties[$property][$node->getId()] = $node; + } + + /** + * Remove a reverse property. + * + * @param string $property The name of the property. + * @param NodeInterface $node The node which has a property pointing + * to this node instance. + */ + protected function removeReverseProperty($property, NodeInterface $node) + { + unset($this->revProperties[$property][$node->getId()]); + + if (0 === count($this->revProperties[$property])) { + unset($this->revProperties[$property]); + } + } + + /** + * Checks whether a value is a valid property value. + * + * @param mixed $value The value to check. + * + * @return bool Returns true if the value is a valid property value; + * false otherwise. + */ + protected function isValidPropertyValue($value) + { + return (is_scalar($value) || + (is_object($value) && + ((($value instanceof NodeInterface) && ($value->getGraph() === $this->graph)) || + ($value instanceof Value)))); + } + + /** + * Normalizes a property value by converting scalars to Value objects. + * + * @param mixed $value The value to normalize. + * + * @return NodeInterface|Value The normalized value. + */ + protected function normalizePropertyValue($value) + { + if (false === is_scalar($value)) { + return $value; + } + + return Value::fromJsonLd((object) array('@value' => $value)); + } + + /** + * Checks whether the two specified values are the same. + * + * Scalars and nodes are checked for identity, value objects for + * equality. + * + * @param mixed $value1 Value 1. + * @param mixed $value2 Value 2. + * + * @return bool Returns true if the two values are equals; otherwise false. + */ + protected function equalValues($value1, $value2) + { + if (gettype($value1) !== gettype($value2)) { + return false; + } + + if (is_object($value1) && ($value1 instanceof Value)) { + return $value1->equals($value2); + } + + return ($value1 === $value2); + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/NodeInterface.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/NodeInterface.php new file mode 100644 index 0000000..7091994 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/NodeInterface.php @@ -0,0 +1,218 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +/** + * A generic interface for nodes in a JSON-LD graph. + * + * @author Markus Lanthaler + */ +interface NodeInterface +{ + /** + * Get ID + * + * @return string|null The ID of the node or null. + */ + public function getId(); + + /** + * Set the node type + * + * @param null|NodeInterface|array[NodeInterface] The type(s) of this node. + * + * @return self + * + * @throws \InvalidArgumentException If type is not null, a Node or an + * array of Nodes. + */ + public function setType($type); + + /** + * Add a type to this node + * + * @param NodeInterface The type to add. + * + * @return self + */ + public function addType(NodeInterface $type); + + /** + * Remove a type from this node + * + * @param NodeInterface The type to remove. + * + * @return self + */ + public function removeType(NodeInterface $type); + + /** + * Get node type + * + * @return null|NodeInterface|NodeInterface[] Returns the type(s) of this node. + */ + public function getType(); + + /** + * Get the nodes which have this node as their type + * + * This will return all nodes that link to this Node instance via the + * @type (rdf:type) property. + * + * @return NodeInterface[] Returns the node(s) having this node as their + * type. + */ + public function getNodesWithThisType(); + + /** + * Get the graph the node belongs to + * + * @return null|GraphInterface Returns the graph the node belongs to or + * null if the node doesn't belong to any graph. + */ + public function getGraph(); + + /** + * Removes the node from the graph + * + * This will also remove all references to and from other nodes in this + * node's graph. + * + * @return self + */ + public function removeFromGraph(); + + /** + * Is this node a blank node + * + * A blank node is a node whose identifier has just local meaning. It has + * therefore a node identifier with the prefix _: or no + * identifier at all. + * + * @return bool Returns true if the node is a blank node, otherwise false. + */ + public function isBlankNode(); + + /** + * Set a property of the node + * + * If the value is or contains a reference to a node which is not part + * of the graph, the referenced node will added to the graph as well. + * If the referenced node is already part of another graph a copy of the + * node will be created and added to the graph. + * + * @param string $property The name of the property. + * @param mixed $value The value of the property. This MUST NOT be + * an array. Use null to remove the property. + * + * @return self + * + * @throws \InvalidArgumentException If value is an array or an object + * which is neither a language-tagged + * string nor a typed value or a node. + */ + public function setProperty($property, $value); + + /** + * Adds a value to a property of the node + * + * If the value already exists, it won't be added again, i.e., there + * won't be any duplicate property values. + * + * If the value is or contains a reference to a node which is not part + * of the graph, the referenced node will added to the graph as well. + * If the referenced node is already part of another graph a copy of the + * node will be created and added to the graph. + * + * @param string $property The name of the property. + * @param mixed $value The value of the property. This MUST NOT be + * an array. + * + * @return self + * + * @throws \InvalidArgumentException If value is an array or an object + * which is neither a language-tagged + * string nor a typed value or a node. + */ + public function addPropertyValue($property, $value); + + /** + * Removes a property and all it's values + * + * @param string $property The name of the property to remove. + * + * @return self + */ + public function removeProperty($property); + + /** + * Removes a property value + * + * @param string $property The name of the property. + * @param mixed $value The value of the property. This MUST NOT be + * an array. + * + * @return self + */ + public function removePropertyValue($property, $value); + + /** + * Get the properties of this node + * + * @return array Returns an associative array containing all properties + * of this node. The key is the property name whereas the + * value is the property's value. + */ + public function getProperties(); + + /** + * Get the value of a property + * + * @param string $property The name of the property. + * + * @return mixed Returns the value of the property or null if the + * property doesn't exist. + */ + public function getProperty($property); + + /** + * Get the reverse properties of this node + * + * @return array Returns an associative array containing all reverse + * properties of this node. The key is the property name + * whereas the value is an array of nodes linking to this + * instance via that property. + */ + public function getReverseProperties(); + + /** + * Get the nodes of a reverse property + * + * This will return all nodes that link to this Node instance via the + * specified property. + * + * @param string $property The name of the reverse property. + * + * @return null|NodeInterface|NodeInterface[] Returns the node(s) pointing + * to this instance via the specified + * property or null if no such node exists. + */ + public function getReverseProperty($property); + + /** + * Compares this node object to the specified value. + * + * @param mixed $other The value this instance should be compared to. + * + * @return bool Returns true if the passed value is the same as this + * instance; false otherwise. + */ + public function equals(NodeInterface $other); +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Processor.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/Processor.php new file mode 100644 index 0000000..1c1ff3e --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Processor.php @@ -0,0 +1,2973 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +use stdClass as JsonObject; +use ML\JsonLD\Exception\JsonLdException; +use ML\JsonLD\Exception\InvalidQuadException; +use ML\IRI\IRI; + +/** + * Processor processes JSON-LD documents as specified by the JSON-LD + * specification. + * + * @author Markus Lanthaler + */ +class Processor +{ + /** Timeout for retrieving remote documents in seconds */ + const REMOTE_TIMEOUT = 10; + + /** Maximum number of recursion that are allowed to resolve an IRI */ + const CONTEXT_MAX_IRI_RECURSIONS = 10; + + /** + * @var array A list of all defined keywords + */ + private static $keywords = array('@context', '@id', '@value', '@language', '@type', + '@container', '@list', '@set', '@graph', '@reverse', + '@base', '@vocab', '@index', '@null'); + // TODO Introduce @null supported just for framing + + /** + * @var array Framing options keywords + */ + private static $framingKeywords = array('@explicit', '@default', '@embed', + //'@omitDefault', // TODO Is this really needed? + '@embedChildren'); // TODO How should this be called? + // TODO Add @preserve, @null?? Update spec keyword list + + /** + * @var IRI The base IRI + */ + private $baseIri = null; + + /** + * Compact arrays with just one element to a scalar + * + * If set to true, arrays holding just one element are compacted to + * scalars, otherwise the arrays are kept as arrays. + * + * @var bool + */ + private $compactArrays; + + /** + * Optimize compacted output + * + * If set to true, the processor is free to optimize the result to produce + * an even compacter representation than the algorithm described by the + * official JSON-LD specification. + * + * @var bool + */ + private $optimize; + + /** + * Use native types when converting from RDF + * + * If set to true, the processor will try to convert datatyped literals + * to native types instead of using the expanded object form when + * converting from RDF. xsd:boolean values will be converted to booleans + * whereas xsd:integer and xsd:double values will be converted to numbers. + * + * @var bool + */ + private $useNativeTypes; + + /** + * Use rdf:type instead of \@type when converting from RDF + * + * If set to true, the JSON-LD processor will use the expanded rdf:type + * IRI as the property instead of \@type when converting from RDF. + * + * @var bool + */ + private $useRdfType; + + /** + * Produce generalized RDF + * + * Unless set to true, triples/quads with a blank node predicate are + * dropped when converting to RDF. + * + * @var bool + */ + private $generalizedRdf; + + /** + * @var array Blank node map + */ + private $blankNodeMap = array(); + + /** + * @var integer Blank node counter + */ + private $blankNodeCounter = 0; + + /** + * @var DocumentFactoryInterface The factory to create new documents + */ + private $documentFactory = null; + + /** + * @var DocumentLoaderInterface The document loader + */ + private $documentLoader = null; + + /** + * Constructor + * + * The options parameter must be passed and all off the following properties + * have to be set: + * + *
+ *
base
+ *
The base IRI.
+ * + *
compactArrays
+ *
If set to true, arrays holding just one element are compacted + * to scalars, otherwise the arrays are kept as arrays.
+ * + *
optimize
+ *
If set to true, the processor is free to optimize the result to + * produce an even compacter representation than the algorithm + * described by the official JSON-LD specification.
+ * + *
useNativeTypes
+ *
If set to true, the processor will try to convert datatyped + * literals to native types instead of using the expanded object form + * when converting from RDF. xsd:boolean values will be + * converted to booleans whereas xsd:integer and + * xsd:double values will be converted to numbers.
+ * + *
useRdfType
+ *
If set to true, the JSON-LD processor will use the expanded + * rdf:type IRI as the property instead of @type + * when converting from RDF.
+ *
+ * + * @param JsonObject $options Options to configure the various algorithms. + */ + public function __construct($options) + { + $this->baseIri = new IRI($options->base); + $this->compactArrays = (bool) $options->compactArrays; + $this->optimize = (bool) $options->optimize; + $this->useNativeTypes = (bool) $options->useNativeTypes; + $this->useRdfType = (bool) $options->useRdfType; + $this->generalizedRdf = (bool) $options->produceGeneralizedRdf; + $this->documentFactory = $options->documentFactory; + $this->documentLoader = $options->documentLoader; + } + + /** + * Parses a JSON-LD document to a PHP value + * + * @param string $document A JSON-LD document. + * + * @return mixed A PHP value. + * + * @throws JsonLdException If the JSON-LD document is not valid. + */ + public static function parse($document) + { + if (function_exists('mb_detect_encoding') && + (false === mb_detect_encoding($document, 'UTF-8', true))) { + throw new JsonLdException( + JsonLdException::LOADING_DOCUMENT_FAILED, + 'The JSON-LD document does not appear to be valid UTF-8.' + ); + } + + $data = json_decode($document, false, 512); + + switch (json_last_error()) { + case JSON_ERROR_NONE: + break; // no error + case JSON_ERROR_DEPTH: + throw new JsonLdException( + JsonLdException::LOADING_DOCUMENT_FAILED, + 'The maximum stack depth has been exceeded.' + ); + case JSON_ERROR_STATE_MISMATCH: + throw new JsonLdException( + JsonLdException::LOADING_DOCUMENT_FAILED, + 'Invalid or malformed JSON.' + ); + case JSON_ERROR_CTRL_CHAR: + throw new JsonLdException( + JsonLdException::LOADING_DOCUMENT_FAILED, + 'Control character error (possibly incorrectly encoded).' + ); + case JSON_ERROR_SYNTAX: + throw new JsonLdException( + JsonLdException::LOADING_DOCUMENT_FAILED, + 'Syntax error, malformed JSON.' + ); + case JSON_ERROR_UTF8: + throw new JsonLdException( + JsonLdException::LOADING_DOCUMENT_FAILED, + 'Malformed UTF-8 characters (possibly incorrectly encoded).' + ); + default: + throw new JsonLdException( + JsonLdException::LOADING_DOCUMENT_FAILED, + 'Unknown error while parsing JSON.' + ); + } + + return (empty($data)) ? null : $data; + } + + /** + * Parses a JSON-LD document and returns it as a Document + * + * @param array|JsonObject $input The JSON-LD document to process. + * + * @return Document The parsed JSON-LD document. + * + * @throws JsonLdException If the JSON-LD input document is invalid. + */ + public function getDocument($input) + { + $nodeMap = new JsonObject(); + $nodeMap->{'-' . JsonLD::DEFAULT_GRAPH} = new JsonObject(); + $this->generateNodeMap($nodeMap, $input); + + // We need to keep track of blank nodes as they are renamed when + // inserted into the Document + $nodes = array(); + + if (null === $this->documentFactory) { + $this->documentFactory = new DefaultDocumentFactory(); + } + + $document = $this->documentFactory->createDocument($this->baseIri); + + foreach ($nodeMap as $graphName => &$nodes) { + $graphName = substr($graphName, 1); + if (JsonLD::DEFAULT_GRAPH === $graphName) { + $graph = $document->getGraph(); + } else { + $graph = $document->createGraph($graphName); + } + + foreach ($nodes as $id => &$item) { + $node = $graph->createNode($item->{'@id'}, true); + unset($item->{'@id'}); + + // Process node type as it needs to be handled differently than + // other properties + // TODO Could this be avoided by enforcing rdf:type instead of @type? + if (property_exists($item, '@type')) { + foreach ($item->{'@type'} as $type) { + $node->addType($graph->createNode($type), true); + } + unset($item->{'@type'}); + } + + foreach ($item as $property => $values) { + foreach ($values as $value) { + if (property_exists($value, '@value')) { + $node->addPropertyValue($property, Value::fromJsonLd($value)); + } elseif (property_exists($value, '@id')) { + $node->addPropertyValue( + $property, + $graph->createNode($value->{'@id'}, true) + ); + } else { + // TODO Handle lists + throw new \Exception('Lists are not supported by getDocument() yet'); + } + } + } + } + } + + + unset($nodeMap); + + return $document; + } + + /** + * Expands a JSON-LD document + * + * @param mixed $element A JSON-LD element to be expanded. + * @param array $activectx The active context. + * @param null|string $activeprty The active property. + * @param boolean $frame True if a frame is being expanded, otherwise false. + * + * @return mixed The expanded document. + * + * @throws JsonLdException + */ + public function expand(&$element, $activectx = array(), $activeprty = null, $frame = false) + { + if (is_scalar($element)) { + + if ((null === $activeprty) || ('@graph' === $activeprty)) { + $element = null; + } else { + $element = $this->expandValue($element, $activectx, $activeprty); + } + + return; + } + + if (null === $element) { + return; + } + + if (is_array($element)) { + $result = array(); + foreach ($element as &$item) { + $this->expand($item, $activectx, $activeprty, $frame); + + // Check for lists of lists + if (('@list' === $this->getPropertyDefinition($activectx, $activeprty, '@container')) || + ('@list' === $activeprty)) { + if (is_array($item) || (is_object($item) && property_exists($item, '@list'))) { + throw new JsonLdException( + JsonLdException::LIST_OF_LISTS, + "List of lists detected in property \"$activeprty\".", + $element + ); + } + } + + if (is_array($item)) { + $result = array_merge($result, $item); + } elseif (null !== $item) { + $result[] = $item; + } + } + + $element = $result; + + return; + } + + // Otherwise it's an object. Process its local context if available + if (property_exists($element, '@context')) { + $this->processContext($element->{'@context'}, $activectx); + unset($element->{'@context'}); + } + + $properties = get_object_vars($element); + ksort($properties); + + $element = new JsonObject(); + + foreach ($properties as $property => $value) { + $expProperty = $this->expandIri($property, $activectx, false, true); + + // Make sure to keep framing keywords if a frame is being expanded + if ($frame && in_array($expProperty, self::$framingKeywords)) { + // and that the default value is expanded + if ('@default' === $expProperty) { + $this->expand($value, $activectx, $activeprty, $frame); + } + + self::setProperty($element, $expProperty, $value, JsonLdException::COLLIDING_KEYWORDS); + continue; + } + + if (in_array($expProperty, self::$keywords)) { + if ('@reverse' === $activeprty) { + throw new JsonLdException( + JsonLdException::INVALID_REVERSE_PROPERTY_MAP, + 'No keywords or keyword aliases are allowed in @reverse-maps, found ' . $expProperty + ); + } + $this->expandKeywordValue($element, $activeprty, $expProperty, $value, $activectx, $frame); + + continue; + } elseif (false === strpos($expProperty, ':')) { + // the expanded property is neither a keyword nor an IRI + continue; + } + + $propertyContainer = $this->getPropertyDefinition($activectx, $property, '@container'); + + if (is_object($value) && in_array($propertyContainer, array('@language', '@index'))) { + $result = array(); + + $value = (array) $value; // makes it easier to order the key-value pairs + ksort($value); + + if ('@language' === $propertyContainer) { + foreach ($value as $key => $val) { + // TODO Make sure key is a valid language tag + + if (false === is_array($val)) { + $val = array($val); + } + + foreach ($val as $item) { + if (false === is_string($item)) { + throw new JsonLdException( + JsonLdException::INVALID_LANGUAGE_MAP_VALUE, + "Detected invalid value in $property->$key: it must be a string as it " . + "is part of a language map.", + $item + ); + } + + $result[] = (object) array( + '@value' => $item, + '@language' => strtolower($key) + ); + } + } + } else { + // @container: @index + foreach ($value as $key => $val) { + if (false === is_array($val)) { + $val = array($val); + } + + $this->expand($val, $activectx, $property, $frame); + + foreach ($val as $item) { + if (false === property_exists($item, '@index')) { + $item->{'@index'} = $key; + } + + $result[] = $item; + } + } + } + + $value = $result; + } else { + $this->expand($value, $activectx, $property, $frame); + } + + // Remove properties with null values + if (null === $value) { + continue; + } + + // If property has an @list container and value is not yet an + // expanded @list-object, transform it to one + if (('@list' === $propertyContainer) && + ((false === is_object($value) || (false === property_exists($value, '@list'))))) { + if (false === is_array($value)) { + $value = array($value); + } + + $obj = new JsonObject(); + $obj->{'@list'} = $value; + $value = $obj; + } + + $target = $element; + if ($this->getPropertyDefinition($activectx, $property, '@reverse')) { + if (false === property_exists($target, '@reverse')) { + $target->{'@reverse'} = new JsonObject(); + } + $target = $target->{'@reverse'}; + + if (false === is_array($value)) { + $value = array($value); + } + + foreach ($value as $val) { + if (property_exists($val, '@value') || property_exists($val, '@list')) { + throw new JsonLdException( + JsonLdException::INVALID_REVERSE_PROPERTY_VALUE, + 'Detected invalid value in @reverse-map (only nodes are allowed', + $val + ); + } + } + } + + self::mergeIntoProperty($target, $expProperty, $value, true); + } + + // All properties have been processed. Make sure the result is valid + // and optimize it where possible + $numProps = count(get_object_vars($element)); + + // Remove free-floating nodes + if ((false === $frame) && ((null === $activeprty) || ('@graph' === $activeprty)) && + (((0 === $numProps) || property_exists($element, '@value') || property_exists($element, '@list') || + ((1 === $numProps) && property_exists($element, '@id'))))) { + + $element = null; + return; + } + + // Indexes are allowed everywhere + if (property_exists($element, '@index')) { + $numProps--; + } + + if (property_exists($element, '@value')) { + $numProps--; // @value + if (property_exists($element, '@language')) { + if (false === $frame) { + if (false === is_string($element->{'@language'})) { + throw new JsonLdException( + JsonLdException::INVALID_LANGUAGE_TAGGED_STRING, + 'Invalid value for @language detected (must be a string).', + $element + ); + } + + if (false === is_string($element->{'@value'})) { + throw new JsonLdException( + JsonLdException::INVALID_LANGUAGE_TAGGED_VALUE, + 'Only strings can be language tagged.', + $element + ); + } + } + + $numProps--; + } elseif (property_exists($element, '@type')) { + if ((false === $frame) && ((false === is_string($element->{'@type'})) || + (false === strpos($element->{'@type'}, ':')) || + ('_:' === substr($element->{'@type'}, 0, 2)))) { + throw new JsonLdException( + JsonLdException::INVALID_TYPED_VALUE, + 'Invalid value for @type detected (must be an IRI).', + $element + ); + } + + $numProps--; + } + + if ($numProps > 0) { + throw new JsonLdException( + JsonLdException::INVALID_VALUE_OBJECT, + 'Detected an invalid @value object.', + $element + ); + } elseif (null === $element->{'@value'}) { + // object has just an @value property that is null, can be replaced with that value + $element = $element->{'@value'}; + } + + return; + } + + // Not an @value object, make sure @type is an array + if (property_exists($element, '@type') && (false === is_array($element->{'@type'}))) { + $element->{'@type'} = array($element->{'@type'}); + } + if (($numProps > 1) && ((property_exists($element, '@list') || property_exists($element, '@set')))) { + throw new JsonLdException( + JsonLdException::INVALID_SET_OR_LIST_OBJECT, + 'An object with a @list or @set property can\'t contain other properties.', + $element + ); + } elseif (property_exists($element, '@set')) { + // @set objects can be optimized away as they are just syntactic sugar + $element = $element->{'@set'}; + } elseif (($numProps === 1) && (false === $frame) && property_exists($element, '@language')) { + // if there's just @language and nothing else and we are not expanding a frame, drop whole object + $element = null; + } + } + + /** + * Expands the value of a keyword + * + * @param JsonObject $element The object this property-value pair is part of. + * @param string $activeprty The active property. + * @param string $keyword The keyword whose value is being expanded. + * @param mixed $value The value to expand. + * @param array $activectx The active context. + * @param boolean $frame True if a frame is being expanded, otherwise false. + * + * @throws JsonLdException + */ + private function expandKeywordValue(&$element, $activeprty, $keyword, $value, $activectx, $frame) + { + // Ignore all null values except for @value as in that case it is + // needed to determine what @type means + if ((null === $value) && ('@value' !== $keyword)) { + return; + } + + if ('@id' === $keyword) { + if (false === is_string($value)) { + throw new JsonLdException( + JsonLdException::INVALID_ID_VALUE, + 'Invalid value for @id detected (must be a string).', + $element + ); + } + + $value = $this->expandIri($value, $activectx, true); + self::setProperty($element, $keyword, $value, JsonLdException::COLLIDING_KEYWORDS); + + return; + } + + if ('@type' === $keyword) { + if (is_string($value)) { + $value = $this->expandIri($value, $activectx, true, true); + self::setProperty($element, $keyword, $value, JsonLdException::COLLIDING_KEYWORDS); + + return; + } + + if (false === is_array($value)) { + $value = array($value); + } + + $result = array(); + + foreach ($value as $item) { + if (is_string($item)) { + $result[] = $this->expandIri($item, $activectx, true, true); + } else { + if (false === $frame) { + throw new JsonLdException( + JsonLdException::INVALID_TYPE_VALUE, + "Invalid value for $keyword detected.", + $value + ); + } + + self::mergeIntoProperty($element, $keyword, $item); + } + } + + // Don't keep empty arrays + if (count($result) >= 1) { + self::mergeIntoProperty($element, $keyword, $result, true); + } + } + + if (('@value' === $keyword)) { + if (false === $frame) { + if ((null !== $value) && (false === is_scalar($value))) { + // we need to preserve @value: null to distinguish values form nodes + throw new JsonLdException( + JsonLdException::INVALID_VALUE_OBJECT_VALUE, + "Invalid value for @value detected (must be a scalar).", + $value + ); + } + } elseif (false === is_array($value)) { + $value = array($value); + } + + self::setProperty($element, $keyword, $value, JsonLdException::COLLIDING_KEYWORDS); + + return; + } + + if (('@language' === $keyword) || ('@index' === $keyword)) { + if (false === $frame) { + if (false === is_string($value)) { + throw ('@language' === $keyword) + ? new JsonLdException( + JsonLdException::INVALID_LANGUAGE_TAGGED_STRING, + '@language must be a string', + $value + ) + : new JsonLdException( + JsonLdException::INVALID_INDEX_VALUE, + '@index must be a string', + $value + ); + } + } elseif (false === is_array($value)) { + $value = array($value); + } + + self::setProperty($element, $keyword, $value, JsonLdException::COLLIDING_KEYWORDS); + + return; + } + + // TODO Optimize the following code, there's a lot of repetition, only the $activeprty param is changing + if ('@list' === $keyword) { + if ((null === $activeprty) || ('@graph' === $activeprty)) { + return; + } + + $this->expand($value, $activectx, $activeprty, $frame); + + if (false === is_array($value)) { + $value = array($value); + } + + foreach ($value as $val) { + if (is_object($val) && property_exists($val, '@list')) { + throw new JsonLdException(JsonLdException::LIST_OF_LISTS, 'List of lists detected.', $element); + } + } + + self::mergeIntoProperty($element, $keyword, $value, true); + + return; + } + + if ('@set' === $keyword) { + $this->expand($value, $activectx, $activeprty, $frame); + self::mergeIntoProperty($element, $keyword, $value, true); + + return; + } + + if ('@reverse' === $keyword) { + if (false === is_object($value)) { + throw new JsonLdException( + JsonLdException::INVALID_REVERSE_VALUE, + 'Detected invalid value for @reverse (must be an object).', + $value + ); + } + + $this->expand($value, $activectx, $keyword, $frame); + + // Do not create @reverse-containers inside @reverse containers + if (property_exists($value, $keyword)) { + foreach (get_object_vars($value->{$keyword}) as $prop => $val) { + self::mergeIntoProperty($element, $prop, $val, true); + } + + unset($value->{$keyword}); + } + + $value = get_object_vars($value); + + if ((count($value) > 0) && (false === property_exists($element, $keyword))) { + $element->{$keyword} = new JsonObject(); + } + + foreach ($value as $prop => $val) { + foreach ($val as $v) { + if (property_exists($v, '@value') || property_exists($v, '@list')) { + throw new JsonLdException( + JsonLdException::INVALID_REVERSE_PROPERTY_VALUE, + 'Detected invalid value in @reverse-map (only nodes are allowed', + $v + ); + } + self::mergeIntoProperty($element->{$keyword}, $prop, $v, true); + } + } + + return; + } + + if ('@graph' === $keyword) { + $this->expand($value, $activectx, $keyword, $frame); + self::mergeIntoProperty($element, $keyword, $value, true); + + return; + } + } + + /** + * Expands a scalar value + * + * @param mixed $value The value to expand. + * @param array $activectx The active context. + * @param string $activeprty The active property. + * + * @return JsonObject The expanded value. + */ + private function expandValue($value, $activectx, $activeprty) + { + $def = $this->getPropertyDefinition($activectx, $activeprty); + + $result = new JsonObject(); + + if ('@id' === $def['@type']) { + $result->{'@id'} = $this->expandIri($value, $activectx, true); + } elseif ('@vocab' === $def['@type']) { + $result->{'@id'} = $this->expandIri($value, $activectx, true, true); + } else { + $result->{'@value'} = $value; + + if (isset($def['@type'])) { + $result->{'@type'} = $def['@type']; + } elseif (isset($def['@language']) && is_string($result->{'@value'})) { + $result->{'@language'} = $def['@language']; + } + } + + return $result; + } + + /** + * Expands a JSON-LD IRI value (term, compact IRI, IRI) to an absolute + * IRI and relabels blank nodes + * + * @param mixed $value The value to be expanded to an absolute IRI. + * @param array $activectx The active context. + * @param bool $relativeIri Specifies whether $value should be treated as + * relative IRI against the base IRI or not. + * @param bool $vocabRelative Specifies whether $value is relative to @vocab + * if set or not. + * @param null|JsonObject $localctx If the IRI is being expanded as part of context + * processing, the current local context has to be + * passed as well. + * @param array $path A path of already processed terms to detect + * circular dependencies + * + * @return string The expanded IRI. + */ + private function expandIri( + $value, + $activectx, + $relativeIri = false, + $vocabRelative = false, + $localctx = null, + $path = array() + ) { + if ((null === $value) || in_array($value, self::$keywords)) { + return $value; + } + + if ($localctx) { + if (in_array($value, $path)) { + throw new JsonLdException( + JsonLdException::CYCLIC_IRI_MAPPING, + 'Cycle in context definition detected: ' . join(' -> ', $path) . ' -> ' . $path[0], + $localctx + ); + } else { + $path[] = $value; + + if (count($path) >= self::CONTEXT_MAX_IRI_RECURSIONS) { + throw new JsonLdException( + JsonLdException::UNSPECIFIED, + 'Too many recursions in term definition: ' . join(' -> ', $path) . ' -> ' . $path[0], + $localctx + ); + } + } + + if (isset($localctx->{$value})) { + $nested = null; + + if (is_string($localctx->{$value})) { + $nested = $localctx->{$value}; + } elseif (isset($localctx->{$value}->{'@id'})) { + $nested = $localctx->{$value}->{'@id'}; + } + + if ($nested && (end($path) !== $nested)) { + return $this->expandIri($nested, $activectx, false, true, $localctx, $path); + } + } + } + + // Terms apply only for vocab-relative IRIs + if ((true === $vocabRelative) && array_key_exists($value, $activectx)) { + return $activectx[$value]['@id']; + } + + if (false !== strpos($value, ':')) { + list($prefix, $suffix) = explode(':', $value, 2); + + if (('_' === $prefix) || ('//' === substr($suffix, 0, 2))) { + // Safety measure to prevent reassigned of, e.g., http:// + // the "_" prefix is reserved for blank nodes and can't be expanded + return $value; + } + + if ($localctx) { + $prefix = $this->expandIri($prefix, $activectx, false, true, $localctx, $path); + + // If prefix contains a colon, we have successfully expanded it + if (false !== strpos($prefix, ':')) { + return $prefix . $suffix; + } + } elseif (array_key_exists($prefix, $activectx)) { + // compact IRI + return $activectx[$prefix]['@id'] . $suffix; + } + } else { + if ($vocabRelative && array_key_exists('@vocab', $activectx)) { + return $activectx['@vocab'] . $value; + } elseif (($relativeIri) && (null !== $activectx['@base'])) { + return (string) $activectx['@base']->resolve($value); + } + } + + // can't expand it, return as is + return $value; + } + + /** + * Compacts a JSON-LD document + * + * Attention: This method must be called with an expanded element, + * otherwise it might not work. + * + * @param mixed $element A JSON-LD element to be compacted. + * @param array $activectx The active context. + * @param array $inversectx The inverse context. + * @param null|string $activeprty The active property. + * + * @return mixed The compacted JSON-LD document. + */ + public function compact(&$element, $activectx = array(), $inversectx = array(), $activeprty = null) + { + if (is_array($element)) { + $result = array(); + foreach ($element as &$item) { + $this->compact($item, $activectx, $inversectx, $activeprty); + if (null !== $item) { + $result[] = $item; + } + } + + if ($this->compactArrays && (1 === count($result))) { + $element = $result[0]; + } else { + $element = $result; + } + + return; + } + + if (false === is_object($element)) { + // element is already in compact form, nothing else to do + return; + } + + if (property_exists($element, '@value') || property_exists($element, '@id')) { + $def = $this->getPropertyDefinition($activectx, $activeprty); + $element = $this->compactValue($element, $def, $activectx, $inversectx); + + if (false === is_object($element)) { + return; + } + } + + // Otherwise, compact all properties + $properties = get_object_vars($element); + ksort($properties); + + $inReverse = ('@reverse' === $activeprty); + $element = new JsonObject(); + + foreach ($properties as $property => $value) { + if (in_array($property, self::$keywords)) { + if ('@id' === $property) { + $value = $this->compactIri($value, $activectx, $inversectx); + } elseif ('@type' === $property) { + if (is_string($value)) { + $value = $this->compactIri($value, $activectx, $inversectx, null, true); + } else { + foreach ($value as &$iri) { + $iri = $this->compactIri($iri, $activectx, $inversectx, null, true); + } + + if ($this->compactArrays && (1 === count($value))) { + $value = $value[0]; + } + } + } elseif (('@graph' === $property) || ('@list' === $property)) { + $this->compact($value, $activectx, $inversectx, $property); + + if (false === is_array($value)) { + $value = array($value); + } + } elseif ('@reverse' === $property) { + $this->compact($value, $activectx, $inversectx, $property); + + // Move reverse properties out of the map into element + foreach (get_object_vars($value) as $prop => $val) { + if ($this->getPropertyDefinition($activectx, $prop, '@reverse')) { + $alwaysArray = ('@set' === $this->getPropertyDefinition($activectx, $prop, '@container')); + self::mergeIntoProperty($element, $prop, $val, $alwaysArray); + unset($value->{$prop}); + } + } + + if (0 === count(get_object_vars($value))) { + continue; // no properties left in the @reverse-map + } + } + + // Get the keyword alias from the inverse context if available + $activeprty = (isset($inversectx[$property]['term'])) + ? $inversectx[$property]['term'] + : $property; + + self::setProperty($element, $activeprty, $value, JsonLdException::COLLIDING_KEYWORDS); + + // ... continue with next property + continue; + } + + // handle @null-objects as used in framing + if (is_object($value) && property_exists($value, '@null')) { + $activeprty = $this->compactIri($property, $activectx, $inversectx, null, true, $inReverse); + + if (false === property_exists($element, $activeprty)) { + $element->{$activeprty} = null; + } + + continue; + } + + // Make sure that empty arrays are preserved + if (0 === count($value)) { + $activeprty = $this->compactIri($property, $activectx, $inversectx, null, true, $inReverse); + + self::mergeIntoProperty($element, $activeprty, $value); + + // ... continue with next property + continue; + } + + // Compact every item in value separately as they could map to different terms + foreach ($value as $item) { + $activeprty = $this->compactIri($property, $activectx, $inversectx, $item, true, $inReverse); + $def = $this->getPropertyDefinition($activectx, $activeprty); + + if (in_array($def['@container'], array('@language', '@index'))) { + if (false === property_exists($element, $activeprty)) { + $element->{$activeprty} = new JsonObject(); + } + + $def[$def['@container']] = $item->{$def['@container']}; + $item = $this->compactValue($item, $def, $activectx, $inversectx); + + $this->compact($item, $activectx, $inversectx, $activeprty); + + self::mergeIntoProperty($element->{$activeprty}, $def[$def['@container']], $item); + + continue; + } + + if (is_object($item)) { + if (property_exists($item, '@list')) { + $this->compact($item->{'@list'}, $activectx, $inversectx, $activeprty); + + if (false === is_array($item->{'@list'})) { + $item->{'@list'} = array($item->{'@list'}); + } + + if ('@list' === $def['@container']) { + // a term can just hold one list if it has a @list container + // (we don't support lists of lists) + self::setProperty( + $element, + $activeprty, + $item->{'@list'}, + JsonLdException::COMPACTION_TO_LIST_OF_LISTS + ); + + continue; // ... continue with next value + } else { + $result = new JsonObject(); + + $alias = $this->compactIri('@list', $activectx, $inversectx, null, true); + $result->{$alias} = $item->{'@list'}; + + if (isset($item->{'@index'})) { + $alias = $this->compactIri('@index', $activectx, $inversectx, null, true); + $result->{$alias} = $item->{'@index'}; + } + + $item = $result; + } + } else { + $this->compact($item, $activectx, $inversectx, $activeprty); + } + } + + // Merge value back into resulting object making sure that value is always + // an array if a container is set or compactArrays is set to false + $asArray = ((false === $this->compactArrays) || (false === $def['compactArrays'])); + + self::mergeIntoProperty($element, $activeprty, $item, $asArray); + } + } + } + + /** + * Compacts a value + * + * The passed property definition must be an associative array + * containing the following data: + * + * + * @type => type IRI or null + * @language => language code or null + * @index => index string or null + * @container => the container: @set, @list, @language, or @index + * + * + * @param mixed $value The value to compact (arrays are not allowed!). + * @param array $definition The active property's definition. + * @param array $activectx The active context. + * @param array $inversectx The inverse context. + * + * @return mixed The compacted value. + */ + private function compactValue($value, $definition, $activectx, $inversectx) + { + if ('@index' === $definition['@container']) { + unset($value->{'@index'}); + } + + $numProperties = count(get_object_vars($value)); + + // @id object + if (property_exists($value, '@id')) { + if (1 === $numProperties) { + if ('@id' === $definition['@type']) { + return $this->compactIri($value->{'@id'}, $activectx, $inversectx); + } + + if ('@vocab' === $definition['@type']) { + return $this->compactIri($value->{'@id'}, $activectx, $inversectx, null, true); + } + } + + return $value; + } + + // @value object + $criterion = (isset($value->{'@type'})) ? '@type' : null; + $criterion = (isset($value->{'@language'})) ? '@language' : $criterion; + + if (null !== $criterion) { + if ((2 === $numProperties) && ($value->{$criterion} === $definition[$criterion])) { + return $value->{'@value'}; + } + + return $value; + } + + // the object has neither a @type nor a @language property + // check the active property's definition + if (is_string($value->{'@value'}) && (null !== $definition['@language'])) { + // if the property is language tagged or there's a default language, + // we can't compact the value if it is a string + return $value; + } + + // we can compact the value + return (1 === $numProperties) ? $value->{'@value'} : $value; + } + + /** + * Compacts an absolute IRI (or aliases a keyword) + * + * If the IRI couldn't be compacted, the IRI is returned as is. + * + * @param mixed $iri The IRI to be compacted. + * @param array $activectx The active context. + * @param array $inversectx The inverse context. + * @param mixed $value The value of the property to compact. + * @param bool $vocabRelative If `true` is passed, this method tries + * to convert the IRI to an IRI relative to + * `@vocab`; otherwise, that fall back + * mechanism is disabled. + * @param bool $reverse Is the IRI used within a @reverse container? + * + * @return string Returns the compacted IRI on success; otherwise the + * IRI is returned as is. + */ + private function compactIri($iri, $activectx, $inversectx, $value = null, $vocabRelative = false, $reverse = false) + { + if ((true === $vocabRelative) && array_key_exists($iri, $inversectx)) { + if (null !== $value) { + $valueProfile = $this->getValueProfile($value, $inversectx); + + $container = ('@list' === $valueProfile['@container']) + ? array('@list', '@null') + : array($valueProfile['@container'], '@set', '@null'); + + if (null === $valueProfile['typeLang']) { + $typeOrLang = array('@null'); + $typeOrLangValue = array('@null'); + } else { + $typeOrLang = array($valueProfile['typeLang'], '@null'); + $typeOrLangValue = array(); + + if (true === $reverse) { + $typeOrLangValue[] = '@reverse'; + } + + if (('@type' === $valueProfile['typeLang']) && ('@id' === $valueProfile['typeLangValue'])) { + array_push($typeOrLangValue, '@id', '@vocab', '@null'); + } elseif (('@type' === $valueProfile['typeLang']) && + ('@vocab' === $valueProfile['typeLangValue'])) { + array_push($typeOrLangValue, '@vocab', '@id', '@null'); + } else { + $typeOrLangValue = array($valueProfile['typeLangValue'], '@null'); + } + } + + $result = $this->queryInverseContext($inversectx[$iri], $container, $typeOrLang, $typeOrLangValue); + + if (null !== $result) { + return $result; + } + } elseif (isset($inversectx[$iri]['term'])) { + return $inversectx[$iri]['term']; + } + } + + // Compact using @vocab + if ($vocabRelative && isset($activectx['@vocab']) && (0 === strpos($iri, $activectx['@vocab'])) && + (false !== ($vocabIri = substr($iri, strlen($activectx['@vocab'])))) && + (false === isset($activectx[$vocabIri]))) { + return $vocabIri; + } + + // Try to compact to a compact IRI + foreach ($inversectx as $termIri => $def) { + $termIriLen = strlen($termIri); + + if (isset($def['term']) && (0 === strncmp($iri, $termIri, $termIriLen))) { + $compactIri = substr($iri, $termIriLen); + + if (false !== $compactIri && '' !== $compactIri) { + $compactIri = $def['term'] . ':' . $compactIri; + + if (false === isset($activectx[$compactIri]) || + ((false === $vocabRelative) && ($iri === $activectx[$compactIri]['@id']))) { + return $compactIri; + } + } + } + } + + // Last resort, convert to a relative IRI + if ((false === $vocabRelative) && (null !== $activectx['@base'])) { + return (string) $activectx['@base']->baseFor($iri); + } + + // IRI couldn't be compacted, return as is + return $iri; + } + + /** + * Verifies whether two JSON-LD subtrees are equal not + * + * Please note that two unlabeled blank nodes will never be equal by + * definition. + * + * @param mixed $a The first subtree. + * @param mixed $b The second subree. + * + * @return bool Returns true if the two subtrees are equal; otherwise + * false. + */ + private static function subtreeEquals($a, $b) + { + if (gettype($a) !== gettype($b)) { + return false; + } + + if (is_scalar($a)) { + return ($a === $b); + } + + if (is_array($a)) { + $len = count($a); + + if ($len !== count($b)) { + return false; + } + + // TODO Ignore order for sets? + for ($i = 0; $i < $len; $i++) { + if (false === self::subtreeEquals($a[$i], $b[$i])) { + return false; + } + } + + return true; + } + + if (!property_exists($a, '@id') && + !property_exists($a, '@value') && + !property_exists($a, '@list')) { + // Blank nodes can never match as they can't be identified + return false; + } + + $properties = array_keys(get_object_vars($a)); + + if (count($properties) !== count(get_object_vars($b))) { + return false; + } + + foreach ($properties as $property) { + if ((false === property_exists($b, $property)) || + (false === self::subtreeEquals($a->{$property}, $b->{$property}))) { + return false; + } + } + + return true; + } + + /** + * Calculates a value profile + * + * A value profile represent the schema of the value ignoring the + * concrete value. It is an associative array containing the following + * keys-value pairs: + * + * * `@container`: the container, defaults to `@set` + * * `typeLang`: is set to `@type` for typed values or `@language` for + * (language-tagged) strings; for all other values it is set to + * `null` + * * `typeLangValue`: set to the type of a typed value or the language + * of a language-tagged string (`@null` for all other strings); for + * all other values it is set to `null` + * + * @param JsonObject $value The value. + * @param array $inversectx The inverse context. + * + * @return array The value profile. + */ + private function getValueProfile(JsonObject $value, $inversectx) + { + $valueProfile = array( + '@container' => '@set', + 'typeLang' => '@type', + 'typeLangValue' => '@id' + ); + + if (property_exists($value, '@index')) { + $valueProfile['@container'] = '@index'; + } + + if (property_exists($value, '@id')) { + if (isset($inversectx[$value->{'@id'}]['term'])) { + $valueProfile['typeLangValue'] = '@vocab'; + } else { + $valueProfile['typeLangValue'] = '@id'; + } + + return $valueProfile; + } + + if (property_exists($value, '@value')) { + if (property_exists($value, '@type')) { + $valueProfile['typeLang'] = '@type'; + $valueProfile['typeLangValue'] = $value->{'@type'}; + } elseif (property_exists($value, '@language')) { + $valueProfile['typeLang'] = '@language'; + $valueProfile['typeLangValue'] = $value->{'@language'}; + + if (false === property_exists($value, '@index')) { + $valueProfile['@container'] = '@language'; + } + } else { + $valueProfile['typeLang'] = '@language'; + $valueProfile['typeLangValue'] = '@null'; + } + + return $valueProfile; + } + + if (property_exists($value, '@list')) { + $len = count($value->{'@list'}); + + if ($len > 0) { + $valueProfile = $this->getValueProfile($value->{'@list'}[0], $inversectx); + } + + if (false === property_exists($value, '@index')) { + $valueProfile['@container'] = '@list'; + } + + + for ($i = $len - 1; $i > 0; $i--) { + $profile = $this->getValueProfile($value->{'@list'}[$i], $inversectx); + + if (($valueProfile['typeLang'] !== $profile['typeLang']) || + ($valueProfile['typeLangValue'] !== $profile['typeLangValue'])) { + $valueProfile['typeLang'] = null; + $valueProfile['typeLangValue'] = null; + + return $valueProfile; + } + } + } + + return $valueProfile; + } + + /** + * Queries the inverse context to find the term for a given query + * path (= value profile) + * + * @param array $inversectx The inverse context (or a subtree thereof) + * @param string[] $containers + * @param string[] $typeOrLangs + * @param string[] $typeOrLangValues + * + * @return null|string The best matching term or null if none was found. + */ + private function queryInverseContext($inversectx, $containers, $typeOrLangs, $typeOrLangValues) + { + foreach ($containers as $container) { + foreach ($typeOrLangs as $typeOrLang) { + foreach ($typeOrLangValues as $typeOrLangValue) { + if (isset($inversectx[$container][$typeOrLang][$typeOrLangValue])) { + return $inversectx[$container][$typeOrLang][$typeOrLangValue]; + } + } + } + } + + return null; + } + + /** + * Returns a property's definition + * + * The result will be in the form + * + * + * array('@type' => type or null, + * '@language' => language or null, + * '@container' => container or null, + * 'isKeyword' => true or false) + * + * + * If `$only` is set, only the value of that key of the array + * above will be returned. + * + * @param array $activectx The active context. + * @param string $property The property. + * @param null|string $only If set, only this element of the + * definition will be returned. + * + * @return array|string|null Returns either the property's definition or + * null if not found. + */ + private function getPropertyDefinition($activectx, $property, $only = null) + { + $result = array( + '@reverse' => false, + '@type' => null, + '@language' => (isset($activectx['@language'])) + ? $activectx['@language'] + : null, + '@index' => null, + '@container' => null, + 'isKeyword' => false, + 'compactArrays' => true + ); + + if (in_array($property, self::$keywords)) { + $result['@type'] = (('@id' === $property) || ('@type' === $property)) + ? '@id' + : null; + $result['@language'] = null; + $result['isKeyword'] = true; + $result['compactArrays'] = (bool) (('@list' !== $property) && ('@graph' !== $property)); + } else { + $def = (isset($activectx[$property])) ? $activectx[$property] : null; + + if (null !== $def) { + $result['@id'] = $def['@id']; + $result['@reverse'] = $def['@reverse']; + + if (isset($def['@type'])) { + $result['@type'] = $def['@type']; + $result['@language'] = null; + } elseif (array_key_exists('@language', $def)) { // could be null + $result['@language'] = $def['@language']; + } + + if (isset($def['@container'])) { + $result['@container'] = $def['@container']; + + if (('@list' === $def['@container']) || ('@set' === $def['@container'])) { + $result['compactArrays'] = false; + } + } + } + } + + if ($only) { + return (isset($result[$only])) ? $result[$only] : null; + } + + return $result; + } + + /** + * Processes a local context to update the active context + * + * @param mixed $loclctx The local context. + * @param array $activectx The active context. + * @param array $remotectxs The already included remote contexts. + * + * @throws JsonLdException + */ + public function processContext($loclctx, &$activectx, $remotectxs = array()) + { + if (is_object($loclctx)) { + $loclctx = clone $loclctx; + } + + if (false === is_array($loclctx)) { + $loclctx = array($loclctx); + } + + foreach ($loclctx as $context) { + if (null === $context) { + $activectx = array('@base' => $this->baseIri); + } elseif (is_object($context)) { + // make sure we don't modify the passed context + $context = clone $context; + + if (property_exists($context, '@base')) { + if (count($remotectxs) > 0) { + // do nothing, @base is ignored in a remote context + } elseif (null === $context->{'@base'}) { + $activectx['@base'] = null; + } elseif (false === is_string($context->{'@base'})) { + throw new JsonLdException( + JsonLdException::INVALID_BASE_IRI, + 'The value of @base must be an IRI or null.', + $context + ); + } else { + $base = new IRI($context->{'@base'}); + if (false === $base->isAbsolute()) { + if (null === $activectx['@base']) { + throw new JsonLdException( + JsonLdException::INVALID_BASE_IRI, + 'The relative base IRI cannot be resolved to an absolute IRI.', + $context + ); + } + + $activectx['@base'] = $activectx['@base']->resolve($base); + } else { + $activectx['@base'] = $base; + } + } + + unset($context->{'@base'}); + } + + if (property_exists($context, '@vocab')) { + if (null === $context->{'@vocab'}) { + unset($activectx['@vocab']); + } elseif ((false === is_string($context->{'@vocab'})) || + (false === strpos($context->{'@vocab'}, ':'))) { + throw new JsonLdException( + JsonLdException::INVALID_VOCAB_MAPPING, + 'The value of @vocab must be an absolute IRI or null.invalid vocab mapping, ', + $context + ); + } else { + $activectx['@vocab'] = $context->{'@vocab'}; + } + + unset($context->{'@vocab'}); + } + + if (property_exists($context, '@language')) { + if ((null !== $context->{'@language'}) && (false === is_string($context->{'@language'}))) { + throw new JsonLdException( + JsonLdException::INVALID_DEFAULT_LANGUAGE, + 'The value of @language must be a string.', + $context + ); + } + + $activectx['@language'] = $context->{'@language'}; + unset($context->{'@language'}); + } + + foreach ($context as $key => $value) { + unset($context->{$key}); + unset($activectx[$key]); + + if (in_array($key, self::$keywords)) { + throw new JsonLdException(JsonLdException::KEYWORD_REDEFINITION, null, $key); + } + + if ((null === $value) || is_string($value)) { + $value = (object) array('@id' => $value); + } elseif (is_object($value)) { + $value = clone $value; // make sure we don't modify context entries + } else { + throw new JsonLdException(JsonLdException::INVALID_TERM_DEFINITION); + } + + if (property_exists($value, '@reverse')) { + if (property_exists($value, '@id')) { + throw new JsonLdException( + JsonLdException::INVALID_REVERSE_PROPERTY, + "Invalid term definition using both @reverse and @id detected", + $value + ); + } + + if (property_exists($value, '@container') && + ('@index' !== $value->{'@container'}) && + ('@set' !== $value->{'@container'})) { + throw new JsonLdException( + JsonLdException::INVALID_REVERSE_PROPERTY, + "Terms using the @reverse feature support only @set- and @index-containers.", + $value + ); + } + + $value->{'@id'} = $value->{'@reverse'}; + $value->{'@reverse'} = true; + } else { + $value->{'@reverse'} = false; + } + + if (property_exists($value, '@id')) { + if ((null !== $value->{'@id'}) && (false === is_string($value->{'@id'}))) { + throw new JsonLdException(JsonLdException::INVALID_IRI_MAPPING, null, $value->{'@id'}); + } + + $path = array(); + if ($key !== $value->{'@id'}) { + $path[] = $key; + } + + $expanded = $this->expandIri($value->{'@id'}, $activectx, false, true, $context, $path); + + if ($value->{'@reverse'} && (false === strpos($expanded, ':'))) { + throw new JsonLdException( + JsonLdException::INVALID_IRI_MAPPING, + "Reverse properties must expand to absolute IRIs, \"$key\" expands to \"$expanded\"." + ); + } elseif ('@context' === $expanded) { + throw new JsonLdException( + JsonLdException::INVALID_KEYWORD_ALIAS, + 'Aliases for @context are not supported', + $value + ); + } + } else { + $expanded = $this->expandIri($key, $activectx, false, true, $context); + } + + + if ((null === $expanded) || in_array($expanded, self::$keywords)) { + // if it's an aliased keyword or the IRI is null, we ignore all other properties + // TODO Should we throw an exception if there are other properties? + $activectx[$key] = array('@id' => $expanded, '@reverse' => false); + + continue; + } elseif (false === strpos($expanded, ':')) { + throw new JsonLdException( + JsonLdException::INVALID_IRI_MAPPING, + "Failed to expand \"$key\" to an absolute IRI.", + $loclctx + ); + } + + $activectx[$key] = array('@id' => $expanded, '@reverse' => $value->{'@reverse'}); + + if (isset($value->{'@type'})) { + if (false === is_string($value->{'@type'})) { + throw new JsonLdException(JsonLdException::INVALID_TYPE_MAPPING); + } + + $expanded = $this->expandIri($value->{'@type'}, $activectx, false, true, $context); + + if (('@id' !== $expanded) && ('@vocab' !== $expanded) && + ((false === strpos($expanded, ':') || (0 === strpos($expanded, '_:'))))) { + throw new JsonLdException( + JsonLdException::INVALID_TYPE_MAPPING, + "Failed to expand $expanded to an absolute IRI.", + $loclctx + ); + } + + $activectx[$key]['@type'] = $expanded; + } elseif (property_exists($value, '@language')) { + if ((false === is_string($value->{'@language'})) && (null !== $value->{'@language'})) { + throw new JsonLdException( + JsonLdException::INVALID_LANGUAGE_MAPPING, + 'The value of @language must be a string or null.', + $value + ); + } + + // Note the else. Language tagging applies just to term without type coercion + $activectx[$key]['@language'] = $value->{'@language'}; + } + + if (isset($value->{'@container'})) { + if (in_array($value->{'@container'}, array('@list', '@set', '@language', '@index'))) { + $activectx[$key]['@container'] = $value->{'@container'}; + } else { + throw new JsonLdException( + JsonLdException::INVALID_CONTAINER_MAPPING, + 'A container mapping of ' . $value->{'@container'} . ' is not supported.' + ); + } + } + } + } elseif (is_string($context)) { + $remoteContext = new IRI($context); + if ($remoteContext->isAbsolute()) { + $remoteContext = (string) $remoteContext; + } elseif (null === $activectx['@base']) { + throw new JsonLdException( + JsonLdException::INVALID_BASE_IRI, + 'Can not resolve the relative URL of the remote context as no base has been set: ' . $remoteContext + ); + } else { + $remoteContext = (string) $activectx['@base']->resolve($context); + } + if (in_array($remoteContext, $remotectxs)) { + throw new JsonLdException( + JsonLdException::RECURSIVE_CONTEXT_INCLUSION, + 'Recursive inclusion of remote context: ' . join(' -> ', $remotectxs) . ' -> ' . $remoteContext + ); + } + $remotectxs[] = $remoteContext; + + try { + $remoteContext = $this->loadDocument($remoteContext); + } catch (JsonLdException $e) { + throw new JsonLdException( + JsonLdException::LOADING_REMOTE_CONTEXT_FAILED, + "Loading $remoteContext failed", + null, + null, + $e + ); + } + + if (is_object($remoteContext) && property_exists($remoteContext, '@context')) { + // TODO Use the context's IRI as base IRI when processing remote contexts (ISSUE-24) + $this->processContext($remoteContext->{'@context'}, $activectx, $remotectxs); + } else { + throw new JsonLdException( + JsonLdException::INVALID_REMOTE_CONTEXT, + 'Remote context "' . $context . '" is invalid.', + $remoteContext + ); + } + } else { + throw new JsonLdException(JsonLdException::INVALID_LOCAL_CONTEXT); + } + } + } + + /** + * Load a JSON-LD document + * + * The document can be supplied directly as string, by passing a file + * path, or by passing a URL. + * + * @param null|string|array|JsonObject $input The JSON-LD document or a path + * or URL pointing to one. + * + * @return mixed The loaded JSON-LD document + * + * @throws JsonLdException + */ + private function loadDocument($input) + { + if (false === is_string($input)) { + // Return as is - it has already been parsed + return $input; + } + + $document = $this->documentLoader->loadDocument($input); + + return $document->document; + } + + /** + * Creates an inverse context to simplify IRI compaction + * + * The inverse context is a multidimensional array that has the + * following shape: + * + * + * [container|@null|term] + * [@type|@language][typeIRI|languageCode] + * [@null][@null] + * [term|propGen] + * [ array of terms ] + * + * + * @param array $activectx The active context. + * + * @return array The inverse context. + */ + public function createInverseContext($activectx) + { + $inverseContext = array(); + + $defaultLanguage = isset($activectx['@language']) ? $activectx['@language'] : '@null'; + $propertyGenerators = isset($activectx['@propertyGenerators']) ? $activectx['@propertyGenerators'] : array(); + + unset($activectx['@base']); + unset($activectx['@vocab']); + unset($activectx['@language']); + unset($activectx['@propertyGenerators']); + + $activectx = array_merge($activectx, $propertyGenerators); + unset($propertyGenerators); + + uksort($activectx, array($this, 'sortTerms')); + + // Put every IRI of each term into the inverse context + foreach ($activectx as $term => $def) { + if (null === $def['@id']) { + // this is necessary since some terms can be decoupled from @vocab + continue; + } + + $container = (isset($def['@container'])) ? $def['@container'] : '@null'; + $iri = $def['@id']; + + if (false === isset($inverseContext[$iri]['term']) && (false === $def['@reverse'])) { + $inverseContext[$iri]['term'] = $term; + } + + $typeOrLang = '@null'; + $typeLangValue = '@null'; + + if (true === $def['@reverse']) { + $typeOrLang = '@type'; + $typeLangValue = '@reverse'; + } elseif (isset($def['@type'])) { + $typeOrLang = '@type'; + $typeLangValue = $def['@type']; + } elseif (array_key_exists('@language', $def)) { // can be null + $typeOrLang = '@language'; + $typeLangValue = (null === $def['@language']) ? '@null' : $def['@language']; + } else { + // Every untyped term is implicitly set to the default language + if (false === isset($inverseContext[$iri][$container]['@language'][$defaultLanguage])) { + $inverseContext[$iri][$container]['@language'][$defaultLanguage] = $term; + } + } + + if (false === isset($inverseContext[$iri][$container][$typeOrLang][$typeLangValue])) { + $inverseContext[$iri][$container][$typeOrLang][$typeLangValue] = $term; + } + } + + // Sort the whole inverse context in reverse order, the longest IRI comes first + uksort($inverseContext, array($this, 'sortTerms')); + $inverseContext = array_reverse($inverseContext); + + return $inverseContext; + } + + /** + * Creates a node map of an expanded JSON-LD document + * + * All keys in the node map are prefixed with "-" to support empty strings. + * + * @param JsonObject $nodeMap The object holding the node map. + * @param JsonObject|JsonObject[] $element An expanded JSON-LD element to + * be put into the node map + * @param string $activegraph The graph currently being processed. + * @param null|string $activeid The node currently being processed. + * @param null|string $activeprty The property currently being processed. + * @param null|JsonObject $list The list object if a list is being + * processed. + */ + private function generateNodeMap( + &$nodeMap, + $element, + $activegraph = JsonLD::DEFAULT_GRAPH, + $activeid = null, + $activeprty = null, + &$list = null + ) { + if (is_array($element)) { + foreach ($element as $item) { + $this->generateNodeMap($nodeMap, $item, $activegraph, $activeid, $activeprty, $list); + } + + return; + } + + // Relabel blank nodes in @type and add a node to the current graph + if (property_exists($element, '@type')) { + $types = null; + + if (is_array($element->{'@type'})) { + $types = &$element->{'@type'}; + } else { + $types = array(&$element->{'@type'}); + } + + foreach ($types as &$type) { + if (0 === strncmp($type, '_:', 2)) { + $type = $this->getBlankNodeId($type); + } + } + } + + if (property_exists($element, '@value')) { + // Handle value objects + if (null === $list) { + $this->mergeIntoProperty( + $nodeMap->{'-' . $activegraph}->{'-' . $activeid}, + $activeprty, + $element, + true, + true + ); + } else { + $this->mergeIntoProperty($list, '@list', $element, true, false); + } + } elseif (property_exists($element, '@list')) { + // lists + $result = new JsonObject(); + $result->{'@list'} = array(); + + $this->generateNodeMap($nodeMap, $element->{'@list'}, $activegraph, $activeid, $activeprty, $result); + $this->mergeIntoProperty( + $nodeMap->{'-' . $activegraph}->{'-' . $activeid}, + $activeprty, + $result, + true, + false + ); + } else { + // and node objects + if (false === property_exists($element, '@id')) { + $id = $this->getBlankNodeId(); + } elseif (0 === strncmp($element->{'@id'}, '_:', 2)) { + $id = $this->getBlankNodeId($element->{'@id'}); + } else { + $id = $element->{'@id'}; + } + unset($element->{'@id'}); + + // Create node in node map if it doesn't exist yet + if (false === property_exists($nodeMap->{'-' . $activegraph}, '-' . $id)) { + $node = new JsonObject(); + $node->{'@id'} = $id; + $nodeMap->{'-' . $activegraph}->{'-' . $id} = $node; + } else { + $node = $nodeMap->{'-' . $activegraph}->{'-' . $id}; + } + + // Add reference to active property + if (is_object($activeid)) { + $this->mergeIntoProperty($node, $activeprty, $activeid, true, true); + } elseif (null !== $activeprty) { + $reference = new JsonObject(); + $reference->{'@id'} = $id; + + if (null === $list) { + $this->mergeIntoProperty( + $nodeMap->{'-' . $activegraph}->{'-' . $activeid}, + $activeprty, + $reference, + true, + true + ); + } else { + $this->mergeIntoProperty($list, '@list', $reference, true, false); + } + } + + if (property_exists($element, '@type')) { + $this->mergeIntoProperty($node, '@type', $element->{'@type'}, true, true); + unset($element->{'@type'}); + } + + if (property_exists($element, '@index')) { + $this->setProperty( + $node, + '@index', + $element->{'@index'}, + JsonLdException::CONFLICTING_INDEXES + ); + unset($element->{'@index'}); + } + + if (property_exists($element, '@reverse')) { + $reference = array('@id' => $id); + + // First, add the reverse property to all nodes pointing to this node and then + // add them to the node mape + foreach (get_object_vars($element->{'@reverse'}) as $property => $value) { + foreach ($value as $val) { + $this->generateNodeMap($nodeMap, $val, $activegraph, (object) $reference, $property); + } + } + + unset($element->{'@reverse'}); + } + + // This node also represent a named graph, process it + if (property_exists($element, '@graph')) { + if (JsonLD::MERGED_GRAPH !== $activegraph) { + if (false === property_exists($nodeMap, '-' . $id)) { + $nodeMap->{'-' . $id} = new JsonObject(); + } + + $this->generateNodeMap($nodeMap, $element->{'@graph'}, $id); + } else { + $this->generateNodeMap($nodeMap, $element->{'@graph'}, JsonLD::MERGED_GRAPH); + } + + unset($element->{'@graph'}); + } + + // Process all other properties in order + $properties = get_object_vars($element); + ksort($properties); + + foreach ($properties as $property => $value) { + if (0 === strncmp($property, '_:', 2)) { + $property = $this->getBlankNodeId($property); + } + + if (false === property_exists($node, $property)) { + $node->{$property} = array(); + } + + $this->generateNodeMap($nodeMap, $value, $activegraph, $id, $property); + } + } + } + + /** + * Generate a new blank node identifier + * + * If an identifier is passed, a new blank node identifier is generated + * for it and stored for subsequent use. Calling the method with the same + * identifier (except null) will thus always return the same blank node + * identifier. + * + * @param null|string $id If available, existing blank node identifier. + * + * @return string Returns a blank node identifier. + */ + private function getBlankNodeId($id = null) + { + if ((null !== $id) && isset($this->blankNodeMap[$id])) { + return $this->blankNodeMap[$id]; + } + + $bnode = '_:b' . $this->blankNodeCounter++; + $this->blankNodeMap[$id] = $bnode; + + return $bnode; + } + + /** + * Flattens a JSON-LD document + * + * @param mixed $element A JSON-LD element to be flattened. + * + * @return array An array representing the flattened element. + */ + public function flatten($element) + { + $nodeMap = new JsonObject(); + $nodeMap->{'-' . JsonLD::DEFAULT_GRAPH} = new JsonObject(); + + $this->generateNodeMap($nodeMap, $element); + + $defaultGraph = $nodeMap->{'-' . JsonLD::DEFAULT_GRAPH}; + unset($nodeMap->{'-' . JsonLD::DEFAULT_GRAPH}); + + // Store named graphs in the @graph property of the node representing + // the graph in the default graph + foreach ($nodeMap as $graphName => $graph) { + if (!isset($defaultGraph->{$graphName})) { + $defaultGraph->{$graphName} = new JsonObject(); + $defaultGraph->{$graphName}->{'@id'} = substr($graphName, 1); + } + + $graph = (array) $graph; + ksort($graph); + $defaultGraph->{$graphName}->{'@graph'} = array_values( + array_filter($graph, array($this, 'hasNodeProperties')) + ); + } + + $defaultGraph = (array) $defaultGraph; + ksort($defaultGraph); + + return array_values( + array_filter($defaultGraph, array($this, 'hasNodeProperties')) + ); + } + + /** + * Converts an expanded JSON-LD document to RDF quads + * + * The result is an array of Quads. + * + * @param array $document The expanded JSON-LD document to be transformed into quads. + * + * @return Quad[] The extracted quads. + */ + public function toRdf(array $document) + { + $nodeMap = new JsonObject(); + $nodeMap->{'-' . JsonLD::DEFAULT_GRAPH} = new JsonObject(); + + $this->generateNodeMap($nodeMap, $document); + + $result = array(); + + foreach ($nodeMap as $graphName => $graph) { + $graphName = substr($graphName, 1); + if (JsonLD::DEFAULT_GRAPH === $graphName) { + $activegraph = null; + } else { + $activegraph = new IRI($graphName); + + if (false === $activegraph->isAbsolute()) { + continue; + } + } + + foreach ($graph as $subject => $node) { + $activesubj = new IRI(substr($subject, 1)); + + if (false === $activesubj->isAbsolute()) { + continue; + } + + foreach ($node as $property => $values) { + if ('@id' === $property) { + continue; + } elseif ('@type' === $property) { + $activeprty = new IRI(RdfConstants::RDF_TYPE); + foreach ($values as $value) { + $result[] = new Quad($activesubj, $activeprty, new IRI($value), $activegraph); + } + + continue; + } elseif ('@' === $property[0]) { + continue; + } + + // Exclude triples/quads with a blank node predicate if generalized RDF isn't enabled + if ((0 === strncmp($property, '_:', 2)) && (false === $this->generalizedRdf)) { + continue; + } + + $activeprty = new IRI($property); + if (false === $activeprty->isAbsolute()) { + continue; + } + + foreach ($values as $value) { + if (property_exists($value, '@list')) { + $quads = array(); + $head = $this->listToRdf($value->{'@list'}, $quads, $activegraph); + + $result[] = new Quad($activesubj, $activeprty, $head, $activegraph); + foreach ($quads as $quad) { + $result[] = $quad; + } + } else { + $object = $this->elementToRdf($value); + + if (null === $object) { + continue; + } + + $result[] = new Quad($activesubj, $activeprty, $object, $activegraph); + } + } + } + } + } + + return $result; + } + + /** + * Converts a JSON-LD element to a RDF Quad object + * + * @param JsonObject $element The element to be converted. + * + * @return IRI|TypedValue|LanguageTagged|null The converted element to be used as Quad object. + */ + private function elementToRdf(JsonObject $element) + { + if (property_exists($element, '@value')) { + return Value::fromJsonLd($element); + } + + $iri = new IRI($element->{'@id'}); + + return $iri->isAbsolute() ? $iri : null; + } + + /** + * Converts a JSON-LD list to a linked RDF list (quads) + * + * @param array $entries The list entries + * @param array $quads The array to be used to hold the linked list + * @param null|IRI $graph The graph to be used in the constructed Quads + * + * @return IRI Returns the IRI of the head of the list + */ + private function listToRdf(array $entries, array &$quads, IRI $graph = null) + { + if (0 === count($entries)) { + return new IRI(RdfConstants::RDF_NIL); + } + + $head = new IRI($this->getBlankNodeId()); + $quads[] = new Quad($head, new IRI(RdfConstants::RDF_FIRST), $this->elementToRdf($entries[0]), $graph); + + $bnode = $head; + for ($i = 1, $len = count($entries); $i < $len; $i++) { + $next = new IRI($this->getBlankNodeId()); + + $quads[] = new Quad($bnode, new IRI(RdfConstants::RDF_REST), $next, $graph); + + $object = $this->elementToRdf($entries[$i]); + if (null !== $object) { + $quads[] = new Quad($next, new IRI(RdfConstants::RDF_FIRST), $object, $graph); + } + + $bnode = $next; + } + + $quads[] = new Quad($bnode, new IRI(RdfConstants::RDF_REST), new IRI(RdfConstants::RDF_NIL), $graph); + + return $head; + } + + /** + * Converts an array of RDF quads to a JSON-LD document + * + * The resulting JSON-LD document will be in expanded form. + * + * @param Quad[] $quads The quads to convert + * + * @return array The JSON-LD document. + * + * @throws InvalidQuadException If the quad is invalid. + */ + public function fromRdf(array $quads) + { + $graphs = new JsonObject(); + $graphs->{JsonLD::DEFAULT_GRAPH} = new JsonObject(); + $usages = new JsonObject(); + + foreach ($quads as $quad) { + $graphName = JsonLD::DEFAULT_GRAPH; + + if ($quad->getGraph()) { + $graphName = (string) $quad->getGraph(); + + // Add a reference to this graph to the default graph if it + // doesn't exist yet + if (false === isset($graphs->{JsonLD::DEFAULT_GRAPH}->{$graphName})) { + $graphs->{JsonLD::DEFAULT_GRAPH}->{$graphName} = + self::objectToJsonLd($quad->getGraph()); + } + } + + if (false === isset($graphs->{$graphName})) { + $graphs->{$graphName} = new JsonObject(); + } + $graph = $graphs->{$graphName}; + + // Subjects and properties are always IRIs (blank nodes are IRIs + // as well): convert them to a string representation + $subject = (string) $quad->getSubject(); + $property = (string) $quad->getProperty(); + $object = $quad->getObject(); + + // All nodes are stored in the node map + if (false === isset($graph->{$subject})) { + $graph->{$subject} = self::objectToJsonLd($quad->getSubject()); + } + $node = $graph->{$subject}; + + // ... as are all objects that are IRIs or blank nodes + if (($object instanceof IRI) && (false === isset($graph->{(string) $object}))) { + $graph->{(string) $object} = self::objectToJsonLd($object); + } + + if (($property === RdfConstants::RDF_TYPE) && (false === $this->useRdfType) && + ($object instanceof IRI)) { + self::mergeIntoProperty($node, '@type', (string) $object, true, true); + } else { + $value = self::objectToJsonLd($object, $this->useNativeTypes); + + self::mergeIntoProperty($node, $property, $value, true, true); + + // If the object is an IRI or blank node it might be the + // beginning of a list. Store a reference to its usage so + // that we can replace it with a list object later + if ($object instanceof IRI) { + $objectStr = (string) $object; + + // Usages of rdf:nil are stored per graph, while... + if (RdfConstants::RDF_NIL == $objectStr) { + $graph->{$objectStr}->usages[] = array( + 'node' => $node, + 'prop' => $property, + 'value' => $value); + // references to other nodes are stored globally (blank nodes could be shared across graphs) + } else { + if (!isset($usages->{$objectStr})) { + $usages->{$objectStr} = array(); + } + + // Make sure that the same triple isn't counted multiple times + // TODO Making $usages->{$objectStr} a set would make this code simpler + $graphSubjectProperty = $graphName . '|' . $subject . '|' . $property; + if (false === isset($usages->{$objectStr}[$graphSubjectProperty])) { + $usages->{$objectStr}[$graphSubjectProperty] = array( + 'graph' => $graphName, + 'node' => $node, + 'prop' => $property, + 'value' => $value); + } + } + } + } + } + + // Transform linked lists to @list objects + $this->createListObjects($graphs, $usages); + + // Generate the resulting document starting with the default graph + $document = array(); + + $nodes = get_object_vars($graphs->{JsonLD::DEFAULT_GRAPH}); + ksort($nodes); + + foreach ($nodes as $id => $node) { + // is it a named graph? + if (isset($graphs->{$id})) { + $node->{'@graph'} = array(); + + $graphNodes = get_object_vars($graphs->{$id}); + ksort($graphNodes); + + foreach ($graphNodes as $graphNodeId => $graphNode) { + // Only add the node when it has properties other than @id + if (count(get_object_vars($graphNode)) > 1) { + $node->{'@graph'}[] = $graphNode; + } + } + } + + if (count(get_object_vars($node)) > 1) { + $document[] = $node; + } + } + + return $document; + } + + /** + * Reconstruct @list arrays from linked list structures + * + * @param JsonObject $graphs The graph map + * @param JsonObject $usages The global node usage map + */ + private function createListObjects($graphs, $usages) + { + foreach ($graphs as $graph) { + if (false === isset($graph->{RdfConstants::RDF_NIL})) { + continue; + } + + $nil = $graph->{RdfConstants::RDF_NIL}; + + foreach ($nil->usages as $usage) { + $u = $usage; + + $node = $u['node']; + $prop = $u['prop']; + $head = $u['value']; + + $list = array(); + $listNodes = array(); + + while ((RdfConstants::RDF_REST === $prop) && + (1 === count($usages->{$node->{'@id'}})) && + property_exists($node, RdfConstants::RDF_FIRST) && + property_exists($node, RdfConstants::RDF_REST) && + (1 === count($node->{RdfConstants::RDF_FIRST})) && + (1 === count($node->{RdfConstants::RDF_REST})) && + ((3 === count(get_object_vars($node))) || // only @id, rdf:first & rdf:next + ((4 === count(get_object_vars($node))) && // or an additional rdf:type = rdf:List + property_exists($node, '@type') && + ($node->{'@type'} === array(RdfConstants::RDF_LIST))) + ) + ) { + $list[] = reset($node->{RdfConstants::RDF_FIRST}); + $listNodes[] = $node->{'@id'}; + + + $u = reset($usages->{$node->{'@id'}}); + $node = $u['node']; + $prop = $u['prop']; + $head = $u['value']; + + if (0 !== strncmp($node->{'@id'}, '_:', 2)) { + break; + } + }; + + // The list is nested in another list + if (RdfConstants::RDF_FIRST === $prop) { + // If it is empty, we can't do anything but keep the rdf:nil node + if (RdfConstants::RDF_NIL === $head->{'@id'}) { + continue; + } + + // ... otherwise we keep the head and convert the rest to @list + $head = $graph->{$head->{'@id'}}; + $head = reset($head->{RdfConstants::RDF_REST}); + + array_pop($list); + array_pop($listNodes); + } + + unset($head->{'@id'}); + $head->{'@list'} = array_reverse($list); + + foreach ($listNodes as $node) { + unset($graph->{$node}); + } + } + + unset($nil->usages); + } + } + + /** + * Frames a JSON-LD document according a supplied frame + * + * @param array|JsonObject $element A JSON-LD element to be framed. + * @param mixed $frame The frame. + * + * @return array $result The framed element in expanded form. + * + * @throws JsonLdException + */ + public function frame($element, $frame) + { + if ((false === is_array($frame)) || (1 !== count($frame)) || (false === is_object($frame[0]))) { + throw new JsonLdException( + JsonLdException::UNSPECIFIED, + 'The frame is invalid. It must be a single object.', + $frame + ); + } + + $frame = $frame[0]; + + $options = new JsonObject(); + $options->{'@embed'} = true; + $options->{'@embedChildren'} = true; // TODO Change this as soon as the tests haven been updated + + foreach (self::$framingKeywords as $keyword) { + if (property_exists($frame, $keyword)) { + $options->{$keyword} = $frame->{$keyword}; + unset($frame->{$keyword}); + } elseif (false === property_exists($options, $keyword)) { + $options->{$keyword} = false; + } + } + + $procOptions = new JsonObject(); + $procOptions->base = (string) $this->baseIri; // TODO Check which base IRI to use + $procOptions->compactArrays = $this->compactArrays; + $procOptions->optimize = $this->optimize; + $procOptions->useNativeTypes = $this->useNativeTypes; + $procOptions->useRdfType = $this->useRdfType; + $procOptions->produceGeneralizedRdf = $this->generalizedRdf; + $procOptions->documentFactory = $this->documentFactory; + $procOptions->documentLoader = $this->documentLoader; + + $processor = new Processor($procOptions); + + $graph = JsonLD::MERGED_GRAPH; + if (property_exists($frame, '@graph')) { + $graph = JsonLD::DEFAULT_GRAPH; + } + + $nodeMap = new JsonObject(); + $nodeMap->{'-' . $graph} = new JsonObject(); + $processor->generateNodeMap($nodeMap, $element, $graph); + + // Sort the node map to ensure a deterministic output + // TODO Move this to a separate function as basically the same is done in flatten()? + $nodeMap = (array) $nodeMap; + foreach ($nodeMap as &$nodes) { + $nodes = (array) $nodes; + ksort($nodes); + $nodes = (object) $nodes; + } + $nodeMap = (object) $nodeMap; + + unset($processor); + + $result = array(); + + foreach ($nodeMap->{'-' . $graph} as $node) { + $this->nodeMatchesFrame($node, $frame, $options, $nodeMap, $graph, $result); + } + + return $result; + } + + /** + * Checks whether a node matches a frame or not. + * + * @param JsonObject $node The node. + * @param null|JsonObject $frame The frame. + * @param JsonObject $options The current framing options. + * @param JsonObject $nodeMap The node map. + * @param string $graph The currently used graph. + * @param array $parent The parent to which matching results should be added. + * @param array $path The path of already processed nodes. + * + * @return bool Returns true if the node matches the frame, otherwise false. + */ + private function nodeMatchesFrame($node, $frame, $options, $nodeMap, $graph, &$parent, $path = array()) + { + // TODO How should lists be handled? Is the @list required in the frame (current behavior) or not? + // https://github.com/json-ld/json-ld.org/issues/110 + // TODO Add support for '@omitDefault'? + $filter = null; + if (null !== $frame) { + $filter = get_object_vars($frame); + } + + $result = new JsonObject(); + + // Make sure that @id is always in the result if the node matches the filter + if (property_exists($node, '@id')) { + $result->{'@id'} = $node->{'@id'}; + + if ((null === $filter) && in_array($node->{'@id'}, $path)) { + $parent[] = $result; + + return true; + } + + $path[] = $node->{'@id'}; + } + + // If no filter is specified, simply return the passed node - {} is a wildcard + if ((null === $filter) || (0 === count($filter))) { + // TODO What effect should @explicit have with a wildcard match? + if (is_object($node)) { + if ((true === $options->{'@embed'}) || (false === property_exists($node, '@id'))) { + $this->addMissingNodeProperties($node, $options, $nodeMap, $graph, $result, $path); + } + + $parent[] = $result; + } else { + $parent[] = $node; + } + + return true; + } + + foreach ($filter as $property => $validValues) { + if (is_array($validValues) && (0 === count($validValues))) { + if (property_exists($node, $property) || + (('@graph' === $property) && isset($result->{'@id'}) && + property_exists($nodeMap, $result->{'@id'}))) { + return false; // [] says that the property must not exist but it does + } + + continue; + } + + // If the property does not exist or is empty + if ((false === property_exists($node, $property)) || (is_array($node->{$property}) && 0 === count($node->{$property}))) { + // first check if it's @graph and whether the referenced graph exists + if ('@graph' === $property) { + if (isset($result->{'@id'}) && property_exists($nodeMap, $result->{'@id'})) { + $result->{'@graph'} = array(); + $match = false; + + foreach ($nodeMap->{'-' . $result->{'@id'}} as $item) { + foreach ($validValues as $validValue) { + $match |= $this->nodeMatchesFrame( + $item, + $validValue, + $options, + $nodeMap, + $result->{'@id'}, + $result->{'@graph'} + ); + } + } + + if (false === $match) { + return false; + } else { + continue; // with next property + } + } else { + // the referenced graph doesn't exist + return false; + } + } + + // otherwise, look if we have a default value for it + if (false === is_array($validValues)) { + $validValues = array($validValues); + } + + $defaultFound = false; + foreach ($validValues as $validValue) { + if (is_object($validValue) && property_exists($validValue, '@default')) { + if (null === $validValue->{'@default'}) { + $result->{$property} = new JsonObject(); + $result->{$property}->{'@null'} = true; + } else { + $result->{$property} = (is_array($validValue->{'@default'})) + ? $validValue->{'@default'} + : array($validValue->{'@default'}); + } + $defaultFound = true; + break; + } + } + + if (true === $defaultFound) { + continue; + } + + return false; // required property does not exist and no default value was found + } + + // Check whether the values of the property match the filter + $match = false; + $result->{$property} = array(); + + if (false === is_array($validValues)) { + if ($node->{$property} === $validValues) { + $result->{$property} = $node->{$property}; + continue; + } else { + return false; + } + } + + foreach ($validValues as $validValue) { + if (is_object($validValue)) { + // Extract framing options from subframe ($validValue is a subframe) + $validValue = clone $validValue; + $newOptions = clone $options; + unset($newOptions->{'@default'}); + + foreach (self::$framingKeywords as $keyword) { + if (property_exists($validValue, $keyword)) { + $newOptions->{$keyword} = $validValue->{$keyword}; + unset($validValue->{$keyword}); + } + } + + $nodeValues = $node->{$property}; + if (false === is_array($nodeValues)) { + $nodeValues = array($nodeValues); + } + + foreach ($nodeValues as $value) { + if (is_object($value) && property_exists($value, '@id')) { + $match |= $this->nodeMatchesFrame( + $nodeMap->{'-' . $graph}->{'-' . $value->{'@id'}}, + $validValue, + $newOptions, + $nodeMap, + $graph, + $result->{$property}, + $path + ); + } else { + $match |= $this->nodeMatchesFrame( + $value, + $validValue, + $newOptions, + $nodeMap, + $graph, + $result->{$property}, + $path + ); + } + } + } elseif (is_array($validValue)) { + throw new JsonLdException( + JsonLdException::UNSPECIFIED, + "Invalid frame detected. Property \"$property\" must not be an array of arrays.", + $frame + ); + } else { + // This will just catch non-expanded IRIs for @id and @type + $nodeValues = $node->{$property}; + if (false === is_array($nodeValues)) { + $nodeValues = array($nodeValues); + } + + if (in_array($validValue, $nodeValues)) { + $match = true; + $result->{$property} = $node->{$property}; + } + } + } + + if (false === $match) { + return false; + } + } + + // Discard subtree if this object should not be embedded + if ((false === $options->{'@embed'}) && property_exists($node, '@id')) { + $result = new JsonObject(); + $result->{'@id'} = $node->{'@id'}; + $parent[] = $result; + + return true; + } + + // all properties matched the filter, add the properties of the + // node which haven't been added yet + if (false === $options->{'@explicit'}) { + $this->addMissingNodeProperties($node, $options, $nodeMap, $graph, $result, $path); + } + + $parent[] = $result; + + return true; + } + + /** + * Adds all properties from node to result if they haven't been added yet + * + * @param JsonObject $node The node whose properties should processed. + * @param JsonObject $options The current framing options. + * @param JsonObject $nodeMap The node map. + * @param string $graph The currently used graph. + * @param JsonObject $result The object to which the properties should be added. + * @param array $path The path of already processed nodes. + */ + private function addMissingNodeProperties($node, $options, $nodeMap, $graph, &$result, $path) + { + foreach ($node as $property => $value) { + if (property_exists($result, $property)) { + continue; // property has already been added + } + + if (true === $options->{'@embedChildren'}) { + if (false === is_array($value)) { + $result->{$property} = unserialize(serialize($value)); // create a deep-copy + continue; + } + + $result->{$property} = array(); + foreach ($value as $item) { + if (is_object($item)) { + if (property_exists($item, '@id')) { + $item = $nodeMap->{'-' . $graph}->{'-' . $item->{'@id'}}; + } + + $this->nodeMatchesFrame($item, null, $options, $nodeMap, $graph, $result->{$property}, $path); + } else { + $result->{$property}[] = $item; + } + } + + } else { + // TODO Perform deep object copy?? + $result->{$property} = unserialize(serialize($value)); // create a deep-copy + } + } + } + + /** + * Adds a property to an object if it doesn't exist yet + * + * If the property already exists, an exception is thrown as otherwise + * the existing value would be lost. + * + * @param JsonObject $object The object. + * @param string $property The name of the property. + * @param mixed $value The value of the property. + * + * @throws JsonLdException If the property exists already JSON-LD. + */ + private static function setProperty(&$object, $property, $value, $errorCode = null) + { + if (property_exists($object, $property) && + (false === self::subtreeEquals($object->{$property}, $value))) { + + if ($errorCode) { + throw new JsonLdException( + $errorCode, + "Object already contains a property \"$property\".", + $object + ); + } + + throw new JsonLdException( + JsonLdException::UNSPECIFIED, + "Object already contains a property \"$property\".", + $object + ); + } + + $object->{$property} = $value; + } + + /** + * Merges a value into a property of an object + * + * @param JsonObject $object The object. + * @param string $property The name of the property to which the value + * should be merged into. + * @param mixed $value The value to merge into the property. + * @param bool $alwaysArray If set to true, the resulting property will + * always be an array. + * @param bool $unique If set to true, the value is only added if + * it doesn't exist yet. + */ + private static function mergeIntoProperty(&$object, $property, $value, $alwaysArray = false, $unique = false) + { + // No need to add a null value + if (null === $value) { + return; + } + + if (is_array($value)) { + // Make sure empty arrays are created since we preserve them in expansion + if ((0 === count($value)) && (false === property_exists($object, $property))) { + $object->{$property} = array(); + } + + foreach ($value as $val) { + static::mergeIntoProperty($object, $property, $val, $alwaysArray, $unique); + } + + return; + } + + if (property_exists($object, $property)) { + if (false === is_array($object->{$property})) { + $object->{$property} = array($object->{$property}); + } + + if ($unique) { + foreach ($object->{$property} as $item) { + if (self::subtreeEquals($item, $value)) { + return; + } + } + } + + $object->{$property}[] = $value; + } else { + $object->{$property} = ($alwaysArray) ? array($value) : $value; + } + } + + /** + * Compares two values by their length and then lexicographically + * + * If two strings have different lengths, the shorter one will be + * considered less than the other. If they have the same length, they + * are compared lexicographically. + * + * @param mixed $a Value A. + * @param mixed $b Value B. + * + * @return int If value A is shorter than value B, -1 will be returned; if it's + * longer 1 will be returned. If both values have the same length + * and value A is considered lexicographically less, -1 will be + * returned, if they are equal 0 will be returned, otherwise 1 + * will be returned. + */ + private static function sortTerms($a, $b) + { + $lenA = strlen($a); + $lenB = strlen($b); + + if ($lenA < $lenB) { + return -1; + } elseif ($lenA === $lenB) { + return strcmp($a, $b); + } else { + return 1; + } + } + + /** + * Converts an object to a JSON-LD representation + * + * Only {@link IRI IRIs}, {@link LanguageTaggedString language-tagged strings}, + * and {@link TypedValue typed values} are converted by this method. All + * other objects are returned as-is. + * + * @param JsonObject $object The object to convert. + * @param boolean $useNativeTypes If set to true, native types are used + * for xsd:integer, xsd:double, and + * xsd:boolean, otherwise typed strings + * will be used instead. + * + * @return mixed The JSON-LD representation of the object. + */ + private static function objectToJsonLd($object, $useNativeTypes = true) + { + if ($object instanceof IRI) { + $result = new JsonObject(); + $result->{'@id'} = (string) $object; + + return $result; + } elseif ($object instanceof Value) { + return $object->toJsonLd($useNativeTypes); + } + + return $object; + } + + /** + * Checks whether a node has properties and not just an @id + * + * This is used to filter nodes consisting just of an @id-member when + * flattening and converting from RDF. + * + * @param JsonObject $node The node + * + * @return boolean True if the node has properties (other than @id), + * false otherwise. + */ + private function hasNodeProperties($node) + { + return (count(get_object_vars($node)) > 1); + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Quad.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/Quad.php new file mode 100644 index 0000000..af6e134 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Quad.php @@ -0,0 +1,152 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +use ML\IRI\IRI; + +/** + * A quad + * + * @author Markus Lanthaler + */ +class Quad +{ + /** + * The subject + * + * @var IRI + */ + private $subject; + + /** + * The property or predicate + * + * @var IRI + */ + private $property; + + /** + * The object + * + * @var Value|IRI + */ + private $object; + + /** + * The graph + * + * @var IRI + */ + private $graph; + + /** + * Constructor + * + * @param IRI $subject The subject. + * @param IRI $property The property. + * @param Value|IRI $object The object. + * @param null|IRI $graph The graph. + * + * @throws InvalidArgumentException If the object parameter has a wrong type + */ + public function __construct(IRI $subject, IRI $property, $object, IRI $graph = null) + { + $this->subject = $subject; + $this->property = $property; + $this->setObject($object); // use setter which checks the type + $this->graph = $graph; + } + + /** + * Set the subject + * + * @param IRI $subject The subject + */ + public function setSubject(IRI $subject) + { + $this->subject = $subject; + } + + /** + * Get the subject + * + * @return IRI The subject + */ + public function getSubject() + { + return $this->subject; + } + + /** + * Set the property + * + * @param IRI $property The property + */ + public function setProperty(IRI $property) + { + $this->property = $property; + } + + /** + * Get the property + * + * @return IRI The property + */ + public function getProperty() + { + return $this->property; + } + + /** + * Set the object + * + * @param IRI|Value $object The object + * + * @throws InvalidArgumentException If object is of wrong type. + */ + public function setObject($object) + { + if (!($object instanceof IRI) && !($object instanceof Value)) { + throw new \InvalidArgumentException('Object must be an IRI or Value object'); + } + + $this->object = $object; + } + + /** + * Get the object + * + * @return IRI|Value The object + */ + public function getObject() + { + return $this->object; + } + + /** + * Set the graph + * + * @param null|IRI $graph The graph + */ + public function setGraph(IRI $graph = null) + { + $this->graph = $graph; + } + + /** + * Get the graph + * + * @return IRI The graph + */ + public function getGraph() + { + return $this->graph; + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/QuadParserInterface.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/QuadParserInterface.php new file mode 100644 index 0000000..6f9bbea --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/QuadParserInterface.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +/** + * Quad parser interface + * + * @author Markus Lanthaler + */ +interface QuadParserInterface +{ + /** + * Parses quads + * + * @param string $input The serialized quads to parse. + * + * @return Quad[] An array of extracted quads. + */ + public function parse($input); +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/QuadSerializerInterface.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/QuadSerializerInterface.php new file mode 100644 index 0000000..34cc439 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/QuadSerializerInterface.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +/** + * Quad serializer interface + * + * @author Markus Lanthaler + */ +interface QuadSerializerInterface +{ + /** + * Serializes quads to a string. + * + * @param Quad[] $quads Array of quads to be serialized. + * + * @return string The serialized quads. + */ + public function serialize(array $quads); +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/README.md b/Resources/Private/PHP/embed/vendor/ml/json-ld/README.md new file mode 100644 index 0000000..24912e2 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/README.md @@ -0,0 +1,104 @@ +JsonLD [![Continuous integration](https://github.com/lanthaler/JsonLD/actions/workflows/ci.yaml/badge.svg)](https://github.com/lanthaler/JsonLD/actions/workflows/ci.yaml) +============== + +JsonLD is a fully conforming [JSON-LD](http://www.w3.org/TR/json-ld/) +processor written in PHP. It is extensively tested and passes the +[official JSON-LD test suite](https://github.com/json-ld/tests). + +There's an [online playground](http://www.markus-lanthaler.com/jsonld/playground/) +where you can evaluate the processor's basic functionality. + +Additionally to the features defined by the [JSON-LD API specification](http://www.w3.org/TR/json-ld-api/), +JsonLD supports [framing](http://json-ld.org/spec/latest/json-ld-framing/) +(including [value matching](https://github.com/json-ld/json-ld.org/issues/110), +[deep-filtering](https://github.com/json-ld/json-ld.org/issues/110), +[aggressive re-embedding](https://github.com/json-ld/json-ld.org/issues/119), and +[named graphs](https://github.com/json-ld/json-ld.org/issues/118)) and an experimental +[object-oriented interface for JSON-LD documents](https://github.com/lanthaler/JsonLD/issues/15). + + +Installation +------------ + +The easiest way to install `JsonLD` is by requiring it with [Composer](https://getcomposer.org/). + +``` +composer require ml/json-ld +``` + +... and including Composer's autoloader to your project + +```php +require('vendor/autoload.php'); +``` + +Of course, you can also download JsonLD as +[ZIP archive](https://github.com/lanthaler/JsonLD/releases) from Github. + +JsonLD requires PHP 5.3 or later. + + +Usage +------------ + +The library supports the official [JSON-LD API](http://www.w3.org/TR/json-ld-api/) as +well as a object-oriented interface for JSON-LD documents (not fully implemented yet, +see [issue #15](https://github.com/lanthaler/JsonLD/issues/15) for details). + +All classes are extensively documented. Please have a look at the source code. + +```php +// Official JSON-LD API +$expanded = JsonLD::expand('document.jsonld'); +$compacted = JsonLD::compact('document.jsonld', 'context.jsonld'); +$framed = JsonLD::frame('document.jsonld', 'frame.jsonld'); +$flattened = JsonLD::flatten('document.jsonld'); +$quads = JsonLD::toRdf('document.jsonld'); + +// Output the expanded document (pretty print) +print JsonLD::toString($expanded, true); + +// Serialize the quads as N-Quads +$nquads = new NQuads(); +$serialized = $nquads->serialize($quads); +print $serialized; + +// And parse them again to a JSON-LD document +$quads = $nquads->parse($serialized); +$document = JsonLD::fromRdf($quads); + +print JsonLD::toString($document, true); + +// Node-centric API +$doc = JsonLD::getDocument('document.jsonld'); + +// get the default graph +$graph = $doc->getGraph(); + +// get all nodes in the graph +$nodes = $graph->getNodes(); + +// retrieve a node by ID +$node = $graph->getNode('http://example.com/node1'); + +// get a property +$node->getProperty('http://example.com/vocab/name'); + +// add a new blank node to the graph +$newNode = $graph->createNode(); + +// link the new blank node to the existing node +$node->addPropertyValue('http://example.com/vocab/link', $newNode); + +// even reverse properties are supported; this returns $newNode +$node->getReverseProperty('http://example.com/vocab/link'); + +// serialize the graph and convert it to a string +$serialized = JsonLD::toString($graph->toJsonLd()); +``` + + +Commercial Support +------------ + +Commercial support is available on request. diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/RdfConstants.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/RdfConstants.php new file mode 100644 index 0000000..edeec01 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/RdfConstants.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +/** + * Some RDF constants. + * + * @author Markus Lanthaler + */ +abstract class RdfConstants +{ + const RDF_TYPE = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type'; + const RDF_LIST = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#List'; + const RDF_FIRST = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#first'; + const RDF_REST = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#rest'; + const RDF_NIL = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#nil'; + const XSD_INTEGER = 'http://www.w3.org/2001/XMLSchema#integer'; + const XSD_DOUBLE = 'http://www.w3.org/2001/XMLSchema#double'; + const XSD_BOOLEAN = 'http://www.w3.org/2001/XMLSchema#boolean'; + const XSD_STRING = 'http://www.w3.org/2001/XMLSchema#string'; +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/RemoteDocument.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/RemoteDocument.php new file mode 100644 index 0000000..9be1286 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/RemoteDocument.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +/** + * RemoteDocument + * + * @author Markus Lanthaler + */ +class RemoteDocument +{ + /** + * @var string The URL of the loaded document. + */ + public $documentUrl; + + /** + * @var string The document's media type + */ + public $mediaType; + + /** + * @var mixed The retrieved document. This can either be the raw payload + * or the already parsed document. + */ + public $document; + + /** + * @var string|null The value of the context Link header if available; + * otherwise null. + */ + public $contextUrl; + + /** + * Constructor + * + * @param null|string $documentUrl The final URL of the loaded document. + * @param mixed $document The retrieved document (parsed or raw). + * @param null|string $mediaType The document's media type. + * @param null|string $contextUrl The value of the context Link header + * if available; otherwise null. + */ + public function __construct($documentUrl = null, $document = null, $mediaType = null, $contextUrl = null) + { + $this->documentUrl = $documentUrl; + $this->document = $document; + $this->mediaType = $mediaType; + $this->contextUrl = $contextUrl; + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/DocumentTest.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/DocumentTest.php new file mode 100644 index 0000000..72115d2 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/DocumentTest.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD\Test; + +use ML\JsonLD\JsonLD; +use ML\JsonLD\Document; + +/** + * Test the parsing of a JSON-LD document into a Document. + * + * @author Markus Lanthaler + */ +class DocumentTest extends \PHPUnit_Framework_TestCase +{ + /** + * The document instance being used throughout the tests. + * + * @var Document + */ + protected $document; + + /** + * Create the document to test. + */ + protected function setUp() + { + $this->document = JsonLD::getDocument( + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR . 'dataset.jsonld', + array('base' => 'http://example.com/dataset.jsonld') + ); + } + + + /** + * Tests whether all nodes are returned and blank nodes are renamed accordingly. + */ + public function testGetIri() + { + $this->assertEquals( + 'http://example.com/dataset.jsonld', + $this->document->getIri() + ); + } + + /** + * Tests whether all nodes are interlinked correctly. + */ + public function testGetGraphNames() + { + // The blank node graph name _:_:graphBn gets relabeled to _:b0 during node map generation + $this->assertEquals( + array('_:b0', 'http://example.com/named-graph'), + $this->document->getGraphNames() + ); + } + + /** + * Tests whether all nodes also have the correct reverse links. + */ + public function testContainsGraph() + { + $this->assertTrue( + $this->document->containsGraph('/named-graph'), + 'Relative IRI' + ); + $this->assertTrue( + $this->document->containsGraph('http://example.com/named-graph'), + 'Absolute IRI' + ); + $this->assertTrue( + $this->document->containsGraph('_:b0'), + 'Blank node identifier' + ); + + $this->assertFalse( + $this->document->containsGraph('http://example.org/not-here'), + 'Non-existent graph' + ); + } + + /** + * Tests isBlankNode() + */ + public function testRemoveGraph() + { + $this->document->removeGraph('/named-graph'); + + $this->assertFalse( + $this->document->containsGraph('/named-graph'), + 'Is the removed graph still there?' + ); + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/EarlReportGenerator.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/EarlReportGenerator.php new file mode 100644 index 0000000..6ba34b5 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/EarlReportGenerator.php @@ -0,0 +1,273 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD\Test; + +/** + * EarlReportGenerator + * + * A test listener to create an EARL report. It can be configured uses + * the following configuration + * + * + * + * + * + * + * ... + * + * + * ... + * + * + * ... + * + * + * ... + * + * + * ... + * + * + * ... + * + * + * ... + * + * + * ... + * + * + * ... + * + * + * ... + * + * + * + * + * + * + * @author Markus Lanthaler + */ +class EarlReportGenerator extends \PHPUnit_Util_Printer implements \PHPUnit_Framework_TestListener +{ + /** + * @var string + */ + protected $testTypeOfInterest = 'ML\\JsonLD\\Test\\W3CTestSuiteTest'; + + /** + * @var array Lookup table for EARL statuses + */ + protected $earlStatuses; + + /** + * @var array Options + */ + protected $options; + + /** + * @var array Collected EARL assertions + */ + protected $assertions; + + /** + * Constructor + * + * @param array $options Configuration options + */ + public function __construct(array $options = array()) + { + $reqOptions = array( + 'target', + 'project-name', + 'project-url', + 'project-homepage', + 'license-url', + 'project-description', + 'programming-language', + 'developer-name', + 'developer-url', + 'developer-homepage' + ); + + foreach ($reqOptions as $option) { + if (false === isset($options[$option])) { + throw new \InvalidArgumentException( + sprintf('The "%s" option is not set', $option) + ); + } + } + + $this->options = $options; + + $this->earlStatuses = array( + \PHPUnit_Runner_BaseTestRunner::STATUS_PASSED => 'earl:passed', + \PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED => 'earl:untested', + \PHPUnit_Runner_BaseTestRunner::STATUS_INCOMPLETE => 'earl:cantTell', + \PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE => 'earl:failed', + \PHPUnit_Runner_BaseTestRunner::STATUS_ERROR => 'earl:failed' + ); + + $this->assertions = array(); + + parent::__construct($options['target']); + } + + /** + * A test ended. + * + * @param \PHPUnit_Framework_Test $test + * @param float $time + */ + public function endTest(\PHPUnit_Framework_Test $test, $time) + { + if (false === ($test instanceof $this->testTypeOfInterest)) { + return; + } + + $assertion = array( + '@type' => 'earl:Assertion', + 'earl:assertedBy' => $this->options['developer-url'], + 'earl:mode' => 'earl:automatic', + 'earl:test' => $test->getTestId(), + 'earl:result' => array( + '@type' => 'earl:TestResult', + 'earl:outcome' => $this->earlStatuses[$test->getStatus()], + 'dc:date' => date('c') + ) + ); + + $this->assertions[] = $assertion; + } + + + /** + * @inheritdoc + */ + public function flush() + { + if (0 === $this->assertions) { + return; + } + + $report = array( + '@context' => array( + 'doap' => 'http://usefulinc.com/ns/doap#', + 'foaf' => 'http://xmlns.com/foaf/0.1/', + 'dc' => 'http://purl.org/dc/terms/', + 'earl' => 'http://www.w3.org/ns/earl#', + 'xsd' => 'http://www.w3.org/2001/XMLSchema#', + 'doap:homepage' => array('@type' => '@id'), + 'doap:license' => array('@type' => '@id'), + 'dc:creator' => array('@type' => '@id'), + 'foaf:homepage' => array('@type' => '@id'), + 'subjectOf' => array('@reverse' => 'earl:subject'), + 'earl:assertedBy' => array('@type' => '@id'), + 'earl:mode' => array('@type' => '@id'), + 'earl:test' => array('@type' => '@id'), + 'earl:outcome' => array('@type' => '@id'), + 'dc:date' => array('@type' => 'xsd:date') + ), + '@id' => $this->options['project-url'], + '@type' => array('doap:Project', 'earl:TestSubject', 'earl:Software'), + 'doap:name' => $this->options['project-name'], + 'dc:title' => $this->options['project-name'], + 'doap:homepage' => $this->options['project-homepage'], + 'doap:license' => $this->options['license-url'], + 'doap:description' => $this->options['project-description'], + 'doap:programming-language' => $this->options['programming-language'], + 'doap:developer' => array( + '@id' => $this->options['developer-url'], + '@type' => array('foaf:Person', 'earl:Assertor'), + 'foaf:name' => $this->options['developer-name'], + 'foaf:homepage' => $this->options['developer-homepage'] + ), + 'dc:creator' => $this->options['developer-url'], + 'dc:date' => array( + '@value' => date('Y-m-d'), + '@type' => 'xsd:date' + ), + 'subjectOf' => $this->assertions + ); + + $options = 0; + + if (PHP_VERSION_ID >= 50400) { + $options |= JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT; + $report = json_encode($report, $options); + } else { + $report = json_encode($report); + $report = str_replace('\\/', '/', $report); // unescape slahes + + // unescape unicode + $report = preg_replace_callback( + '/\\\\u([a-f0-9]{4})/', + function ($match) { + return iconv('UCS-4LE', 'UTF-8', pack('V', hexdec($match[1]))); + }, + $report + ); + } + + $this->write($report); + + parent::flush(); + } + + /** + * @inheritdoc + */ + public function startTestSuite(\PHPUnit_Framework_TestSuite $suite) + { + } + + /** + * @inheritdoc + */ + public function endTestSuite(\PHPUnit_Framework_TestSuite $suite) + { + } + + /** + * @inheritdoc + */ + public function addError(\PHPUnit_Framework_Test $test, \Exception $e, $time) + { + } + + /** + * @inheritdoc + */ + public function addFailure(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_AssertionFailedError $e, $time) + { + } + + /** + * @inheritdoc + */ + public function addIncompleteTest(\PHPUnit_Framework_Test $test, \Exception $e, $time) + { + } + + /** + * @inheritdoc + */ + public function addSkippedTest(\PHPUnit_Framework_Test $test, \Exception $e, $time) + { + } + + /** + * @inheritdoc + */ + public function startTest(\PHPUnit_Framework_Test $test) + { + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/FileGetContentsLoaderTest.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/FileGetContentsLoaderTest.php new file mode 100644 index 0000000..8fcb873 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/FileGetContentsLoaderTest.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD\Test; + +use ML\IRI\IRI; +use ML\JsonLD\FileGetContentsLoader; + +/** + * Test the parsing of a JSON-LD document into a Document. + */ +class FileGetContentsLoaderTest extends \PHPUnit_Framework_TestCase +{ + + protected $iri; + + protected $loader; + + public function setUp() + { + parent::setUp(); + + $this->iri = new IRI('https://www.example.com'); + $this->loader = new FileGetContentsLoader; + } + + public function tearDown() + { + unset($iri); + unset($this->loader); + + parent::tearDown(); + } + + public function testParseLinkHeadersExactsValues() + { + $headers = array( + '; param1=foo; param2="bar";', + ); + + $parsed = $this->loader->parseLinkHeaders($headers, $this->iri); + + $this->assertEquals('https://www.example.com', $parsed[0]['uri']); + $this->assertEquals('foo', $parsed[0]['param1']); + $this->assertEquals('bar', $parsed[0]['param2']); + } + + public function testParseLinkHeadersTrimsValues() + { + $headers = array( + '< https://www.example.com >; param1= foo ; param2=" bar ";', + ); + + $parsed = $this->loader->parseLinkHeaders($headers, $this->iri); + + $this->assertEquals('https://www.example.com', $parsed[0]['uri']); + $this->assertEquals('foo', $parsed[0]['param1']); + $this->assertEquals('bar', $parsed[0]['param2']); + } + + public function testParseLinkHeadersWithMultipleHeaders() + { + $headers = array( + '; param1=foo; param2=bar;', + '; param1=fizz; param2=buzz;', + ); + + $parsed = $this->loader->parseLinkHeaders($headers, $this->iri); + + $this->assertCount(2, $parsed); + } + + public function testParseLinkHeadersWithMultipleLinks() + { + $headers = array( + '; param1=foo; param2=bar;, ' + . '; param1=fizz; param2=buzz;' + ); + + $parsed = $this->loader->parseLinkHeaders($headers, $this->iri); + + $this->assertCount(2, $parsed); + $this->assertEquals('https://www.example.com', $parsed[0]['uri']); + $this->assertEquals('https://www.example.org', $parsed[1]['uri']); + } + + public function testParseLinkHeadersConvertsRelativeLinksToAbsolute() + { + $headers = array(';'); + $parsed = $this->loader->parseLinkHeaders($headers, $this->iri); + $this->assertEquals('https://www.example.com/foo/bar', $parsed[0]['uri']); + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/dataset.jsonld b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/dataset.jsonld new file mode 100644 index 0000000..d876810 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/dataset.jsonld @@ -0,0 +1,36 @@ +{ + "@context": { + "@vocab": "http://example.com/vocab#", + "references": { "@type": "@id" } + }, + "@graph": [ + { + "@id": "/node1", + "references": [ "_:graphBn", "/named-graph" ] + }, + { + "@id": "_:graphBn", + "@graph": [ + { + "@id": "_:graphBn/node1", + "name": "_:graphBn/node1", + "references": [ "_:bnode", "/node1", "/named-graph/node1" ] + } + ] + }, + { + "@id": "/named-graph", + "@graph": [ + { + "@id": "/named-graph/node1", + "name": "/named-graph/node1", + "references": [ "_:bnode", "/node1", "_:graphBn/node1" ] + } + ] + }, + { + "@id": "_:bnode", + "name": "_:bnode" + } + ] +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-compacted.jsonld b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-compacted.jsonld new file mode 100644 index 0000000..828b2da --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-compacted.jsonld @@ -0,0 +1,24 @@ +{ + "@context": { + "t1": "http://example.com/t1", + "t2": "http://example.com/t2", + "term1": "http://example.com/term1", + "term2": "http://example.com/term2", + "term3": "http://example.com/term3", + "term4": "http://example.com/term4", + "term5": "http://example.com/term5" + }, + "@id": "http://example.com/id1", + "@type": "t1", + "term1": "v1", + "term2": { "@value": "v2", "@type": "t2" }, + "term3": { "@value": "v3", "@language": "en" }, + "term4": 4, + "term5": [ 50, 51 ], + "http://example.com/term6": [ + { "@value": "1", "@type": "t1" }, + { "@value": "2", "@type": "t2" }, + { "@value": "3", "@language": "en" }, + { "@value": "4", "@language": "de" } + ] +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-context.jsonld b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-context.jsonld new file mode 100644 index 0000000..79129cb --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-context.jsonld @@ -0,0 +1,11 @@ +{ + "@context": { + "t1": "http://example.com/t1", + "t2": "http://example.com/t2", + "term1": "http://example.com/term1", + "term2": "http://example.com/term2", + "term3": "http://example.com/term3", + "term4": "http://example.com/term4", + "term5": "http://example.com/term5" + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-expanded.jsonld b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-expanded.jsonld new file mode 100644 index 0000000..7daa785 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-expanded.jsonld @@ -0,0 +1,20 @@ +[ + { + "@id": "http://example.com/id1", + "@type": [ "http://example.com/t1" ], + "http://example.com/term1": [ {"@value": "v1"} ], + "http://example.com/term2": [ {"@value": "v2", "@type": "http://example.com/t2"} ], + "http://example.com/term3": [ {"@value": "v3", "@language": "en"} ], + "http://example.com/term4": [ {"@value": 4} ], + "http://example.com/term5": [ + { "@value": 50 }, + { "@value": 51 } + ], + "http://example.com/term6": [ + { "@value": "1", "@type": "http://example.com/t1" }, + { "@value": "2", "@type": "http://example.com/t2" }, + { "@value": "3", "@language": "en" }, + { "@value": "4", "@language": "de" } + ] + } +] diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-flattened.jsonld b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-flattened.jsonld new file mode 100644 index 0000000..bfe8d63 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-flattened.jsonld @@ -0,0 +1,34 @@ +{ + "@context": { + "t1": "http://example.com/t1", + "t2": "http://example.com/t2", + "term1": "http://example.com/term1", + "term2": "http://example.com/term2", + "term3": "http://example.com/term3", + "term4": "http://example.com/term4", + "term5": "http://example.com/term5" + }, + "@graph": [ + { + "@id": "http://example.com/id1", + "@type": "t1", + "term1": "v1", + "term2": { + "@type": "t2", + "@value": "v2" + }, + "term3": { + "@language": "en", + "@value": "v3" + }, + "term4": 4, + "term5": [ 50, 51 ], + "http://example.com/term6": [ + { "@value": "1", "@type": "t1" }, + { "@value": "2", "@type": "t2" }, + { "@value": "3", "@language": "en" }, + { "@value": "4", "@language": "de" } + ] + } + ] +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-in.jsonld b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-in.jsonld new file mode 100644 index 0000000..dec8fd7 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-in.jsonld @@ -0,0 +1,22 @@ +{ + "@context": { + "t1": "http://example.com/t1", + "t2": "http://example.com/t2", + "term1": "http://example.com/term1", + "term3": "http://example.com/term3", + "term5": "http://example.com/term5" + }, + "@id": "http://example.com/id1", + "@type": "t1", + "term1": "v1", + "http://example.com/term2": { "@value": "v2", "@type": "t2" }, + "term3": { "@value": "v3", "@language": "en" }, + "http://example.com/term4": 4, + "term5": [ 50, 51 ], + "http://example.com/term6": [ + { "@value": "1", "@type": "t1" }, + { "@value": "2", "@type": "t2" }, + { "@value": "3", "@language": "en" }, + { "@value": "4", "@language": "de" } + ] +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-serialized-document.jsonld b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-serialized-document.jsonld new file mode 100644 index 0000000..bdb4008 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/Fixtures/sample-serialized-document.jsonld @@ -0,0 +1,23 @@ +[ + { + "@id": "http://example.com/id1", + "@type": [ "http://example.com/t1" ], + "http://example.com/term1": [ {"@value": "v1"} ], + "http://example.com/term2": [ {"@value": "v2", "@type": "http://example.com/t2"} ], + "http://example.com/term3": [ {"@value": "v3", "@language": "en"} ], + "http://example.com/term4": [ {"@value": 4} ], + "http://example.com/term5": [ + {"@value": 50 }, + {"@value": 51 } + ], + "http://example.com/term6": [ + { "@value": "1", "@type": "http://example.com/t1" }, + { "@value": "2", "@type": "http://example.com/t2" }, + { "@value": "3", "@language": "en" }, + { "@value": "4", "@language": "de" } + ] + }, + { + "@id": "http://example.com/t1" + } +] diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/GraphTest.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/GraphTest.php new file mode 100644 index 0000000..8e452ab --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/GraphTest.php @@ -0,0 +1,915 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD\Test; + +use ML\JsonLD\Document; +use ML\JsonLD\FileGetContentsLoader; +use ML\JsonLD\Graph; +use ML\JsonLD\GraphInterface; +use ML\JsonLD\Node; +use ML\JsonLD\LanguageTaggedString; +use ML\JsonLD\TypedValue; +use ML\JsonLD\RdfConstants; + +/** + * Test the parsing of a JSON-LD document into a Graph. + * + * @author Markus Lanthaler + */ +class GraphTest extends \PHPUnit_Framework_TestCase +{ + /** + * The graph instance being used throughout the tests. + * + * @var GraphInterface + */ + protected $graph; + + /** + * The document loader used to parse expected values. + */ + protected $documentLoader; + + /** + * Create the graph to test. + */ + protected function setUp() + { + $json = << 'http://example.com/node/index.jsonld')); + $this->graph = $doc->getGraph(); + $this->documentLoader = new FileGetContentsLoader(); + } + + + /** + * Tests whether all nodes are returned and blank nodes are renamed accordingly. + */ + public function testGetNodes() + { + $nodeIds = array( + 'http://example.com/node/1', + 'http://example.com/node/2', + 'http://example.com/node/3', + '_:b0', + '_:b1', + '_:b2', + '_:b3', + 'http://vocab.com/type/node', + 'http://vocab.com/type/nodeWithAliases' + ); + + $nodes = $this->graph->getNodes(); + $this->assertCount(count($nodeIds), $nodes); + + foreach ($nodes as $node) { + // Is the node's ID valid? + $this->assertContains($node->getId(), $nodeIds, 'Found unexpected node ID: ' . $node->getId()); + + // Is the node of the right type? + $this->assertInstanceOf('ML\JsonLD\Node', $node); + + // Does the graph return the same instance? + $n = $this->graph->getNode($node->getId()); + $this->assertSame($node, $n, 'same instance'); + $this->assertTrue($node->equals($n), 'equals'); + $this->assertSame($this->graph, $n->getGraph(), 'linked to graph'); + } + } + + /** + * Tests whether all nodes are interlinked correctly. + */ + public function testNodeRelationships() + { + $node1 = $this->graph->getNode('http://example.com/node/1'); + $node2 = $this->graph->getNode('http://example.com/node/2'); + $node3 = $this->graph->getNode('http://example.com/node/3'); + + $node1_1 = $this->graph->getNode('_:b0'); + $node2_1 = $this->graph->getNode('_:b1'); + $node2_2 = $this->graph->getNode('_:b2'); + $node3_1 = $this->graph->getNode('_:b3'); + + $nodeType = $this->graph->getNode('http://vocab.com/type/node'); + $nodeWithAliasesType = $this->graph->getNode('http://vocab.com/type/nodeWithAliases'); + + $this->assertSame($node2, $node1->getProperty('http://vocab.com/link'), 'n1 -link-> n2'); + $this->assertSame($node1_1, $node1->getProperty('http://vocab.com/contains'), 'n1 -contains-> n1.1'); + $this->assertSame($nodeType, $node1->getType(), 'n1 type'); + + $this->assertSame($node3, $node2->getProperty('http://vocab.com/link'), 'n2 -link-> n3'); + $values = $node2->getProperty('http://vocab.com/contains'); + $this->assertCount(2, $values, 'n2 -contains-> 2 nodes'); + $this->assertSame($node2_1, $values[0], 'n2 -contains-> n2.1'); + $this->assertSame($node2_2, $values[1], 'n2 -contains-> n2.1'); + $this->assertSame($nodeWithAliasesType, $node2->getType(), 'n2 type'); + + $this->assertSame($node1, $node3->getProperty('http://vocab.com/link'), 'n3 -link-> n1'); + $this->assertSame($node3_1, $node3->getProperty('http://vocab.com/contains'), 'n3 -contains-> n3.1'); + $this->assertSame($nodeType, $node3->getType(), 'n3 type'); + } + + /** + * Tests whether all nodes also have the correct reverse links. + */ + public function testNodeReverseRelationships() + { + $node1 = $this->graph->getNode('http://example.com/node/1'); + $node2 = $this->graph->getNode('http://example.com/node/2'); + $node3 = $this->graph->getNode('http://example.com/node/3'); + + $node1_1 = $this->graph->getNode('_:b0'); + $node2_1 = $this->graph->getNode('_:b1'); + $node2_2 = $this->graph->getNode('_:b2'); + $node3_1 = $this->graph->getNode('_:b3'); + + $nodeType = $this->graph->getNode('http://vocab.com/type/node'); + $nodeWithAliasesType = $this->graph->getNode('http://vocab.com/type/nodeWithAliases'); + + $this->assertSame($node1, $node2->getReverseProperty('http://vocab.com/link'), 'n2 <-link- n1'); + $this->assertSame($node1, $node1_1->getReverseProperty('http://vocab.com/contains'), 'n1.1 <-contains- n1'); + + $this->assertSame($node2, $node3->getReverseProperty('http://vocab.com/link'), 'n3 <-link- n2'); + $this->assertSame($node2, $node2_1->getReverseProperty('http://vocab.com/contains'), 'n2.1 <-contains- n2'); + $this->assertSame($node2, $node2_2->getReverseProperty('http://vocab.com/contains'), 'n2.1 <-contains- n2'); + + $this->assertSame($node3, $node1->getReverseProperty('http://vocab.com/link'), 'n1 <-link- n3'); + $this->assertSame($node3, $node3_1->getReverseProperty('http://vocab.com/contains'), 'n3.1 <-contains- n3'); + + $this->assertSame(array($node1, $node3), $nodeType->getReverseProperty(Node::TYPE), 'n1+n3 <-type- nodeType'); + $this->assertSame(array($node2), $nodeWithAliasesType->getNodesWithThisType(), 'n2 <-type- nodeWithAliases'); + } + + /** + * Tests isBlankNode() + */ + public function testNodeIsBlankNode() + { + $this->assertFalse($this->graph->getNode('http://example.com/node/1')->isBlankNode(), 'n1'); + $this->assertFalse($this->graph->getNode('http://example.com/node/2')->isBlankNode(), 'n2'); + $this->assertFalse($this->graph->getNode('http://example.com/node/3')->isBlankNode(), 'n3'); + + $this->assertTrue($this->graph->getNode('_:b0')->isBlankNode(), '_:b0'); + $this->assertTrue($this->graph->getNode('_:b1')->isBlankNode(), '_:b1'); + $this->assertTrue($this->graph->getNode('_:b2')->isBlankNode(), '_:b2'); + $this->assertTrue($this->graph->getNode('_:b3')->isBlankNode(), '_:b3'); + + $node = $this->graph->createNode(); + $this->assertTrue($node->isBlankNode(), 'new node without ID'); + + $node = $this->graph->createNode('_:fljdf'); + $this->assertTrue($node->isBlankNode(), 'new node blank node ID'); + + $node = $this->graph->createNode('http://www.example.com/node/new'); + $this->assertFalse($node->isBlankNode(), 'new node with ID'); + } + + /** + * Tests if reverse node relationships are updated when a property is updated. + */ + public function testNodeReverseRelationshipsUpdated() + { + $node1 = $this->graph->getNode('http://example.com/node/1'); + $node1_1 = $this->graph->getNode('_:b0'); + $node2 = $this->graph->getNode('http://example.com/node/2'); + $node3 = $this->graph->getNode('http://example.com/node/3'); + + $nodeType = $this->graph->getNode('http://vocab.com/type/node'); + $nodeWithAliasesType = $this->graph->getNode('http://vocab.com/type/nodeWithAliases'); + + $revProperties = $node2->getReverseProperties(); + $this->assertCount(1, $revProperties, 'Check number of node2\'s reverse properties'); + $this->assertSame( + array('http://vocab.com/link' => array($node1)), + $revProperties, + 'Check node2\'s reverse properties' + ); + + $node1->setProperty('http://vocab.com/link', null); + $this->assertNull($node1->getProperty('http://vocab.com/link'), 'n1 -link-> n2 removed'); + + $node1->removePropertyValue('http://vocab.com/contains', $node1_1); + $this->assertNull($node1->getProperty('http://vocab.com/contains'), 'n1 -contains-> n1.1 removed'); + + $this->assertNull($node2->getReverseProperty('http://vocab.com/link'), 'n2 <-link- n1 removed'); + $this->assertNull($node1_1->getReverseProperty('http://vocab.com/contains'), 'n1.1 <-contains- n1 removed'); + + $expectedProperties = array( + Node::TYPE => $this->graph->getNode('http://vocab.com/type/node'), + 'http://vocab.com/name' => new TypedValue('1', RdfConstants::XSD_STRING) + ); + $properties = $node1->getProperties(); + $this->assertCount(2, $properties, 'Check number of properties'); + $this->assertEquals($expectedProperties, $properties, 'Check properties'); + + $this->assertSame(array($node1, $node3), $nodeType->getNodesWithThisType(), 'n1+n3 <-type- nodeType'); + $this->assertSame($node2, $nodeWithAliasesType->getReverseProperty(Node::TYPE), 'n2 <-type- nodeWithAliases'); + + $node1->setType(null); + $node2->removeType($nodeWithAliasesType); + + $this->assertSame($node3, $nodeType->getReverseProperty(Node::TYPE), 'n3 <-type- nodeType'); + $this->assertSame(array(), $nodeWithAliasesType->getNodesWithThisType(), 'nodeWithAliases removed from n2'); + } + + /** + * Tests the removal of nodes from the graph. + */ + public function testNodeRemoval() + { + // Remove node 1 + $node1 = $this->graph->getNode('/node/1'); + $node1_1 = $this->graph->getNode('_:b0'); + $node2 = $this->graph->getNode('http://example.com/node/2'); + + $this->assertTrue($this->graph->containsNode('http://example.com/node/1'), 'node 1 in graph?'); + + $this->assertSame( + array('http://vocab.com/link' => array($node1)), + $node2->getReverseProperties(), + 'Check node2\'s reverse properties' + ); + + $this->assertSame( + array('http://vocab.com/contains' => array($node1)), + $node1_1->getReverseProperties(), + 'Check node1.1\'s reverse properties' + ); + + $node1->removeFromGraph(); + + $this->assertSame(array(), $node2->getReverseProperties(), 'n2 reverse properties'); + $this->assertNull($node2->getReverseProperty('http://vocab.com/link'), 'n2 <-link- n1 removed'); + + $this->assertSame(array(), $node1_1->getReverseProperties(), 'n1.1 reverse properties'); + $this->assertNull($node1_1->getReverseProperty('http://vocab.com/contains'), 'n1.1 <-contains- n1 removed'); + + $this->assertFalse($this->graph->containsNode('/node/1'), 'node 1 still in graph?'); + $this->assertNull($node1->getGraph(), 'node 1\'s graph reset?'); + + // Remove node 2 + $node2 = $this->graph->getNode('http://example.com/node/2'); + $node2_1 = $this->graph->getNode('_:b1'); + $node2_2 = $this->graph->getNode('_:b2'); + $node3 = $this->graph->getNode('/node/3'); + + $this->assertTrue($this->graph->containsNode('/node/2'), 'node 2 in graph?'); + + $this->assertSame( + array('http://vocab.com/link' => array($node2)), + $node3->getReverseProperties(), + 'Check node3\'s reverse properties' + ); + + $this->assertSame( + array('http://vocab.com/contains' => array($node2)), + $node2_1->getReverseProperties(), + 'Check node2.1\'s reverse properties' + ); + + $this->assertSame( + array('http://vocab.com/contains' => array($node2)), + $node2_2->getReverseProperties(), + 'Check node2.2\'s reverse properties' + ); + + $this->graph->removeNode($node2); + + $this->assertSame(array(), $node3->getReverseProperties(), 'n3 reverse properties'); + $this->assertNull($node3->getReverseProperty('http://vocab.com/link'), 'n3 <-link- n2 removed'); + + $this->assertSame(array(), $node2_1->getReverseProperties(), 'n2.1 reverse properties'); + $this->assertNull($node2_1->getReverseProperty('http://vocab.com/contains'), 'n2.1 <-contains- n2 removed'); + + $this->assertSame(array(), $node2_2->getReverseProperties(), 'n2.2 reverse properties'); + $this->assertNull($node2_2->getReverseProperty('http://vocab.com/contains'), 'n2.2 <-contains- n2 removed'); + + $this->assertFalse($this->graph->containsNode('./2'), 'node 2 still in graph?'); + } + + /** + * Tests the removal of node types from the graph. + */ + public function testNodeTypeRemoval() + { + // Remove nodeType + $node1 = $this->graph->getNode('http://example.com/node/1'); + $node3 = $this->graph->getNode('/node/3'); + $nodeType = $this->graph->getNode('http://vocab.com/type/node'); + + $this->assertTrue($this->graph->containsNode('http://vocab.com/type/node'), 'node type in graph?'); + + $this->assertSame($nodeType, $node1->getType(), 'n1 type'); + $this->assertSame($nodeType, $node3->getType(), 'n3 type'); + + $this->assertSame( + array(Node::TYPE => array($node1, $node3)), + $nodeType->getReverseProperties(), + 'Check node type\'s reverse properties' + ); + + $this->graph->removeNode($nodeType); + + $this->assertSame(array(), $nodeType->getReverseProperties(), 'node type\'s reverse properties'); + $this->assertSame(array(), $nodeType->getNodesWithThisType(), 'n1+n3 <-type- node type removed'); + + $this->assertNull($node1->getType(), 'n1 type removed'); + $this->assertNull($node3->getType(), 'n3 type removed'); + + $this->assertFalse($this->graph->containsNode('http://vocab.com/type/node'), 'node type still in graph?'); + } + + /** + * Tests if adding a value maintains uniqueness + */ + public function testNodePropertyUniqueness() + { + // Null + $node = $this->graph->getNode('http://example.com/node/1'); + $this->assertNull($node->getProperty('http://example.com/node/1'), 'inexistent'); + + $node->addPropertyValue('http://vocab.com/inexistent', null); + $this->assertNull($node->getProperty('http://example.com/node/1'), 'inexistent + null'); + + $node->removeProperty('http://vocab.com/inexistent'); + $node->removePropertyValue('http://vocab.com/inexistent', null); + $this->assertNull($node->getProperty('http://example.com/node/1'), 'inexistent removed'); + + // Scalars + $node = $this->graph->getNode('http://example.com/node/1'); + + $initialNameValue = $node->getProperty('http://vocab.com/name'); + + $this->assertEquals( + new TypedValue('1', RdfConstants::XSD_STRING), + $node->getProperty('http://vocab.com/name'), + 'name: initial value' + ); + + $node->addPropertyValue('http://vocab.com/name', '1'); + $node->addPropertyValue('http://vocab.com/name', null); + $this->assertSame($initialNameValue, $node->getProperty('http://vocab.com/name'), 'name: still same'); + + $node->addPropertyValue('http://vocab.com/name', 1); + $this->assertEquals( + array($initialNameValue, new TypedValue('1', RdfConstants::XSD_INTEGER)), + $node->getProperty('http://vocab.com/name'), + 'name: new value' + ); + + $node->removePropertyValue('http://vocab.com/name', 1); + $this->assertSame($initialNameValue, $node->getProperty('http://vocab.com/name'), 'name: removed new value'); + + // Language-tagged strings + $node = $this->graph->getNode('http://example.com/node/2'); + $value = $node->getProperty('http://vocab.com/lang'); + + $this->assertInstanceOf('ML\JsonLD\LanguageTaggedString', $value, 'lang: initial value type'); + $this->assertEquals('language-tagged string', $value->getValue(), 'lang: initial value'); + $this->assertEquals('en', $value->getLanguage(), 'lang: initial language'); + + $sameLangValue = new LanguageTaggedString('language-tagged string', 'en'); + $this->assertTrue($value->equals($sameLangValue), 'lang: equals same'); + + $newLangValue1 = new LanguageTaggedString('language-tagged string', 'de'); + $this->assertFalse($value->equals($newLangValue1), 'lang: equals new1'); + + $newLangValue2 = new LanguageTaggedString('other language-tagged string', 'en'); + $this->assertFalse($value->equals($newLangValue2), 'lang: equals new2'); + + $node->addPropertyValue('http://vocab.com/lang', $sameLangValue); + $this->assertSame($value, $node->getProperty('http://vocab.com/lang'), 'lang: still same'); + + $node->addPropertyValue('http://vocab.com/lang', $newLangValue1); + $node->addPropertyValue('http://vocab.com/lang', $newLangValue2); + + $value = $node->getProperty('http://vocab.com/lang'); + $this->assertCount(3, $value, 'lang: count values added'); + + $this->assertTrue($sameLangValue->equals($value[0]), 'lang: check values 1'); + $this->assertTrue($newLangValue1->equals($value[1]), 'lang: check values 2'); + $this->assertTrue($newLangValue2->equals($value[2]), 'lang: check values 3'); + + $node->removePropertyValue('http://vocab.com/lang', $newLangValue1); + $value = $node->getProperty('http://vocab.com/lang'); + $this->assertCount(2, $value, 'lang: count value 1 removed again'); + + $this->assertTrue($sameLangValue->equals($value[0]), 'lang: check values 1 (2)'); + $this->assertTrue($newLangValue2->equals($value[1]), 'lang: check values 2 (2)'); + + // Typed values + $node = $this->graph->getNode('http://example.com/node/2'); + $value = $node->getProperty('http://vocab.com/typed'); + + $this->assertInstanceOf('ML\JsonLD\TypedValue', $value, 'typed: initial value class'); + $this->assertEquals('typed value', $value->getValue(), 'typed: initial value'); + $this->assertEquals('http://vocab.com/type/datatype', $value->getType(), 'typed: initial value type'); + + $sameTypedValue = new TypedValue('typed value', 'http://vocab.com/type/datatype'); + $this->assertTrue($value->equals($sameTypedValue), 'typed: equals same'); + + $newTypedValue1 = new TypedValue('typed value', 'http://vocab.com/otherType'); + $this->assertFalse($value->equals($newTypedValue1), 'typed: equals new1'); + + $newTypedValue2 = new TypedValue('other typed value', 'http://vocab.com/type/datatype'); + $this->assertFalse($value->equals($newTypedValue2), 'typed: equals new2'); + + $node->addPropertyValue('http://vocab.com/typed', $sameTypedValue); + $this->assertSame($value, $node->getProperty('http://vocab.com/typed'), 'typed: still same'); + + $node->addPropertyValue('http://vocab.com/typed', $newTypedValue1); + $node->addPropertyValue('http://vocab.com/typed', $newTypedValue2); + + $value = $node->getProperty('http://vocab.com/typed'); + $this->assertCount(3, $value, 'typed: count values added'); + + $this->assertTrue($sameTypedValue->equals($value[0]), 'typed: check values 1'); + $this->assertTrue($newTypedValue1->equals($value[1]), 'typed: check values 2'); + $this->assertTrue($newTypedValue2->equals($value[2]), 'typed: check values 3'); + + $node->removePropertyValue('http://vocab.com/typed', $newTypedValue1); + $value = $node->getProperty('http://vocab.com/typed'); + $this->assertCount(2, $value, 'typed: count value 1 removed again'); + + $this->assertTrue($sameTypedValue->equals($value[0]), 'typed: check values 1 (2)'); + $this->assertTrue($newTypedValue2->equals($value[1]), 'typed: check values 2 (2)'); + + // Nodes + $node = $this->graph->getNode('http://example.com/node/3'); + $node1 = $this->graph->getNode('http://example.com/node/1'); + + $value = $node->getProperty('http://vocab.com/link'); + + $this->assertInstanceOf('ML\JsonLD\Node', $value, 'node: initial value class'); + $this->assertSame($node1, $value, 'node: initial node'); + + $newNode1 = $this->graph->createNode(); + $this->assertTrue($this->graph->containsNode($newNode1), 'node: new1 in graph'); + + $newNode2 = $this->graph->createNode('http://example.com/node/new/2'); + $this->assertTrue($this->graph->containsNode($newNode2), 'node: new2 in graph'); + + $node->addPropertyValue('http://vocab.com/link', $node1); + $this->assertSame($node1, $node->getProperty('http://vocab.com/link'), 'node: still same'); + + $node->addPropertyValue('http://vocab.com/link', $newNode1); + $node->addPropertyValue('http://vocab.com/link', $newNode2); + + $value = $node->getProperty('http://vocab.com/link'); + $this->assertCount(3, $value, 'node: count values added'); + + $this->assertSame($node1, $value[0], 'node: check values 1'); + $this->assertSame($newNode1, $value[1], 'node: check values 2'); + $this->assertSame($newNode2, $value[2], 'node: check values 3'); + + $node->removePropertyValue('http://vocab.com/link', $newNode1); + $value = $node->getProperty('http://vocab.com/link'); + $this->assertCount(2, $value, 'typed: count new node 1 removed again'); + + $this->assertTrue($node1->equals($value[0]), 'node: check values 1 (2)'); + $this->assertTrue($newNode2->equals($value[1]), 'node: check values 2 (2)'); + + // Node types + $node1 = $this->graph->getNode('http://example.com/node/1'); + $nodeType = $this->graph->getNode('http://vocab.com/type/node'); + $nodeWithAliasesType = $this->graph->getNode('http://vocab.com/type/nodeWithAliases'); + + $this->assertSame($nodeType, $node1->getType(), 'type: n1 initial type'); + + $newType1 = $this->graph->createNode(); + $this->assertTrue($this->graph->containsNode($newNode1), 'type: new1 in graph'); + + $node1->addType($nodeType); + $this->assertSame($nodeType, $node1->getType(), 'type: n1 type still same'); + + $node1->addType($nodeWithAliasesType); + $node1->addType($newType1); + + $value = $node1->getType(); + $this->assertCount(3, $value, 'type: count values added'); + + $this->assertSame($nodeType, $value[0], 'type: check values 1'); + $this->assertSame($nodeWithAliasesType, $value[1], 'type: check values 2'); + $this->assertSame($newType1, $value[2], 'type: check values 3'); + + $node1->removeType($nodeWithAliasesType); + $value = $node1->getType(); + $this->assertCount(2, $value, 'typed: count nodeWithAliasesType removed again'); + + $this->assertTrue($nodeType->equals($value[0]), 'type: check values 1 (2)'); + $this->assertTrue($newType1->equals($value[1]), 'type: check values 2 (2)'); + + } + + /** + * Tests whether it is possible to add invalid values + * + * @expectedException InvalidArgumentException + */ + public function testAddInvalidPropertyValue() + { + $graph = new Graph(); + $newNode = $graph->createNode(); + + $node1 = $this->graph->getNode('http://example.com/node/1'); + $node1->addPropertyValue('http://vocab.com/link', $newNode); + } + + /** + * Tests whether it is possible to set the node's type to an invalid + * value + * + * @expectedException InvalidArgumentException + */ + public function testSetInvalidTypeValue() + { + $node1 = $this->graph->getNode('http://example.com/node/1'); + $node1->setType('http://vocab.com/type/aTypeAsString'); + } + + /** + * Tests whether it is possible to set the node's type to an invalid + * value when an array is used. + * + * @expectedException InvalidArgumentException + */ + public function testSetInvalidTypeArray() + { + $types = array( + $this->graph->getNode('http://vocab.com/type/nodeWithAliases'), + 'http://vocab.com/type/aTypeAsString' + ); + + $node1 = $this->graph->getNode('http://example.com/node/1'); + + $node1->setType($types); + } + + /** + * Tests whether it is possible to add an type which is not part of the + * graph + * + * @expectedException InvalidArgumentException + */ + public function testAddTypeNotInGraph() + { + $graph = new Graph(); + $newType = $graph->createNode(); + + $node1 = $this->graph->getNode('http://example.com/node/1'); + $node1->addType($newType); + } + + /** + * Tests whether nodes are contained in the graph + */ + public function testContains() + { + $node1 = $this->graph->getNode('http://example.com/node/1'); + $nodeb_0 = $this->graph->getNode('_:b0'); + + $this->assertTrue($this->graph->containsNode($node1), 'node1 obj'); + $this->assertTrue($this->graph->containsNode('http://example.com/node/1'), 'node1 IRI'); + $this->assertFalse($this->graph->containsNode('http://example.com/node/X'), 'inexistent IRI'); + $this->assertTrue($this->graph->containsNode($nodeb_0), '_:b0'); + $this->assertFalse($this->graph->containsNode('_:b0'), '_:b0 IRI'); + $this->assertFalse($this->graph->containsNode(new TypedValue('val', 'http://example.com/type')), 'typed value'); + } + + /** + * Tests whether creating an existing node returns the instance of that node + */ + public function testCreateExistingNode() + { + $node1 = $this->graph->getNode('http://example.com/node/1'); + $nodeType = $this->graph->getNode('http://vocab.com/type/node'); + + $this->assertSame($node1, $this->graph->createNode('http://example.com/node/1')); + $this->assertSame($nodeType, $this->graph->createNode('http://vocab.com/type/node')); + } + + /** + * Tests the merging of two graphs + */ + public function testMerge() + { + $this->markTestSkipped("Merging graphs doesn't work yet as blank nodes are not relabeled properly"); + + $json = << 'http://example.com/node/index.jsonld'))->getGraph(); + + // Merge graph2 into graph + $this->graph->merge($graph2); + + $nodeIds = array( + 'http://example.com/node/1', + 'http://example.com/node/2', + 'http://example.com/node/3', + 'http://example.com/node/4', + '_:b0', + '_:b1', + '_:b2', + '_:b3', + '_:b4', + 'http://vocab.com/type/node', + 'http://vocab.com/type/nodeWithAliases' + ); + + $nodes = $this->graph->getNodes(); + $this->assertCount(count($nodeIds), $nodes); + + foreach ($nodes as $node) { + // Is the node's ID valid? + $this->assertContains($node->getId(), $nodeIds, 'Found unexpected node ID: ' . $node->getId()); + + // Is the node of the right type? + $this->assertInstanceOf('ML\JsonLD\Node', $node); + + // Does the graph return the same instance? + $n = $this->graph->getNode($node->getId()); + $this->assertSame($node, $n, 'same instance'); + $this->assertTrue($node->equals($n), 'equals'); + $this->assertSame($this->graph, $n->getGraph(), 'linked to graph'); + + // It must not share node objects with graph 2 + $this->assertNotSame($node, $graph2->getNode($node->getId()), 'shared instance between graph and graph 2'); + } + + // Check that the properties have been updated as well + $node1 = $this->graph->getNode('http://example.com/node/1'); + $node2 = $this->graph->getNode('http://example.com/node/2'); + $node3 = $this->graph->getNode('http://example.com/node/3'); + $node4 = $this->graph->getNode('http://example.com/node/4'); + + $this->assertEquals( + new TypedValue('1', RdfConstants::XSD_STRING), + $node1->getProperty('http://vocab.com/name'), + 'n1->name' + ); + $this->assertSame($node2, $node1->getProperty('http://vocab.com/link'), 'n1 -link-> n2'); + $this->assertCount(2, $node1->getProperty('http://vocab.com/contains'), 'n1 -contains-> 2 blank nodes'); + + $this->assertEquals( + array( + new TypedValue('2', RdfConstants::XSD_STRING), + new TypedValue('and a different name in graph 2', RdfConstants::XSD_STRING) + ), + $node2->getProperty('http://vocab.com/name'), + 'n2->name' + ); + + $this->assertSame(array($node3, $node4), $node2->getProperty('http://vocab.com/link'), 'n2 -link-> n3 & n4'); + $this->assertEquals( + new TypedValue('this was added in graph 2', RdfConstants::XSD_STRING), + $node2->getProperty('http://vocab.com/newFromGraph2'), + 'n2->newFromGraph2' + ); + + $this->assertEquals( + new TypedValue('node 4 from graph 2', RdfConstants::XSD_STRING), + $node4->getProperty('http://vocab.com/name'), + 'n4->name' + ); + + // Verify that graph 2 wasn't changed + $nodeIds = array( + 'http://example.com/node/1', + 'http://example.com/node/2', + '_:b0', // ex:contains: { ex:nested } + 'http://example.com/node/4', + 'http://vocab.com/type/node' + ); + + $nodes = $graph2->getNodes(); + $this->assertCount(count($nodeIds), $nodes); + + foreach ($nodes as $node) { + // Is the node's ID valid? + $this->assertContains($node->getId(), $nodeIds, 'Found unexpected node ID in graph 2: ' . $node->getId()); + + // Is the node of the right type? + $this->assertInstanceOf('ML\JsonLD\Node', $node); + + // Does the graph return the same instance? + $n = $graph2->getNode($node->getId()); + $this->assertSame($node, $n, 'same instance (graph 2)'); + $this->assertTrue($node->equals($n), 'equals (graph 2)'); + $this->assertSame($graph2, $n->getGraph(), 'linked to graph (graph 2)'); + } + } + + /** + * Tests the serialization of nodes + */ + public function testSerializeNode() + { + $expected = $this->documentLoader->loadDocument( + '{ + "@id": "http://example.com/node/1", + "@type": [ "http://vocab.com/type/node" ], + "http://vocab.com/name": [ { "@value": "1" } ], + "http://vocab.com/link": [ { "@id": "http://example.com/node/2" } ], + "http://vocab.com/contains": [ { "@id": "_:b0" } ] + }' + ); + $expected = $expected->document; + + $node1 = $this->graph->getNode('http://example.com/node/1'); + $this->assertEquals($expected, $node1->toJsonLd(), 'Serialize node 1'); + } + + /** + * Tests the serialization of graphs + */ + public function testSerializeGraph() + { + // This is the expanded and flattened version of the test document + // (the blank node labels have been renamed from _:t... to _:b...) + $expected = $this->documentLoader->loadDocument( + '[{ + "@id": "_:b0", + "http://vocab.com/nested": [{ + "@value": "1.1" + }] + }, { + "@id": "_:b1", + "http://vocab.com/nested": [{ + "@value": "2.1" + }] + }, { + "@id": "_:b2", + "http://vocab.com/nested": [{ + "@value": "2.2" + }] + }, { + "@id": "_:b3", + "http://vocab.com/nested": [{ + "@value": "3.1" + }] + }, { + "@id": "http://example.com/node/1", + "@type": ["http://vocab.com/type/node"], + "http://vocab.com/contains": [{ + "@id": "_:b0" + }], + "http://vocab.com/link": [{ + "@id": "http://example.com/node/2" + }], + "http://vocab.com/name": [{ + "@value": "1" + }] + }, { + "@id": "http://example.com/node/2", + "@type": ["http://vocab.com/type/nodeWithAliases"], + "http://vocab.com/aliases": [{ + "@value": "node2" + }, { + "@value": 2, + "@type": "http://www.w3.org/2001/XMLSchema#integer" + }], + "http://vocab.com/contains": [{ + "@id": "_:b1" + }, { + "@id": "_:b2" + }], + "http://vocab.com/lang": [{ + "@language": "en", + "@value": "language-tagged string" + }], + "http://vocab.com/link": [{ + "@id": "http://example.com/node/3" + }], + "http://vocab.com/name": [{ + "@value": "2" + }], + "http://vocab.com/typed": [{ + "@type": "http://vocab.com/type/datatype", + "@value": "typed value" + }] + }, { + "@id": "http://example.com/node/3", + "@type": ["http://vocab.com/type/node"], + "http://vocab.com/contains": [{ + "@id": "_:b3" + }], + "http://vocab.com/lang": [{ + "@language": "en", + "@value": "language-tagged string: en" + }, { + "@language": "de", + "@value": "language-tagged string: de" + }], + "http://vocab.com/link": [{ + "@id": "http://example.com/node/1" + }], + "http://vocab.com/name": [{ + "@value": "3" + }], + "http://vocab.com/typed": [{ + "@type": "http://vocab.com/type/datatype", + "@value": "typed value" + }, { + "@language": "ex:/type/otherDataType", + "@value": "typed value" + }, { + "@language": "ex:/type/datatype", + "@value": "typed value" + }] + }, { + "@id": "http://vocab.com/type/node" + }, { + "@id": "http://vocab.com/type/nodeWithAliases" + }]' + ); + $expected = $expected->document; + + $this->assertEquals($expected, $this->graph->toJsonLd(false), 'Serialize graph'); + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/JsonLDApiTest.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/JsonLDApiTest.php new file mode 100644 index 0000000..dcb7dbf --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/JsonLDApiTest.php @@ -0,0 +1,132 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD\Test; + +use ML\JsonLD\JsonLD; + +/** + * Tests JsonLD's API + * + * @author Markus Lanthaler + */ +class JsonLDApiTest extends JsonTestCase +{ + /** + * Tests the expansion API + * + * @group expansion + */ + public function testExpansion() + { + $path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR; + $expected = json_decode(file_get_contents($path . 'sample-expanded.jsonld')); + + $input = $path . 'sample-in.jsonld'; + $this->assertJsonEquals($expected, JsonLD::expand($input), 'Passing the file path'); + + $input = file_get_contents($input); + $this->assertJsonEquals($expected, JsonLD::expand($input), 'Passing the raw input (string)'); + + $input = json_decode($input); + $this->assertJsonEquals($expected, JsonLD::expand($input), 'Passing the parsed object'); + } + + /** + * Tests the compaction API + * + * @group compaction + */ + public function testCompaction() + { + $path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR; + $expected = json_decode(file_get_contents($path . 'sample-compacted.jsonld')); + + $input = $path . 'sample-in.jsonld'; + $context = $path . 'sample-context.jsonld'; + $this->assertJsonEquals($expected, JsonLD::compact($input, $context), 'Passing the file path'); + + $input = file_get_contents($input); + $context = file_get_contents($context); + $this->assertJsonEquals($expected, JsonLD::compact($input, $context), 'Passing the raw input (string)'); + + $input = json_decode($input); + $context = json_decode($context); + $this->assertJsonEquals($expected, JsonLD::compact($input, $context), 'Passing the parsed object'); + } + + /** + * Tests the flattening API + * + * @group flattening + */ + public function testFlatten() + { + $path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR; + $expected = json_decode(file_get_contents($path . 'sample-flattened.jsonld')); + + $input = $path . 'sample-in.jsonld'; + $context = $path . 'sample-context.jsonld'; + $this->assertJsonEquals($expected, JsonLD::flatten($input, $context), 'Passing the file path'); + + $input = file_get_contents($input); + $context = file_get_contents($context); + $this->assertJsonEquals($expected, JsonLD::flatten($input, $context), 'Passing the raw input (string)'); + + $input = json_decode($input); + $context = json_decode($context); + $this->assertJsonEquals($expected, JsonLD::flatten($input, $context), 'Passing the parsed object'); + } + + /** + * Tests the framing API + * + * This test intentionally uses the same fixtures as the flattening tests. + * + * @group framing + */ + public function testFrame() + { + $path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR; + $expected = json_decode(file_get_contents($path . 'sample-flattened.jsonld')); + + $input = $path . 'sample-in.jsonld'; + $context = $path . 'sample-context.jsonld'; + $this->assertJsonEquals($expected, JsonLD::frame($input, $context), 'Passing the file path'); + + $input = file_get_contents($input); + $context = file_get_contents($context); + $this->assertJsonEquals($expected, JsonLD::frame($input, $context), 'Passing the raw input (string)'); + + $input = json_decode($input); + $context = json_decode($context); + $this->assertJsonEquals($expected, JsonLD::frame($input, $context), 'Passing the parsed object'); + } + + /** + * Tests the document API + * + * This test intentionally uses the same fixtures as the flattening tests. + */ + public function testGetDocument() + { + + $path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR; + $expected = json_decode(file_get_contents($path . 'sample-serialized-document.jsonld')); + + $input = $path . 'sample-in.jsonld'; + $this->assertJsonEquals($expected, JsonLD::getDocument($input)->toJsonLd(), 'Passing the file path'); + + $input = file_get_contents($input); + $this->assertJsonEquals($expected, JsonLD::getDocument($input)->toJsonLd(), 'Passing the raw input (string)'); + + $input = json_decode($input); + $this->assertJsonEquals($expected, JsonLD::getDocument($input)->toJsonLd(), 'Passing the parsed object'); + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/JsonTestCase.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/JsonTestCase.php new file mode 100644 index 0000000..8e8d0bd --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/JsonTestCase.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD\Test; + +/** + * A JSON Test Case + * + * This class extends {@link \PHPUnit_Framework_TestCase} with an assertion + * to compare JSON. + * + * @author Markus Lanthaler + */ +abstract class JsonTestCase extends \PHPUnit_Framework_TestCase +{ + /** + * Asserts that two JSON structures are equal. + * + * @param object|array $expected + * @param object|array $actual + * @param string $message + */ + public static function assertJsonEquals($expected, $actual, $message = '') + { + $expected = self::normalizeJson($expected); + $actual = self::normalizeJson($actual); + + self::assertEquals($expected, $actual, $message); + } + + /** + * Brings the keys of objects to a deterministic order to enable + * comparison of JSON structures + * + * @param mixed $element The element to normalize. + * + * @return mixed The same data with all object keys ordered in a + * deterministic way. + */ + private static function normalizeJson($element) + { + if (is_array($element)) { + foreach ($element as &$item) { + $item = self::normalizeJson($item); + } + } elseif (is_object($element)) { + $element = (array) $element; + ksort($element); + $element = (object) $element; + + foreach ($element as &$item) { + $item = self::normalizeJson($item); + } + } + + return $element; + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/NQuadsTest.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/NQuadsTest.php new file mode 100644 index 0000000..1dbfdf1 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/NQuadsTest.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD\Test; + +use ML\JsonLD\JsonLD; +use ML\JsonLD\NQuads; + +/** + * Tests NQuads + * + * @author Markus Lanthaler + */ +class NQuadsTest extends \PHPUnit_Framework_TestCase +{ + /** + * Tests that parsing an invalid NQuad file fails + * + * @expectedException \ML\JsonLD\Exception\InvalidQuadException + */ + public function testInvalidParse() + { + $nquads = new NQuads(); + $nquads->parse('Invalid NQuads file'); + } + + /** + * Tests escaping + */ + public function testEscaping() + { + $doc = ''; + $doc .= ' '; + $doc .= ' "String with line-break \n and quote (\")" .'; + $doc .= "\n"; + + $nquads = new NQuads(); + $parsed = JsonLD::fromRdf($nquads->parse($doc)); + $serialized = $nquads->serialize(JsonLD::toRdf($parsed)); + + $this->assertSame($doc, $serialized); + } + + /** + * Tests blank node label parsing + */ + public function testParseBlankNodes() + { + $nquads = new NQuads(); + + $this->assertNotEmpty($nquads->parse('_:b "Test" .'), 'just a letter'); + + $this->assertNotEmpty($nquads->parse('_:b1 "Test" .'), 'letter and number'); + + $this->assertNotEmpty($nquads->parse('_:_b1 "Test" .'), 'beginning _'); + + $this->assertNotEmpty($nquads->parse('_:b_1 "Test" .'), 'containing _'); + + $this->assertNotEmpty($nquads->parse('_:b1_ "Test" .'), 'ending _'); + + $this->assertNotEmpty($nquads->parse('_:b-1 "Test" .'), 'containing -'); + + $this->assertNotEmpty($nquads->parse('_:b-1 "Test" .'), 'ending -'); + + $this->assertNotEmpty($nquads->parse('_:b.1 "Test" .'), 'containing .'); + } + + /** + * Tests that parsing fails for blank node labels beginning with "-" + * + * @expectedException \ML\JsonLD\Exception\InvalidQuadException + */ + public function testParseBlankNodeDashAtTheBeginning() + { + $nquads = new NQuads(); + $nquads->parse('_:-b1 "Test" .'); + } + + /** + * Tests that parsing fails for blank node labels beginning with "." + * + * @expectedException \ML\JsonLD\Exception\InvalidQuadException + */ + public function testParseBlankNodePeriodAtTheBeginning() + { + $nquads = new NQuads(); + $nquads->parse('_:.b1 "Test" .'); + } + + /** + * Tests that parsing fails for blank node labels ending with "." + * + * @expectedException \ML\JsonLD\Exception\InvalidQuadException + */ + public function testParseBlankNodePeriodAtTheEnd() + { + $nquads = new NQuads(); + $nquads->parse('_:b1. "Test" .'); + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/TestManifestIterator.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/TestManifestIterator.php new file mode 100644 index 0000000..79272cc --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/TestManifestIterator.php @@ -0,0 +1,120 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD\Test; + +/** + * TestManifestIterator reads a test manifest and returns the contained test + * definitions. + * + * @author Markus Lanthaler + */ +class TestManifestIterator implements \Iterator +{ + /** The current position. */ + private $key = 0; + + /** The test directory. */ + private $directory; + + /** The test manifest. */ + private $manifest; + + /** The URL of the test manifest. */ + private $url; + + /** The total number of tests. */ + private $numberTests = 0; + + /** + * Constructor + * + * @param string $file The manifest's filename. + * @param string $url The manifest's URL. + */ + public function __construct($file, $url) + { + if (file_exists($file)) { + $this->manifest = json_decode(file_get_contents($file)); + $this->numberTests = count($this->manifest->{'sequence'}); + $this->url = $url; + $this->directory = dirname($file) . DIRECTORY_SEPARATOR; + } + } + + /** + * Rewinds the TestManifestIterator to the first element. + */ + public function rewind() + { + $this->key = 0; + } + + /** + * Checks if current position is valid. + * + * @return bool True if the current position is valid; otherwise, false. + */ + public function valid() + { + return ($this->key < $this->numberTests); + } + + /** + * Returns the key of the current element. + * + * @return string The key of the current element + */ + public function key() + { + return $this->url . $this->manifest->{'sequence'}[$this->key]->{'@id'}; + } + + /** + * Returns the current element. + * + * @return array Returns an array containing the name of the test and the + * test definition object. + */ + public function current() + { + $test = $this->manifest->{'sequence'}[$this->key]; + $options = isset($test->{'option'}) + ? clone $test->{'option'} // cloning because we are modifying it + : new \stdClass(); + + if (false === property_exists($options, 'base')) { + if (property_exists($this->manifest, 'baseIri')) { + $options->base = $this->manifest->{'baseIri'} . $test->{'input'}; + } else { + $options->base = $test->{'input'}; + } + } + + if (isset($options->{'expandContext'}) && (false === strpos($options->{'expandContext'}, ':'))) { + $options->{'expandContext'} = $this->directory . $options->{'expandContext'}; + } + + $test = array( + 'name' => $test->{'name'}, + 'test' => $test, + 'options' => $options + ); + + return $test; + } + + /** + * Moves forward to next element. + */ + public function next() + { + $this->key++; + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/ValueTest.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/ValueTest.php new file mode 100644 index 0000000..d4f5a00 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/ValueTest.php @@ -0,0 +1,138 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD\Test; + +use ML\JsonLD\LanguageTaggedString; +use ML\JsonLD\TypedValue; + +/** + * Test LanguageTaggedString and TypedValue + * + * @author Markus Lanthaler + */ +class ValueTest extends \PHPUnit_Framework_TestCase +{ + /** + * Tests LanguageTaggedString + */ + public function testLanguageTaggedString() + { + $string1 = new LanguageTaggedString('', ''); + $this->assertSame('', $string1->getValue(), 'string1 value'); + $this->assertSame('', $string1->getLanguage(), 'string1 language'); + + $string2 = new LanguageTaggedString('wert', 'de'); + $this->assertSame('wert', $string2->getValue(), 'string2 value'); + $this->assertSame('de', $string2->getLanguage(), 'string2 language'); + + $string3 = new LanguageTaggedString('value', 'en'); + $this->assertSame('value', $string3->getValue(), 'string3 value'); + $this->assertSame('en', $string3->getLanguage(), 'string3 language'); + } + + /** + * Tests LanguageTaggedString with an invalid value + * + * @expectedException \InvalidArgumentException + */ + public function testLanguageTaggedStringInvalidValue() + { + $string1 = new LanguageTaggedString('value', 'language'); + $string1->setValue(1); + } + + /** + * Tests LanguageTaggedString with an invalid language + * + * @expectedException \InvalidArgumentException + */ + public function testLanguageTaggedStringInvalidLanguage() + { + $string1 = new LanguageTaggedString('value', 'language'); + $string1->setLanguage(null); + } + + /** + * Tests TypedValue + */ + public function testTypedValue() + { + $value1 = new TypedValue('', ''); + $this->assertSame('', $value1->getValue(), 'string1 value'); + $this->assertSame('', $value1->getType(), 'string1 type'); + + $value2 = new TypedValue('wert', 'http://example.com/type1'); + $this->assertSame('wert', $value2->getValue(), 'string2 value'); + $this->assertSame('http://example.com/type1', $value2->getType(), 'string2 type'); + + $value3 = new TypedValue('value', 'http://example.com/type2'); + $this->assertSame('value', $value3->getValue(), 'string3 value'); + $this->assertSame('http://example.com/type2', $value3->getType(), 'string3 type'); + } + + /** + * Tests TypedValue with an invalid value + * + * @expectedException \InvalidArgumentException + */ + public function testTypedValueInvalidValue() + { + $value1 = new LanguageTaggedString('value', 'language'); + $value1->setValue(1); + } + + /** + * Tests TypedValue with an invalid type + * + * @expectedException \InvalidArgumentException + */ + public function testTypedValueInvalidLanguage() + { + $value1 = new TypedValue('value', 'http://example.com/type'); + $value1->setType(1); + } + + /** + * Tests TypedValue with an invalid type + */ + public function testEquals() + { + $string1a = new LanguageTaggedString('value', 'en'); + $string1b = new LanguageTaggedString('value', 'en'); + $string2 = new LanguageTaggedString('value', 'de'); + $string3 = new LanguageTaggedString('wert', 'en'); + + $this->assertTrue($string1a->equals($string1b), 's1a == s1b?'); + $this->assertFalse($string1a->equals($string2), 's1a == s2?'); + $this->assertFalse($string1a->equals($string3), 's1a == s3?'); + $this->assertFalse($string1b->equals($string2), 's1b == s2?'); + $this->assertFalse($string1b->equals($string3), 's1b == s3?'); + $this->assertFalse($string2->equals($string3), 's2 == s3?'); + + + $typed1a = new TypedValue('value', 'http://example.com/type1'); + $typed1b = new TypedValue('value', 'http://example.com/type1'); + $typed2 = new TypedValue('value', 'http://example.com/type2'); + $typed3 = new TypedValue('wert', 'http://example.com/type1'); + + $this->assertTrue($typed1a->equals($typed1b), 't1a == t1b?'); + $this->assertFalse($typed1a->equals($typed2), 't1a == t2?'); + $this->assertFalse($typed1a->equals($typed3), 't1a == t3?'); + $this->assertFalse($typed1b->equals($typed2), 't1b == t2?'); + $this->assertFalse($typed1b->equals($typed3), 't1b == t3?'); + $this->assertFalse($typed2->equals($typed3), 't2 == t3?'); + + $string4 = new LanguageTaggedString('', ''); + $typed4 = new TypedValue('', ''); + + $this->assertFalse($string4->equals($typed4), 's4 == t4'); + $this->assertFalse($typed4->equals($string4), 's4 == t4'); + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/W3CTestSuiteTest.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/W3CTestSuiteTest.php new file mode 100644 index 0000000..fdfcb6a --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/W3CTestSuiteTest.php @@ -0,0 +1,368 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD\Test; + +use ML\JsonLD\JsonLD; +use ML\JsonLD\NQuads; +use ML\JsonLD\Test\TestManifestIterator; + +/** + * The official W3C JSON-LD test suite. + * + * @link http://www.w3.org/2013/json-ld-tests/ Official W3C JSON-LD test suite + * + * @author Markus Lanthaler + */ +class W3CTestSuiteTest extends JsonTestCase +{ + /** + * The base directory from which the test manifests, input, and output + * files should be read. + */ + private $basedir; + + /** + * The URL corresponding to the base directory + */ + private $baseurl = 'http://json-ld.org/test-suite/tests/'; + + /** + * @var string The test's ID. + */ + private $id; + + /** + * Constructs a test case with the given name. + * + * @param null|string $name + * @param array $data + * @param string $dataName + */ + public function __construct($name = null, array $data = array(), $dataName = '') + { + $this->id = $dataName; + + parent::__construct($name, $data, $dataName); + $this->basedir = dirname(__FILE__) . '/../vendor/json-ld/tests/'; + } + + /** + * Returns the test identifier. + * + * @return string The test identifier + */ + public function getTestId() + { + return $this->id; + } + + /** + * Tests expansion. + * + * @param string $name The test name. + * @param object $test The test definition. + * @param object $options The options to configure the algorithms. + * + * @group expansion + * @dataProvider expansionProvider + */ + public function testExpansion($name, $test, $options) + { + $expected = json_decode(file_get_contents($this->basedir . $test->{'expect'})); + $result = JsonLD::expand($this->basedir . $test->{'input'}, $options); + + $this->assertJsonEquals($expected, $result); + } + + /** + * Provides expansion test cases. + */ + public function expansionProvider() + { + return new TestManifestIterator( + $this->basedir . 'expand-manifest.jsonld', + $this->baseurl . 'expand-manifest.jsonld' + ); + } + + /** + * Tests compaction. + * + * @param string $name The test name. + * @param object $test The test definition. + * @param object $options The options to configure the algorithms. + * + * @group compaction + * @dataProvider compactionProvider + */ + public function testCompaction($name, $test, $options) + { + $expected = json_decode(file_get_contents($this->basedir . $test->{'expect'})); + $result = JsonLD::compact( + $this->basedir . $test->{'input'}, + $this->basedir . $test->{'context'}, + $options + ); + + $this->assertJsonEquals($expected, $result); + } + + + /** + * Provides compaction test cases. + */ + public function compactionProvider() + { + return new TestManifestIterator( + $this->basedir . 'compact-manifest.jsonld', + $this->baseurl . 'compact-manifest.jsonld' + ); + } + + /** + * Tests flattening. + * + * @param string $name The test name. + * @param object $test The test definition. + * @param object $options The options to configure the algorithms. + * + * @group flattening + * @dataProvider flattenProvider + */ + public function testFlatten($name, $test, $options) + { + $expected = json_decode(file_get_contents($this->basedir . $test->{'expect'})); + $context = (isset($test->{'context'})) + ? $this->basedir . $test->{'context'} + : null; + + $result = JsonLD::flatten($this->basedir . $test->{'input'}, $context, $options); + + $this->assertJsonEquals($expected, $result); + } + + /** + * Provides flattening test cases. + */ + public function flattenProvider() + { + return new TestManifestIterator( + $this->basedir . 'flatten-manifest.jsonld', + $this->baseurl . 'flatten-manifest.jsonld' + ); + } + + /** + * Tests remote document loading. + * + * @param string $name The test name. + * @param object $test The test definition. + * @param object $options The options to configure the algorithms. + * + * @group remote + * @dataProvider remoteDocumentLoadingProvider + */ + public function testRemoteDocumentLoading($name, $test, $options) + { + if (in_array('jld:NegativeEvaluationTest', $test->{'@type'})) { + $this->setExpectedException('ML\JsonLD\Exception\JsonLdException', null, $test->{'expect'}); + } else { + $expected = json_decode($this->replaceBaseUrl(file_get_contents($this->basedir . $test->{'expect'}))); + } + + unset($options->base); + + $result = JsonLD::expand($this->replaceBaseUrl($this->baseurl . $test->{'input'}), $options); + + if (isset($expected)) { + $this->assertJsonEquals($expected, $result); + } + } + + /** + * Provides remote document loading test cases. + */ + public function remoteDocumentLoadingProvider() + { + return new TestManifestIterator( + $this->basedir . 'remote-doc-manifest.jsonld', + $this->baseurl . 'remote-doc-manifest.jsonld' + ); + } + + /** + * Replaces the base URL 'http://json-ld.org/' with 'https://json-ld.org:443/'. + * + * The test location of the test suite has been changed as the site has been + * updated to use HTTPS everywhere. + * + * @param string $input The input string. + * + * @return string The input string with all occurrences of the old base URL replaced with the new HTTPS-based one. + */ + private function replaceBaseUrl($input) { + return str_replace('http://json-ld.org/', 'https://json-ld.org:443/', $input); + } + + /** + * Tests errors (uses flattening). + * + * @param string $name The test name. + * @param object $test The test definition. + * @param object $options The options to configure the algorithms. + * + * @group errors + * @dataProvider errorProvider + */ + public function testError($name, $test, $options) + { + $this->setExpectedException('ML\JsonLD\Exception\JsonLdException', null, $test->{'expect'}); + + JsonLD::flatten( + $this->basedir . $test->{'input'}, + (isset($test->{'context'})) ? $this->basedir . $test->{'context'} : null, + $options + ); + } + + /** + * Provides error test cases. + */ + public function errorProvider() + { + return new TestManifestIterator( + $this->basedir . 'error-manifest.jsonld', + $this->baseurl . 'error-manifest.jsonld' + ); + } + + /** + * Tests framing. + * + * @param string $name The test name. + * @param object $test The test definition. + * @param object $options The options to configure the algorithms. + * + * @group framing + * @dataProvider framingProvider + */ + public function testFraming($name, $test, $options) + { + $ignoredTests = array( + 'frame-0005-in.jsonld', + 'frame-0009-in.jsonld', + 'frame-0010-in.jsonld', + 'frame-0012-in.jsonld', + 'frame-0013-in.jsonld', + 'frame-0023-in.jsonld', + 'frame-0024-in.jsonld', + 'frame-0027-in.jsonld', + 'frame-0028-in.jsonld', + 'frame-0029-in.jsonld', + 'frame-0030-in.jsonld' + ); + + if (in_array($test->{'input'}, $ignoredTests)) { + $this->markTestSkipped( + 'This implementation uses deep value matching and aggressive re-embedding. See ISSUE-110 and ISSUE-119.' + ); + } + + $expected = json_decode(file_get_contents($this->basedir . $test->{'expect'})); + $result = JsonLD::frame( + $this->basedir . $test->{'input'}, + $this->basedir . $test->{'frame'}, + $options + ); + + $this->assertJsonEquals($expected, $result); + } + + /** + * Provides framing test cases. + */ + public function framingProvider() + { + return new TestManifestIterator( + $this->basedir . 'frame-manifest.jsonld', + $this->baseurl . 'frame-manifest.jsonld' + ); + } + + /** + * Tests conversion to RDF quads. + * + * @param string $name The test name. + * @param object $test The test definition. + * @param object $options The options to configure the algorithms. + * + * @group toRdf + * @dataProvider toRdfProvider + */ + public function testToRdf($name, $test, $options) + { + $expected = trim(file_get_contents($this->basedir . $test->{'expect'})); + $quads = JsonLD::toRdf($this->basedir . $test->{'input'}, $options); + + $serializer = new NQuads(); + $result = $serializer->serialize($quads); + + // Sort quads (the expected quads are already sorted) + $result = explode("\n", trim($result)); + sort($result); + $result = implode("\n", $result); + + $this->assertEquals($expected, $result); + } + + /** + * Provides conversion to RDF quads test cases. + */ + public function toRdfProvider() + { + return new TestManifestIterator( + $this->basedir . 'toRdf-manifest.jsonld', + $this->baseurl . 'toRdf-manifest.jsonld' + ); + } + + /** + * Tests conversion from quads. + * + * @param string $name The test name. + * @param object $test The test definition. + * @param object $options The options to configure the algorithms. + * + * @group fromRdf + * @dataProvider fromRdfProvider + */ + public function testFromRdf($name, $test, $options) + { + $expected = json_decode(file_get_contents($this->basedir . $test->{'expect'})); + + $parser = new NQuads(); + $quads = $parser->parse(file_get_contents($this->basedir . $test->{'input'})); + + $result = JsonLD::fromRdf($quads, $options); + + $this->assertEquals($expected, $result); + } + + /** + * Provides conversion to quads test cases. + */ + public function fromRdfProvider() + { + return new TestManifestIterator( + $this->basedir . 'fromRdf-manifest.jsonld', + $this->baseurl . 'fromRdf-manifest.jsonld' + ); + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/bootstrap.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/bootstrap.php new file mode 100644 index 0000000..977c824 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Test/bootstrap.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +use stdClass as JsonObject; + +/** + * A typed value represents a value with an associated type. + * + * @author Markus Lanthaler + */ +final class TypedValue extends Value +{ + /** + * The type of the value in the form of an IRI. + * + * @var string + */ + private $type; + + /** + * Constructor + * + * @param string $value The value. + * @param string $type The type. + */ + public function __construct($value, $type) + { + $this->setValue($value); + $this->setType($type); + } + + /** + * Set the type + * + * For the sake of simplicity, the type is currently just a Node + * identifier in the form of a string and not a Node reference. + * This might be changed in the future. + * + * @param string $type The type. + * + * @return self + * + * @throws \InvalidArgumentException If the type is not a string. No + * further checks are currently done. + */ + public function setType($type) + { + if (!is_string($type)) { + throw new \InvalidArgumentException('type must be a string.'); + } + + $this->type = $type; + + return $this; + } + + /** + * Get the type + * + * For the sake of simplicity, the type is currently just a Node + * identifier in the form of a string and not a Node reference. + * This might be changed in the future. + * + * @return string The type. + */ + public function getType() + { + return $this->type; + } + + /** + * {@inheritdoc} + */ + public function toJsonLd($useNativeTypes = true) + { + $result = new JsonObject(); + + if (RdfConstants::XSD_STRING === $this->type) { + $result->{'@value'} = $this->value; + + return $result; + } + + if (true === $useNativeTypes) { + if (RdfConstants::XSD_BOOLEAN === $this->type) { + if ('true' === $this->value) { + $result->{'@value'} = true; + + return $result; + } elseif ('false' === $this->value) { + $result->{'@value'} = false; + + return $result; + } + + } elseif (RdfConstants::XSD_INTEGER === $this->type) { + if (preg_match('/^[\+|-]?\d+$/', trim($this->value))) { + $result->{'@value'} = intval($this->value); + + return $result; + } + } elseif (RdfConstants::XSD_DOUBLE === $this->type) { + // TODO Need to handle +/-INF and NaN as well? + if (preg_match('/^[\+|-]?\d+(?:\.\d*)?(?:[eE][\+|-]?\d+)?$/', trim($this->value))) { + $result->{'@value'} = floatval($this->value); + + return $result; + } + // TODO Need to preserve doubles without fraction for round-tripping?? + } + } + + $result->{'@value'} = $this->value; + $result->{'@type'} = $this->type; + + return $result; + } + + /** + * {@inheritdoc} + */ + public function equals($other) + { + if (get_class($this) !== get_class($other)) { + return false; + } + + return ($this->value === $other->value) && ($this->type === $other->type); + + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/Value.php b/Resources/Private/PHP/embed/vendor/ml/json-ld/Value.php new file mode 100644 index 0000000..0839f64 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/Value.php @@ -0,0 +1,123 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ML\JsonLD; + +use stdClass as JsonObject; + +/** + * Value is the abstract base class used for typed values and + * language-tagged strings. + * + * @author Markus Lanthaler + */ +abstract class Value implements JsonLdSerializable +{ + /** + * The value in the form of a string + * + * @var string + */ + protected $value; + + /** + * Set the value + * + * @param string $value The value. + * + * @return self + * + * @throws \InvalidArgumentException If the value is not a string. + */ + public function setValue($value) + { + if (!is_string($value)) { + throw new \InvalidArgumentException('value must be a string.'); + } + + $this->value = $value; + + return $this; + } + + /** + * Get the value + * + * @return string The value. + */ + public function getValue() + { + return $this->value; + } + + /** + * Create a LanguageTaggedString or TypedValue from a JSON-LD element + * + * If the passed value element can't be transformed to a language-tagged + * string or a typed value false is returned. + * + * @param JsonObject $element The JSON-LD element + * + * @return false|LanguageTaggedString|TypedValue The parsed object + */ + public static function fromJsonLd(JsonObject $element) + { + if (false === property_exists($element, '@value')) { + return false; + } + + $value = $element->{'@value'}; + $type = (property_exists($element, '@type')) + ? $element->{'@type'} + : null; + $language = (property_exists($element, '@language')) + ? $element->{'@language'} + : null; + + if (is_int($value) || is_float($value)) { + if (($value != (int) $value) || (RdfConstants::XSD_DOUBLE === $type)) { + $value = preg_replace('/(0{0,14})E(\+?)/', 'E', sprintf('%1.15E', $value)); + + if ((null === $type) && (null === $language)) { + return new TypedValue($value, RdfConstants::XSD_DOUBLE); + } + } else { + $value = sprintf('%d', $value); + if ((null === $type) && (null === $language)) { + return new TypedValue($value, RdfConstants::XSD_INTEGER); + } + } + } elseif (is_bool($value)) { + $value = ($value) ? 'true' : 'false'; + + if ((null === $type) && (null === $language)) { + return new TypedValue($value, RdfConstants::XSD_BOOLEAN); + } + } elseif (false === is_string($value)) { + return false; + } + + // @type gets precedence + if ((null === $type) && (null !== $language)) { + return new LanguageTaggedString($value, $language); + } + + return new TypedValue($value, (null === $type) ? RdfConstants::XSD_STRING : $type); + } + + /** + * Compares this instance to the specified value. + * + * @param mixed $other The value this instance should be compared to. + * + * @return bool Returns true if the passed value is the same as this + * instance; false otherwise. + */ + abstract public function equals($other); +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/composer.json b/Resources/Private/PHP/embed/vendor/ml/json-ld/composer.json new file mode 100644 index 0000000..d362c7c --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/composer.json @@ -0,0 +1,30 @@ +{ + "name": "ml/json-ld", + "type": "library", + "description": "JSON-LD Processor for PHP", + "keywords": [ "JSON-LD", "jsonld" ], + "homepage": "http://www.markus-lanthaler.com", + "license": "MIT", + "authors": [ + { + "name": "Markus Lanthaler", + "email": "mail@markus-lanthaler.com", + "homepage": "http://www.markus-lanthaler.com", + "role": "Developer" + } + ], + "require": { + "php": ">=5.3.0", + "ext-json": "*", + "ml/iri": "^1.1.1" + }, + "require-dev": { + "json-ld/tests": "1.0", + "phpunit/phpunit": "^4" + }, + "autoload": { + "psr-4": { + "ML\\JsonLD\\": "" + } + } +} diff --git a/Resources/Private/PHP/embed/vendor/ml/json-ld/phpunit.xml.dist b/Resources/Private/PHP/embed/vendor/ml/json-ld/phpunit.xml.dist new file mode 100644 index 0000000..1a96be6 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/ml/json-ld/phpunit.xml.dist @@ -0,0 +1,74 @@ + + + + + + ./Test/ + + + + + + ./ + + ./Test + ./vendor + + + + + + + + + + + diff --git a/Resources/Private/PHP/embed/vendor/oscarotero/html-parser/.github/workflows/test.yml b/Resources/Private/PHP/embed/vendor/oscarotero/html-parser/.github/workflows/test.yml new file mode 100644 index 0000000..614a0e9 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/oscarotero/html-parser/.github/workflows/test.yml @@ -0,0 +1,44 @@ +name: "testing" + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + tests: + name: Tests + runs-on: ubuntu-latest + + strategy: + matrix: + php: + - 7.2 + - 7.3 + - 7.4 + - 8.0 + - 8.1 + - 8.2 + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + + - name: Cache PHP dependencies + uses: actions/cache@v3 + with: + path: vendor + key: ${{ runner.os }}-php-${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-php-${{ matrix.php }}-composer- + + - name: Install dependencies + run: composer install + + - name: Tests + run: composer test diff --git a/Resources/Private/PHP/embed/vendor/oscarotero/html-parser/CHANGELOG.md b/Resources/Private/PHP/embed/vendor/oscarotero/html-parser/CHANGELOG.md new file mode 100644 index 0000000..04f30ad --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/oscarotero/html-parser/CHANGELOG.md @@ -0,0 +1,54 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +## [0.1.7] - 2022-12-17 +### Added +- Support for PHP 8.2 [#4]. + +### Changed +- Use GitHub Workflows for testing. + +## [0.1.6] - 2020-11-19 +### Added +- Added a second argument to `parse` and `parseFragment` to specify the encoding instead autodetect [#2] [#3]. + +## [0.1.5] - 2020-08-31 +### Fixed +- Support for PHP 8 [#1]. + +## [0.1.4] - 2019-12-15 +### Fixed +- Changed the way to handle different encodings detecting the and elements + +## [0.1.3] - 2019-07-20 +### Fixed +- UTF-8 econding issues + +## [0.1.2] - 2019-05-25 +### Fixed +- Improved encoding detection + +## [0.1.1] - 2019-04-21 +### Fixed +- `parseFragment` was returning a fragment containing only the first element + +## [0.1.0] - 2019-04-21 +First version + +[#1]: https://github.com/oscarotero/html-parser/issues/1 +[#2]: https://github.com/oscarotero/html-parser/issues/2 +[#3]: https://github.com/oscarotero/html-parser/issues/3 +[#4]: https://github.com/oscarotero/html-parser/issues/4 + +[0.1.7]: https://github.com/oscarotero/html-parser/compare/v0.1.6...v0.1.7 +[0.1.6]: https://github.com/oscarotero/html-parser/compare/v0.1.5...v0.1.6 +[0.1.5]: https://github.com/oscarotero/html-parser/compare/v0.1.4...v0.1.5 +[0.1.4]: https://github.com/oscarotero/html-parser/compare/v0.1.3...v0.1.4 +[0.1.3]: https://github.com/oscarotero/html-parser/compare/v0.1.2...v0.1.3 +[0.1.2]: https://github.com/oscarotero/html-parser/compare/v0.1.1...v0.1.2 +[0.1.1]: https://github.com/oscarotero/html-parser/compare/v0.1.0...v0.1.1 +[0.1.0]: https://github.com/oscarotero/html-parser/releases/tag/v0.1.0 diff --git a/Resources/Private/PHP/embed/vendor/oscarotero/html-parser/LICENSE b/Resources/Private/PHP/embed/vendor/oscarotero/html-parser/LICENSE new file mode 100644 index 0000000..604fe28 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/oscarotero/html-parser/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Oscar Otero + +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/Resources/Private/PHP/embed/vendor/oscarotero/html-parser/README.md b/Resources/Private/PHP/embed/vendor/oscarotero/html-parser/README.md new file mode 100644 index 0000000..1ca5462 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/oscarotero/html-parser/README.md @@ -0,0 +1,25 @@ +# HTML parser + +Simple utility to parse html strings to DOMDocument. + +```sh +composer require oscarotero/html-parser +``` + +## Usage + +```php +use HtmlParser\Parser; + +$html = 'Hello world'; + +//Convert a string to a DOMDocument +$document = Parser::parse($html); + +//Convert a string to a DOMDocumentFragment +$fragment = Parser::parseFragment('

Hello world

'); + +//Convert a DOMDocument or DOMDocumentFragment to a string +echo Parser::stringify($document); +echo Parser::stringify($fragment); +``` diff --git a/Resources/Private/PHP/embed/vendor/oscarotero/html-parser/composer.json b/Resources/Private/PHP/embed/vendor/oscarotero/html-parser/composer.json new file mode 100644 index 0000000..21707df --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/oscarotero/html-parser/composer.json @@ -0,0 +1,41 @@ +{ + "name": "oscarotero/html-parser", + "type": "library", + "description": "Parse html strings to DOMDocument", + "keywords": ["html", "parser", "dom"], + "homepage": "https://github.com/oscarotero/html-parser", + "license": "MIT", + "authors": [ + { + "name": "Oscar Otero", + "email": "oom@oscarotero.com", + "homepage": "http://oscarotero.com", + "role": "Developer" + } + ], + "support": { + "email": "oom@oscarotero.com", + "issues": "https://github.com/oscarotero/html-parser/issues" + }, + "require": { + "php": "^7.2 || ^8" + }, + "autoload": { + "psr-4": { + "HtmlParser\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "HtmlParser\\Tests\\": "tests" + } + }, + "require-dev": { + "phpunit/phpunit": "^8.0", + "friendsofphp/php-cs-fixer": "^2.11" + }, + "scripts": { + "test": "phpunit", + "cs-fix": "php-cs-fixer fix ." + } +} diff --git a/Resources/Private/PHP/embed/vendor/oscarotero/html-parser/src/Parser.php b/Resources/Private/PHP/embed/vendor/oscarotero/html-parser/src/Parser.php new file mode 100644 index 0000000..e92b329 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/oscarotero/html-parser/src/Parser.php @@ -0,0 +1,95 @@ +saveHTML($node); + } + + return $node->ownerDocument->saveHTML($node); + } + + public static function parse(string $html, ?string $encoding = null): DOMDocument + { + $detected = $encoding ?? mb_detect_encoding($html); + + if ($detected) { + $html = mb_encode_numericentity($html, [0x80, 0xFFFFFF, 0, -1], $detected); + } + + $document = self::createDOMDocument($html); + $xpath = new DOMXPath($document); + + $charset = $xpath->query('.//meta[@charset]')->item(0); + $httpEquiv = $xpath->query('.//meta[@http-equiv]')->item(0); + + if ($charset || $httpEquiv) { + $charset = $charset ? self::stringify($charset) : null; + $httpEquiv = $httpEquiv ? self::stringify($httpEquiv) : null; + + $html = preg_replace( + '/]*>/', + ''.$charset.$httpEquiv, + $html + ); + + return self::createDOMDocument($html); + } + + return $document; + } + + public static function parseFragment(string $html, ?string $encoding = null): DOMDocumentFragment + { + $html = "{$html}"; + $document = static::parse($html, $encoding); + $fragment = $document->createDocumentFragment(); + + $body = $document->getElementsByTagName('body')->item(0); + + $nodes = []; + + foreach ($body->childNodes as $node) { + $nodes[] = $node; + } + + foreach ($nodes as $node) { + $fragment->appendChild($node); + } + + return $fragment; + } + + private static function createDOMDocument(string $code): DOMDocument + { + $errors = libxml_use_internal_errors(true); + + // Enabled by default in PHP 8 + if (PHP_MAJOR_VERSION < 8) { + $entities = libxml_disable_entity_loader(true); + } + + $document = new DOMDocument(); + $document->loadHTML($code); + + libxml_use_internal_errors($errors); + + if (PHP_MAJOR_VERSION < 8) { + libxml_disable_entity_loader($entities); + } + + return $document; + } +} diff --git a/Resources/Private/PHP/embed/vendor/psr/http-client/CHANGELOG.md b/Resources/Private/PHP/embed/vendor/psr/http-client/CHANGELOG.md new file mode 100644 index 0000000..e2dc25f --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/psr/http-client/CHANGELOG.md @@ -0,0 +1,23 @@ +# Changelog + +All notable changes to this project will be documented in this file, in reverse chronological order by release. + +## 1.0.1 + +Allow installation with PHP 8. No code changes. + +## 1.0.0 + +First stable release. No changes since 0.3.0. + +## 0.3.0 + +Added Interface suffix on exceptions + +## 0.2.0 + +All exceptions are in `Psr\Http\Client` namespace + +## 0.1.0 + +First release diff --git a/Resources/Private/PHP/embed/vendor/psr/http-client/LICENSE b/Resources/Private/PHP/embed/vendor/psr/http-client/LICENSE new file mode 100644 index 0000000..cd5e002 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/psr/http-client/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2017 PHP Framework Interoperability Group + +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/Resources/Private/PHP/embed/vendor/psr/http-client/README.md b/Resources/Private/PHP/embed/vendor/psr/http-client/README.md new file mode 100644 index 0000000..6876b84 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/psr/http-client/README.md @@ -0,0 +1,12 @@ +HTTP Client +=========== + +This repository holds all the common code related to [PSR-18 (HTTP Client)][psr-url]. + +Note that this is not a HTTP Client implementation of its own. It is merely abstractions that describe the components of a HTTP Client. + +The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist. + +[psr-url]: http://www.php-fig.org/psr/psr-18 +[package-url]: https://packagist.org/packages/psr/http-client +[implementation-url]: https://packagist.org/providers/psr/http-client-implementation diff --git a/Resources/Private/PHP/embed/vendor/psr/http-client/composer.json b/Resources/Private/PHP/embed/vendor/psr/http-client/composer.json new file mode 100644 index 0000000..c195f8f --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/psr/http-client/composer.json @@ -0,0 +1,27 @@ +{ + "name": "psr/http-client", + "description": "Common interface for HTTP clients", + "keywords": ["psr", "psr-18", "http", "http-client"], + "homepage": "https://github.com/php-fig/http-client", + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/Resources/Private/PHP/embed/vendor/psr/http-client/src/ClientExceptionInterface.php b/Resources/Private/PHP/embed/vendor/psr/http-client/src/ClientExceptionInterface.php new file mode 100644 index 0000000..aa0b9cf --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/psr/http-client/src/ClientExceptionInterface.php @@ -0,0 +1,10 @@ +=7.0.0", + "psr/http-message": "^1.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/Resources/Private/PHP/embed/vendor/psr/http-factory/src/RequestFactoryInterface.php b/Resources/Private/PHP/embed/vendor/psr/http-factory/src/RequestFactoryInterface.php new file mode 100644 index 0000000..cb39a08 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/psr/http-factory/src/RequestFactoryInterface.php @@ -0,0 +1,18 @@ +=5.3.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/Resources/Private/PHP/embed/vendor/psr/http-message/src/MessageInterface.php b/Resources/Private/PHP/embed/vendor/psr/http-message/src/MessageInterface.php new file mode 100644 index 0000000..dd46e5e --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/psr/http-message/src/MessageInterface.php @@ -0,0 +1,187 @@ +getHeaders() as $name => $values) { + * echo $name . ": " . implode(", ", $values); + * } + * + * // Emit headers iteratively: + * foreach ($message->getHeaders() as $name => $values) { + * foreach ($values as $value) { + * header(sprintf('%s: %s', $name, $value), false); + * } + * } + * + * While header names are not case-sensitive, getHeaders() will preserve the + * exact case in which headers were originally specified. + * + * @return string[][] Returns an associative array of the message's headers. Each + * key MUST be a header name, and each value MUST be an array of strings + * for that header. + */ + public function getHeaders(); + + /** + * Checks if a header exists by the given case-insensitive name. + * + * @param string $name Case-insensitive header field name. + * @return bool Returns true if any header names match the given header + * name using a case-insensitive string comparison. Returns false if + * no matching header name is found in the message. + */ + public function hasHeader($name); + + /** + * Retrieves a message header value by the given case-insensitive name. + * + * This method returns an array of all the header values of the given + * case-insensitive header name. + * + * If the header does not appear in the message, this method MUST return an + * empty array. + * + * @param string $name Case-insensitive header field name. + * @return string[] An array of string values as provided for the given + * header. If the header does not appear in the message, this method MUST + * return an empty array. + */ + public function getHeader($name); + + /** + * Retrieves a comma-separated string of the values for a single header. + * + * This method returns all of the header values of the given + * case-insensitive header name as a string concatenated together using + * a comma. + * + * NOTE: Not all header values may be appropriately represented using + * comma concatenation. For such headers, use getHeader() instead + * and supply your own delimiter when concatenating. + * + * If the header does not appear in the message, this method MUST return + * an empty string. + * + * @param string $name Case-insensitive header field name. + * @return string A string of values as provided for the given header + * concatenated together using a comma. If the header does not appear in + * the message, this method MUST return an empty string. + */ + public function getHeaderLine($name); + + /** + * Return an instance with the provided value replacing the specified header. + * + * While header names are case-insensitive, the casing of the header will + * be preserved by this function, and returned from getHeaders(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new and/or updated header and value. + * + * @param string $name Case-insensitive header field name. + * @param string|string[] $value Header value(s). + * @return static + * @throws \InvalidArgumentException for invalid header names or values. + */ + public function withHeader($name, $value); + + /** + * Return an instance with the specified header appended with the given value. + * + * Existing values for the specified header will be maintained. The new + * value(s) will be appended to the existing list. If the header did not + * exist previously, it will be added. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new header and/or value. + * + * @param string $name Case-insensitive header field name to add. + * @param string|string[] $value Header value(s). + * @return static + * @throws \InvalidArgumentException for invalid header names or values. + */ + public function withAddedHeader($name, $value); + + /** + * Return an instance without the specified header. + * + * Header resolution MUST be done without case-sensitivity. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that removes + * the named header. + * + * @param string $name Case-insensitive header field name to remove. + * @return static + */ + public function withoutHeader($name); + + /** + * Gets the body of the message. + * + * @return StreamInterface Returns the body as a stream. + */ + public function getBody(); + + /** + * Return an instance with the specified message body. + * + * The body MUST be a StreamInterface object. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return a new instance that has the + * new body stream. + * + * @param StreamInterface $body Body. + * @return static + * @throws \InvalidArgumentException When the body is not valid. + */ + public function withBody(StreamInterface $body); +} diff --git a/Resources/Private/PHP/embed/vendor/psr/http-message/src/RequestInterface.php b/Resources/Private/PHP/embed/vendor/psr/http-message/src/RequestInterface.php new file mode 100644 index 0000000..a96d4fd --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/psr/http-message/src/RequestInterface.php @@ -0,0 +1,129 @@ +getQuery()` + * or from the `QUERY_STRING` server param. + * + * @return array + */ + public function getQueryParams(); + + /** + * Return an instance with the specified query string arguments. + * + * These values SHOULD remain immutable over the course of the incoming + * request. They MAY be injected during instantiation, such as from PHP's + * $_GET superglobal, or MAY be derived from some other value such as the + * URI. In cases where the arguments are parsed from the URI, the data + * MUST be compatible with what PHP's parse_str() would return for + * purposes of how duplicate query parameters are handled, and how nested + * sets are handled. + * + * Setting query string arguments MUST NOT change the URI stored by the + * request, nor the values in the server params. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated query string arguments. + * + * @param array $query Array of query string arguments, typically from + * $_GET. + * @return static + */ + public function withQueryParams(array $query); + + /** + * Retrieve normalized file upload data. + * + * This method returns upload metadata in a normalized tree, with each leaf + * an instance of Psr\Http\Message\UploadedFileInterface. + * + * These values MAY be prepared from $_FILES or the message body during + * instantiation, or MAY be injected via withUploadedFiles(). + * + * @return array An array tree of UploadedFileInterface instances; an empty + * array MUST be returned if no data is present. + */ + public function getUploadedFiles(); + + /** + * Create a new instance with the specified uploaded files. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated body parameters. + * + * @param array $uploadedFiles An array tree of UploadedFileInterface instances. + * @return static + * @throws \InvalidArgumentException if an invalid structure is provided. + */ + public function withUploadedFiles(array $uploadedFiles); + + /** + * Retrieve any parameters provided in the request body. + * + * If the request Content-Type is either application/x-www-form-urlencoded + * or multipart/form-data, and the request method is POST, this method MUST + * return the contents of $_POST. + * + * Otherwise, this method may return any results of deserializing + * the request body content; as parsing returns structured content, the + * potential types MUST be arrays or objects only. A null value indicates + * the absence of body content. + * + * @return null|array|object The deserialized body parameters, if any. + * These will typically be an array or object. + */ + public function getParsedBody(); + + /** + * Return an instance with the specified body parameters. + * + * These MAY be injected during instantiation. + * + * If the request Content-Type is either application/x-www-form-urlencoded + * or multipart/form-data, and the request method is POST, use this method + * ONLY to inject the contents of $_POST. + * + * The data IS NOT REQUIRED to come from $_POST, but MUST be the results of + * deserializing the request body content. Deserialization/parsing returns + * structured data, and, as such, this method ONLY accepts arrays or objects, + * or a null value if nothing was available to parse. + * + * As an example, if content negotiation determines that the request data + * is a JSON payload, this method could be used to create a request + * instance with the deserialized parameters. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated body parameters. + * + * @param null|array|object $data The deserialized body data. This will + * typically be in an array or object. + * @return static + * @throws \InvalidArgumentException if an unsupported argument type is + * provided. + */ + public function withParsedBody($data); + + /** + * Retrieve attributes derived from the request. + * + * The request "attributes" may be used to allow injection of any + * parameters derived from the request: e.g., the results of path + * match operations; the results of decrypting cookies; the results of + * deserializing non-form-encoded message bodies; etc. Attributes + * will be application and request specific, and CAN be mutable. + * + * @return array Attributes derived from the request. + */ + public function getAttributes(); + + /** + * Retrieve a single derived request attribute. + * + * Retrieves a single derived request attribute as described in + * getAttributes(). If the attribute has not been previously set, returns + * the default value as provided. + * + * This method obviates the need for a hasAttribute() method, as it allows + * specifying a default value to return if the attribute is not found. + * + * @see getAttributes() + * @param string $name The attribute name. + * @param mixed $default Default value to return if the attribute does not exist. + * @return mixed + */ + public function getAttribute($name, $default = null); + + /** + * Return an instance with the specified derived request attribute. + * + * This method allows setting a single derived request attribute as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated attribute. + * + * @see getAttributes() + * @param string $name The attribute name. + * @param mixed $value The value of the attribute. + * @return static + */ + public function withAttribute($name, $value); + + /** + * Return an instance that removes the specified derived request attribute. + * + * This method allows removing a single derived request attribute as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that removes + * the attribute. + * + * @see getAttributes() + * @param string $name The attribute name. + * @return static + */ + public function withoutAttribute($name); +} diff --git a/Resources/Private/PHP/embed/vendor/psr/http-message/src/StreamInterface.php b/Resources/Private/PHP/embed/vendor/psr/http-message/src/StreamInterface.php new file mode 100644 index 0000000..f68f391 --- /dev/null +++ b/Resources/Private/PHP/embed/vendor/psr/http-message/src/StreamInterface.php @@ -0,0 +1,158 @@ + + * [user-info@]host[:port] + * + * + * If the port component is not set or is the standard port for the current + * scheme, it SHOULD NOT be included. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.2 + * @return string The URI authority, in "[user-info@]host[:port]" format. + */ + public function getAuthority(); + + /** + * Retrieve the user information component of the URI. + * + * If no user information is present, this method MUST return an empty + * string. + * + * If a user is present in the URI, this will return that value; + * additionally, if the password is also present, it will be appended to the + * user value, with a colon (":") separating the values. + * + * The trailing "@" character is not part of the user information and MUST + * NOT be added. + * + * @return string The URI user information, in "username[:password]" format. + */ + public function getUserInfo(); + + /** + * Retrieve the host component of the URI. + * + * If no host is present, this method MUST return an empty string. + * + * The value returned MUST be normalized to lowercase, per RFC 3986 + * Section 3.2.2. + * + * @see http://tools.ietf.org/html/rfc3986#section-3.2.2 + * @return string The URI host. + */ + public function getHost(); + + /** + * Retrieve the port component of the URI. + * + * If a port is present, and it is non-standard for the current scheme, + * this method MUST return it as an integer. If the port is the standard port + * used with the current scheme, this method SHOULD return null. + * + * If no port is present, and no scheme is present, this method MUST return + * a null value. + * + * If no port is present, but a scheme is present, this method MAY return + * the standard port for that scheme, but SHOULD return null. + * + * @return null|int The URI port. + */ + public function getPort(); + + /** + * Retrieve the path component of the URI. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * Normally, the empty path "" and absolute path "/" are considered equal as + * defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically + * do this normalization because in contexts with a trimmed base path, e.g. + * the front controller, this difference becomes significant. It's the task + * of the user to handle both "" and "/". + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.3. + * + * As an example, if the value should include a slash ("/") not intended as + * delimiter between path segments, that value MUST be passed in encoded + * form (e.g., "%2F") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.3 + * @return string The URI path. + */ + public function getPath(); + + /** + * Retrieve the query string of the URI. + * + * If no query string is present, this method MUST return an empty string. + * + * The leading "?" character is not part of the query and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.4. + * + * As an example, if a value in a key/value pair of the query string should + * include an ampersand ("&") not intended as a delimiter between values, + * that value MUST be passed in encoded form (e.g., "%26") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.4 + * @return string The URI query string. + */ + public function getQuery(); + + /** + * Retrieve the fragment component of the URI. + * + * If no fragment is present, this method MUST return an empty string. + * + * The leading "#" character is not part of the fragment and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.5. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.5 + * @return string The URI fragment. + */ + public function getFragment(); + + /** + * Return an instance with the specified scheme. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified scheme. + * + * Implementations MUST support the schemes "http" and "https" case + * insensitively, and MAY accommodate other schemes if required. + * + * An empty scheme is equivalent to removing the scheme. + * + * @param string $scheme The scheme to use with the new instance. + * @return static A new instance with the specified scheme. + * @throws \InvalidArgumentException for invalid or unsupported schemes. + */ + public function withScheme($scheme); + + /** + * Return an instance with the specified user information. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified user information. + * + * Password is optional, but the user information MUST include the + * user; an empty string for the user is equivalent to removing user + * information. + * + * @param string $user The user name to use for authority. + * @param null|string $password The password associated with $user. + * @return static A new instance with the specified user information. + */ + public function withUserInfo($user, $password = null); + + /** + * Return an instance with the specified host. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified host. + * + * An empty host value is equivalent to removing the host. + * + * @param string $host The hostname to use with the new instance. + * @return static A new instance with the specified host. + * @throws \InvalidArgumentException for invalid hostnames. + */ + public function withHost($host); + + /** + * Return an instance with the specified port. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified port. + * + * Implementations MUST raise an exception for ports outside the + * established TCP and UDP port ranges. + * + * A null value provided for the port is equivalent to removing the port + * information. + * + * @param null|int $port The port to use with the new instance; a null value + * removes the port information. + * @return static A new instance with the specified port. + * @throws \InvalidArgumentException for invalid ports. + */ + public function withPort($port); + + /** + * Return an instance with the specified path. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified path. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * If the path is intended to be domain-relative rather than path relative then + * it must begin with a slash ("/"). Paths not starting with a slash ("/") + * are assumed to be relative to some base path known to the application or + * consumer. + * + * Users can provide both encoded and decoded path characters. + * Implementations ensure the correct encoding as outlined in getPath(). + * + * @param string $path The path to use with the new instance. + * @return static A new instance with the specified path. + * @throws \InvalidArgumentException for invalid paths. + */ + public function withPath($path); + + /** + * Return an instance with the specified query string. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified query string. + * + * Users can provide both encoded and decoded query characters. + * Implementations ensure the correct encoding as outlined in getQuery(). + * + * An empty query string value is equivalent to removing the query string. + * + * @param string $query The query string to use with the new instance. + * @return static A new instance with the specified query string. + * @throws \InvalidArgumentException for invalid query strings. + */ + public function withQuery($query); + + /** + * Return an instance with the specified URI fragment. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified URI fragment. + * + * Users can provide both encoded and decoded fragment characters. + * Implementations ensure the correct encoding as outlined in getFragment(). + * + * An empty fragment value is equivalent to removing the fragment. + * + * @param string $fragment The fragment to use with the new instance. + * @return static A new instance with the specified fragment. + */ + public function withFragment($fragment); + + /** + * Return the string representation as a URI reference. + * + * Depending on which components of the URI are present, the resulting + * string is either a full URI or relative reference according to RFC 3986, + * Section 4.1. The method concatenates the various components of the URI, + * using the appropriate delimiters: + * + * - If a scheme is present, it MUST be suffixed by ":". + * - If an authority is present, it MUST be prefixed by "//". + * - The path can be concatenated without delimiters. But there are two + * cases where the path has to be adjusted to make the URI reference + * valid as PHP does not allow to throw an exception in __toString(): + * - If the path is rootless and an authority is present, the path MUST + * be prefixed by "/". + * - If the path is starting with more than one "/" and no authority is + * present, the starting slashes MUST be reduced to one. + * - If a query is present, it MUST be prefixed by "?". + * - If a fragment is present, it MUST be prefixed by "#". + * + * @see http://tools.ietf.org/html/rfc3986#section-4.1 + * @return string + */ + public function __toString(); +} diff --git a/Resources/Private/Templates/RsmoembedDefault.html b/Resources/Private/Templates/RsmoembedDefault.html new file mode 100644 index 0000000..ce6db50 --- /dev/null +++ b/Resources/Private/Templates/RsmoembedDefault.html @@ -0,0 +1,33 @@ + + + + + + + + {rsm:jsonToObject(value: data.tx_rsmoembed_data)} + + + +
+ + + +
+
+
+
+ + + + diff --git a/Resources/Public/Css/styles.css b/Resources/Public/Css/styles.css new file mode 100644 index 0000000..9ced23a --- /dev/null +++ b/Resources/Public/Css/styles.css @@ -0,0 +1,19 @@ +.tx_rsmoembed_default__item { + display: block; + position: relative; } + .tx_rsmoembed_default__item__link { + display: block; + position: relative; } + .tx_rsmoembed_default__item__image { + display: block; + width: 100%; + height: auto; } + +[data-rsmoembed-uid] { + display: block; + position: relative; } + +[data-rsmoembed-uid] * { + pointer-events: none; } + +/*# sourceMappingURL=styles.css.map */ diff --git a/Resources/Public/Css/styles.css.map b/Resources/Public/Css/styles.css.map new file mode 100644 index 0000000..90fb7c3 --- /dev/null +++ b/Resources/Public/Css/styles.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "AACI,2BAAQ;EACJ,OAAO,EAAE,KAAK;EACd,QAAQ,EAAE,QAAQ;EAClB,iCAAO;IACH,OAAO,EAAE,KAAK;IACd,QAAQ,EAAE,QAAQ;EAEtB,kCAAQ;IACJ,OAAO,EAAE,KAAK;IACd,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;;AASxB,oBAAqB;EACjB,OAAO,EAAE,KAAK;EACd,QAAQ,EAAE,QAAQ;;AAEtB,sBAAuB;EACnB,cAAc,EAAE,IAAI", +"sources": ["styles.scss"], +"names": [], +"file": "styles.css" +} \ No newline at end of file diff --git a/Resources/Public/Css/styles.scss b/Resources/Public/Css/styles.scss new file mode 100644 index 0000000..efe8e8f --- /dev/null +++ b/Resources/Public/Css/styles.scss @@ -0,0 +1,27 @@ +.tx_rsmoembed_default { + &__item { + display: block; + position: relative; + &__link{ + display: block; + position: relative; + } + &__image{ + display: block; + width: 100%; + height: auto; + } + //iframe { + // display: block; + // width: 100%; + // min-height: 100%; + //} + } +} +[data-rsmoembed-uid] { + display: block; + position: relative; +} +[data-rsmoembed-uid] * { + pointer-events: none; +} diff --git a/Resources/Public/Icons/Backend/rsmoembed_default.svg b/Resources/Public/Icons/Backend/rsmoembed_default.svg new file mode 100644 index 0000000..4419608 --- /dev/null +++ b/Resources/Public/Icons/Backend/rsmoembed_default.svg @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/Resources/Public/Icons/Extension.svg b/Resources/Public/Icons/Extension.svg new file mode 100644 index 0000000..4419608 --- /dev/null +++ b/Resources/Public/Icons/Extension.svg @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/Resources/Public/JavaScript/main.js b/Resources/Public/JavaScript/main.js new file mode 100644 index 0000000..3c4b840 --- /dev/null +++ b/Resources/Public/JavaScript/main.js @@ -0,0 +1,26 @@ +var RSM_OEMBED = { + init: function () { + RSM_OEMBED.addEvents(); + }, + addEvents: function () { + document.addEventListener('click', function (click) { + if (click.target.matches('[data-rsmoembed-uid]')) { + click.preventDefault(); + //console.log(click.target.dataset.rsmoembedUid); + var _xhr = new XMLHttpRequest(), + _self = click.target, + _uid = click.target.dataset.rsmoembedUid, + _url = '/?tx_rsmoembed_api[action]=findOne&tx_rsmoembed_api[uid]=' + _uid; + + _xhr.open('GET', _url, true); + _xhr.onreadystatechange = function () { + if (this.readyState === 4 && this.status === 200) { + _self.parentNode.innerHTML = this.responseText; + } + }; + _xhr.send(null); + } + }, false); + } +} +RSM_OEMBED.init(); diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..d4abed8 --- /dev/null +++ b/composer.json @@ -0,0 +1,49 @@ +{ + "name": "ressourcenmangel/rsmoembed", + "type": "typo3-cms-extension", + "description": "A simple content element to embed elements like facebook, youtube, soundcloud, ...", + "authors": [ + { + "name": "Matthias Kappenberg", + "email": "matthias.kappenberg@ressourcenmangel.de", + "role": "Developer" + } + ], + "keywords": ["oembed","youtube","vimeo","soundclud"], + "license": "GPL-2.0-or-later", + "require": { + "php": "^7.4 || ^8.0", + "typo3/cms-core": "^11.5" + }, + "require-dev": { + "typo3/testing-framework": "^6.9.0" + }, + "autoload": { + "psr-4": { + "Ressourcenmangel\\Rsmoembed\\": "Classes" + } + }, + "autoload-dev": { + "psr-4": { + "Ressourcenmangel\\Rsmoembed\\Tests\\": "Tests" + } + }, + "replace": { + "typo3-ter/rsmoembed": "self.version" + }, + "config": { + "vendor-dir": ".Build/vendor", + "bin-dir": ".Build/bin" + }, + "scripts": { + "post-autoload-dump": [ + "TYPO3\\TestingFramework\\Composer\\ExtensionTestEnvironment::prepare" + ] + }, + "extra": { + "typo3/cms": { + "web-dir": ".Build/public", + "extension-key": "rsmoembed" + } + } +} diff --git a/ext_emconf.php b/ext_emconf.php new file mode 100644 index 0000000..26d9fd9 --- /dev/null +++ b/ext_emconf.php @@ -0,0 +1,19 @@ + 'Ressourcenmangel Oembed', + 'description' => 'A simple content element to embed elements like facebook, youtube, soundcloud, ...', + 'category' => 'plugin', + 'author' => 'Matthias Kappenberg', + 'author_email' => 'matthias.kappenberg@ressourcenmangel.de', + 'state' => 'stable', + 'clearCacheOnLoad' => 1, + 'version' => '1.0.0', + 'constraints' => [ + 'depends' => [ + 'typo3' => '11.5.0-11.5.99', + ], + 'conflicts' => [], + 'suggests' => [], + ], +]; diff --git a/ext_localconf.php b/ext_localconf.php new file mode 100644 index 0000000..7e30eee --- /dev/null +++ b/ext_localconf.php @@ -0,0 +1,31 @@ +' + ); + + // Register a node in ext_localconf.php +// $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'][1601576934] = [ +// 'nodeName' => 'OEmbedData', +// 'priority' => 50, +// 'class' => \DIMENSION\Oembedsimple\Form\Element\OEmbedData::class, +// ]; + + + $composerAutoloadFile = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('rsmoembed') + . 'Resources/Private/PHP/embed/vendor/autoload.php'; + require_once($composerAutoloadFile); + + } +); diff --git a/ext_tables.php b/ext_tables.php new file mode 100644 index 0000000..32c3bcc --- /dev/null +++ b/ext_tables.php @@ -0,0 +1,24 @@ +registerIcon( + $iconKey, + \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class, + ['source' => 'EXT:rsmoembed/Resources/Public/Icons/Backend/' . $iconKey . '.svg'] + ); + $GLOBALS['TCA']['tt_content']['ctrl']['typeicon_classes'][$iconKey] = $iconKey; + } + +})(); diff --git a/ext_tables.sql b/ext_tables.sql new file mode 100644 index 0000000..efc35ab --- /dev/null +++ b/ext_tables.sql @@ -0,0 +1,7 @@ +CREATE TABLE tt_content +( + tx_rsmoembed_url varchar(1024) NOT NULL DEFAULT '', + tx_rsmoembed_data text NOT NULL DEFAULT '', + tx_rsmoembed_image_download smallint(1) unsigned NOT NULL DEFAULT '0', + tx_rsmoembed_image int(11) unsigned NOT NULL DEFAULT '0' +);